Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Anton Nazarenko
Published

Memory game

Here is the implementation of the pretty simple game - Memory. The goal is to pick a sequence using just a brute force and your memory:)

IntermediateShowcase (no instructions)4,893
Memory game

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
IR NPN Phototransistor 3mm
×4
Resistor 221k ohm
Resistor 221k ohm
×4
LED (generic)
LED (generic)
×4
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Resistor 1k ohm
Resistor 1k ohm
×4
Coin Cell Battery CR2032
Coin Cell Battery CR2032
×1

Story

Read more

Schematics

Initial scheme (like on the video)

Code

The final version of the code

Arduino
Code for Arduino Mega with all the latest features.
#define NOTE_G3  196
#define NOTE_B3  247
#define NOTE_C4  262

#include <EEPROM.h>

const byte MIN_SENSOR_VALUE = 45;
const byte MIN_TASK_DIFFICULTY = 4;
const byte MAX_TASK_DIFFICULTY = 16;

byte TASK_DIFFICULTY = MIN_TASK_DIFFICULTY;

byte programmingPort = 49; // Digital port
byte relayPort = 31; // Digital port
byte tonePort = 3; // PWM port
byte sensors[4]={1,0,2,3}; // Analog ports
byte sensorLEDs[4]={7,5,6,4}; // PWM output (invert to +5V,  HIGH=LOW and LOW=HIGH)
byte progressLEDs[MAX_TASK_DIFFICULTY]={26,28,30,32, 34,36,38,40, 42,44,46,48, 50,52,53,51}; // Digital ports
byte task[MAX_TASK_DIFFICULTY]={3,1,3,2, 3,1,4,1, 2,1,4,3, 2,1,4,1};

int melody1[] = {NOTE_B3, NOTE_G3, NOTE_C4}; //correct melody
int noteDurations1[] = {16,32,32};
int melody2[] = {NOTE_C4, NOTE_G3, NOTE_B3}; //wrong melody
int noteDurations2[] = {8,16,8};

int progress = 0; //current task/level
byte currentCode = 0;

boolean IsProgrammingMode = false;
boolean isTheEnd = false;

void Init()
{
  IsProgrammingMode = false;
  isTheEnd = false;
  progress = 0;
  currentCode = 0;
  
  // getting settings from eeprom
  TASK_DIFFICULTY = EEPROM.read(1);
  if(TASK_DIFFICULTY <= MIN_TASK_DIFFICULTY)
  {
     TASK_DIFFICULTY = MIN_TASK_DIFFICULTY;
  }
  
  for(byte i=0; i<MAX_TASK_DIFFICULTY; i++)
  {
      pinMode(progressLEDs[i], OUTPUT);
  }
  for(int i=0; i<4; i++)
  {
      pinMode(sensorLEDs[i], OUTPUT);
  }
  pinMode(relayPort, OUTPUT);
  pinMode(programmingPort, INPUT);
  CorrectMelody();
}

void SaveSettings()
{
  EEPROM.write(1,TASK_DIFFICULTY);
}


boolean ReadSensor(byte sensorId)
{
  int val = analogRead(sensors[sensorId]);
  //Serial.print(" SENSOR [");
  //Serial.print(sensorId);
  //Serial.print("]=");
  //Serial.println(val);
  return val>MIN_SENSOR_VALUE;
}

// reading
byte GetCurrentCode()
{
  byte res=0;
  for(int i=1; i<5; i++)
  {
    if(ReadSensor(i-1))
      res+=i;
  }  
  
  if(res>4)
    res=0;
    
  return res;
}


void CheckProgrammingMode()
{
  if(digitalRead(programmingPort)==HIGH)
  {
     if(IsProgrammingMode)
     {
       // Stop the programming
       IsProgrammingMode=false;
       SetSensorLEDs(LOW);
       SaveSettings();
       Init();
       ShowProgress(0); 
       CloseDoor();       
     }else
     {
       IsProgrammingMode=true;
       SetSensorLEDs(HIGH);
       // TODO: Зажечь все светодиоды и подсветить текущий уровень сложности
     }
     
     delay(1000);
  }
}


void TurnOnSensorLED(byte id)
{
   digitalWrite(sensorLEDs[id], LOW);
}

// indicate the shot
void SetSensorLEDs(int level)
{  
  for(byte i=0; i<4; i++)
  if(level==LOW)
    digitalWrite(sensorLEDs[i], HIGH);
  else
    digitalWrite(sensorLEDs[i], LOW);
}

void ShowProgress(byte progress)
{
   for(byte i=0; i<MAX_TASK_DIFFICULTY; i++)
   {
     if(i<progress)
       digitalWrite(progressLEDs[i], HIGH);
     else
       digitalWrite(progressLEDs[i], LOW);
   }
}

void SimpleMelody(byte thisNote)
{
  
    int noteDuration = 1000/noteDurations1[thisNote];
    tone(tonePort, melody1[thisNote],noteDuration); 
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(tonePort);
  
}

void CorrectMelody()
{
  for (int thisNote = 0; thisNote < 1; thisNote++) {
    int noteDuration = 1000/noteDurations1[thisNote];
    tone(tonePort, melody1[thisNote],noteDuration); 
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(tonePort);
  }
}

void WrongMelody()
{
  for (int thisNote = 0; thisNote < 2; thisNote++) {
    int noteDuration = 1000/noteDurations2[thisNote];
    tone(tonePort, melody2[thisNote],noteDuration); 
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(tonePort);
  }
}

void OpenDoor()
{
   digitalWrite(relayPort, HIGH);
}

void CloseDoor()
{
   digitalWrite(relayPort, LOW); 
}


void setup() {                
  //Serial.begin(9600);
  Init();
  OpenDoor();
  SetSensorLEDs(HIGH);
  ShowProgress(16);
  
  delay(500); 
  SetSensorLEDs(LOW);
  ShowProgress(0);
  CloseDoor();
  //Serial.println("--- INIT COMPLETE ---");
}

void loop() {
  
  CheckProgrammingMode();
  
  //Serial.print("IsProgramming = ");
  //Serial.println(IsProgrammingMode);
  
  byte code = GetCurrentCode();
  
  if(IsProgrammingMode)
  {       
      //Serial.print("TASK_DIFFICULTY = ");
      //Serial.println(TASK_DIFFICULTY);
      
      if(code==1||code==2)
      {
        if(TASK_DIFFICULTY<MAX_TASK_DIFFICULTY)
        {
          TASK_DIFFICULTY+=1;  
          //ShowProgress(TASK_DIFFICULTY);
          SimpleMelody(0);
          delay(200);
        }                
      }
      if(code==3||code==4)
      {
        if(TASK_DIFFICULTY>MIN_TASK_DIFFICULTY)
        {
          TASK_DIFFICULTY-=1; 
          //ShowProgress(TASK_DIFFICULTY);
          SimpleMelody(2);
          delay(200);
        }                
      }
      
      ShowProgress(TASK_DIFFICULTY);
      return;
  }
  
  
  
//  Serial.print("PrevCode = ");
//  Serial.print(currentCode);
//  Serial.print(" CurrCode = ");
//  Serial.print(code);
//  Serial.print(" RquredCode = ");
//  Serial.print(task[progress]);
//  Serial.print(" Progress = ");
//  Serial.println(progress);
    
  if(isTheEnd)
  {
    progress+=1;
    if(progress>MAX_TASK_DIFFICULTY)
    {      
      progress= -MAX_TASK_DIFFICULTY+1;
    }
    SetSensorLEDs(LOW);
    byte led = abs(progress%4);
    
    if(led==2)
      led=3;
    else
      if(led==3)
        led=2;  
    
    TurnOnSensorLED(led);
    byte res = abs(progress);
    ShowProgress(res);
    
    delay(100);
    return;
  }  
  
  
    
  if(currentCode!=code && code!=0)
  {
    SetSensorLEDs(LOW);
    TurnOnSensorLED(code-1);
  
     if(code==task[progress])
     {
       currentCode=code;       
       progress+=1;       
       ShowProgress(progress);
       CorrectMelody();
       
       if(progress>=TASK_DIFFICULTY)
       {
         CorrectMelody();
         CorrectMelody();
         CorrectMelody();
         isTheEnd=true;
         OpenDoor();       
       }

     }
     else
     {
       isTheEnd=false;
       progress=0;
       ShowProgress(progress);
       currentCode=0;
       SetSensorLEDs(LOW);
       WrongMelody();       
     }
  }
  
      
}

Credits

Anton Nazarenko

Anton Nazarenko

4 projects • 13 followers
Thanks to Pavel Nazarenko.

Comments