/* Like all Arduino code - copied from somewhere else :)
So don't claim it as your own
-----------------------------------------------------
Author: BF - 24/10
Acknowledgment: crapaud_curieux
*/
#include <Adafruit_NeoPixel.h>
#include <TM1637Display.h> // Include the TM1637Display library
#define LED_PIN 6 // Connect the LED strip data pin to pin 6 on Arduino
#define BT_PIN_RED 8 // Connect the red button to pin 8
#define BT_PIN_GREEN 9 // Connect the green button to pin 9
#define BT_PIN_BLUE 10 // Connect the blue button to pin 10
#define BT_PIN_YELLOW 11 // Connect the yellow button to pin 11
#define NUM_LEDS 30 // Define the number of LEDs in the strip
#define BLUE 0x0000FF
#define RED 0xFF0000
#define GREEN 0x00FF00
#define YELLOW 0xFFFF00
#define OFF 0x000000
#define WHITE 0xFFFFFF
// TM1637 display configuration
#define CLK 2 // Define the CLK pin
#define DIO 3 // Define the DIO pin
TM1637Display display(CLK, DIO); // Create a display object
// Buzzer configuration
#define BUZZER_PIN 4 // Define the Buzzer pin
// Button states and counters
int lastButtonStateRed = 0;
int buttonStateRed = 0;
float buttonPushCounterRed = 0;
int lastButtonStateGreen = 0;
int buttonStateGreen = 0;
float buttonPushCounterGreen = 0;
int lastButtonStateBlue = 0;
int buttonStateBlue = 0;
float buttonPushCounterBlue = 0;
int lastButtonStateYellow = 0;
int buttonStateYellow = 0;
float buttonPushCounterYellow = 0;
unsigned long lastDebounceTimeRed = 0;
unsigned long lastDebounceTimeGreen = 0;
unsigned long lastDebounceTimeBlue = 0;
unsigned long lastDebounceTimeYellow = 0;
unsigned long debounceDelay = 50; // Debouncing delay (50 ms)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Score counters for each player
int scoreRed = 0;
int scoreGreen = 0;
int scoreBlue = 0;
int scoreYellow = 0;
// Handles LED animation when a button is pressed: turn on the LED at 'pos' with the requested color, and turn off the LED at 'pos-1'
void advance(int pos, long color) {
strip.setPixelColor(pos, color);
if (pos > 0) {
strip.setPixelColor(pos - 1, OFF);
}
strip.show(); // Very important: the 'strip.show' function sends the command to the LED strip
}
void startAnimation() {
int positions[3] = {0, 1, 2}; // LEDs to light up
for (int k = 0; k < NUM_LEDS; k++) {
for (int i = 0; i < 3; i++) {
if (k + positions[i] < NUM_LEDS) {
strip.setPixelColor(k + positions[i], WHITE); // Light up LEDs
}
}
if (k > 0) {
strip.setPixelColor(k - 1, OFF); // Turn off the previous LED
}
strip.show(); // Update the strip
delay(40); // Delay
strip.setPixelColor(k, OFF);
strip.show(); // Update the strip
}
beep(); // Call the beep function at the end of the animation
}
void endAnimation(long color) {
int positions[5] = {0, 1, 2, 3, 4}; // LEDs to light up
for (int pass = 0; pass < 2; pass++) { // Two passes
for (int k = 0; k < NUM_LEDS; k++) {
for (int i = 0; i < 5; i++) {
if (k + positions[i] < NUM_LEDS) {
strip.setPixelColor(k + positions[i], color); // Light up LEDs
}
}
if (k > 0) {
strip.setPixelColor(k - 1, OFF); // Turn off the previous LED
}
strip.show(); // Update the strip
delay(20); // Delay
}
}
// Turn off the last LED after the end of the animation
strip.setPixelColor(NUM_LEDS - 1, OFF);
strip.show(); // Final update to the strip
}
// Buzzer function to beep
void beep() {
tone(BUZZER_PIN, 250, 200); // Play a tone at 500 Hz for 200 ms
}
// Reads the button states
void readButtons() {
buttonStateRed = digitalRead(BT_PIN_RED);
buttonStateGreen = digitalRead(BT_PIN_GREEN);
buttonStateBlue = digitalRead(BT_PIN_BLUE);
buttonStateYellow = digitalRead(BT_PIN_YELLOW);
}
// Setup function
void setup() {
Serial.begin(9600);
strip.begin();
pinMode(BT_PIN_RED, INPUT_PULLUP);
pinMode(BT_PIN_GREEN, INPUT_PULLUP);
pinMode(BT_PIN_BLUE, INPUT_PULLUP);
pinMode(BT_PIN_YELLOW, INPUT_PULLUP);
// Setup TM1637 display
display.setBrightness(0x0f); // Set brightness level (0x00 to 0x0f)
// Setup buzzer pin
pinMode(BUZZER_PIN, OUTPUT); // Set the buzzer pin as output
strip.show();
startAnimation();
}
// Function to test button presses with debounce
void checkButton(int *oldState, int newState, float *counter, long color, unsigned long *lastDebounceTime) {
unsigned long currentTime = millis(); // Get the current time
// Only trigger on button press (falling edge detection: HIGH -> LOW) after debounce delay
if (*oldState == HIGH && newState == LOW && (currentTime - *lastDebounceTime) > debounceDelay) {
*counter = *counter + 0.5; // Increment by 1 with each press/release
//*counter = *counter + 1; // Increment by 2 with each press/release
Serial.print("Color : ");
if (color == 16711680) {
Serial.print("Rouge");
}
else if (color == 65280) {
Serial.print("Vert");
}
else if (color == 255) {
Serial.print("Bleu");
}
else if (color == 16776960) {
Serial.print("Jaune");
}
Serial.print(" - ");
Serial.print("Counter : ");
Serial.println(*counter);
advance(*counter, color);
*lastDebounceTime = currentTime; // Update the debounce time
}
// Update the previous button state
*oldState = newState;
}
// Resets all counters
void resetCounters() {
buttonPushCounterRed = 0;
buttonPushCounterGreen = 0;
buttonPushCounterBlue = 0;
buttonPushCounterYellow = 0;
}
// Update TM1637 display with scores
void updateDisplay() {
// Combine scores into a single number
int displayNumber = (scoreRed * 1000) + (scoreGreen * 100) + (scoreBlue * 10) + scoreYellow;
// Show the number on the TM1637 display
display.showNumberDec(displayNumber, false); // Display without leading zeros
}
// Main loop
void loop() {
// Read the button states
readButtons();
// Test each button with its corresponding color and debounce logic
checkButton(&lastButtonStateRed, buttonStateRed, &buttonPushCounterRed, RED, &lastDebounceTimeRed);
checkButton(&lastButtonStateGreen, buttonStateGreen, &buttonPushCounterGreen, GREEN, &lastDebounceTimeGreen);
checkButton(&lastButtonStateBlue, buttonStateBlue, &buttonPushCounterBlue, BLUE, &lastDebounceTimeBlue);
checkButton(&lastButtonStateYellow, buttonStateYellow, &buttonPushCounterYellow, YELLOW, &lastDebounceTimeYellow);
// Victory conditions
if (buttonPushCounterRed > 29) {
endAnimation(RED);
scoreRed++; // Increment score for red
updateDisplay(); // Update TM1637 display
resetCounters();
delay(random(2000, 5000)); // Random delay between 2 and 5 seconds
startAnimation();
}
if (buttonPushCounterGreen > 29) {
endAnimation(GREEN);
scoreGreen++; // Increment score for green
updateDisplay(); // Update TM1637 display
resetCounters();
delay(random(2000, 5000)); // Random delay between 2 and 5 seconds
startAnimation();
}
if (buttonPushCounterBlue > 29) {
endAnimation(BLUE);
scoreBlue++; // Increment score for blue
updateDisplay(); // Update TM1637 display
resetCounters();
delay(random(2000, 5000)); // Random delay between 2 and 5 seconds
startAnimation();
}
if (buttonPushCounterYellow > 29) {
endAnimation(YELLOW);
scoreYellow++; // Increment score for yellow
updateDisplay(); // Update TM1637 display
resetCounters();
delay(random(2000, 5000)); // Random delay between 2 and 5 seconds
startAnimation();
}
}