Nella progettazione di un sistema di automazione sono molto spesso previsti apparati di interazione e di allarme che potranno essere visivi o sonori. Per quanto riguarda gli apparati sonori spesso vengono utilizzati dei buzzer, chiamati anche cicalini. Con questo dispositivo potremo quindi segnalare lo stato di un sistema.
I buzzer possono essere di due tipi:
attivi
passivi
I buzzer possono essere di tipo magnetico o piezoelettrici la scelta del tipo dipende sostanzialmente da tre fattori:
segnale di pilotaggio
potenza di uscita richiesta
spazio fisico disponibile
Buzzer attivo
Un buzzer attivo usa un oscillatore interno che permette di emettere un tono a frequenza fissa se viene alimentato con una tensione continua.
L’oscillatore interno è in grado di modificare il campo magnetico di una bobina a cui è connesso meccanicamente una membrana che oscillerà alla frequenza fissata dall’oscillatore.
Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono abilitando o disabilitando l’alimentazione del buzzer.
Caratteristiche tecniche di un buzzer attivo
Tensione nominale: 6V DC
Tensione di esercizio: 4-8V DC
Corrente nominale: < 30mA
Tipo di suono: segnale acustico continuo
Frequenza di risonanza: ~2300 Hz
Buzzer passivo
Un buzzer passivo non possiede un oscillatore interno e quindi è indispensabile un circuito esterno in grado di generare un’onda quadra che mettere in oscillazione la membrana interna del buzzer, questi attuatori potranno così emettere toni a diversa frequenza.
Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono per un certo tempo ad una determinata frequenza utilizzando il la modulazione digitale PWM.
Caratteristiche tecniche di un buzzer attivo
Tensione nominale: 5V DC
Tensione di esercizio: 4-8V DC
Corrente nominale massima: ≤ 32 mA
Min. Uscita audio a 10 cm: 85 dB
Temperatura di esercizio: da 20°C a 45°C
Pilotare un buzzer con Arduino
Per produrre un suono con Arduino si utilizza la funzione tone, il link vi rimanda al references di Arduino in cui troverete tutti i dettagli di utilizzo della funzione.
pin: sarà il pin (PWM) su cui sarà presente il segnale modulato a cui verrà connesso il buzzer.
frequenza: frequenza del suono emesso. (unsigned int)
durata: la durata del tono espressa in millisecondi. (unsigned long)
Come indicato nel references:
Genera un’onda quadra alla frequenza specificata ( e duty cycle al 50% ) su un pin. Una durata puà essere specificata, altrimenti l’onda continua fino alla chiamata di noTone(). Il pin può essere connesso ad un buzzer piezoelettrico o altro speaker per riprodurre toni.
Solo un tono alla volta può essere generato. Se un tono è gia in riproduzione su un pin differente, la chiamata a tone() non avrà alcun effetto. Se il tono è in riproduzione sullo stesso pin, la chiamata ne imposterà la frequenza.
L’uso della funzione tone() interferirà con l’output PWM sui pin 3 e 11 (sulle schede diverse dalla Mega ).
Non è possibile generare toni inferioni a 31Hz. Per i dettagli tecnici, vedi le note di Brett Hagman.
NOTA: Se vuoi riprodurre toni differenti su pin multipli, hai bisogno di chiamare noTone() su un pin prima di chiamare tone() sul pin successivo.
La funzione noTone() interrompe la generazione dell’onda quadra causata da tone(). L’uso di noTone() non ha alcun effetto se non si sta generando alcun tono.
Con Arduino è possibile riprodurre un solo tono alla volta in quanto l’utilizzo della funzione tone è legato ad un timer specifico del microcontrollore, il timer2 e se questo è richiesto da altre funzioni, come ad esempio un analogRead su pin PWM la funzione tone non potrà essere utilizzata. Per aggirare questo limite è possibile utilizzare la libreria Tone.h che vedremo nella prossime lezioni.
Il suono che può essere riprodotto mediante un altoparlante o un buzzer passivo collegato ad Arduino sarà un suono “metallico”, non sarà simile a quello di uno strumento musicale, e questo verrà ottenuto utilizzando un’onda quadra alla frequenza specificata.
Per riprodurre suoni simili a quelli di uno strumento musicale bisognerà utilizzare una scheda elettronica esterna che verrà controllata da Arduino, ma vedremo questa possibilità in una lezione successiva.
Per questa lezione utilizzerò prima un buzzer attivo e successivamente un buzzer passivo.
// inizializzazione pin a cui è collegto il buzzer
14
pinMode(buzzerPin, OUTPUT);
15
}
16
17
voidloop() {
18
19
// buzzer ON
20
digitalWrite(buzzerPin,HIGH);
21
delay(buzzerRitardo);
22
23
// buzzer OFF
24
digitalWrite(buzzerPin,LOW);
25
delay(buzzerRitardo);
26
}
Esempio 02 – utilizzo buzzer attivo
Per richiamare l’uso di valori interi dalla Serial Monitor di seguito uno sketch che permette di inserire da computer il valore del delay che regola l’ON e l’OFF del buzzer attivo.
Lo schema di collegamento è il medesimo dell’esempio precedente.
Utilizziamo ora un trimmer per modificare il delay che varia tra 100 e 1000 millisecondi, per fare questa operazione utilizzeremo la funzione map che rimapperà i valori presenti su A0 nell’intervallo 100, 1000.
// per stampare una sola volta il messaggio sulla Serial Monitor
15
boolabilitaMessaggio = 0;
16
17
// variabile in cui memorizzare il valore restituito dall'analogRead
18
intval = 0;
19
20
voidsetup() {
21
22
// inizializzazione della serial monitor
23
Serial.begin(9600);
24
25
// inizializzazione pin a cui è collegto il buzzer
26
pinMode(buzzerPin, OUTPUT);
27
}
28
29
voidloop() {
30
31
// valore analogico letto su A0 inserito con il trimmer
32
val = analogRead(A0);
33
34
// Togliere il commento per valutare
35
// valore massimo/minimo del valore restituito
36
// dall'analogRead in questo modo si potranno
37
// inserire nella map i valori massimi e minimi
38
// dell'intervallo di partenza
39
40
// Serial.println(val);
41
// delay(1000);
42
43
// ValMax = 285, ValMin = 719
44
// riconvertiti nell'intervallo 100, 1000
45
46
buzzerRitardo = map(val, 285, 719, 100, 1000);
47
48
// funzione permette di fare suonare il Buzzer
49
suona();
50
}
51
52
voidsuona() {
53
// buzzer ON
54
digitalWrite(buzzerPin,HIGH);
55
delay(buzzerRitardo);
56
57
// buzzer OFF
58
digitalWrite(buzzerPin,LOW);
59
delay(buzzerRitardo);
60
}
Esempio 4 – utilizzo buzzer passivo
Utilizziamo ora un buzzer passivo per riprodurre un tono in base alla frequenza impostata da un trimmer collegato al pin A0. Si faccia attenzione che ora il buzzer è collegato al pin 5 di tipo PWM
// variabile in cui memorizzare la frequenza del tono
14
intintonazionePin = 0;
15
16
// variabile in cui memorizzare il valore restituito dall'analogRead
17
intval = 0;
18
19
// frequenza del tono
20
unsigned intfrequenza;
21
22
// durata del tono
23
unsigned longdurata = 10;
24
25
voidsetup()
26
{
27
// inizializzazione pin a cui è collegto il buzzer
28
pinMode(buzzerPin, OUTPUT);
29
}
30
31
voidloop()
32
{
33
// valore analogico letto su A0 inserito con il trimmer
34
val = analogRead(A0);
35
36
// Togliere il commento per valutare
37
// valore massimo/minimo del valore restituito
38
// dall'analogRead in questo modo si potranno
39
// inserire nella map i valori massimi e minimi
40
// dell'intervallo di partenza
41
42
// Serial.println(val);
43
// delay(1000);
44
45
// ValMax = 285, ValMin = 719
46
// riconvertiti nell'intervallo 1000, 5000
47
48
// frequenza assunerà un valore tra 1000 Hz e 5000 Hz
49
frequenza = map(val, 285, 719, 1000, 5000);
50
51
// emissione del tono
52
tone(buzzerPin, frequenza, durata);
53
54
// pausa di 1 millisecondo
55
delay(1);
56
}
Nella prossime lezioni, utilizzando un buzzer passivo, realizzeremo dei brevi brani musicali e successivamente sostituiremo il buzzer con un altoparlante da 8 Ohm.
Sensors in fingers & palm trigger custom sounds while connected wrist controller, hand gestures control effects with reverb, echo, etc.
Perché vi segnalo questo progetto?
Analizzo molto spesso kickstarter ed ultimamente, su segnalazione di un caro amico, mi ha colpito in modo particolare il progetto Remidi, un guanto interattivo in grado essere un nuovo strumento musicale senza precedenti, un oggetto che da grazia e movimento alla produzione di musica che potrebbe far nascere nuove modalità di interazione tra persone e per me, che mi occupo di formazione, intravedo un potenziale oggetto che potrebbe migliorare l’espressività negli adolescenti introversi o dare sfogo all’iperattività di altri o ancora un nuovo ausilio per alcune disabilità.
Per questa lezione ho utilizzato LilyPad Buzzer che ho acquistato su Sparkfun. Si tratta di un piccolo buzzer induttivo con due pin I/O in grado di riprodurre suoni di un livello sufficientemente alto da poter essere sentiti ad esempio se avete il buzzer in tasca, ma non aspettatevi livelli sonori elevatissimi.
Le dimensioni sono di 20 mm di diametro e 0,8 mm di spessore.
Passo 01
Come consigliato nella lezione n. 3 procedete anche per questa piccola scheda alla realizzazione del supporto protettivo in cartocino al fine di evitare scivolamenti dei morsetti a coccodrillo.
Passo 02
Collegate il “+” del buzzer al piedino 9 di LilyPad e il “-” del buzzer al “-” di LiLyPad come rappresentato nell’immagine:
Passo 03
Avviate l’IDE di Arduino e copiate ed incollate il codice che trovate di seguito:
/* Arduino LilyPad: lezione 04: suono
* Uso del modulo buzzer
* Michele Maffucci LilyPad Buzzer per realizzare semplici note musicali
* https://www.maffucci.it/2011/06/30/arduino-lilypa-zione-04-suono/
* Progetto originale:
* http://web.media.mit.edu/~leah/LilyPad/07_sound.html
* per un grafico sulle differenti frequenze delle note:
* http://www.phy.mtu.edu/~suits/notefreqs.html
*/
int ledPin = 13; // il LED � connesso al pin digitale 13
int speakerPin = 9; // il buzzer � connesso al pin digitale 9 (uscita di tipo PWM)
void setup()
{
pinMode(ledPin, OUTPUT); // si imposta ledPin come pin di output
pinMode(speakerPin, OUTPUT); // si imposta speakerPin come pin di output
}
void loop() // inizio del loop
{
scale(); // chiamata della funzione scale()
delay(1000); // attesa di 1 secondo
}
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds) // funzione che produce il suono
{
int x;
// converte il periodo della nota in un intero lungo
long delayAmount = (long)(1000000/frequencyInHertz);
long loopTime = (long)((timeInMilliseconds*1000)/(delayAmount*2));
for (x=0;x<loopTime;x++)
{
digitalWrite(speakerPin,HIGH);
delayMicroseconds(delayAmount);
digitalWrite(speakerPin,LOW);
delayMicroseconds(delayAmount);
}
}
void scale ()
{
// speakerPin: piedino LilyPad; numero da: 2093 a 4186: frequenza della nota; 500: durata della nota
digitalWrite(ledPin,HIGH); //accende il LED
beep(speakerPin,2093,500); //C: suona le note C (C7 come da tabella linkata sopra) per 500ms
beep(speakerPin,2349,500); //D
beep(speakerPin,2637,500); //E
beep(speakerPin,2793,500); //F
beep(speakerPin,3136,500); //G
beep(speakerPin,3520,500); //A
beep(speakerPin,3951,500); //B
beep(speakerPin,4186,500); //C
digitalWrite(ledPin,LOW); //spegne il LED
}
Un long � un tipo intero lungo che pu� contenere un numero intero positivo o negativo (quindi senza punto decimale) di 32 bit con valori compresi tra 2.147.483.647 a – 2.147.483.648
Analizziamo con molta attenzione la funzione beep.
long delayAmount = (long)(1000000/frequencyInHertz); ?
Domanda: cosa vuol dire 1000000/frequencyInHertz:
Vi ricordo che il periodo di una forma d’onda �:
T =1/f
dove f � la frequenza espressa in Hertz. L’unit� di misura del periodo T � il secondo.
quindi la formula:
1000000/frequencyInHertz
pu� essere scritta come:
1000000 * (1/frequencyInHertz)
ovvero:
1000000 * T
Domanda: perch� moltiplichiamo per 1000000?
Perch� la variabile delayAmount verr� passata a delayMicroseconds() che � una funzione che mette in pausa il programma per un tempo, espresso in microsecondi, specificato dal parametro.
Domanda: ma in un secondo quanti microsecondi ci sono?
1 milione di microsecondi
Ecco spiegato l’arcano, poich� delayMicroseconds() accetta un parametro in microsecondi bisogna moltiplicare 1/frequencyInHertz per 1000000.
Domanda: cosa vuol dire (long) nell’istruzione:
long delayAmount = (long)(1000000/frequencyInHertz);
Per spiegare questa linea di codice devo parlarvi di Type-casting.
In C � possibile forzare il tipo di una variabile (int, long, float, …) in un altro tipo, utilizzando l’operatore “()”
Ad esempio:
int a;
int b=67;
float c=3.14;
float d;
char lettera='M';
/* assegna il valore 3 (solo la parte intera) ad a */
a=(int)c
/* assegna il valore 77 (codice ASCII) ad a */
a=(int)lettera
/* assegna alla variabile d il valore di b, 67.0 (valore float) */
d=(float)b
In alcuni casi il Type-casting viene fatto automaticamente dal compilatore in altri casi bisogna specificarlo. Il Type-casting � una richiesta al compilatore di trasformazione di tipo.
Quando siamo in dubbio � buona norma eseguire il Type-casting.
Il Type-casting risulta utile ad esempio in una divisione:
int x, y;
float w;
w=(float)x/(float)y;
questa operazione assicura che la divisione sia in floating-point.
Tornando alla nostra istruzione:
long delayAmount = (long)(1000000/frequencyInHertz);
quando effettuiamo un passaggio di valore ad una funzione bisogna convertire long in (long , infatti delayAmount viene passata a delayMicroseconds.
Domanda: ma cos’� delayAmount?
� il periodo T della frequenza della nota.
Domanda: a cosa serve loopTime?
loopTime definisce il numero di volte in cui la nota deve essere suonata.
la nota viene suonata per un tempo delayAmount, periodo della della nota
l’uscita speakerPin (pin 9) viene portata a massa (spento)
digitalWrite(speakerPin,LOW);
per una quantit� di tempo pari al periodo:
delayMicroseconds(delayAmount);
La variazione del timbro della nota avviene se utilizzate la modulazione di larghezza di impulso in inglese Pulse Width Modulation, in questo modo se il treno di impulsi � sufficientemente elevato l’orecchio umano non percepir� una sequenza di impulsi ma un suono costante.