When I was a child, in 1980, I spent some time playing a fun game that asked me to watch, remember and repeat a random sequence proposed from time to time by the microcontroller in a challenge that was inexorably won by the machine! The game was invented in 1978 and was called Simon; today I read his story on Wikipedia: https://en.wikipedia.org/wiki/Simon_(game).The device creates a series of tones and lights and requires a user to repeat the sequence. If the user succeeds, the series becomes progressively longer and more complex. Once the user fails or the time limit runs out, the game is over. Here I propose a simple realization with Arduino uno that you can simulate in https://www.tinkercad.com/things/jKi6DJadMBu or realize in practice with four LEDs and four buttons, plus one for the reset of the game.
Below is the circuit and the sketch made with the students of 3AO Electronics of the school year 2020/21 at IIS Maxwell, Milan.
/* V1.0 - Spadaro Filippo 28 may 2021 btnNONE: nessun pulsante premuto btnGREEN: stampa btnGREEN btnYELLOW: stampa btnYELLOW btnRED: btnRED btnBLUE: btnBLUE btnSELECT: stampa SELECT */ #define btnGREEN 2 #define btnYELLOW 3 #define btnRED 4 #define btnBLUE 5 #define btnSELECT 1 #define btnNONE 0 #define pinLEDGREEN 2 #define pinLEDYELLOW 3 #define pinLEDRED 4 #define pinLEDBLUE 5 // define the button debounce int lcd_key = btnNONE; int lcd_key_precedente = btnNONE; int adc_key_in = 0; // game variables int sequenza[20]; int fineSequenza = 0, i, pulsantePremuto, contaPulsante; bool indovinaSequenza = false; // random sequence void generaSequenza(int inizio, int fine) { for (i=0; i<20; i++) { sequenza[i]=random(inizio,fine+1); Serial.print(sequenza[i]); Serial.print(" "); } Serial.println(); } // print sequence void stampaSequenza(int inizio, int fine) { for (i=inizio; i<fine; i++) { digitalWrite(sequenza[i],HIGH); delay(500); digitalWrite(sequenza[i],LOW); delay(500); } } // light only one LED void illuminaUnLed(int LED1Illuminato, int LED2Spento, int LED3Spento, int LED4Spento) { digitalWrite(LED1Illuminato,HIGH); digitalWrite(LED2Spento,LOW); digitalWrite(LED3Spento,LOW); digitalWrite(LED4Spento,LOW); delay(300); digitalWrite(LED1Illuminato,LOW); digitalWrite(LED2Spento,LOW); digitalWrite(LED3Spento,LOW); digitalWrite(LED4Spento,LOW); delay(300); } // light all LED void illuminaTuttiLed(int LED1Illuminato, int LED2Illuminato, int LED3Illuminato, int LED4Illuminato) { digitalWrite(LED1Illuminato,HIGH); digitalWrite(LED2Illuminato,HIGH); digitalWrite(LED3Illuminato,HIGH); digitalWrite(LED4Illuminato,HIGH); delay(300); digitalWrite(LED1Illuminato,LOW); digitalWrite(LED2Illuminato,LOW); digitalWrite(LED3Illuminato,LOW); digitalWrite(LED4Illuminato,LOW); delay(300); } void giocoDiLuciAccensione(int LED1, int LED2, int LED3, int LED4) { digitalWrite(LED1,HIGH); delay(200); digitalWrite(LED1,LOW); digitalWrite(LED2,HIGH); delay(200); digitalWrite(LED2,LOW); digitalWrite(LED3,HIGH); delay(200); digitalWrite(LED3,LOW); digitalWrite(LED4,HIGH); delay(200); digitalWrite(LED4,LOW); delay(200); digitalWrite(LED1,HIGH); digitalWrite(LED2,HIGH); digitalWrite(LED3,HIGH); digitalWrite(LED4,HIGH); delay(200); digitalWrite(LED1,LOW); digitalWrite(LED2,LOW); digitalWrite(LED3,LOW); digitalWrite(LED4,LOW); delay(200); digitalWrite(LED1,HIGH); digitalWrite(LED2,HIGH); digitalWrite(LED3,HIGH); digitalWrite(LED4,HIGH); delay(200); digitalWrite(LED1,LOW); digitalWrite(LED2,LOW); digitalWrite(LED3,LOW); digitalWrite(LED4,LOW); delay(2000); } // read the button value int read_LCD_buttons() { adc_key_in = analogRead(0); // read analog A0 value // Serial.println(adc_key_in); // per il debug /* Resistori tra 5V e 0V: 2.2k - 1k - 1k - 1k - 2.2k */ if (adc_key_in > 1000) return btnNONE; // 1023
if (adc_key_in < 50) return btnGREEN; // 0
if (adc_key_in < 350) return btnYELLOW; // 320
if (adc_key_in < 500) return btnRED; // 487
if (adc_key_in < 650) return btnBLUE; // 590
if (adc_key_in < 800) return btnSELECT; // 719 return btnNONE; } void setup() { Serial.begin(9600); Serial.println("Push start button"); // display "Push the buttons" pinMode(pinLEDGREEN,OUTPUT); pinMode(pinLEDYELLOW,OUTPUT); pinMode(pinLEDRED,OUTPUT); pinMode(pinLEDBLUE,OUTPUT); randomSeed(analogRead(1)); } void loop() { lcd_key = read_LCD_buttons(); // lettura pulsanti // Serial.println(lcd_key); // per il debug if ((lcd_key != btnNONE) && (lcd_key_precedente == btnNONE)) // Anti-rimbalzo { // A seconda del pulsante premuto, esegue un'azione switch (lcd_key) { case btnGREEN: { illuminaUnLed(pinLEDGREEN, pinLEDYELLOW, pinLEDRED, pinLEDBLUE); pulsantePremuto= btnGREEN; delay(200); if (sequenza[contaPulsante]==pulsantePremuto) { if (indovinaSequenza==true) { if (contaPulsante<fineSequenza-1) { contaPulsante++; } else { fineSequenza++; stampaSequenza(0, fineSequenza); contaPulsante = 0; } } else { illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } } else { indovinaSequenza = false; illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } break; } case btnYELLOW: { illuminaUnLed(pinLEDYELLOW, pinLEDGREEN, pinLEDRED, pinLEDBLUE); pulsantePremuto= btnYELLOW; delay(200); if (sequenza[contaPulsante]==pulsantePremuto) { if (indovinaSequenza==true) { if (contaPulsante<fineSequenza-1) { contaPulsante++; } else { fineSequenza++; stampaSequenza(0, fineSequenza); contaPulsante = 0; } } else { illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } } else { indovinaSequenza = false; illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } break; } case btnRED: { illuminaUnLed(pinLEDRED, pinLEDYELLOW, pinLEDGREEN, pinLEDBLUE); pulsantePremuto= btnRED; delay(200); if (sequenza[contaPulsante]==pulsantePremuto) { if (indovinaSequenza==true) { if (contaPulsante<fineSequenza-1) { contaPulsante++; } else { fineSequenza++; stampaSequenza(0, fineSequenza); contaPulsante = 0; } } else { illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } } else { indovinaSequenza = false; illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } break; } case btnBLUE: { illuminaUnLed(pinLEDBLUE, pinLEDYELLOW, pinLEDGREEN, pinLEDRED); pulsantePremuto= btnBLUE; delay(200); if (sequenza[contaPulsante]==pulsantePremuto) { if (indovinaSequenza==true) { if (contaPulsante<fineSequenza-1) { contaPulsante++; } else { fineSequenza++; stampaSequenza(0, fineSequenza); contaPulsante = 0; } } else { illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } } else { indovinaSequenza = false; illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); } break; } case btnSELECT: { giocoDiLuciAccensione(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN); generaSequenza(pinLEDGREEN, pinLEDBLUE); indovinaSequenza = true; fineSequenza = 1; stampaSequenza(0, fineSequenza); contaPulsante = 0; break; } case btnNONE: { // nulla da eseguire break; } } } lcd_key_precedente = lcd_key; delay(50); }
In the realization of the game input, I propose to acquire the signal of the chosen button by using a single analog pin instead of using 5 digital pins, one for each button. In this way I save 5 Arduino digital pins against an alalogic one. The LEDs, on the other hand, are connected to the digital pins. To read the buttons I create a pull-up voltage divider with 5 resistors placed between 5V and 0: 2.2kOhm - 1kOhm - 1kOhm - 1kOhm - 2.2kOhm and acquire the voltage levels with analogRead() which change according to the button that is held down. The function that takes care of this is read_LCD_buttons() which returns the value of the pressed button, and the game is then handled by a switch-case.
A debounce algorithm (managed with the use of the two variables lcd_key and lcd_key_precedente) allows the correct reception of the button chosen by the player: you can see it at the beginning and at the end of the loop().