Lezione 7 – Corso di Elettronica Creativa con Arduino Sensor Kit

Utilizzo del microfono analogico

In questa lezione vedremo come utilizzare il sensore di suono integrato nell’Arduino Sensor Kit, leggeremo il segnale analogico prodotto con l’istruzione analogRead() e ne interpreteremo i valori.
Verrà introdotto, in modo estremamente semplice il concetto di decibel e vedremo come procedere alla calibrazione del microfono in funzione delle attività di sperimentazione che verranno proposte.

Il microfono del Sensor Kit è pre‑cablat​o sulla linea analogica A0 tramite il connettore Grove, quindi non sono necessari ulteriori collegamenti.

Principio di funzionamento

Il modulo Grove Sound Sensor è un ottimo strumento per misurare i rumori intorno a voi. Quando l’aria vibra a causa di un suono, una sottile membrana nel microfono si piega avanti e indietro. Questi movimenti generano una variazione di tensione: più forte è il suono, più grande è la variazione e quindi più alto sarà il numero che andremo a leggere con Arduino mediante l’istruzione analogRead().

Approfondimento tecnico

Per chi ha qualche competenza in più in elettronica aggiungo che all’interno del modulo è presente un microfono a elettrete o microfono electret collegato a un piccolo amplificatore (LM358). L’amplificatore rende il segnale abbastanza grande da poter essere rilevabile da Arduino. Un circuito chiamato rivelatore di inviluppo converte le onde sonore in un valore di tensione continua che rappresenta l’intensità del suono istantaneo.

  • Il segnale in uscita varia da 0 V (silenzio) a 5 V (suono molto forte).
  • Arduino lo misura con il convertitore A/D a 10 bit, producendo numeri da 0 a 1023.
  • Il modulo è sensibile a frequenze fino a ~20 kHz (oltre il limite dell’udito umano).
  • L’amplificatore amplifica il segnale di circa 26 dB, così anche suoni deboli diventano misurabili.
  • Il consumo di corrente è basso, circa 4‑5 mA.

Nelle specifiche del dispositivo parlo di convertitore A/D a 10 bit e decibel (dB) e indico che l’amplificatore amplifica, in modo più semplice, ingrandisce di 26 dB, vediamo cosa vuol dire.

Qualche concetto tecnico spiegato in modo semplice

Cos’è un convertitore A/D a 10 bit

Un convertitore A/D (Analogico → Digitale) è come un traduttore: trasforma la tensione continua che esce dal sensore in numeri che il microcontrollore può elaborare.

10 bit significa che abbiamo 2¹⁰ = 1024 possibili valori, da 0 (0 V) a 1023 (5 V circa). Ogni “scalino” vale quindi circa 5 V / 1023 ≈ 0,005 V (5 millivolt). Più bit, più la scala è fine e la misura precisa.

Che cosa sono i decibel (dB) e perché l’amplificatore “ingrandisce” di 26 dB?

Il decibel (dB) è una grandezza adimensionale ed è un modo logaritmico di confrontare due grandezze: dice “quante volte più grande” è un segnale rispetto a un altro, ma usa il logaritmo per compattare numeri dimensionalmente diversi in una scala più gestibile. Inoltre il nostro orecchio non percepisce l’intensità del suono in modo lineare: se la potenza acustica raddoppia non ci sembra “due volte più forte”, ma solo un po’ più intensa. Questa risposta psicoacustica si descrive bene con una scala logaritmica, perciò usiamo i decibel.

Per le tensioni si usa la formula:

dB = 20 × log10(V2 / V1)

  • 0 dB ⇒ stessa tensione
  • +6 dB ⇒ tensione circa doppia
  • −6 dB ⇒ tensione circa metà

Dire che l’amplificatore aumenta il segnale di 26 dB significa che la tensione in uscita è circa 20× (volte) più grande di quella che entra (perché 20× ≈ 26 dB). Così anche un suono debole crea un segnale abbastanza grande da essere misurato da Arduino.

ATTENZIONE

Questo sensore è pensato per percepire la presenza di suoni e valutarne l’intensità, non per registrare l’audio né per misurazioni professionali in decibel. Per avere dati certificati servono microfoni calibrati e convertitori più veloci.

Esempio di base

1/*
2  Prof. Maffucci Michele
3  24.06.25
4  LED reagisce al suono
5  Accende il LED sul pin 6 se il valore supera la soglia impostata.
6*/
7 
8const int pinSuono   = A2;    // pin a cui è connesso il sensore
9const int pinLED     = 6;     // LED del Sensor Kik
10const int sogliaRumore = 200; // valore da calibrare in base all'ambiente
11 
12void setup() {
13  pinMode(pinLED, OUTPUT);
14  Serial.begin(9600);
15}
16 
17void loop() {
18  int livello = analogRead(pinSuono);
19  bool rumoreForte;
20  // per approfondimenti sui tipi di dati:
22 
23if (livello > sogliaRumore) {
24    rumoreForte = true;
25  } else {
26    rumoreForte = false;
27  }
28 
29if (rumoreForte) {
30    digitalWrite(pinLED, HIGH);  // se supera la soglia il LED viene acceso
31  } else {
32    digitalWrite(pinLED, LOW);   // se non supera la soglia il led viene mantenuto apento
33  }
34 
35Serial.print("Livello: ");
36  Serial.print(livello);
37  Serial.print("  Rumore forte? ");
38  Serial.println(rumoreForte ? "SI" : "NO");
39 
40delay(500);
41}

Esempio 1 – uso del plotter seriale

Il Serial Plotter dell’IDE Arduino è uno strumento grafico che trasforma le righe di Serial.println() in un diagramma in tempo reale. È utilissimo per vedere l’andamento dei valori del sensore di suono (ma anche di altri sensori) senza dover esportare i dati.

Per poter visualizzare il grafico procedete in questo modo:

  • Caricare lo sketch che stampa i valori.
    Ricordarsi di impostare nel setup() la stessa velocità usata dal Plotter, tipicamente Serial.begin(9600); o Serial.begin(115200);
  • Clic su Strumenti > Plotter seriale. Comparirà una finestra con l’asse del tempo (orizzontale) e il valore (verticale).

Come vengono tracciate le linee del grafico

  • Ogni riga stampata con un solo numero crea un unico grafico (linea blu).
  • Se in una riga separate più numeri con uno spazio o un tab, il Plotter disegnerà una linea per ciascun numero, con colori diversi. Vedremo come fare negli esempi che seguono.

Modifichiamo l’esempio di base mostrando solamente il valore numerico restituito dalla analogRead() e poi mostriamone l’andamento sul Plotter seriale.
Nell’esempio (poiché mentre creavo lo sketch mi sono spostato in altro luogo) ho modificato la soglia di sensibilità a 300 e aumentato la frequenza con cui viene visualizzato il valore.

1/*
2  Prof. Maffucci Michele
3  24.06.25
4  LED reagisce al suono
5  Accende il LED sul pin 6 se il valore supera la soglia impostata.
6  Visualizzare il grafico sul Plotter seriale.
7*/
8 
9const int pinSuono   = A2;    // pin a cui è connesso il sensore
10const int pinLED     = 6;     // LED del Sensor Kit
11const int sogliaRumore = 300; // valore da calibrare in base all'ambiente
12 
13void setup() {
14  pinMode(pinLED, OUTPUT);
15  Serial.begin(9600);
16}
17 
18void loop() {
19  int livello = analogRead(pinSuono);
20  Serial.println(livello);
21  bool rumoreForte;
22  // per approfondimenti sui tipi di dati:
24 
25if (livello > sogliaRumore) {
26    rumoreForte = true;
27  } else {
28    rumoreForte = false;
29  }
30 
31if (rumoreForte) {
32    digitalWrite(pinLED, HIGH);  // se supera la soglia il LED viene acceso
33  } else {
34    digitalWrite(pinLED, LOW);   // se non supera la soglia il led viene mantenuto apento
35  }
36 
37delay(50);
38}

Vediamo ora come tracciare sul Plotter seriale il valore letto dal sensore e la soglia che nell’esempio che segue è fissata a 500.

1/*
2  Prof. Maffucci Michele
3  24.06.25
4  LED reagisce al suono
5  Accende il LED sul pin 6 se il valore supera la soglia impostata.
6  Visualizzazione della soglia e del grafico del segnale sul Plotter seriale.
7*/
8 
9const int pinSuono   = A2;    // pin a cui è connesso il sensore
10const int pinLED     = 6;     // LED del Sensor Kit
11const int sogliaRumore = 500; // valore da calibrare in base all'ambiente
12 
13void setup() {
14  pinMode(pinLED, OUTPUT);
15  Serial.begin(9600);
16}
17 
18void loop() {
19  int livello = analogRead(pinSuono);
20 
21Serial.print(livello);
22  Serial.print(" ");
23  Serial.println(sogliaRumore);
24 
25bool rumoreForte;
26  // per approfondimenti sui tipi di dati:
28 
29if (livello > sogliaRumore) {
30    rumoreForte = true;
31  } else {
32    rumoreForte = false;
33  }
34 
35if (rumoreForte) {
36    digitalWrite(pinLED, HIGH);  // se supera la soglia il LED viene acceso
37  } else {
38    digitalWrite(pinLED, LOW);   // se non supera la soglia il led viene mantenuto apento
39  }
40 
41delay(50);
42}

Esempio 2 – media dei valori – (divisione classica)

Per “addolcire” i dati (cioè smussarli o in inglese smoothing) calcoliamo la media di un gruppo di letture: in questo modo i picchi molto rapidi (rumori casuali) si attenuano e rimane l’andamento generale del suono, più facile da vedere sul grafico.
Prenderemo, come fatto anche sullo sketch di base del sito Arduino, 32 campioni dopo di che ne faremo la media.

Perché dividiamo per 32?

  • 32 è un numero comodo perché è una potenza di due (2⁵). In informatica dividere per potenze di due è veloce: basta uno shift (» 5) invece di una divisione lenta.
  • Una finestra da 32 campioni è abbastanza lunga da ridurre il rumore ma non così lunga da rendere il LED “pigro”. Se campioniamo a circa 1 kHz, 32 campioni coprono solo 32 ms, quindi la risposta rimane visivamente veloce.
  • Volendo più o meno filtraggio si può cambiare la dimensione: 8 o 16 campioni per una risposta più rapida, 64 per un’uscita più stabile.

Questa prima versione calcola la media di 32 campioni usando la classica divisione /32. Se il valore supera la soglia, il LED collegato al D6 si accende.

1/*
2  Prof. Maffucci Michele
3  25.06.25
4  LED reagisce al suono
5  Accende il LED sul pin 6 se il valore supera la soglia impostata.
6  Visualizzare il grafico sul Plotter seriale.
7  Media 32 campioni calcolata con divisione classica.
8*/
9 
10const int pinSuono = A2;   // oppure A2 se usi il modulo Grove separato
11const int pinLED   = 6;    // LED dell'Arduino Sensor Kit
12const int sogliaMax = 300; // soglia di esempio
13 
14void setup() {
15  Serial.begin(9600);
16  pinMode(pinLED, OUTPUT);
17}
18 
19void loop() {
20  long sommaSuono = 0;
21  for (int i = 0; i < 32; i++) {
22    sommaSuono += analogRead(pinSuono);
23  }
24 
25int soundValue = sommaSuono / 32;    // media dei valori
26  Serial.println(soundValue);
27 
28// Accendi il LED se superi la soglia
29  if (soundValue > sogliaMax) {
30    digitalWrite(pinLED, HIGH);
31  } else {
32    digitalWrite(pinLED, LOW);
33  }
34 
35delay(50);
36}

Esempio 2 – media dei valori – (bitshift)

Facciamo la stessa cosa ma dividiamo per 32 usando lo shift a destra di 5 bit (>> 5), che è più veloce su microcontrollori a 8 bit come l’ATmega328P.

1/*
2  Prof. Maffucci Michele
3  25.06.25
4  LED reagisce al suono
5  Accende il LED sul pin 6 se il valore supera la soglia impostata.
6  Visualizzare il grafico sul Plotter seriale.
7  Media 32 campioni calcolata con bitshift.
8*/
9 
10const int pinSuono = A2;   // oppure A2 se usi il modulo Grove separato
11const int pinLED   = 6;    // LED dell'Arduino Sensor Kit
12const int sogliaMax = 300; // soglia di esempio
13 
14void setup() {
15  Serial.begin(9600);
16  pinMode(pinLED, OUTPUT);
17}
18 
19void loop() {
20  long sommaSuono = 0;
21  for (int i = 0; i < 32; i++) {
22    sommaSuono += analogRead(pinSuono);
23  }
24 
25int soundValue = sommaSuono >> 5;    // divide per 32 con bitshift
26  Serial.println(soundValue);
27 
28if (soundValue > sogliaMax) {
29    digitalWrite(pinLED, HIGH);
30  } else {
31    digitalWrite(pinLED, LOW);
32  }
33 
34delay(50);
35}

Entrambi gli esempi 1 e 2 ottengono la stessa media, ma il bitshift richiede meno cicli macchina. Su progetti didattici le differenze sono trascurabili.

Le sperimentazioni con il microfono non termineranno con questa lezione, vedremo anche come realizzare un grafico con media mobile, come stimare in modo approssimato i Decibel, come realizzare un “baccanometro” ovvero un misuratore di rumore “live” per l’aula i cui dati vengono memorizzati su SD e poi approfondiremo meglio l’uso del Plotter seriale e del bitshift, ma tutto questo in altre lezioni.

Buon Coding a tutti. 🙂

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.