#define LED 12
#define BUT 11
#define BUZZER 10 // Buzzer pin
enum State {
READY,
WAIT,
GO,
RESULT,
FOUL
};
State currentState = READY;
unsigned long stateEntryTime = 0;
unsigned long goTime = 0;
unsigned long reactionTime = 0;
unsigned long waitDelay = 0;
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUT, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
digitalWrite(LED, LOW);
Serial.begin(9600);
Serial.println("Reaction Game Ready!");
delay(1000);
enterState(READY); // ✅ ensure FSM starts cleanly
}
//
// 🎵 SOUND EFFECTS
//
void playFoul() {
for (int i = 0; i < 6; i++) {
tone(BUZZER, 1000, 100); delay(100);
tone(BUZZER, 600, 100); delay(100);
}
noTone(BUZZER);
}
//Non blocking Waiting Tune
unsigned long lastToneTime = 0;
bool heartbeatHigh = false;
void playTension(unsigned long now) {
if (now - lastToneTime > (heartbeatHigh ? 200 : 500)) {
if (heartbeatHigh) {
tone(BUZZER, 500, 100); // short bass note
} else {
tone(BUZZER, 700, 80); // higher beat
}
heartbeatHigh = !heartbeatHigh;
lastToneTime = now;
}
}
void enterState(State newState)
{
currentState = newState;
stateEntryTime = millis();
switch(newState)
{
case READY:
digitalWrite(LED, LOW);
Serial.println("Press button to start");
break;
case WAIT:
digitalWrite(LED, LOW);
waitDelay = random(2000,5000);
Serial.println("Wait...");
break;
case GO:
digitalWrite(LED,HIGH);
goTime = millis();
Serial.println("GO! Press Now!");
break;
case RESULT:
digitalWrite(LED, LOW);
Serial.print("Reaction Time: ");
Serial.print(reactionTime);
Serial.println(" ms"); // newline at the end
break;
case FOUL:
digitalWrite(LED, LOW);
playFoul(); // 🔊 foul sound
Serial.println("Too Early! Foul!");
break;
}
}
static bool pressedBefore = false;
void fsmUpdate()
{
unsigned long now = millis();
bool buttonPressed = digitalRead(BUT) == LOW;
switch(currentState)
{
case READY:
if (buttonPressed)
{
pressedBefore = true;
} else if (pressedBefore && !buttonPressed) {
enterState(WAIT);
pressedBefore = false;
}
break;
case WAIT:
playTension(now);
if(buttonPressed)
enterState(FOUL);
else if (now - stateEntryTime >= waitDelay)
enterState(GO);
break;
case GO:
if(buttonPressed)
{
reactionTime = now - goTime;
enterState(RESULT);
}
break;
case RESULT:
if(now - stateEntryTime >= 3000)
{
enterState(READY);
}
break;
case FOUL:
if(now - stateEntryTime >= 2000)
{
enterState(READY);
}
break;
}
}
void loop()
{
fsmUpdate();
}