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 LEDs, 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.
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.
// 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 }