![10 Numerazione capitolo](10-num-capitolo.png) ## 10 - ZOOTROPIO **CREA IMMAGINI IN MOVIMENTO CON ARDUINO COLLEGANDO UN MOTORE A UN PONTE H E AD ALCUNE IMMAGINI FISSE** > **Scopri:** i ponti H > > **Tempo:** 30 MINUTI > **Livello:** ■ ■ ■ □ □ > **Basato sui progetti:** 1, 2, 3, 4, 9 **Prima ancora di internet, della televisione e del cinema, le immagini in movimento erano state create con uno strumento chiamato *zootropio*. Lo zootropio crea l'illusione del movimento a partire da un gruppo di immagini fisse che si distinguono l'una dalle altre per poche differenze. Normalmente è un cilindro con delle fessure ai lati. Quando il cilindro gira e guardi attraverso le fessure, i tuoi occhi percepiscono le immagini fisse come animate. Le fessure aiutano a evitare che le immagini siano sfocate e la velocità con cui appaiono le immagini spiega perché sembrano muoversi. Originariamente, era fatto a mano o con un meccanismo a manovella.** ![Ingredienti](10-ingredienti.png) >**INGREDIENTI** >* Potenziometro >* Ponte H (L293D) >* 2 Resistenze da 10 Kilo Ohm >* 2 Pulsanti >* Motore >* Connettore per batteria 9V In questo progetto, costruirai il tuo zootropio che anima una pianta carnivora. Creerai il movimento con un motore. Per rendere il sistema ancora più avanzato, aggiungerai un interruttore che consente di controllare la direzione, un altro per spegnerlo e accenderlo e un potenziometro per il controllo della velocità. Nel progetto della girandola motorizzata avevi un motore da girare in una sola direzione. Se si dovesse invertire l'alimentazione e la massa del motore, il motore girerebbe nella direzione opposta. Non è molto pratico farlo ogni volta che si desidera far girare qualcosa in una direzione diversa, quindi dovrai utilizzare un componente chiamato ponte H per invertire la polarità del motore. ![Ponte H](10-ponteH.png) > **I ponti H** sono componenti conosciuti come **circuiti integrati (IC)**. I circuiti integrati sono componenti che contengono circuiti complessi in un contenitore molto piccolo. Questi possono contribuire a semplificare i circuiti più complessi inserendoli in un componente facilmente sostituibile. Per esempio, il ponte H che stai utilizzando in questo progetto contiene un certo numero di transistor. Per costruire il circuito contenuto all'interno del ponte H avresti bisogno di un'altra breadboard. ![Ponte H](10-ponteH-pin.png) Puoi accedere al circuito contenuto nel circuito integrato attraverso i piedini che escono dai lati. Circuiti integrati diversi hanno un diverso numero di piedini e non tutti sono utilizzati in ogni circuito. A volte è conveniente riferirsi ai piedini per numero piuttosto che con la funzione. Guardando un circuito integrato, la parte con la tacca è la parte in alto. Puoi identificare i numeri dei piedini contando dall'alto a sinistra in senso antiorario come in Fig. 1. ### COSTRUISCI IL CIRCUITO ![Schema del circuito e montaggio](10-immagine_circuito_zootropio.png) 1. Collega alimentazione e massa da un lato della breadboard ad Arduino. 2. Aggiungi 2 pulsanti alla breadboard collegando un lato di ciascuno all'alimentazione. Aggiungi una resistenza pull-down da 10 kilo ohm in serie con la massa sul piedino di uscita di entrambi gli interruttori. L'interruttore sul piedino 4 controlla la direzione, l'interruttore sul piedino 5 accende e spegne il motore. 3. Collega il potenziometro alla breadboard. Collega 5V da un lato e la massa dall'altro. Collega il piedino centrale all'input analogico 0 sull'Arduino. Questo serve per controllare la velocità del motore. 4. Metti il ponte H sulla breadboard in modo che sia al centro (vedi la Fig. 2 per il dettaglio della posizione). Collega il piedino 1 del ponte H al piedino digitale 9 di Arduino. Questo è il piedino di abilitazione sul ponte H. Quando riceve 5V accende il motore, quando riceve 0V spegne il motore. Usa questo piedino per la modulazione di larghezza di impulso del ponte H e regolare la velocità del motore. 5. Collega il piedino 2 del ponte H al piedino digitale 3 di Arduino. Collega il piedino 7 al piedino digitale 2. Questi piedini servono per comunicare con il ponte H, comunicandogli in quale direzione girare. Se il piedino 3 è **LOW** e il piedino 2 è **HIGH**, il motore gira in una direzione. Se il piedino 2 è **LOW** e il piedino 3 è **HIGH**, il motore gira nella direzione opposta. Se entrambi i piedini sono **HIGH** o **LOW** nello stesso tempo, il motore si ferma. 6. Il ponte H si alimenta dal piedino 16 (vedi Fig. 1); collegalo a 5V. I piedini 4 e 5 vanno entrambi a massa. 7. Collega il motore ai piedini 3 e 6 del ponte H. Questi due piedini si accendono o si spengono a seconda dei segnali che mandi ai piedini 2 e 7. 8. Inserisci il connettore della batteria (senza la batteria collegata!) alla massa sulla breadboard. Collega la massa da Arduino alla massa della batteria. Collega il piedino 8 del ponte H all'alimentazione della batteria. Questo è il piedino dal quale il ponte H alimenta il motore. Assicurati di non avere collegate tra loro le linee di alimentazione 9V e 5V. Devono essere separate, solo le masse devono essere collegate tra loro. ![Schema elettrico](10-schema_elettrico_zootropio.png) *Fig.3: schema elettrico.* ### IL CODICE #### Crea le costanti Crea le costanti per i piedini di ingresso e uscita. ```cpp const int controlPin1 = 2; const int controlPin2 = 3; const int enablePin = 9; const int directionSwitchPin = 4; const int onOffSwitchStateSwitchPin = 5; const int potPin = A0; ``` #### Crea le variabili per ricordare lo stato del programma Usa le variabili per memorizzare i valori degli ingressi. Potrai fare la rilevazione del cambio di stato per entrambi gli interruttori, confrontando lo stato da un loop all'altro, come nel progetto della clessidra. Oltre a memorizzare lo stato attuale, è necessario registrare il precedente stato di ogni interruttore. ```cpp int onOffSwitchState = 0; int previousOnOffSwitchState = 0; int directionSwitchState = 0; int previousDirectionSwitchState = 0; ``` #### Crea le variabili per il controllo del motore `motorDirection` tiene traccia della direzione in cui gira il motore e `motorPower` tiene traccia se il motore sta girando oppure no. ```cpp int motorEnabled = 0; int motorSpeed = 0; int motorDirection = 1; ``` #### Dichiara i piedini digitali come input e output Nel `setup()`, imposta la direzione di ogni piedino di ingresso e uscita. ```cpp void setup(){ pinMode(directionSwitchPin, INPUT); pinMode(onOffSwitchStateSwitchPin, INPUT); pinMode(controlPin1, OUTPUT); pinMode(controlPin2, OUTPUT); pinMode(enablePin, OUTPUT); } ``` #### Spegni il motore Imposta il piedino di abilitazione a **LOW** per iniziare, in modo che il motore non giri subito. ```cpp digitalWrite(enablePin, LOW); } ``` #### Leggi il sensore Nel tuo `loop()`, leggi lo stato dell'interruttore acceso/spento e immagazzinalo nella variabile `onOffSwitchState`. ```cpp void loop(){ onOffSwitchState = digitalRead(onOffSwitchStateSwitchPin); delay(1); directionSwitchState = digitalRead(directionSwitchPin); motorSpeed = analogRead(potPin)/4; ``` #### Controlla se il sensore acceso/spento è cambiato Se c'è una differenza tra lo stato attuale e precedente dell'interruttore e l'interruttore è attualmente **HIGH**, imposta la variabile `motorPower` a 1. Se è **LOW**, imposta la variabile a 0. Leggi i valori del pulsante di direzione e del potenziometro. Conserva i valori nelle loro rispettive variabili. ```cpp if(onOffSwitchState != previousOnOffSwitchState){ if(onOffSwitchState == HIGH){ motorEnabled = !motorEnabled; } } ``` #### Controlla se la direzione è cambiata Controlla se il pulsante di direzione è in una posizione differente rispetto a prima. Se è diversa, cambia la variabile di direzione del motore. Ci sono solo 2 modi in cui il motore può girare, alterna così la variabile tra i due stati. Per raggiungere questo obiettivo utilizza l'operatore di inversione in questo modo: `motorDirection = !motorDirection`. ```cpp if (directionSwitchState != previousDirectionSwitchState) { if (directionSwitchState == HIGH) { motorDirection = !motorDirection; } } ``` #### Cambia i piedini per far girare il motore nella giusta direzione La variabile `motorDirection` determina in quale direzione il motore sta girando. Per determinare la direzione, imposta i piedini di controllo, uno **HIGH** e l'altro **LOW**. Quando `motorDirection` cambia, inverte gli stati dei piedini di controllo. Se il pulsante di direzione viene premuto, gira il motore nella direzione opposta invertendo lo stato del `controlPin`. ```cpp if (motorDirection == 1) { digitalWrite(controlPin1, HIGH); digitalWrite(controlPin2, LOW); } else { digitalWrite(controlPin1, LOW); digitalWrite(controlPin2, HIGH); } ``` #### Modula il motore se è attivo Se la variabile `motorEnabled` è 1, imposta la velocità del motore usando la funzione `analogWrite()` per modulare a larghezza di impulso il piedino. Se `motorEnabled` è 0, spegni il motore impostando il valore `analogWrite` a 0. ```cpp if (motorEnabled == 1) { analogWrite(enablePin, motorSpeed); } else { analogWrite(enablePin, 0); } ``` #### Salva lo stato attuale per il prossimo loop() Prima di uscire dal `loop()`, salva lo stato attuale degli interruttori come stato precedente per la prossima parte del programma. ```cpp previousDirectionSwitchState = directionSwitchState; previousOnOffSwitchState = onOffSwitchState; } ``` ### USALO Collega Arduino al computer. Collega la batteria al connettore. Quando premi l'interruttore acceso/spento, il motore dovrebbe iniziare a girare. Se giri il potenziometro, dovrebbe accelerare e rallentare. Premendo il tasto acceso/spento un'altra volta si ferma il motore. Prova a premere il tasto di direzione e verifica che il motore gira in entrambe le direzioni. Inoltre, se ruoti la manopola del potenziometro dovresti vedere la velocità del motore aumentare o diminuire a seconda del valore che sta inviando. **Dopo aver verificato che il circuito funziona come previsto, scollega la batteria e il cavo USB dal circuito.** ![Forbici e colla](forbici-colla.png) > Per costruire il tuo zootropio, prendi la girandola che hai utilizzato nel progetto 09 e il ritaglio con le fessure verticali che è incluso nel kit. Una volta che il CD è saldamente collegato all'albero motore, collega tutto. Tieni il progetto in alto, in modo da poter guardare attraverso le fessure (ma assicurati che il CD sia fissato ma non troppo vicino al motore). Dovresti vedere la sequenza di immagini fisse "in movimento"! Se lo zootropio sta andando troppo velocemente o troppo lentamente, ruota la manopola del potenziometro per regolare la velocità dell'animazione. > > Prova a premere l'interruttore che cambia la direzione per vedere come appare l'animazione riprodotta al contrario. Lo zootropio e le immagini fornite nel kit sono solo il punto di partenza: prova a sperimentare con le tue animazioni, utilizzando il ritaglio come riferimento. > > Inizia con una immagine semplice. Individua un punto fisso in essa, e fai piccoli cambiamenti in ogni frame. Cerca gradualmente di tornare all'immagine originale in modo che l'animazione prosegua in un ciclo continuo. > Trovi il modello da ritagliare nel capitolo PAPERCRAFT, in fondo al testo. ![Istruzioni di assemblaggio zootropio 1](10-immagine_assemblaggio_zootropio_1.png) ![Istruzioni di assemblaggio zootropio 2](10-immagine_assemblaggio_zootropio_2.png) *1. Fissa il CD sulla base di legno. Aggiungi un po' di colla per assicurarti che non si stacchi quando si avvia il motore.* *2. Usa le linguette per chiudere il cartone, formando un cerchio.* *3. Inserisci le quattro linguette nella base dello zootropio.* *4. Inserisci la striscia di carta con le immagini nello zootropio.* ![Lente](lente.png) > **Gli zootropi funzionano grazie a un fenomeno chiamato "persistenza della visione"** (in inglese abbreviato con l'acronimo POV): l'illusione del movimento che si crea quando i nostri occhi osservano le immagini fisse, con minime variazioni in rapida successione. Se ricerchi online "POV Display", trovi molti progetti che utilizzano questo effetto, molti dei quali con i LED e con Arduino. ![Cervello](cervello.png) > **Fai una base per sostenere il motore.** Una scatola di cartone di piccole dimensioni con un foro potrebbe funzionare come base, lasciando le mani libere di giocare con gli interruttori e le manopole. In questo modo sarà più facile mostrare il tuo lavoro a tutti. > > **Con un po' di lavoro, puoi fare in modo che il tuo zootropio funzioni anche in situazioni di scarsa luminosità.** Collega un LED e una resistenza a uno dei piedini di uscita digitali liberi. Aggiungi anche un secondo potenziometro e collegalo a un ingresso analogico. Metti la luce in modo che illumini le immagini. Utilizzando l'ingresso analogico per misurare il tempo dei lampeggi del LED, prova e riprova in modo che la spia lampeggi quando la fessura è davanti ai tuoi occhi. Questo potrebbe richiedere un po' di lavoro con le manopole, ma l'effetto che ne risulta è davvero spettacolare! ![Pianta carnivora](10-pianta-carnivora.png) ### CODICE COMPLETO ```cpp /* Arduino Starter Kit example Project 10 - Zoetrope This sketch is written to accompany Project 10 in the Arduino Starter Kit Parts required: - two 10 kilohm resistors - two momentary pushbuttons - one 10 kilohm potentiometer - motor - 9V battery - H-Bridge created 13 Sep 2012 by Scott Fitzgerald Thanks to Federico Vanzati for improvements https://store.arduino.cc/genuino-starter-kit This example code is part of the public domain. */ const int controlPin1 = 2; // connected to pin 7 on the H-bridge const int controlPin2 = 3; // connected to pin 2 on the H-bridge const int enablePin = 9; // connected to pin 1 on the H-bridge const int directionSwitchPin = 4; // connected to the switch for direction const int onOffSwitchStateSwitchPin = 5; // connected to the switch for turning the motor on and off const int potPin = A0; // connected to the potentiometer's output // create some variables to hold values from your inputs int onOffSwitchState = 0; // current state of the on/off switch int previousOnOffSwitchState = 0; // previous position of the on/off switch int directionSwitchState = 0; // current state of the direction switch int previousDirectionSwitchState = 0; // previous state of the direction switch int motorEnabled = 0; // Turns the motor on/off int motorSpeed = 0; // speed of the motor int motorDirection = 1; // current direction of the motor void setup() { // initialize the inputs and outputs pinMode(directionSwitchPin, INPUT); pinMode(onOffSwitchStateSwitchPin, INPUT); pinMode(controlPin1, OUTPUT); pinMode(controlPin2, OUTPUT); pinMode(enablePin, OUTPUT); // pull the enable pin LOW to start digitalWrite(enablePin, LOW); } void loop() { // read the value of the on/off switch onOffSwitchState = digitalRead(onOffSwitchStateSwitchPin); delay(1); // read the value of the direction switch directionSwitchState = digitalRead(directionSwitchPin); // read the value of the pot and divide by 4 to get a value that can be // used for PWM motorSpeed = analogRead(potPin) / 4; // if the on/off button changed state since the last loop() if (onOffSwitchState != previousOnOffSwitchState) { // change the value of motorEnabled if pressed if (onOffSwitchState == HIGH) { motorEnabled = !motorEnabled; } } // if the direction button changed state since the last loop() if (directionSwitchState != previousDirectionSwitchState) { // change the value of motorDirection if pressed if (directionSwitchState == HIGH) { motorDirection = !motorDirection; } } // change the direction the motor spins by talking to the control pins // on the H-Bridge if (motorDirection == 1) { digitalWrite(controlPin1, HIGH); digitalWrite(controlPin2, LOW); } else { digitalWrite(controlPin1, LOW); digitalWrite(controlPin2, HIGH); } // if the motor is supposed to be on if (motorEnabled == 1) { // PWM the enable pin to vary the speed analogWrite(enablePin, motorSpeed); } else { // if the motor is not supposed to be on //turn the motor off analogWrite(enablePin, 0); } // save the current on/off switch state as the previous previousDirectionSwitchState = directionSwitchState; // save the current switch state as the previous previousOnOffSwitchState = onOffSwitchState; } ```