![06 Numerazione capitolo](06-num-capitolo.png) ## 06 - THEREMIN COMANDATO DALLA LUCE **È ORA DI FARE RUMORE! USANDO UNA FOTORESISTENZA E UN PIEZO, POTRAI FARE IL TUO THEREMIN COMANDATO DALLA LUCE** > **Scopri:** produrre suoni con la funzione `tone()`, calibrazione di sensori analogici > > **Tempo:** 45 MINUTI > **Livello:** ■ ■ ■ ■ □ > **Basato sui progetti:** 1, 2, 3, 4 ![Ingredienti](06-ingredienti.png) **INGREDIENTI** * Piezo * Fotoresistenza * Resistenza da 10 Kilo Ohm Il *theremin* è uno strumento musicale che produce suoni in base ai movimenti delle mani del musicista. Probabilmente lo hai sentito in qualche film dell'orrore. Il theremin rileva la posizione delle mani del musicista in relazione a due antenne leggendo le variazioni di capacità sulle antenne, che sono collegate a un circuito analogico che crea il suono. Un'antenna controlla la frequenza del suono e l'altra controlla il volume. Sebbene Arduino non possa replicare esattamente i misteriosi suoni di questo strumento, è possibile emularli usando la funzione `tone()`. La Fig. 1 mostra le differenze tra gli impulsi emessi da `analogWrite()` e `tone()`. Questo permette a un trasduttore come uno speaker o un piezo di vibrare a velocità diverse. ![Fig. 1: Differenza tra PWM e tone()](06-immagine_pwm_vs_tone.png) * **PWM 50:** `analogWrite(50)` - Nota come è basso il segnale nella maggior parte del tempo, ma la frequenza è la stessa di PWM 200. * **PWM 200:** `analogWrite(200)` - Nota come è alta la tensione nella maggior parte del tempo, ma la frequenza è la stessa di PWM 50. * **TONE 440:** `tone(9, 440)` - Il ciclo di lavoro è al 50% (acceso metà del tempo, spento metà del tempo), ma cambia la frequenza. * **TONE 880:** `tone(9, 880)` - Lo stesso ciclo di lavoro di Tone 440, ma il doppio della frequenza. Invece di misurare la capacità con Arduino, usa una fotoresistenza per rilevare la quantità di luce. Muovendo le mani sul sensore, cambia la quantità di luce che cade sulla fotoresistenza, come hai fatto nel Progetto 04. Il cambiamento di tensione sul piedino analogico determina la frequenza delle note. Collega le fotoresistenze ad Arduino usando un partitore di tensione come hai fatto nel Progetto 04. Probabilmente nei progetti precedenti hai notato che quando leggi questo circuito usando la funzione `analogRead()` le tue letture non coprono l'intervallo tra 0 e 1023. La resistenza fissa connessa a massa determina il valore più basso dell'intervallo e la luminosità della luce determina il valore massimo. Invece di accontentarsi di un intervallo limitato, calibra le letture del sensore prendendo il valore minore e maggiore e mappali alle frequenze sonore usando la funzione `map()` per ottenere un intervallo il più ampio possibile per il theremin. Questo aggiunge il vantaggio di adattare le letture del sensore quando sposti il circuito in un ambiente diverso, come una stanza con condizioni diverse di luce. ![Piezo](06-piezo.png) > Un **piezo** è un piccolo elemento che vibra quando riceve elettricità. Quando si muove, sposta aria intorno a sé creando onde sonore. ### COSTRUISCI IL CIRCUITO ![Schema del circuito e montaggio](06-immagine_circuito_theremin.png) 1. Sulla breadboard, collega le linee esterne all'alimentazione e a massa. 2. Prendi il piezo e collegane un'estremità a massa e l'altra al piedino digitale 8 su Arduino. 3. Posiziona la fotoresistenza sulla breadboard, collegandone un'estremità a 5V. Collega l'altra estremità al piedino analogico 0 di Arduino e a massa attraverso una resistenza da 10 kilo ohm. Il circuito è lo stesso del partitore di tensione del Progetto 04. ![Schema elettrico](06-schema_elettrico.png) ![Cervello](cervello.png) > *I theremin tradizionali possono controllare la frequenza e il volume del suono. In questo esempio, controllerai solo la frequenza. Sebbene non si possa controllare il volume attraverso Arduino, è possibile cambiare manualmente il livello di tensione che giunge al piezo. Cosa accade se metti un potenziometro in serie con il piedino 8 e il piezo? E con un'altra fotoresistenza?* ### IL CODICE #### Crea le variabili per calibrare il sensore Crea una variabile per memorizzare il valore letto dalla fotoresistenza con `analogRead()`. Poi, crea variabili per i valori alto e basso. Imposta il valore iniziale nella variabile `sensorLow` a 1023 e il valore di `sensorHigh` a 0. Quando esegui il programma per la prima volta, confronta questi numeri alla lettura del sensore per trovare i reali valori massimi e minimi. ```cpp int sensorValue; int sensorLow = 1023; int sensorHigh = 0; ``` #### Dai un nome alla costante per l'indicatore di calibrazione Crea una costante chiamata `ledPin`. Userai questo LED come indicatore del fatto che il sensore ha finito la calibrazione. Per questo progetto collegalo al piedino 13. ```cpp const int ledPin = 13; ``` #### Imposta la direzione del piedino digitale e accendilo Nel `setup()`, cambia il `pinMode()` del ledPin a **OUTPUT** e accendi la luce. ```cpp void setup() { pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH); ``` #### Usa un ciclo while() per la calibrazione Nei passi successivi occorre calibrare i valori minimi e massimi del sensore. Usa un'istruzione `while()` per eseguire un ciclo per 5 secondi. Il ciclo `while()` si esegue fino a che si verifica una certa condizione. In questo caso usa la funzione `millis()` per misurare il tempo. `millis()` riporta da quanti millesimi di secondo l'Arduino è acceso o resettato. ```cpp while (millis() < 5000) { ``` > **Comando while()** > [arduino.cc/while](http://arduino.cc/while) #### Confronta i valori del sensore per la calibrazione Nel ciclo, leggi il valore del sensore; se il valore è minore di `sensorLow` (inizialmente 1023), aggiorna questa variabile. Se è più grande di `sensorHigh` (inizialmente 0), aggiornalo. ```cpp sensorValue = analogRead(A0); if (sensorValue > sensorHigh) { sensorHigh = sensorValue; } if (sensorValue < sensorLow) { sensorLow = sensorValue; } } ``` #### Indica che la calibrazione è finita Quando sono passati 5 secondi, termina il ciclo `while()`. Spegni il LED attaccato al piedino 13. Usa i valori maggiore e minore del sensore appena registrato per calcolare la frequenza nella parte principale del programma. ```cpp digitalWrite(ledPin, LOW); } ``` #### Leggi e immagazzina il valore del sensore Nel `loop()`, leggi il valore su A0 e immagazzinalo in `sensorValue`. ```cpp void loop() { sensorValue = analogRead(A0); ``` #### Mappa il valore del sensore a una frequenza Crea una variabile di nome `pitch`. Il valore di `pitch` viene calcolato a partire da `sensorValue`. Utilizza `sensorLow` e `sensorHigh` come i limiti per i valori in entrata. Come valori iniziali d'uscita, prova 50 e 4000. Questi numeri impostano l'intervallo di frequenze che genererà Arduino. ```cpp int pitch = map(sensorValue, sensorLow, sensorHigh, 50, 4000); ``` #### Suona la frequenza Chiama la funzione `tone()` per riprodurre un suono. Ci vogliono tre argomenti: quale piedino suonare (in questo caso il piedino 8), quale frequenza suonare (determinata dalla variabile `pitch`) e per quanto tempo suonare la nota (per iniziare prova con 20 millesimi di secondo). Chiama quindi la funzione `delay()` per 10 millesimi di secondo per creare un po' di stacco tra le note. ```cpp tone(8, pitch, 20); delay(10); } ``` ### USALO Quando accendi Arduino, c'è una finestra di 5 secondi per calibrare il sensore. Per farlo, muovi la mano su e giù sopra la fotoresistenza modificando la quantità di luce che la raggiunge. Quanto più si replicano i movimenti che si prevede di fare mentre si suona lo strumento, migliore è la calibrazione. Dopo 5 secondi, la calibrazione è completa e il LED su Arduino si spegne. Dovresti quindi sentire rumori provenienti dal piezo! Al variare della quantità di luce che cade sui sensori dovrebbe variare la frequenza prodotta dal piezo. ![Forbici e colla](forbici-colla.png) > *L'intervallo nella funzione `map()` che determina il suono è piuttosto ampio; prova a cambiare le frequenze per trovarne una giusta per il tuo stile musicale.* ![Lente](lente.png) > *La funzione `tone()` opera in modo molto simile al PWM in `analogWrite()`, ma con una differenza significativa. In `analogWrite()` la frequenza è fissa; cambia il ciclo di lavoro degli impulsi in un dato periodo di tempo. Con `tone()` invii ancora impulsi, ma cambiando la loro frequenza. `tone()` manda sempre impulsi a un ciclo di lavoro del 50% (metà del tempo il piedino è acceso, l'altra metà del tempo è spento).* **La funzione `tone()` ti offre la possibilità di generare frequenze diverse tramite un altoparlante o un piezo. Usando i sensori in un partitore di tensione, probabilmente non sarà possibile ottenere l'intera gamma di valori tra 0 e 1023. Calibrando i sensori, è possibile mappare gli ingressi a un intervallo adatto.** ### CODICE COMPLETO ```cpp /* Arduino Starter Kit example Project 6 - Light Theremin This sketch is written to accompany Project 6 in the Arduino Starter Kit Parts required: - photoresistor - 10 kilohm resistor - piezo created 13 Sep 2012 by Scott Fitzgerald https://store.arduino.cc/genuino-starter-kit This example code is part of the public domain. */ // variable to hold sensor value int sensorValue; // variable to calibrate low value int sensorLow = 1023; // variable to calibrate high value int sensorHigh = 0; // LED pin const int ledPin = 13; void setup() { // Make the LED pin an output and turn it on pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH); // calibrate for the first five seconds after program runs while (millis() < 5000) { // record the maximum sensor value sensorValue = analogRead(A0); if (sensorValue > sensorHigh) { sensorHigh = sensorValue; } // record the minimum sensor value if (sensorValue < sensorLow) { sensorLow = sensorValue; } } // turn the LED off, signaling the end of the calibration period digitalWrite(ledPin, LOW); } void loop() { //read the input from A0 and store it in a variable sensorValue = analogRead(A0); // map the sensor values to a wide range of pitches int pitch = map(sensorValue, sensorLow, sensorHigh, 50, 4000); // play the tone for 20 ms on pin 8 tone(8, pitch, 20); // wait for a moment delay(10); } ```