#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_NeoPixel.h>
// Διαστάσεις OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Λωρίδα NeoPixel (5 LED στο pin 25)
#define LED_PIN 25
#define NUM_LEDS 5
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Buzzer στο pin 5
#define BUZZER_PIN 5
// Touch buttons (μόνο οι αριθμοί των pins)
#define TOUCH_1 12
#define TOUCH_2 13
#define TOUCH_3 14
#define TOUCH_4 15
const int touchPins[] = {TOUCH_1, TOUCH_2, TOUCH_3, TOUCH_4};
const int ledIndex[] = {4, 3, 2, 1}; // Αντιστοίχηση touch pin → LED
uint32_t ledColor[] = {
strip.Color(100, 0, 0), // Κόκκινο
strip.Color(0, 100, 0), // Πράσινο
strip.Color(0, 0, 100), // Μπλε
strip.Color(100, 100, 0) // Κίτρινο
};
// Νότες (συχνότητες)
#define NOTE_G3 196
#define NOTE_A3 220
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_E4 330
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_C2 65
#define NOTE_G2 98
// Μεταβλητές παιχνιδιού
int turn = 0;
int randomArray[50];
int inputArray[50];
int highscore = 0;
int myScore = 0;
// Μελωδίες
int startTune[] = {NOTE_E4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_G4};
int startDurations[] = {100, 200, 100, 200, 100, 400};
int failTune[] = {NOTE_G2, NOTE_C2};
int failDurations[] = {300, 300};
void playTone(int frequency, int duration) {
if (frequency > 0) {
tone(BUZZER_PIN, frequency, duration);
}
delay(duration);
}
// ------------------------------------------------------------
// Έλεγχος LED
// ------------------------------------------------------------
void setLED(int idx, uint32_t color) {
if (idx >= 0 && idx < NUM_LEDS) {
strip.setPixelColor(idx, color);
strip.show();
}
}
void allLEDs(uint32_t color) {
for (int i = 0; i < NUM_LEDS; i++) strip.setPixelColor(i, color);
strip.show();
}
void ledsOff() {
allLEDs(strip.Color(0, 0, 0));
}
#define TOUCH_THRESHOLD 500 // Κατώφλι πατήματος
bool isTouchPressed(int pin) {
return touchRead(pin) < TOUCH_THRESHOLD;
}
void fail() {
noTone(BUZZER_PIN);
// Αναβόσβημα και ήχος λάθους
for (int i = 0; i < 2; i++) {
allLEDs(strip.Color(50, 50, 50));
playTone(failTune[0], failDurations[0]);
ledsOff();
playTone(failTune[1], failDurations[1]);
}
// Εμφάνιση αποτελεσμάτων στην OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("High: ");
display.println(highscore);
display.setCursor(0, 16);
display.print("You: ");
display.println(myScore);
display.display();
delay(2000);
// Αναμονή για πάτημα οποιουδήποτε κουμπιού (touch)
display.clearDisplay();
display.setCursor(0, 0);
display.println("Press any");
display.setCursor(0, 16);
display.println("to restart");
display.display();
bool anyPressed = false;
while (!anyPressed) {
for (int i = 0; i < 4; i++) {
if (isTouchPressed(touchPins[i])) {
anyPressed = true;
break;
}
}
// Αναβόσβημα LED εν αναμονή
allLEDs(strip.Color(20, 20, 20));
delay(100);
ledsOff();
delay(100);
}
delay(500); // Debounce μετά το πάτημα
turn = 0;
myScore = 0;
display.clearDisplay();
}
void input() {
static unsigned long lastPressTime = 0;
static int lastButton = -1;
for (int i = 0; i <= turn; ) {
for (int b = 0; b < 4; b++) {
if (isTouchPressed(touchPins[b])) {
if (millis() - lastPressTime < 300 && lastButton == b) {
continue;
}
lastPressTime = millis();
lastButton = b;
// Άναμμα LED και ήχος
setLED(ledIndex[b], ledColor[b]);
playTone( (b == 0) ? NOTE_G3 :
(b == 1) ? NOTE_A3 :
(b == 2) ? NOTE_B3 : NOTE_C4, 100);
delay(200); // Χρόνος που μένει το LED αναμμένο
setLED(ledIndex[b], strip.Color(0, 0, 0));
delay(250); // Μικρή παύση μετά
inputArray[i] = b + 1; // 1..4
if (inputArray[i] != randomArray[i]) {
fail();
return;
}
i++;
if (i > turn) break;
}
}
}
turn++;
myScore = turn;
if (myScore > highscore) highscore = myScore;
}
void setup() {
Serial.begin(115200);
// Οθόνη OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("OLED not found");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(" 1o EPAL SYKEON");
display.setCursor(0, 16);
display.println("4LED MEMORY GAME");
display.display();
// NeoPixel
strip.begin();
ledsOff();
randomSeed(analogRead(0));
// Μελωδία έναρξης
for (int i = 0; i < 6; i++) {
playTone(startTune[i], startDurations[i]);
if (i == 0 || i == 2) setLED(ledIndex[0], ledColor[0]);
if (i == 1 || i == 3) setLED(ledIndex[1], ledColor[1]);
if (i == 4 || i == 5) setLED(ledIndex[2], ledColor[2]);
delay(25);
ledsOff();
}
delay(1000);
display.clearDisplay();
}
void loop() {
// Εισαγωγή νέου γύρου (προαιρετικά αναβοσβήνουν όλα)
for (int i = 0; i < 3; i++) {
allLEDs(strip.Color(50, 50, 50));
playTone(NOTE_A4, 100);
ledsOff();
delay(200);
}
delay(500);
// Εμφάνιση σκορ
display.clearDisplay();
display.setCursor(0, 0);
display.print("You: ");
display.println(myScore);
display.setCursor(0, 16);
display.print("High: ");
display.println(highscore);
display.display();
delay(1000);
// Δημιουργία νέας τυχαίας τιμής
randomArray[turn] = random(1, 5);
// Παρουσίαση της ακολουθίας
for (int i = 0; i <= turn; i++) {
int val = randomArray[i];
setLED(ledIndex[val-1], ledColor[val-1]);
playTone( (val==1)?NOTE_G3 : (val==2)?NOTE_A3 : (val==3)?NOTE_B3 : NOTE_C4, 100);
delay(400);
ledsOff();
delay(100);
}
// Λήψη εισόδου
input();
delay(500);
}