Szybki kolor

Typ_projektu
Arduino
Zdjecie główne
Krótki opis projektu

To interaktywna gra zręcznościowa i pamięciowa oparta na mikrokontrolerze ESP8266 (NodeMCU) oraz pasku LED WS2812. Celem gracza jest zapamiętanie i poprawne odtworzenie rosnącej sekwencji kolorów zapalających się na diodach.

Gra ćwiczy:

  • pamięć krótkotrwałą,

  • czas reakcji,

  • koncentrację i koordynację wzrokowo-ruchową.

Niezbędne elementy

1. Płytka  ESP8266 (NodeMCU)

2. Pasek  LED 

3. Buzzer

Opis projektu

Projekt to interaktywna gra elektroniczna łącząca elementy zręcznościowe i pamięciowe. Bazuje na mikrokontrolerze NodeMCU z modułem ESP8266, adresowalnym pasku LED WS2812, zestawie przycisków oraz opcjonalnym buzzerze do sygnalizacji dźwiękowej. Gracz ma za zadanie obserwować i zapamiętywać sekwencję kolorów zapalających się na diodach LED, a następnie odtworzyć ją przy użyciu przypisanych przycisków.

Wraz z postępem w grze, sekwencja staje się coraz dłuższa i trudniejsza, aż do osiągnięcia maksymalnej długości. Gra kończy się dopiero w momencie popełnienia błędu, który sygnalizowany jest miganiem diod w kolorze czerwonym oraz dźwiękiem.

kod programu
#include <Adafruit_NeoPixel.h>

 
#define LED_PIN        6
#define LED_COUNT      8

 
#define BUTTON_BLUE    2
#define BUTTON_PURPLE  7
#define BUTTON_ORANGE  4
#define BUTTON_GREEN   8

 
#define BUZZER_PIN     9
#define MAX_SEQUENCE_LENGTH LED_COUNT

 
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

 
enum Color { BLUE, PURPLE, ORANGE, GREEN, NONE };
Color sequence[MAX_SEQUENCE_LENGTH];
int sequenceLength = 3;
int playerIndex = 0;

 
bool showingSequence = true;
unsigned long lastStepTime = 0;
int showIndex = 0;

 
unsigned long reactionStartTime = 0;

 
void setup() {
  pinMode(BUTTON_BLUE, INPUT_PULLUP);
  pinMode(BUTTON_PURPLE, INPUT_PULLUP);
  pinMode(BUTTON_ORANGE, INPUT_PULLUP);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);  // Buzzer

 
  strip.begin();
  strip.show();

 
  Serial.begin(9600);
  delay(1000);

 
  startupAnimation();  // ✨ animacja i dźwięk startowy

 
  Serial.println("🎮 Simon Says – klikaj po zapaleniu diod, ale nie za wcześnie!");
  startNewRound();
}

 
void loop() {
  // Pokazywanie sekwencji
  if (showingSequence) {
    if (millis() - lastStepTime > 600) {
      if (showIndex > 0) {
        strip.setPixelColor(showIndex - 1, 0); // zgaś poprzednią
      }

 
      if (showIndex < sequenceLength) {
        showColorOnLed(showIndex, sequence[showIndex]);
        lastStepTime = millis();
        showIndex++;
      } else {
        strip.clear();
        strip.show();
        showingSequence = false;
        Serial.println("👉 Możesz odtwarzać sekwencję.");
      }
    }
  }

 
  // Obsługa kliknięć
  static bool buttonReleased = true;
  Color pressed = getPressedButton();

 
  if (pressed == NONE) {
    buttonReleased = true;
    return;
  }

 
  if (buttonReleased) {
    buttonReleased = false;

 
    // Zbyt wcześnie (jeszcze nie pokazany kolor)
    if (playerIndex >= showIndex) {
      Serial.println("❌ Błąd! Kliknięcie przed pokazaniem koloru.");
      errorFeedback();
      sequenceLength = 3;
      startNewRound();
      return;
    }

 
    // Poprawny klik
    if (pressed == sequence[playerIndex]) {
      if (playerIndex == 0) {
        reactionStartTime = millis(); // start pomiaru czasu
      }

 
      playerIndex++;
      if (playerIndex == sequenceLength) {
        unsigned long reactionTime = millis() - reactionStartTime;
        Serial.print("✅ Sekwencja poprawna! Czas reakcji: ");
        Serial.print(reactionTime);
        Serial.println(" ms");

 
        delay(1000);
        if (sequenceLength < MAX_SEQUENCE_LENGTH) {
          sequenceLength++;
        }

 
        startNewRound();
      }
    } else {
      Serial.println("❌ Błąd! Zła sekwencja.");
      errorFeedback();
      sequenceLength = 3;
      startNewRound();
    }

 
    delay(250);  // opóźnienie, by uniknąć szybkich powtórzeń
  }
}

 
void startNewRound() {
  strip.clear();
  strip.show();

 
  showingSequence = true;
  showIndex = 0;
  playerIndex = 0;
  lastStepTime = millis();

 
  Serial.print("\n🧠 Nowa runda. Długość sekwencji: ");
  Serial.println(sequenceLength);

 
  for (int i = 0; i < sequenceLength; i++) {
    sequence[i] = static_cast<Color>(random(0, 4));
  }
}

 
Color getPressedButton() {
  if (digitalRead(BUTTON_BLUE) == LOW)   { delay(30); if (digitalRead(BUTTON_BLUE) == LOW)   return BLUE; }
  if (digitalRead(BUTTON_PURPLE) == LOW) { delay(30); if (digitalRead(BUTTON_PURPLE) == LOW) return PURPLE; }
  if (digitalRead(BUTTON_ORANGE) == LOW) { delay(30); if (digitalRead(BUTTON_ORANGE) == LOW) return ORANGE; }
  if (digitalRead(BUTTON_GREEN) == LOW)  { delay(30); if (digitalRead(BUTTON_GREEN) == LOW)  return GREEN; }
  return NONE;
}

 
void showColorOnLed(int ledIndex, Color color) {
  uint32_t c;
  switch (color) {
    case BLUE:   c = strip.Color(0, 0, 255); break;
    case PURPLE: c = strip.Color(128, 0, 128); break;
    case ORANGE: c = strip.Color(255, 80, 0); break;
    case GREEN:  c = strip.Color(0, 255, 0); break;
    default:     c = 0;
  }
  strip.setPixelColor(ledIndex, c);
  strip.show();
}

 
void errorFeedback() {
  for (int i = 0; i < 3; i++) {
    analogWrite(BUZZER_PIN, 127);  // Włącz buzzer
    for (int j = 0; j < LED_COUNT; j++) {
      strip.setPixelColor(j, strip.Color(255, 0, 0));
    }
    strip.show();
    delay(200);

 
    analogWrite(BUZZER_PIN, 0);  // Wyłącz buzzer
    strip.clear();
    strip.show();
    delay(200);
  }
}

 
void startupAnimation() {
  // Zapalaj diody po kolei na biało
  for (int i = 0; i < LED_COUNT; i++) {
    strip.setPixelColor(i, strip.Color(255, 255, 255));
    strip.show();
    delay(150);
  }

 
  // Długi dźwięk startowy
  analogWrite(BUZZER_PIN, 127);
  delay(800);
  analogWrite(BUZZER_PIN, 0);

 
  strip.clear();
  strip.show();
}
Pliki_projektu
Schemat
Youtube
Tagi
#kolory #refleks #LED #szybkość #dioda