#include <Adafruit_GFX.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Tone.h>
// Pin Definitions
#define SCL_PIN A1
#define SDA_PIN A0
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define RST_PIN 9
#define SS_PIN 10
#define BUZZER_PIN 5
#define RED_PIN 2
#define ORANGE_PIN 3
#define BLUE_PIN 4
#define YELLOW_PIN 6
#define TOUCH_SENSOR_PIN 7 // Connect KY-036 Touch Sensor to this pin
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
// MFRC522 setup
MFRC522 mfrc522(SS_PIN, RST_PIN);
// Game States
enum State {
IDLE,
GAME_RUNNING,
GAME_OVER_DISPLAY,
};
State currentState = IDLE;
unsigned long lastActionTime = 0;
const unsigned long actionInterval = 10000; // 10 seconds per shape
int scoreX = 0;
int scoreH = 0;
int scoreA = 0;
bool isTouchSensorTouched = false;
bool isGameRunning = false;
bool isFirstTouch = true;
bool isCountdownRestarting = false;
unsigned long gameStartTime = 0;
const unsigned long gameDuration = 30000; // 30 seconds per game
unsigned long countdownStartTime = 0;
byte currentShapeUID[4];
char currentShape; // Declare currentShape globally
// Shapes and their corresponding RFID UIDs
char shapes[] = {'X', 'H', 'A'};
byte shapeUIDs[][4] = {
{0x93, 0x33, 0x63, 0xF5},
{0x03, 0xF6, 0x0B, 0xF5},
{0xC3, 0x53, 0x52, 0xF5}
};
Tone buzzer;
int melodyPins[] = {8, 11, 12}; // Pins for generating melody tones
int twinkleMelody[] = {
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4,
};
int twinkleDurations[] = {
250, 250, 250, 250, 250, 250
};
int happyBirthdayMelody[] = {
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_F4, NOTE_E4,
};
int happyBirthdayDurations[] = {
200, 200, 400, 200, 200, 200
};
int janaGanaManaMelody[] = {
NOTE_E5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5
};
int janaGanaManaDurations[] = {
250, 250, 250, 250, 250
};
char previousShape = ' '; // Initialize previousShape to an empty character
void setup(void) {
Serial.begin(115200);
Serial.println("Hello!");
pinMode(SCL_PIN, OUTPUT);
pinMode(SDA_PIN, OUTPUT);
digitalWrite(SCL_PIN, HIGH);
digitalWrite(SDA_PIN, HIGH);
Wire.begin();
SPI.begin();
mfrc522.PCD_Init();
pinMode(RED_PIN, OUTPUT);
pinMode(ORANGE_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
pinMode(YELLOW_PIN, OUTPUT);
buzzer.begin(BUZZER_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.println("Smart Puzzle Game");
display.println("for Kids");
display.display();
display.clearDisplay();
pinMode(TOUCH_SENSOR_PIN, INPUT); // Define TOUCH_SENSOR_PIN as an input
}
void controlLEDs(int red, int orange, int blue, int yellow) {
digitalWrite(RED_PIN, red);
digitalWrite(ORANGE_PIN, orange);
digitalWrite(BLUE_PIN, blue);
digitalWrite(YELLOW_PIN, yellow);
}
void playMelody(int shapeIndex) {
int *notes;
int *durations;
int numNotes;
switch (shapeIndex) {
case 0: // 'X'
notes = twinkleMelody;
durations = twinkleDurations;
numNotes = sizeof(twinkleMelody) / sizeof(twinkleMelody[0]);
break;
case 1: // 'H'
notes = happyBirthdayMelody;
durations = happyBirthdayDurations;
numNotes = sizeof(happyBirthdayMelody) / sizeof(happyBirthdayMelody[0]);
break;
case 2: // 'A'
notes = janaGanaManaMelody;
durations = janaGanaManaDurations;
numNotes = sizeof(janaGanaManaMelody) / sizeof(janaGanaManaMelody[0]);
break;
default:
return; // Invalid shapeIndex
}
for (int i = 0; i < numNotes; i++) {
int noteDuration = durations[i];
if (notes[i] != 0) {
buzzer.play(notes[i], noteDuration);
delay(noteDuration);
buzzer.stop();
} else {
delay(noteDuration);
}
delay(50);
}
}
void displayShape(char shape) {
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 10);
switch (shape) {
case 'X':
display.println("X");
break;
case 'H':
display.println("H");
break;
case 'A':
display.println("A");
break;
}
display.display();
}
void updateScore(int points) {
if (currentShape == 'X') {
scoreX += points;
} else if (currentShape == 'H') {
scoreH += points;
} else if (currentShape == 'A') {
scoreA += points;
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Score: ");
display.println((currentShape == 'X') ? scoreX : (currentShape == 'H') ? scoreH : scoreA);
display.display();
}
void displayTotalScore() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Game Ended");
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Total Score: ");
display.println(scoreX + scoreH + scoreA);
display.display();
delay(3000);
currentState = GAME_OVER_DISPLAY;
gameStartTime = millis();
isCountdownRestarting = false;
}
void startGame() {
scoreX = 0;
scoreH = 0;
scoreA = 0;
gameStartTime = millis();
countdownStartTime = millis();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Game Started");
display.display();
delay(1000);
isGameRunning = true;
isFirstTouch = false;
isCountdownRestarting = true;
getNextRandomShape(); // Use the new function to get a random shape
}
void stopGame() {
displayTotalScore();
isGameRunning = false;
}
void getNextRandomShape() {
char newShape;
do {
newShape = shapes[random(3)]; // Choose a random shape
} while (newShape == previousShape); // Repeat until it's different from the previous shape
previousShape = newShape; // Update the previousShape
int selectedMelody;
switch (newShape) {
case 'X':
selectedMelody = 0;
break;
case 'H':
selectedMelody = 1;
break;
case 'A':
selectedMelody = 2;
break;
}
memcpy(currentShapeUID, shapeUIDs[selectedMelody], 4); // Set the current shape's UID
currentShape = newShape; // Set the current shape
displayShape(currentShape);
controlLEDs(0, 0, 0, 0); // Turn off all LEDs
if (currentShape == 'X') {
controlLEDs(255, 0, 0, 0); // Red LED
playMelody(0); // Play melody for 'X'
} else if (currentShape == 'H') {
controlLEDs(0, 255, 0, 0); // Green LED
playMelody(1); // Play melody for 'H'
} else if (currentShape == 'A') {
controlLEDs(0, 0, 255, 0); // Blue LED
playMelody(2); // Play melody for 'A'
}
currentState = GAME_RUNNING;
lastActionTime = millis();
}
void displayGameInfo(unsigned long remainingTime, char shape, int currentScore) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Time Left: ");
display.println(remainingTime / 1000); // Convert to seconds
display.print("Shape: ");
display.println(shape);
display.print("Score: ");
display.println(currentScore);
display.display();
}
void loop(void) {
if (isGameRunning) {
unsigned long elapsedTime = millis() - gameStartTime;
unsigned long remainingTime = max(0, gameDuration - elapsedTime);
// Display time left, shape, and score for that shape
displayGameInfo(remainingTime, currentShape, (currentShape == 'X') ? scoreX : (currentShape == 'H') ? scoreH : scoreA);
// Check if the game has ended after 30 seconds
if (elapsedTime >= gameDuration) {
stopGame();
return; // Exit the loop early to avoid playing the buzzer and LEDs again
}
}
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
Serial.println("Found an RFID card!");
if (memcmp(mfrc522.uid.uidByte, currentShapeUID, 4) == 0) {
controlLEDs(0, 0, 0, 0); // Turn off all LEDs
buzzer.stop(); // Turn off the buzzer
if (currentShape == 'X') {
scoreX += 2;
} else if (currentShape == 'H') {
scoreH += 3;
} else if (currentShape == 'A') {
scoreA += 5;
}
// Proceed to the next shape immediately
getNextRandomShape(); // Use the new function to get a random shape
}
}
// Check if the KY-036 Touch Sensor is touched
if (digitalRead(TOUCH_SENSOR_PIN) == LOW) {
if (!isTouchSensorTouched) {
isTouchSensorTouched = true;
if (isFirstTouch) {
startGame();
} else if (currentState == GAME_OVER_DISPLAY && !isCountdownRestarting) {
startGame();
} else if (isGameRunning) {
stopGame();
}
}
} else {
isTouchSensorTouched = false;
}
}
Comments