"I Spy" Game With Arduino
Everyone knows the game "I Spy" from his childhood. Let's build an electronic version with the Arduino.
For the prototype you need an Arduino (I'm using an Arduino Uno here), a color sensor, a display (with I2C connector so you don't have to use so much pins), a piezo buzzer and four buttons. And of course some cables and resistors.
The game works like this: The first player looks for an object in the room in one of the four colors red, yellow, green or blue. Then he presses the corresponding button. The second player then has to find an item in this color. If he doesn't find it within a certain period of time, the first player has to prove that this item exists and didn't bluff. Then the player changes.
German reader? : Lies die Anleitung zu diesem Arduino Projekt bei Pollux Labs
Supplies
- Arduino Uno
- Breadboard
- I2C LCD Display
- Color Sensor
- Piezo Buzzer
- 4 10kΩ Resistors
- 4 Buttons
- Jumper Wires (male/male, male/female)
Buttons, Wires & Resistors
First you put the buttons on the breadboard. Of course, colored buttons are best. If you don't have any, you can display the color they stand for in a different way: You can put colored LEDs next to them or just paint them.
Place the buttons in the middle of the breadboard as shown in the photo. Make sure you still have space left or right of the buttons for the piezo buzzer. Connect a pin of the button with a cable to the + bar. Connect the other pin to the - bar with a 10k Ohm resistor. Repeat this three times and you have prepared all four buttons.
Make Some Noise With the Piezo Buzzer
Installing the Piezo Buzzer is also easy. Connect the left pin with a cable to the -bar. The right pin will later receive the power directly from the Arduino. To connect this cable to the Piezo Buzzer you have to put a small cable next to the pin. In the photo this cable is red and above it, you can see the cable (blue) coming from the Arduino.
Connect Buttons & Buzzer to the Arduino
For this, you need 5 cables.
Connect the piezo buzzer to digital pin 11.
Connect the 4 buttons as follows:
- Red Button - Digital Pin 2
- Yellow Button - Digital Pin 3
- Green Button - Digital Pin 4
- Blue Button - Digital Pin 5
Connect the Color Sensor
In this project, we use a TCS230 / TC3200 Color Sensor. Learn more about this sensor here.
To connect the sensor to the Arduino you need 7 cables (male / female). Connect two cables to the pins "GND" (-) and "VCC" (+) and connect them to the power bar.
Connect the remaining 5 directly to your Arduino board as follows:
- S0 - Digital Pin 6
- S1 - Digital Pin 7
- S3 - Digital Pin 8
- S2 - Digital Pin 9
- OUT - Digital Pin 10
Done!
The LCD Display
In this project, we use an I2C LCD display with 4x20 characters. The advantage of this type of display is that you don't need so many pins on your Arduino - that's just 2 plus 2 for power.
All you have to do is connect the display pin "SCL" to pin A5 on your Arduino and the pin "SDA" to pin A4. "GND" and "VCC" are connected to the power bar like the Color Sensor.
The last step on your breadboard is the power supply. Connect the breadboard to the 5V output and a "GND" on your Arduino.
The Code & Beyond
Finally! Connect your Arduino to your PC or MAC and upload the following code. But first, a few points:
In the very first line, you can customize the round time. Default is 10 seconds (10000ms).
You can customize every string in the code to customize your gaming experience.
Also, you can rename "Player1" and "Player2". Give them real names!
A color sensor does not always work reliably, but depends strongly on the lighting conditions and the material that you "scan". If this reflects too much, the sensor may not respond.
If you like, experiment with the color values in the corresponding functions. When your Arduino is connected to your computer and you press one of the colored buttons, the Serial Monitor will display the color values that the sensor detects. Improve the color space that makes up red, for example, by "scanning" different shades of red and adjusting the values in the following functions in the code:
- checkRed()
- checkRedBluff()
- checkYellow()
- checkYellowBluff()
- checkGreen()
- checkGreenBluff()
- checkBlue()
- checkBlueBluff()
And now, here is the code. Another note: I'm not a professional programmer - if you know how to make the code leaner, share it with me.
Have fun!
long roundTime = 10000; // Time for player to find the color
// include the library code:#include // define pins for color sensor#define S0 6#define S1 7#define S2 9#define S3 8#define sensorOut 10 long currentTime; //elapsed time in round long startTime = millis(); //start time of round // values of each color from color sensorint frequencyR = 0;int frequencyG = 0;int frequencyB = 0; int color = 0; // player pointsint pointsPlayer1 = 0;int pointsPlayer2 = 0; int newGame = 0; int keyRead = 0; int playerOnTurn = 2; int rightColorFound = 0; LiquidCrystal_I2C lcd(0x27, 20, 4); //Hier wird festgelegt um was für einen Display es sich handelt. In diesem Fall eines mit 16 Zeichen in 2 Zeilen und der HEX-Adresse 0x27. Für ein vierzeiliges I2C-LCD verwendet man den Code "LiquidCrystal_I2C lcd(0x27, 20, 4)" void setup() { pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); pinMode(sensorOut, INPUT); pinMode(2, INPUT); //RED pinMode(3, INPUT); //YELLOW pinMode(4, INPUT); //GREEN pinMode(5, INPUT); //BLUE digitalWrite(S0,HIGH); digitalWrite(S1,LOW); Serial.begin(9600); lcd.init(); lcd.backlight(); } void loop() { if(pointsPlayer1 == 0 && pointsPlayer2 == 0 && newGame == 0){ startGame(); newGame = 1; }} void startGame(){ tone(11, 250, 150); delay(100); tone(11, 350, 150); delay(100); tone(11, 450, 150); delay(100); tone(11, 550, 150); lcd.clear(); lcd.setCursor(1,1); lcd.print("Welcome to Veo Veo"); delay(2500); player1Chooses(); } void player1Chooses(){ lcd.clear(); lcd.setCursor(6,0); lcd.print("Player 1"); lcd.setCursor(3,2); lcd.print("Choose a color"); while(keyRead == 0){ readKey(); } } void player2Chooses(){ lcd.clear(); lcd.setCursor(6,0); lcd.print("Player 2"); lcd.setCursor(3,2); lcd.print("Choose a color"); while(keyRead == 0){ readKey(); } } void showPoints(){ lcd.clear(); lcd.setCursor(7,0); lcd.print("Score:"); lcd.setCursor(4,2); lcd.print("Player 1: "); lcd.print(pointsPlayer1); lcd.setCursor(4,3); lcd.print("Player 2: "); lcd.print(pointsPlayer2); delay(5000); } void newRound(){ color = 0; keyRead = 0; if(playerOnTurn == 2){ playerOnTurn = 1; pointsPlayer2++; rightColorFound = 0; showPoints(); player2Chooses(); }else{ playerOnTurn = 2; pointsPlayer1++; rightColorFound = 0; showPoints(); player1Chooses(); } } void readKey(){ if(digitalRead(2) == HIGH){ color = 1; keyRead= 1; tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(6,0); lcd.print("Player " + String(playerOnTurn)); lcd.setCursor(3,2); lcd.print("Find a RED thing"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkRed(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); proofBluff(); }else if(digitalRead(3) == HIGH){ color = 4; keyRead= 1; tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(6,0); lcd.print("Player " + String(playerOnTurn)); lcd.setCursor(0,2); lcd.print("YELLOW! Find YELLOW!"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkYellow(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); proofBluff(); }else if(digitalRead(4) == HIGH){ color = 2; keyRead= 1; tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(6,0); lcd.print("Player " + String(playerOnTurn)); lcd.setCursor(2,2); lcd.print("Something Green!"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkGreen(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); proofBluff(); }else if(digitalRead(5) == HIGH){ color = 3; keyRead= 1; tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(6,0); lcd.print("Player " + String(playerOnTurn)); lcd.setCursor(4,2); lcd.print("Gimme BLUE!"); startTime = millis(); //Startzeit des Suchvorgangs while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkBlue(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); proofBluff(); } } void colorPicker(){ digitalWrite(S2,LOW); digitalWrite(S3,LOW); // Reading the output frequency frequencyR = pulseIn(sensorOut, LOW); //Remaping the value of the frequency to the RGB Model of 0 to 255 frequencyR = map(frequencyR, 25,72,255,0); if(frequencyR < 0){ frequencyR = 0; }else if(frequencyR > 255){ frequencyR = 255; } // Printing the value on the serial monitor Serial.print("R= ");//printing name Serial.print(frequencyR);//printing RED color frequency Serial.print(" "); // Setting Green filtered photodiodes to be read digitalWrite(S2,HIGH); digitalWrite(S3,HIGH); // Reading the output frequency frequencyG = pulseIn(sensorOut, LOW); //Remaping the value of the frequency to the RGB Model of 0 to 255 frequencyG = map(frequencyG, 30,90,255,0); if(frequencyG < 0){ frequencyG = 0; }else if(frequencyG > 255){ frequencyG = 255; } // Printing the value on the serial monitor Serial.print("G= ");//printing name Serial.print(frequencyG);//printing RED color frequency Serial.print(" "); // Setting Blue filtered photodiodes to be read digitalWrite(S2,LOW); digitalWrite(S3,HIGH); // Reading the output frequency frequencyB = pulseIn(sensorOut, LOW); //Remaping the value of the frequency to the RGB Model of 0 to 255 frequencyB = map(frequencyB, 25,70,255,0); if(frequencyB < 0){ frequencyB = 0; }else if(frequencyB > 255){ frequencyB = 255; } // Printing the value on the serial monitor Serial.print("B= ");//printing name Serial.print(frequencyB);//printing RED color frequency Serial.println(" "); }void checkRed(){ colorPicker(); if(frequencyR > 200 && frequencyG < 115 && frequencyB < 115){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRound(); } }
void checkYellow(){ colorPicker(); if(frequencyR < 200 && frequencyG > 200 && frequencyB < 210){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRound(); } } void checkGreen(){ colorPicker(); if(frequencyR < 200 && frequencyG > 200 && frequencyB < 210){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRound(); } } void checkBlue(){ colorPicker(); if(frequencyR < 120 && frequencyG < 120 && frequencyB > 150){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRound(); } } void newRoundBluff(){ color = 0; keyRead = 0; //keyRead wieder zurücksetzen if(playerOnTurn == 2){ //Spieler switchen, Punkt geben, anderen spieler aufrufen playerOnTurn = 1; pointsPlayer1++; rightColorFound = 0; showPoints(); player2Chooses(); }else{ playerOnTurn = 2; pointsPlayer2++; // GEHT NICHT rightColorFound = 0; showPoints(); player1Chooses(); } } void proofBluff(){ if(color == 1){ tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(5,0); lcd.print("Opponent!"); lcd.setCursor(0,2); lcd.print("Where is that color?"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkRedBluff(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); newRound(); }else if(color == 2){ tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(5,0); lcd.print("Opponent!"); lcd.setCursor(0,2); lcd.print("Where is that color?"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkGreenBluff(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); newRound(); }else if(color == 4){ tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(5,0); lcd.print("Opponent!"); lcd.setCursor(0,2); lcd.print("Where is that color?"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkYellowBluff(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); newRound(); }else if(color == 3){ tone(11, 450, 150); delay(100); tone(11, 650, 150); delay(100); tone(11, 750, 150); lcd.clear(); lcd.setCursor(5,0); lcd.print("Opponent!"); lcd.setCursor(0,2); lcd.print("Where is that color?"); startTime = millis(); while(rightColorFound == 0 && currentTime - startTime <= roundTime){ checkBlueBluff(); currentTime = millis(); } lcd.clear(); tone(11, 150, 150); delay(300); tone(11, 50, 150); lcd.setCursor(4,2); lcd.print("Time is up!"); delay(1500); newRound(); } } void checkRedBluff(){ colorPicker(); if(frequencyR > 200 && frequencyG < 115 && frequencyB < 115){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRoundBluff(); } } void checkYellowBluff(){ colorPicker(); if(frequencyR < 200 && frequencyG > 200 && frequencyB < 210){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRoundBluff(); } } void checkGreenBluff(){ colorPicker(); if(frequencyR < 200 && frequencyG > 200 && frequencyB < 210){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRoundBluff(); } } void checkBlueBluff(){ colorPicker(); if(frequencyR < 120 && frequencyG < 120 && frequencyB > 150){ lcd.clear(); tone(11, 450, 150); delay(100); tone(11, 650, 350); lcd.setCursor(6,2); lcd.print("Great!"); rightColorFound = 1; delay(3000); newRoundBluff(); } }