Let’s look at what I need to do…
(Post documentation on blog): Get information from at least one analog sensor and at least one digital sensor (switch) , and use this information to control at least two LED s, one in a digital fashion and the other in an analog fashion , in some creative way .
Hmm… so I can do something along the lines of
Ultrasonic Sensor (Analog)
Switch (is a requirement)
4 LEDs (3 controlled by digitalWrite, and one fade In/Out through analog PWM)
In some creative way?? Hmm, how about we turn the entire project into a detective game, where you have to guess the murderer by pointing at one of the 3 suspects, then Arduino will tell you whether you got it right or wrong.
Guess Who’s Murderer
Hence, my project…
The player step into the shoes of a cunning detective, whose aim is to unravel the identity of the true culprit among the Crimson Enigma, the Emerald Marksman, and the Honey Hitwoman.
Using their hand, the player must point to one of the suspects. An ultrasonic sensor, detects the location of the player’s hand, illuminating the corresponding LED to indicate their suspicion.
To make their guess official, the player presses a pushbutton. If the guess is correct, a green LED softly fades in and out. However, if the player points their accusatory finger at the wrong suspect, the game’s buzzer sounds.
The demo video is below.
VIDEO
Art
All artworks are generated with midjourney… and some photoshop thrown in.
CODE
The code is below. Note that I am implementing a entire thing as a state machine, where the game alternates between the
{ SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS }
states. This makes the code clean. The microcontroller randomly selects the murderer using a random number generation algorithm, which is triggered at the start of each new game loop.
const int buttonPin = 12; // Pushbutton pin
const int buzzerPin = 7; // Buzzer pin
const int greenLedPin = 44; // Green LED pin
const int redLedPins [] = { 3, 6, 10 } ; // Red LEDs for murderer selection
const int trigPin = 2; // Ultrasonic sensor trigger pin
const int echoPin = 4; // Ultrasonic sensor echo pin
// Game state definitions
enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS } ;
// Variables for game logic
int lastButtonState = LOW;
unsigned long previousMillis = 0; // for non-blocking delays
pinMode ( buttonPin, INPUT ) ;
pinMode ( buzzerPin, OUTPUT ) ;
pinMode ( greenLedPin, OUTPUT ) ;
for ( int i = 0; i < 3; i++ ) {
pinMode ( redLedPins [ i ] , OUTPUT ) ;
pinMode ( trigPin, OUTPUT ) ;
randomSeed ( analogRead ( 0 )) ;
currentState = SELECT_MURDERER;
murderer = random ( 0, 3 ) ; // Randomly select a murderer among 3 LEDs
Serial. print ( "Murderer is: LED " ) ;
Serial. println ( murderer ) ;
lightRedLEDsBasedOnDistance () ;
if ( buttonState == HIGH && lastButtonState == LOW ) {
Serial. println ( "Button Pressed" ) ;
} else if ( buttonState == LOW && lastButtonState == HIGH ) {
Serial. println ( "Button Released" ) ;
lastButtonState = buttonState;
void lightRedLEDsBasedOnDistance () {
long distance = measureDistance () ;
Serial. print ( "Distance: " ) ;
for ( int i = 0; i < 3; i++ ) {
digitalWrite ( redLedPins [ i ] , LOW ) ;
if ( distance > = 2 && distance < 6 ) {
digitalWrite ( redLedPins [ 0 ] , HIGH ) ;
} else if ( distance > = 6 && distance < 9 ) {
digitalWrite ( redLedPins [ 1 ] , HIGH ) ;
} else if ( distance > = 9 && distance < = 12 ) {
digitalWrite ( redLedPins [ 2 ] , HIGH ) ;
buttonState = digitalRead ( buttonPin ) ;
currentState = CORRECT_GUESS;
currentState = WRONG_GUESS;
void handleCorrectGuess () {
fadeGreenLED () ; // Handles the fading of the LED over 4 seconds
currentState = SELECT_MURDERER;
void handleWrongGuess () {
buzzBuzzer ( 3 ) ; // Buzzes the buzzer 3 times
currentState = SELECT_MURDERER;
for ( int i = 0; i < = 255; i += 5 ) {
analogWrite ( greenLedPin, i ) ;
for ( int i = 255; i > = 0; i -= 5 ) {
analogWrite ( greenLedPin, i ) ;
void buzzBuzzer ( int count ) {
for ( int i = 0; i < count; i++ ) {
digitalWrite ( buzzerPin, HIGH ) ;
digitalWrite ( buzzerPin, LOW ) ;
digitalWrite ( trigPin, LOW ) ;
digitalWrite ( trigPin, HIGH ) ;
digitalWrite ( trigPin, LOW ) ;
long duration = pulseIn ( echoPin, HIGH ) ;
return duration * 0.034 / 2; // Calculate distance in cm
// Pin Definitions
const int buttonPin = 12; // Pushbutton pin
const int buzzerPin = 7; // Buzzer pin
const int greenLedPin = 44; // Green LED pin
const int redLedPins[] = {3, 6, 10}; // Red LEDs for murderer selection
const int trigPin = 2; // Ultrasonic sensor trigger pin
const int echoPin = 4; // Ultrasonic sensor echo pin
// Game state definitions
enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS };
GameState currentState;
// Variables for game logic
int murderer = 0;
int guess = -1;
int buttonState = 0;
int lastButtonState = LOW;
unsigned long previousMillis = 0; // for non-blocking delays
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
for (int i = 0; i < 3; i++) {
pinMode(redLedPins[i], OUTPUT);
}
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
randomSeed(analogRead(0));
currentState = SELECT_MURDERER;
}
void loop() {
switch (currentState) {
case SELECT_MURDERER:
selectMurderer();
break;
case GUESS:
manageGuess();
break;
case CORRECT_GUESS:
handleCorrectGuess();
break;
case WRONG_GUESS:
handleWrongGuess();
break;
}
}
void selectMurderer() {
murderer = random(0, 3); // Randomly select a murderer among 3 LEDs
Serial.print("Murderer is: LED ");
Serial.println(murderer);
currentState = GUESS;
}
void manageGuess() {
lightRedLEDsBasedOnDistance();
readButtonState();
if (buttonState == HIGH && lastButtonState == LOW) {
Serial.println("Button Pressed");
checkGuess();
} else if (buttonState == LOW && lastButtonState == HIGH) {
Serial.println("Button Released");
}
lastButtonState = buttonState;
}
void lightRedLEDsBasedOnDistance() {
long distance = measureDistance();
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
for (int i = 0; i < 3; i++) {
digitalWrite(redLedPins[i], LOW);
}
if (distance >= 2 && distance < 6) {
digitalWrite(redLedPins[0], HIGH);
guess = 0;
} else if (distance >= 6 && distance < 9) {
digitalWrite(redLedPins[1], HIGH);
guess = 1;
} else if (distance >= 9 && distance <= 12) {
digitalWrite(redLedPins[2], HIGH);
guess = 2;
}
}
void readButtonState() {
buttonState = digitalRead(buttonPin);
}
void checkGuess() {
if (guess == murderer) {
currentState = CORRECT_GUESS;
} else {
currentState = WRONG_GUESS;
}
}
void handleCorrectGuess() {
fadeGreenLED(); // Handles the fading of the LED over 4 seconds
currentState = SELECT_MURDERER;
}
void handleWrongGuess() {
buzzBuzzer(3); // Buzzes the buzzer 3 times
currentState = SELECT_MURDERER;
}
void fadeGreenLED() {
for (int i = 0; i <= 255; i += 5) {
analogWrite(greenLedPin, i);
delay(30);
}
for (int i = 255; i >= 0; i -= 5) {
analogWrite(greenLedPin, i);
delay(30);
}
}
void buzzBuzzer(int count) {
for (int i = 0; i < count; i++) {
digitalWrite(buzzerPin, HIGH);
delay(300);
digitalWrite(buzzerPin, LOW);
delay(300);
}
}
long measureDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2; // Calculate distance in cm
}
// Pin Definitions
const int buttonPin = 12; // Pushbutton pin
const int buzzerPin = 7; // Buzzer pin
const int greenLedPin = 44; // Green LED pin
const int redLedPins[] = {3, 6, 10}; // Red LEDs for murderer selection
const int trigPin = 2; // Ultrasonic sensor trigger pin
const int echoPin = 4; // Ultrasonic sensor echo pin
// Game state definitions
enum GameState { SELECT_MURDERER, GUESS, CORRECT_GUESS, WRONG_GUESS };
GameState currentState;
// Variables for game logic
int murderer = 0;
int guess = -1;
int buttonState = 0;
int lastButtonState = LOW;
unsigned long previousMillis = 0; // for non-blocking delays
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
for (int i = 0; i < 3; i++) {
pinMode(redLedPins[i], OUTPUT);
}
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
randomSeed(analogRead(0));
currentState = SELECT_MURDERER;
}
void loop() {
switch (currentState) {
case SELECT_MURDERER:
selectMurderer();
break;
case GUESS:
manageGuess();
break;
case CORRECT_GUESS:
handleCorrectGuess();
break;
case WRONG_GUESS:
handleWrongGuess();
break;
}
}
void selectMurderer() {
murderer = random(0, 3); // Randomly select a murderer among 3 LEDs
Serial.print("Murderer is: LED ");
Serial.println(murderer);
currentState = GUESS;
}
void manageGuess() {
lightRedLEDsBasedOnDistance();
readButtonState();
if (buttonState == HIGH && lastButtonState == LOW) {
Serial.println("Button Pressed");
checkGuess();
} else if (buttonState == LOW && lastButtonState == HIGH) {
Serial.println("Button Released");
}
lastButtonState = buttonState;
}
void lightRedLEDsBasedOnDistance() {
long distance = measureDistance();
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
for (int i = 0; i < 3; i++) {
digitalWrite(redLedPins[i], LOW);
}
if (distance >= 2 && distance < 6) {
digitalWrite(redLedPins[0], HIGH);
guess = 0;
} else if (distance >= 6 && distance < 9) {
digitalWrite(redLedPins[1], HIGH);
guess = 1;
} else if (distance >= 9 && distance <= 12) {
digitalWrite(redLedPins[2], HIGH);
guess = 2;
}
}
void readButtonState() {
buttonState = digitalRead(buttonPin);
}
void checkGuess() {
if (guess == murderer) {
currentState = CORRECT_GUESS;
} else {
currentState = WRONG_GUESS;
}
}
void handleCorrectGuess() {
fadeGreenLED(); // Handles the fading of the LED over 4 seconds
currentState = SELECT_MURDERER;
}
void handleWrongGuess() {
buzzBuzzer(3); // Buzzes the buzzer 3 times
currentState = SELECT_MURDERER;
}
void fadeGreenLED() {
for (int i = 0; i <= 255; i += 5) {
analogWrite(greenLedPin, i);
delay(30);
}
for (int i = 255; i >= 0; i -= 5) {
analogWrite(greenLedPin, i);
delay(30);
}
}
void buzzBuzzer(int count) {
for (int i = 0; i < count; i++) {
digitalWrite(buzzerPin, HIGH);
delay(300);
digitalWrite(buzzerPin, LOW);
delay(300);
}
}
long measureDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2; // Calculate distance in cm
}