Questo progetto mostra come replicare con Arduino, il gioco Simon Says, utilizzando poche componenti base.
Lo scopo del gioco, è riuscire a ricordare la sequenza di accensione corretta dei LED (decisa da Arduino) per il maggior numero di turni.
Materiale utilizzato
– Arduino UNO R3
– 1x breadboard
– 4x LED colorati
– 4x pulsanti pushbutton
– 4x resistenze da 100\330 ohm (valore in base al colore dei LED)
– 1x altoparlante (in alternativa un buzzer)
Iniziamo a costruire il circuito sulla breadboard come in figura:
1) Posizioniamo i pulsanti al centro della breadboard, da un lato collegati a massa, e dall’altro ai pin digitali di Arudino (2,3,4,5)
2) Posizioniamo un LED vicino ad ogni pulsante, collegando il catodo dalla parte dove abbiamo il negativo del pushbutton
3) Posizioniamo le resistenze su ogni LED, un capo collegato all’anodo e l’altro capo ai pin digitali di Arduino (8,9,10,11)
4) Colleghiamo l’altoparlante (o buzzer) al pin digitale 12 e a massa (generalmente i buzzer hanno il simbolo ‘+’ impresso sopra per distinguere il verso)
Il circuito è finito, carichiamo ora lo sketch su Arduino e verifichiamone il funzionamento.
*** Per il corretto funzionamento e compilazione dello Sketch è necessario installare la libreria Tone,
*** per farlo è sufficiente copiare la cartella Tone nel percorso ‘libraries’ dove è installato l’IDE di Arduino
*** e riavviare il programma.
Il codice è così suddiviso:
Parte iniziale
Viene inclusa la libreria Tone.h e definite le variabili globali del programma.
Setup()
Viene inizializzata la comunicazione seriale, definito il pin dell’altoparlante, i pin dei led, i pin dei pulsanti, ‘randomizzato’ il generatore random, e fatta partire una musichetta iniziale con accensione dei led a seguito.
*** Il comando randomSeed() inizializza il generatore di numeri pseudo-casuali,
*** facendolo iniziare in un punto arbitrario nella sua sequenza casuale.
*** Questa sequenza anche se molto lunga è sempre la stessa, per questo lo si inizializza passando il valore
*** di un analogRead(), rendendo così la sequenza abbastanza casuale.
Loop()
All’interno del loop, vengono gestite:
– Inizio partita
– Inizio turno
– Calcolo singolo step sequenza
– Attesa input dell’utente
Input()
In questa funzione si effettua il confronto tra i pulsanti che preme l’utente e la sequenza decisa da Arduino, se ok si prosegue altrimenti si richiama la funzione Fail()
Fail()
Questa funzione fa lampeggiare i led ed emette un suono per far capire all’utente che la sequenza inserita è errata. Fa inoltre ricominciare il gioco impostando la variabile turn a -1
*** Durante l’esecuzione del programma, nel serial monitor compariranno tutti i vari stati,
*** compresa la sequenza da inserire 😀
DOWNLOAD RAR CODICE + LIBRERIA
#include <Tone.h> Tone speakerpin; int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4}; int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500}; int note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5}; int duration[] = {100, 100, 100, 300, 100, 300}; byte button[] = {2, 3, 4, 5}; byte ledpin[] = {8, 9, 10, 11}; int turn = 0; int buttonstate = 0; int randomArray[100]; int inputArray[100]; void setup() { Serial.begin(9600); speakerpin.begin(12); for(int x=0; x<4; x++) { pinMode(ledpin[x], OUTPUT); } for(int x=0; x<4; x++) { pinMode(button[x], INPUT); digitalWrite(button[x], HIGH); } randomSeed(analogRead(0)); for (int thisNote = 0; thisNote < 13; thisNote ++) { speakerpin.play(starttune[thisNote]); if (thisNote==0 || thisNote==2 || thisNote==4 || thisNote== 6) { digitalWrite(ledpin[0], HIGH); } if (thisNote==1 || thisNote==3 || thisNote==5 || thisNote== 7 || thisNote==9 || thisNote==11) { digitalWrite(ledpin[1], HIGH); } if (thisNote==8 || thisNote==12) { digitalWrite(ledpin[2], HIGH); } if (thisNote==10) { digitalWrite(ledpin[3], HIGH); } delay(duration2[thisNote]); speakerpin.stop(); digitalWrite(ledpin[0], LOW); digitalWrite(ledpin[1], LOW); digitalWrite(ledpin[2], LOW); digitalWrite(ledpin[3], LOW); delay(25); } delay(1000); } void loop() { for (int y=0; y<=99; y++) { digitalWrite(ledpin[0], HIGH); digitalWrite(ledpin[1], HIGH); digitalWrite(ledpin[2], HIGH); digitalWrite(ledpin[3], HIGH); for (int thisNote = 0; thisNote < 6; thisNote ++) { speakerpin.play(note[thisNote]); delay(duration[thisNote]); speakerpin.stop(); delay(25); } digitalWrite(ledpin[0], LOW); digitalWrite(ledpin[1], LOW); digitalWrite(ledpin[2], LOW); digitalWrite(ledpin[3], LOW); delay(1000); for (int y=turn; y <= turn; y++) { Serial.println(""); Serial.print("Turn: "); Serial.print(y); Serial.println(""); randomArray[y] = random(1, 5); for (int x=0; x <= turn; x++) { Serial.print(randomArray[x]); for(int y=0; y<4; y++) { if (randomArray[x] == 1 && ledpin[y] == 8) { digitalWrite(ledpin[y], HIGH); speakerpin.play(NOTE_G3, 100); delay(400); digitalWrite(ledpin[y], LOW); delay(100); } if (randomArray[x] == 2 && ledpin[y] == 9) { digitalWrite(ledpin[y], HIGH); speakerpin.play(NOTE_A3, 100); delay(400); digitalWrite(ledpin[y], LOW); delay(100); } if (randomArray[x] == 3 && ledpin[y] == 10) { digitalWrite(ledpin[y], HIGH); speakerpin.play(NOTE_B3, 100); delay(400); digitalWrite(ledpin[y], LOW); delay(100); } if (randomArray[x] == 4 && ledpin[y] == 11) { digitalWrite(ledpin[y], HIGH); speakerpin.play(NOTE_C4, 100); delay(400); digitalWrite(ledpin[y], LOW); delay(100); } } } } input(); } } void input() { for (int x=0; x <= turn;) { for(int y=0; y<4; y++) { buttonstate = digitalRead(button[y]); if (buttonstate == LOW && button[y] == 2) { digitalWrite(ledpin[0], HIGH); speakerpin.play(NOTE_G3, 100); delay(200); digitalWrite(ledpin[0], LOW); inputArray[x] = 1; delay(250); Serial.print(" "); Serial.print(1); if (inputArray[x] != randomArray[x]) { fail(); } x++; } if (buttonstate == LOW && button[y] == 3) { digitalWrite(ledpin[1], HIGH); speakerpin.play(NOTE_A3, 100); delay(200); digitalWrite(ledpin[1], LOW); inputArray[x] = 2; delay(250); Serial.print(" "); Serial.print(2); if (inputArray[x] != randomArray[x]) { fail(); } x++; } if (buttonstate == LOW && button[y] == 4) { digitalWrite(ledpin[2], HIGH); speakerpin.play(NOTE_B3, 100); delay(200); digitalWrite(ledpin[2], LOW); inputArray[x] = 3; delay(250); Serial.print(" "); Serial.print(3); if (inputArray[x] != randomArray[x]) { fail(); } x++; } if (buttonstate == LOW && button[y] == 5) { digitalWrite(ledpin[3], HIGH); speakerpin.play(NOTE_C4, 100); delay(200); digitalWrite(ledpin[3], LOW); inputArray[x] = 4; delay(250); Serial.print(" "); Serial.print(4); if (inputArray[x] != randomArray[x]) { fail(); } x++; } } } delay(500); turn++; } void fail() { for (int y=0; y<=2; y++) { //Flashes lights for failure digitalWrite(ledpin[0], HIGH); digitalWrite(ledpin[1], HIGH); digitalWrite(ledpin[2], HIGH); digitalWrite(ledpin[3], HIGH); speakerpin.play(NOTE_G3, 300); delay(200); digitalWrite(ledpin[0], LOW); digitalWrite(ledpin[1], LOW); digitalWrite(ledpin[2], LOW); digitalWrite(ledpin[3], LOW); speakerpin.play(NOTE_C3, 300); delay(200); } delay(500); turn = -1; }
Considerazioni finali
Spero che questo progetto possa essere utile sia per chi inizia con Arduino, sia per chi ha già un po di esperienza, e vuole partire da un progetto e modificarlo a suo piacimento, si potrebbero infatti aggiungere altri pulsanti e led, aumentare la velocità, mostrare il numero del turno su un display, ecc ecc.. il limite è solo la fantasia.
Enrico Mazzalovo
non c’è che dire, un notevole ed elegante esercizio di programmazione!
quando ero giovane 😉 il mio record con il Simon era di 64 (o forse 67? non ricordo più 😀 )
sarebbe carino implementare l’accelerazione della sequenza, come avveniva sul gioco degli anni ’80. Non sarebbe nemmeno troppo complicato, basterebbe sostituire i delay fissi da 400 e 100 ms con una funzione legata al numero del turno. Se ad esempio per l’accensione abbiamo al turno 1 400ms e volessimo 50ms al turno 100, un decremento lineare messo in grafico avrebbe l’equazione delay = -3.5x + 403.5. Analogamente per il delay tra una luce e l’altra.
si dovrebbe ovviamente fare qualche prova per tarare bene a livello “umano” i delay 🙂 la vera sfida sarebbe se l’incremento fosse logaritmico eheh lì ci sarebbe da divertirsi…
si potrebbe aggiungere uno switch e un potenziometro per stabilire rispettivamente il tipo o la velocità dell’incremento.
complimenti e alla prossima!