You will be able to create and play with the Simon game over a virtual Arduino and buttons. This is made possible by the Wokwi Arduino simulator. In this project, you will learn how to add components, get the code for the Simon game, edit the code, tinker with the project to create your own flavour or even, build it further and make it a tough game -> Unleash your creativity. At the end of the project, you will be able to play with the game. Please post your highest score in the comments ;)
Getting startedLearn how to create a simulation for the ATTiny85 using Arduino style coding. This project will use the following components.
- 4 Wokwi LED elements
- 4 Wokwi momentary switches
- ATtiny85
- Connecting wires
Simon is a simple electronic memory game: the user has to repeat a growing sequence of colours. The sequence is displayed by lighting up the LEDs. Each colour also has a corresponding tone. In each turn, the game will play the sequence, and then wait for the user to repeat the sequence by pressing the buttons according to the colour sequence. If the user repeated the sequence correctly, the game will play a "levelling-up" sound, add a new colour at the end of the sequence, and move to the next turn. The game continues until the user has made a mistake. Then a game over sound is played, and the game restarts.
Wokwi Arduino Simulator tool RefresherKnowing a bit about the menus and the controls 🕹 in the Wokwi Arduino simulator will help in the future.
In the order of the numbers mentioned in the image
1. the sketch, which always has ".ino" extension
2. a ReadMe file, which can be used to share more details about the project. can be left empty or even omitted
3. additional supporting files for the sketch. Wokwi Arduino simulator supports projects which contain multiple files as well. This is one such example
4. diagram.json is a special file. You can add, modify, delete the simulation elements (Arduino, LEDs, Motors, buttons etc)
5. the Simulation window, where all the action takes place. You can make it full screen when the sketch is running
6. The Editor window, where you add, update the Arduino code.
7. Timer - This shows the time elapsed with respect to the simulation. The simulation cannot run exactly at the same speed as the code runs in the real hardware. Hence, you might experience a slower time to sometimes a faster one.
8. This performance meter will show the relative performance of the simulator when compared to the actual hardware one
9. Click this button to RESTART the simulation
10. Click on this button to STOP the simulation
11. Clicking on this button will PAUSE the simulation. You can always resume it by clicking on the same button once more
12. SAVE button. Click here to save the code you just created or modified. Never lose the work :)
13. clicking on this button will give you the shareable code using which you can share your project with your classmates or friends or even on the social media
14. Not but not least, this gives you a little information about the Author an the project name
Here is the sketch for the Simon game// https://wokwi.com/arduino/projects/285525640477671948
/**
Simon Game for ATTiny85
Copyright (C) 2018, Uri Shaked
Licensed under the MIT License.
*/
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include "pitches.h"
/* Constants - define pin numbers for leds, buttons and speaker, and also the game tones */
byte buttonPins[] = {1, 2, 3, 4};
#define SPEAKER_PIN 0
#define MAX_GAME_LENGTH 100
int gameTones[] = { NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G5};
/* Global variales - store the game state */
byte gameSequence[MAX_GAME_LENGTH] = {0};
byte gameIndex = 0;
/**
Set up the GPIO pins
*/
void setup() {
// The following line primes the random number generator. It assumes pin A0 is floating (disconnected)
randomSeed(analogRead(1));
// Disable ADC - saves about 324.5uA in sleep mode!
ADCSRA = 0;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
for (int i = 0; i < 4; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(SPEAKER_PIN, INPUT);
}
ISR(PCINT0_vect) {
GIMSK &= ~0b00100000; // Turn off pin change interrupts
sleep_disable();
}
void sleep() {
sleep_enable();
noInterrupts();
GIMSK |= 0b00100000; // Turn on pin change interrupts
for (byte i = 0; i < 4; i++) {
PCMSK |= 1 << buttonPins[i];
}
interrupts();
sleep_cpu();
}
// The sound-producing function
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds)
{ // http://web.media.mit.edu/~leah/LilyPad/07_sound_code.html
int x;
long delayAmount = (long)(1000000 / frequencyInHertz);
long loopTime = (long)((timeInMilliseconds * 1000) / (delayAmount * 2));
pinMode(speakerPin, OUTPUT);
for (x = 0; x < loopTime; x++) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(delayAmount);
digitalWrite(speakerPin, LOW);
delayMicroseconds(delayAmount);
}
pinMode(speakerPin, INPUT);
}
/**
Lights the given led and plays the suitable tone
*/
void lightLedAndPlaySound(byte ledIndex) {
pinMode(buttonPins[ledIndex], OUTPUT);
digitalWrite(buttonPins[ledIndex], LOW);
beep(SPEAKER_PIN, gameTones[ledIndex], 300);
pinMode(buttonPins[ledIndex], INPUT_PULLUP);
}
/**
Plays the current sequence of notes that the user has to repeat
*/
void playSequence() {
for (int i = 0; i < gameIndex; i++) {
byte currentLed = gameSequence[i];
lightLedAndPlaySound(currentLed);
delay(50);
}
}
/**
Waits until the user pressed one of the buttons, and returns the index of that button
*/
byte readButton() {
for (;;) {
for (int i = 0; i < 4; i++) {
byte buttonPin = buttonPins[i];
if (digitalRead(buttonPin) == LOW) {
return i;
}
}
sleep();
}
}
/**
Plays the tone associated with a specific button + debouncing mechanism
*/
void playButtonTone(byte buttonIndex) {
beep(SPEAKER_PIN, gameTones[buttonIndex], 150);
// Wait until button is released.
while (digitalRead(buttonPins[buttonIndex]) == LOW);
delay(50);
}
/**
Play the game over sequence, and report the game score
*/
void gameOver() {
gameIndex = 0;
delay(200);
// Play a Wah-Wah-Wah-Wah sound
beep(SPEAKER_PIN, NOTE_DS5, 300);
beep(SPEAKER_PIN, NOTE_D5, 300);
beep(SPEAKER_PIN, NOTE_CS5, 300);
for (int i = 0; i < 200; i++) {
beep(SPEAKER_PIN, NOTE_C5 + (i % 20 - 10), 5);
}
delay(500);
}
/**
Get the user input and compare it with the expected sequence. If the user fails, play the game over sequence and restart the game.
*/
void checkUserSequence() {
for (int i = 0; i < gameIndex; i++) {
byte expectedButton = gameSequence[i];
byte actualButton = readButton();
playButtonTone(actualButton);
if (expectedButton == actualButton) {
/* good */
} else {
gameOver();
return;
}
}
}
/**
Plays an hooray sound whenever the user finishes a level
*/
void levelUp() {
beep(SPEAKER_PIN, NOTE_E4, 150);
beep(SPEAKER_PIN, NOTE_G4, 150);
beep(SPEAKER_PIN, NOTE_E5, 150);
beep(SPEAKER_PIN, NOTE_C5, 150);
beep(SPEAKER_PIN, NOTE_D5, 150);
beep(SPEAKER_PIN, NOTE_G5, 150);
}
/**
The main game loop
*/
void loop() {
// Add a random color to the end of the sequence
gameSequence[gameIndex] = random(0, 4);
gameIndex++;
playSequence();
checkUserSequence();
delay(300);
if (gameIndex > 0) {
levelUp();
delay(300);
}
}
Additional file "pitches.h"
/**************************************************
This file defines constants with the frequency
of different musical notes.
*************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
Finally, the heart of the simulation window - the "diagram.json" file
{
"version": 1,
"author": "Uri Shaked",
"editor": "wokwi",
"parts": [
{
"type": "wokwi-attiny85",
"id": "tiny",
"top": 140,
"left": 141.16
},
{
"type": "wokwi-buzzer",
"id": "buzzer",
"top": -7.89,
"left": 121.02,
"attrs": { "volume": "0.1" }
},
{
"type": "wokwi-led",
"id": "led-red",
"top": 10,
"left": 6,
"attrs": { "color": "red" }
},
{
"type": "wokwi-led",
"id": "led-green",
"top": 68,
"left": 6,
"attrs": { "color": "green" }
},
{
"type": "wokwi-led",
"id": "led-blue",
"top": 5.03,
"left": 270,
"attrs": { "color": "blue" }
},
{
"type": "wokwi-led",
"id": "led-yellow",
"top": 68,
"left": 270,
"attrs": { "color": "yellow" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-red",
"top": 10,
"left": 46,
"attrs": { "color": "red" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-green",
"top": 70,
"left": 46,
"attrs": { "color": "green" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-blue",
"top": 10,
"left": 200,
"attrs": { "color": "blue" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-yellow",
"top": 70,
"left": 200,
"attrs": { "color": "yellow" }
}
],
"connections": [
[ "tiny:GND", "buzzer:1", "black", [ "v12", "*", "h30","v10" ] ],
[ "tiny:PB0", "buzzer:2", "purple", [ "v-40", "*", "h0" ] ],
[ "tiny:PB1", "btn-yellow:1.l", "gold", [ "v-48", "*", "h-38" ] ],
[ "tiny:GND", "btn-yellow:2.r", "black", [ "v12", "*", "h6" ] ],
[ "tiny:PB2", "btn-blue:1.l", "blue", [ "v-24", "*", "h-10" ] ],
[ "tiny:GND", "btn-blue:2.r", "black", [ "v12", "*", "h6" ] ],
[ "tiny:PB3", "btn-green:2.r", "green", [ "v10", "*", "h6" ] ],
[ "tiny:GND", "btn-green:1.l", "black", [ "v12", "*", "h-6" ] ],
[ "tiny:PB4", "btn-red:2.r", "orange", [ "v4", "*", "h10" ] ],
[ "tiny:GND", "btn-red:1.l", "black", [ "v12", "*", "h-6" ] ],
[ "tiny:PB1", "led-yellow:C", "gold", [ "v-28", "*", "h-122", "v10" ] ],
[ "tiny:VCC", "led-yellow:A", "red", [ "v-12", "*", "h-17", "v18","h13" ] ],
[ "tiny:PB2", "led-blue:C", "blue", [ "v-24", "*", "h-5" ] ],
[ "tiny:VCC", "led-blue:A", "red", [ "v-12", "*", "h-15", "v81","h13" ] ],
[ "tiny:PB3", "led-green:C", "green", [ "v10", "*", "h0" ] ],
[ "tiny:VCC", "led-green:A", "red", [ "v-12", "*", "h7" ] ],
[ "tiny:PB4", "led-red:C", "orange", [ "v4", "h-150", "v-10" ] ],
[ "tiny:VCC", "led-red:A", "red", [ "v-12", "*", "h7" ] ]
]
}
The Permanent link to the projecthttps://wokwi.com/arduino/projects/285525640477671948
A small GIF showing the working of the project is given below
You can edit the project and play with it on any browsers. Just open the project URL and go to the editor tab. By clicking on the Play button, you will recompile the changes and start the simulations. You can indeed use your smartphone to develop code and play with the simulations.
FinallyIf you have any questions feel free to hop on to the Wokwi Discord server
Also, you can leave comments below and I will be happy to help with your queries.
Share your interesting projects and browse through several curious projects from fellow developers and makers on Facebook Wokwi Group!
Stay Safe!
Don't stop learning!
#wokwiMakes
Comments
Please log in or sign up to comment.