This week, I decided to do an LED puzzle that is similar to Simon Says, where the instructions are given in the form of a melody. I didn’t want to use a song too long or else it’d be too hard, so I used the beginning of the sound of music theme song. The melody goes: 1 2 3 1 3 1 3 2 3 4 4 3 2 4.
There are four buttons on the breadboard, with four corresponding LEDs. They are Green(1), Yellow(2), Blue(3), and Red(4). When the program starts up, the lights will play (show) the melody in full. Then, it’s up to the player to recognize or memorize what the melody is. Then, the player has to press the four buttons in the order that the melody is. If they succeed in the end, all four lights will light up and flash.
In the process of doing this project, I encounter a lot of problems that were great learning experiences for Arduino. For one, when I put the condition where a button is pressed down, Arduino cycles through the execution many times, even though I just pressed it briefly. To solve this problem, I borrowed the method in class notes, where I made a “previous button” value that holds whether a button was just pressed.
There is one part of this project that I really wanted to improve on but couldn’t, which is making a database of melodies and giving them out randomly. There are a few problems that I’ll face if I want to do this. Currently, I have two arrays, one is the original melody array that is recorded when the lights are shown, and the other is the entry array of the player. I then go through a for loop the length of the original melody, and in each loop, I check whether that index is the same between the original and entry. If I wanted to do a database of melodies, I would have to find a way to make the length of the arrays dynamic and make the length of it a variable for the for-loop.
Another improvement I wanted to do was to make my code more optimized, specifically the part where the lights are showing the melody. Right now, I hardcoded the order and delay that each note should be played. What I want to do is to simply enter a dictionary of numbers, the first being the note and the second being the delay, and the code would automatically sort the dictionary into the flashing order for the lights. I ran out of time to do it this time, but I’m confident this is do-able. Getting the code to do this would also help the database idea by making it easier to code in a melody.
Here is my full code:
//buttons and lights initialization: int greenB = 12; int greenL = 13; int yellowB = 9; int yellowL = 10; int blueB = 6; int blueL = 7; int redB = 3; int redL = 4; int prevB = LOW; int prevYB = LOW; int prevBB = LOW; int prevRB = LOW; boolean play = true; boolean yay = false; int song[14]; int entry[14]; int value; int count = 0; void setup() { // put your setup code here, to run once: pinMode(greenL, OUTPUT); pinMode(greenB, INPUT); pinMode(yellowL, OUTPUT); pinMode(yellowB, INPUT); pinMode(blueL, OUTPUT); pinMode(blueB, INPUT); pinMode(redL, OUTPUT); pinMode(redB, INPUT); } void loop() { // put your main code here, to run repeatedly: int Gstate = digitalRead(greenB); int Ystate = digitalRead(yellowB); int Bstate = digitalRead(blueB); int Rstate = digitalRead(redB); //instructions if (play == true){ digitalWrite(greenL, HIGH); delay(650); digitalWrite(greenL, LOW); song[0] = 1; digitalWrite(yellowL, HIGH); delay(250); digitalWrite(yellowL, LOW); song[1] = 2; digitalWrite(blueL, HIGH); delay(250); digitalWrite(blueL, LOW); song[2] = 3; delay(500); digitalWrite(greenL, HIGH); delay(400); digitalWrite(greenL, LOW); song[3] = 1; digitalWrite(blueL, HIGH); delay(400); digitalWrite(blueL, LOW); song[4] = 3; digitalWrite(greenL, HIGH); delay(400); digitalWrite(greenL, LOW); song[5] = 1; digitalWrite(blueL, HIGH); delay(400); digitalWrite(blueL, LOW); song[6] = 3; delay(500); digitalWrite(yellowL, HIGH); delay(600); digitalWrite(yellowL, LOW); song[7] = 2; digitalWrite(blueL, HIGH); delay(250); digitalWrite(blueL, LOW); song[8] = 3; digitalWrite(redL, HIGH); delay(200); digitalWrite(redL, LOW); delay(100); song[9] = 4; digitalWrite(redL, HIGH); delay(200); digitalWrite(redL, LOW); song[10] = 4; delay(100); digitalWrite(blueL, HIGH); delay(250); digitalWrite(blueL, LOW); song[11] = 3; digitalWrite(yellowL, HIGH); delay(250); digitalWrite(yellowL, LOW); song[12] = 2; digitalWrite(redL, LOW); song[13] = 4; digitalWrite(redL, HIGH); delay(650); play = false; } //game if (play == false){ //button lighting when pressed //green if (Gstate == HIGH) { digitalWrite(greenL, HIGH); if (prevB == LOW){ value = 1; count = count + 1; entry[count - 1] = value; prevB = Gstate; } } if (Gstate == LOW) { digitalWrite(greenL, LOW); prevB = Gstate; } //yellow if (Ystate == HIGH) { digitalWrite(yellowL, HIGH); if (prevYB == LOW){ value = 1; count = count + 1; entry[count - 1] = value; prevYB = Ystate; } } if (Ystate == LOW) { digitalWrite(yellowL, LOW); prevYB = Ystate; } //blue if (Bstate == HIGH) { digitalWrite(blueL, HIGH); if (prevBB == LOW){ value = 1; count = count + 1; entry[count - 1] = value; prevBB = Bstate; } } if (Bstate == LOW) { digitalWrite(blueL, LOW); prevBB = Bstate; } //red if (Rstate == HIGH) { digitalWrite(redL, HIGH); if (prevRB == LOW){ value = 1; count = count + 1; entry[count - 1] = value; prevRB = Rstate; } } if (Rstate == LOW) { digitalWrite(redL, LOW); prevRB = Rstate; } if (count >= 14){ for (int i = 0; i <= 14; i++){ if (song[i] == entry[i]){ yay = true; } } } } //win celebration: if (yay == true){ for (int i = 1; i <= 5; i++){ delay(500); digitalWrite(greenL, HIGH); digitalWrite(yellowL, HIGH); digitalWrite(blueL, HIGH); digitalWrite(redL, HIGH); delay(500); digitalWrite(greenL, LOW); digitalWrite(yellowL, LOW); digitalWrite(blueL, LOW); digitalWrite(redL, LOW); delay(500); } yay = false; } }
Demo: