#include <Keypad.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#define BUZZER1 8
#define BUZZER2 9
#define LED_GREEN 22
#define LED_RED 24
#define INPUT_PIN1 25
#define INPUT_PIN2 27
#define INTERRUPT_PIN 29
#define START_PIN 23
#define MPU6050_ADDR 0x68
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const byte ROW_NUM = 4;
const byte COL_NUM = 3;
char keys[ROW_NUM][COL_NUM] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte pin_rows[ROW_NUM] = {41, 51, 49, 45};
byte pin_column[COL_NUM] = {43, 39, 47};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COL_NUM);
const int movementThreshold = 3000; // Adjust this threshold as needed
const int ledPin = 35;
bool countdownCompleted = false;
bool bombArmed = false;
bool bombDetonated = false; // Added this line
bool bombDefused = false;
bool startDetected = false;
unsigned long inputHighStartTime = 0; // Variable to keep track of when the input pins first went HIGH
String enteredCode = "";
int enteredNumber = 0; // Global variable to store the entered number
void setup() {
digitalWrite(35, HIGH);
// Initialize the LCD with 16 columns and 2 rows
lcd.begin(16, 2);
// Clear the LCD
lcd.clear();
// Print "Input Time:" on the top line (row 0)
lcd.setCursor(0, 0);
lcd.print("Input Time:");
char number[4] = ""; // Array to hold the 3-digit number plus null terminator
byte index = 0; // Index to keep track of the number of digits entered
// Continue reading keys until '#' is pressed
while (true) {
char key = keypad.getKey(); // Read the key pressed on the keypad
if (key) {
if (isDigit(key) && index < 3) {
lcd.setCursor(12 + index, 0);
lcd.print(key);
number[index] = key;
index++;
} else if (key == '*' && index > 0) {
index--;
lcd.setCursor(12 + index, 0);
lcd.print(' ');
} else if (key == '#' && index > 0) {
number[index] = '\0'; // Null-terminate the string
enteredNumber = atoi(number); // Convert the string to an integer
break;
}
}
}
Serial.begin(115200);
Wire.begin();
// Initialize MPU-6050
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // Wake up the sensor
Wire.endTransmission(true);
pinMode(BUZZER1, OUTPUT);
pinMode(BUZZER2, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
digitalWrite(LED_GREEN, LOW);
pinMode(INPUT_PIN1, INPUT);
pinMode(INPUT_PIN2, INPUT);
pinMode(INTERRUPT_PIN, INPUT);
pinMode(START_PIN, INPUT);
pinMode(35, OUTPUT);
digitalWrite(35, LOW);
lcd.clear();
lcd.print("Detecting Inputs");
}
void loop() {
// Wait for START_PIN to go HIGH only if it hasn't been detected before
while (!startDetected) {
if (digitalRead(23) == HIGH) {
startDetected = true; // Input has been detected; code will now start
digitalWrite(35, HIGH); // Set pin 35 to HIGH
}
// Optional delay to reduce CPU usage while waiting
delay(50);
}
if (digitalRead(INPUT_PIN1) == HIGH && digitalRead(INPUT_PIN2) == HIGH && !countdownCompleted && !bombDefused) {
lcd.setCursor(0, 1);
lcd.print("Arming: ");
for (int i = 5; i > 0; i--) {
if (digitalRead(INPUT_PIN1) != HIGH || digitalRead(INPUT_PIN2) != HIGH) {
lcd.setCursor(0, 1);
lcd.print(" ");
break;
}
digitalWrite(BUZZER1, HIGH); // turns the buzzer ON
delay(30); // waits for 30 milliseconds while the buzzer is ON
digitalWrite(BUZZER1, LOW); // turns the buzzer OFF
lcd.setCursor(8, 1);
lcd.print(i);
delay(1000);
}
if (digitalRead(INPUT_PIN1) == HIGH && digitalRead(INPUT_PIN2) == HIGH) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Code:");
countdownCompleted = true;
}
}
if(countdownCompleted && !bombArmed) {
char key = keypad.getKey();
if (key) {
digitalWrite(BUZZER1, HIGH); // turns the buzzer ON
delay(30); // waits for 30 milliseconds while the buzzer is ON
digitalWrite(BUZZER1, LOW); // turns the buzzer OFF
if (key == '#') {
if (enteredCode == "123456") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Arm Bomb?");
lcd.setCursor(0, 1);
lcd.print("Countdown: ");
digitalWrite(LED_GREEN, HIGH);
bombArmed = true;
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Incorrect Code");
delay(100);
digitalWrite(BUZZER1, HIGH); // turns the buzzer ON
delay(30); // waits for 30 milliseconds while the buzzer is ON
digitalWrite(BUZZER1, LOW); // turns the buzzer OFF
delay(100);
digitalWrite(BUZZER1, HIGH); // turns the buzzer ON
delay(30); // waits for 30 milliseconds while the buzzer is ON
digitalWrite(BUZZER1, LOW); // turns the buzzer OFF
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter Code:");
enteredCode = "";
}
} else if (key == '*') {
if (enteredCode.length() > 0) {
enteredCode = enteredCode.substring(0, enteredCode.length() - 1);
}
} else if (enteredCode.length() < 6) {
enteredCode += key;
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(enteredCode);
}
}
if (bombArmed) {
lcd.setCursor(0, 1);
lcd.print("Countdown: ");
for (int i = 15; i > 0; i--) {
if(digitalRead(INTERRUPT_PIN) == HIGH) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Bomb Armed");
digitalWrite(LED_GREEN, LOW);
bombArmed = false;
lcd.setCursor(0, 1);
lcd.print("Countdown: ");
unsigned long lastBeepTime = millis();
unsigned long lastSecond = millis();
int countdown = enteredNumber;
float beepInterval = 1000; // initial delay in ms
unsigned long defuseStartTime = 0;
bool enterCodeTriggered = false;
String defuseCode = ""; // To store defuse code input
while (countdown > -1) {
int16_t accelerometerValues[3];
readAccelerometer(accelerometerValues);
// Calculate the total acceleration by summing up the absolute values of each axis
float totalAcceleration = abs(accelerometerValues[0]) + abs(accelerometerValues[1]) + abs(accelerometerValues[2]);
Serial.print("Total acceleration: ");
Serial.println(totalAcceleration);
if (totalAcceleration > movementThreshold) {
countdown = 0;
} else
if (countdown < 10) { // Check if countdown is less than 10
lcd.setCursor(12, 1); // Go to slot 13 on the LCD
lcd.print(" "); // Clear slot 13 by printing a blank character
}
if ((countdown < 100) && (defuseStartTime < 5000))
{ // Check if countdown is less than 10
lcd.setCursor(13, 1); // Go to slot 13 on the LCD
lcd.print(" "); // Clear slot 13 by printing a blank character
}
if ((countdown < 99) && (defuseStartTime > 5000))
{ // Check if countdown is less than 10
lcd.setCursor(15, 1); // Go to slot 13 on the LCD
lcd.print(" "); // Clear slot 13 by printing a blank character
}
if(digitalRead(INPUT_PIN1) == HIGH && digitalRead(INPUT_PIN2) == HIGH && !enterCodeTriggered) {
if(inputHighStartTime == 0) { // Check if this is the moment the pins first went HIGH
inputHighStartTime = millis(); // Store the current time
tone(BUZZER2, 500, 30); // Play a beep on the second buzzer for 30ms at 500Hz
delay(30); // Wait for the beep to finish
} else if(millis() - inputHighStartTime >= 1000) { // Check if the pins have been HIGH for at least 1000 ms
tone(BUZZER2, 500, 30); // Play a beep on the second buzzer for 30ms at 500Hz
delay(30); // Wait for the beep to finish
inputHighStartTime = 0; // Reset the start time
}
if(defuseStartTime == 0) {
defuseStartTime = millis();
}
else if(millis() - defuseStartTime >= 5000) {
lcd.setCursor(0, 0);
lcd.print("Enter Code: ");
defuseCode = ""; // Clear defuseCode when defusing is triggered
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the line
lcd.setCursor(13, 1);
lcd.print(countdown);
enterCodeTriggered = true;
} else {
lcd.setCursor(0, 0);
lcd.print("Defusing Bomb ");
lcd.setCursor(11, 1);
lcd.print(countdown);
}
} else if(!enterCodeTriggered) {
defuseStartTime = 0;
inputHighStartTime = 0; // Reset the start time when the pins are not HIGH
lcd.setCursor(0, 0);
lcd.print("Bomb Armed ");
lcd.setCursor(11, 1);
lcd.print(countdown);
}
// Get key from keypad and display
if (enterCodeTriggered) {
char defuseKey = keypad.getKey();
if (defuseKey) {
// If key is '#', check the entered code
if(defuseKey == '#') {
// Check if the entered code is correct
if (defuseCode == "123456") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Code Accepted");
lcd.setCursor(0, 1);
lcd.print("Bomb Defused ");
lcd.setCursor(13, 1);
lcd.print(countdown + 1); // Print last known countdown time + 1
bombArmed = false;
bombDefused = true; // The bomb has been defused
countdownCompleted = false; // Reset the countdownCompleted variable
enteredCode = ""; // Clear the entered code
// If the code is correct, play two 1500Hz beeps for 30ms each,
// with a delay of 100ms between them. Also flash the green LED twice.
for (int i = 0; i < 3; i++) {
tone(BUZZER1, 1500, 30);
digitalWrite(LED_GREEN, HIGH);
delay(30);
digitalWrite(LED_GREEN, LOW);
if (i < 2) { // Do not delay after the last beep and flash
delay(60);
}
}
return; // Exit the loop and return from the function
} else {
lcd.setCursor(0, 0);
lcd.print("Incorrect Code ");
defuseCode = ""; // Reset defuseCode
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the line
// If the code is incorrect, play two 500Hz beeps for 30ms each,
// with a delay of 100ms between them.
tone(BUZZER2, 500, 30);
delay(100);
tone(BUZZER2, 500, 30);
}
tone(BUZZER2, 500, 30); // Play a 500Hz beep for 30ms on the second buzzer
}
// If key is '*', remove the last character
else if(defuseKey == '*') {
if (defuseCode.length() > 0) {
defuseCode.remove(defuseCode.length() - 1);
}
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the line
lcd.setCursor(0, 1);
lcd.print(defuseCode);
lcd.setCursor(13, 1);
lcd.print(countdown);
tone(BUZZER2, 500, 30); // Play a 500Hz beep for 30ms on the second buzzer
}
// If key is a number, print it
else if(defuseKey >= '0' && defuseKey <= '9' && defuseCode.length() < 6) {
defuseCode += defuseKey; // Append new digit to defuseCode
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the line
lcd.setCursor(0, 1);
lcd.print(defuseCode);
lcd.setCursor(13, 1);
lcd.print(countdown);
tone(BUZZER2, 500, 30); // Play a 500Hz beep for 30ms on the second buzzer
}
}
}
if(millis() - lastBeepTime >= beepInterval) {
digitalWrite(BUZZER1, HIGH); // turns the buzzer ON
delay(30); // waits for 30 milliseconds while the buzzer is ON
digitalWrite(BUZZER1, LOW); // turns the buzzer OFF
digitalWrite(LED_RED, HIGH); // Turn on the LED
lastBeepTime = millis();
beepInterval = map(countdown, 90, 0, 1000, 100); // Remap the interval based on the remaining countdown time.
} else {
digitalWrite(LED_RED, LOW); // Turn off the LED
}
if(millis() - lastSecond >= 1000){
if (enterCodeTriggered) {
lcd.setCursor(13, 1);
lcd.print(" "); // Clear previous time
lcd.setCursor(13, 1);
lcd.print(countdown);
} else {
lcd.setCursor(11, 1);
lcd.print(" "); // Clear previous time
lcd.setCursor(11, 1);
lcd.print(countdown);
}
countdown--;
lastSecond = millis();
}
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Bomb Detonated");
tone(BUZZER1, 1500, 3000); // Play the first buzzer for 3 seconds at 1500Hz
digitalWrite(LED_RED, HIGH); // Turn on the LED for 3 seconds
delay(3000);
digitalWrite(LED_RED, LOW); // Turn off the LED
bombDetonated = true; // Added this line
return;
}
lcd.setCursor(11, 1);
if (i < 10) {
lcd.print(" ");
}
lcd.print(i);
delay(1000);
}
}
if(bombDetonated || bombDefused) {
// Check for reset
if(digitalRead(START_PIN) == LOW) {
if(digitalRead(INTERRUPT_PIN) == LOW)
resetGame();
}
}
}
void resetGame() {
bombArmed = false;
bombDetonated = false;
bombDefused = false;
countdownCompleted = false;
startDetected = false;
enteredCode = "";
lcd.clear();
lcd.print("Detecting Inputs");
// Set LEDs to initial state
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
// Ensure no sounds are being played
noTone(BUZZER1);
noTone(BUZZER2);
digitalWrite(35, LOW);
}
void readAccelerometer(int16_t* values) {
Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B); // Starting register for accelerometer data
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_ADDR, 6, true);
for (int i = 0; i < 3; ++i) {
values[i] = Wire.read() << 8 | Wire.read();
}
}