#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h"
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Pins and components
#define REED_SWITCH_PIN 2
#define DHTPIN 3
#define BUTTON_PIN 4
#define DHTTYPE DHT22
#define LED_PIN 13
#define LED_PIN2 9
bool ledState;
DHT dht(DHTPIN, DHTTYPE);
unsigned long previousMillis = 0;
unsigned long previousMillisforLED = 0;
const long interval = 5000;
// Game variables
bool gameMode = false;
int dinoY = 48;
int obstacleX = 128;
bool isJumping = false;
int jumpHeight = 15;
int jumpCounter = 0;
int gravity = 2;
// Button timing
unsigned long buttonPressStart = 0;
unsigned long lastButtonPress = 0; // Track the last button press in game mode
const long gameTimeout = 8000; // 8-second timeout for inactivity
void setup() {
Serial.begin(9600);
dht.begin();
pinMode(REED_SWITCH_PIN, INPUT_PULLUP);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN2, OUTPUT);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.display();
}
void loop() {
unsigned long currentMillis = millis();
bool reedState = digitalRead(REED_SWITCH_PIN);
bool buttonState = digitalRead(BUTTON_PIN);
// If button is held for 4 seconds, toggle game mode
if (buttonState == LOW) {
if (buttonPressStart == 0) buttonPressStart = millis();
if (millis() - buttonPressStart >= 4000) {
gameMode = !gameMode; // Toggle game mode
buttonPressStart = 0;
display.clearDisplay();
display.display();
lastButtonPress = millis(); // Reset inactivity timer when entering game mode
}
} else {
buttonPressStart = 0;
}
if (gameMode && reedState == HIGH) {
runDinoGame(); // Run game if in game mode and garage is shut
} else {
displayGarageAndSensor(); // Display regular sensor info if not in game mode
}
// Turn off game if inactive for 8 seconds
if (gameMode && millis() - lastButtonPress >= gameTimeout) {
gameMode = false;
display.clearDisplay();
display.display();
}
}
// Function to display garage and temperature/humidity when button is pressed
void displayGarageAndSensor() {
unsigned long currentMillis = millis();
// Check garage state
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
bool reedState = digitalRead(REED_SWITCH_PIN);
if (reedState == LOW) {
display.clearDisplay();
display.setTextSize(2);
display.setCursor(0, 10);
display.println(" Garage");
display.println(" open");
display.display();
// Flash the external LED
if (millis() - previousMillisforLED >= 2000) {
previousMillisforLED = millis();
ledState = !ledState;
digitalWrite(LED_PIN2, ledState);
}
} else {
display.clearDisplay();
display.display();
digitalWrite(LED_PIN2, LOW);
digitalWrite(LED_PIN, LOW);
}
}
// Display temperature/humidity if button pressed and garage shut
if (reedState == HIGH && digitalRead(BUTTON_PIN) == LOW) {
float h = dht.readHumidity();
float t = dht.readTemperature();
display.clearDisplay();
if (isnan(h) || isnan(t)) {
display.setCursor(0, 10);
display.println("DHT read fail");
} else {
display.setTextSize(2);
display.setCursor(0, 10);
display.print("T: ");
display.print(t);
display.println(" C");
display.setCursor(0, 30);
display.print("H: ");
display.print(h);
display.println(" %");
}
display.display();
delay(6000);
}
}
// Dino game logic
void runDinoGame() {
display.clearDisplay();
// Handle jump
if (digitalRead(BUTTON_PIN) == LOW && !isJumping) {
isJumping = true;
jumpCounter = jumpHeight;
lastButtonPress = millis(); // Update last button press when button is pressed in game
}
if (isJumping) {
dinoY -= jumpCounter;
jumpCounter -= gravity;
if (dinoY >= 48) {
dinoY = 48;
isJumping = false;
}
}
// Move obstacle
obstacleX -= 3;
if (obstacleX < 0) obstacleX = 128;
// Draw dino and obstacle
display.fillRect(10, dinoY, 10, 10, SSD1306_WHITE); // Dino
display.fillRect(obstacleX, 48, 10, 10, SSD1306_WHITE); // Obstacle
// Check collision
if (obstacleX < 20 && obstacleX > 0 && dinoY > 38) {
display.clearDisplay();
display.setCursor(20, 30);
display.setTextSize(2);
display.println("Game Over!");
display.display();
delay(2000);
obstacleX = 128;
dinoY = 48;
}
display.display();
delay(50);
}