// --- PIN DEFINITIONS ---
const int ledPins[] = {2, 3, 4, 5, 6};
const int switchPins[] = {8, 9, 10, 11, 12};
const int numSwitches = 5;
// --- GAME STATE VARIABLES ---
int expectedSwitch = 1;
int lastSwitchPressed = 0;
String outputString = "";
// --- NON-BLOCKING LED TIMER VARIABLES ---
unsigned long ledOnTime = 0;
int activeLedPin = -1;
const long ledInterval = 500; // How long an LED stays on (1000ms = 1 second)
// --- ROBUST DEBOUNCE VARIABLES ---
int buttonState[numSwitches];
// Initialize lastButtonState to HIGH (unpressed) for all switches
int lastButtonState[numSwitches] = {HIGH, HIGH, HIGH, HIGH, HIGH};
unsigned long lastDebounceTime[numSwitches] = {0};
unsigned long debounceDelay = 50; // 50 millisecond debounce period
//================================================================
// SETUP FUNCTION - Runs once at the beginning
//================================================================
void setup() {
Serial.begin(9600);
Serial.println("Arduino Sequence Started.");
Serial.println("Press Switch 1 to begin.");
for (int i = 0; i < numSwitches; i++) {
pinMode(ledPins[i], OUTPUT);
pinMode(switchPins[i], INPUT_PULLUP);
}
}
//================================================================
// MAIN LOOP - Runs continuously
//================================================================
void loop() {
// Check if it's time to turn an active LED off
if (activeLedPin != -1) {
if (millis() - ledOnTime >= ledInterval) {
digitalWrite(activeLedPin, LOW);
activeLedPin = -1; // Reset the tracker
}
}
// Check all switches with robust debouncing
for (int i = 0; i < numSwitches; i++) {
int reading = digitalRead(switchPins[i]);
// If the switch state has changed (due to press or bounce), reset the debounce timer
if (reading != lastButtonState[i]) {
lastDebounceTime[i] = millis();
}
// After the reading has been stable for longer than the debounce delay...
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
// ...and if the state has truly changed...
if (reading != buttonState[i]) {
buttonState[i] = reading;
// ...and if the button was just pressed (transitioned from HIGH to LOW)...
if (buttonState[i] == LOW) {
processSwitchPress(i); // ...then process it as a single, valid press.
}
}
}
lastButtonState[i] = reading;
}
}
//================================================================
// PROCESS SWITCH PRESS - Handles the game logic and feedback
//================================================================
void processSwitchPress(int switchIndex){
//Serial.print("\nPressed switch ");
//Serial.println(switchIndex+1);
// If another LED is on, turn it off immediately before turning the new one on
if (activeLedPin != -1) {
digitalWrite(activeLedPin, LOW);
}
int currentSwitch = switchIndex + 1;
// --- Game Logic ---
if (currentSwitch == lastSwitchPressed) {
outputString += "0";
Serial.print("\r" + outputString);
lastSwitchPressed = 0;
}
else if (currentSwitch == expectedSwitch) {
outputString += "1";
Serial.print("\r" + outputString);
lastSwitchPressed = currentSwitch;
expectedSwitch++;
if (expectedSwitch > numSwitches) {
Serial.println("\nSequence Complete. Resetting.");
resetSequence();
}
}
else {
Serial.println("\nError. Sequence Resetting.");
resetSequence();
}
// --- Visual Feedback ---
// Turn the new LED on and start its timer
digitalWrite(ledPins[switchIndex], HIGH);
activeLedPin = ledPins[switchIndex];
ledOnTime = millis();
}
//================================================================
// RESET SEQUENCE - Resets game variables to their initial state
//================================================================
void resetSequence() {
expectedSwitch = 1;
lastSwitchPressed = 0;
outputString = "";
}