06 Numerazione capitolo

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
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()

  • 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

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

  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

Cervello

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.

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.

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.

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.

  while (millis() < 5000) {

Comando while() 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.

    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.

  digitalWrite(ledPin, LOW);
}

Leggi e immagazzina il valore del sensore

Nel loop(), leggi il valore su A0 e immagazzinalo in sensorValue.

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.

  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.

  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

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

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

/*
  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);
}