#include <Keypad.h>
#include <LiquidCrystal_I2C.h> //library for I2c LCD
#define I2C_ADDR 0x27
/* ======== USER SETTINGS =========== */
// special effects
#define ENABLE_TICK_SOUND true
// Define other pin connections
#define UP_BUTTON 2
#define DOWN_BUTTON 3
#define BUZZER 4
int armCode = 1234;
int disarmCode = 4567;
int duration=30; // Duration in seconds
int isArmed=0, enteredVal=0, instant_detonation=0;
String dispString="";
const byte ROWS = 4, COLS = 3; //four rows, three columns
char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
byte rowPins[ROWS] = {8, 7, 6, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A3, A2, A1}; //connect to the column pinouts of the keypad
//Create an object of keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
/*initializing 16x2 LCD at the pre defined I2C address */
LiquidCrystal_I2C lcd(I2C_ADDR, 16, 2);
void setup() {
Serial.begin(9600);
pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
lcd.init();
lcd.backlight();
lcd.clear();
ShowTime(duration);
}
void loop() {
char key = keypad.getKey();// Read the key
// Function will checks for time change buttons and only return
// when start button pressed
if(isArmed==0) WaitForStart(key);
// Start the duration timer
if(isArmed==1) TimeDuration(key);
}
void WaitForStart(char key) {
if (digitalRead(UP_BUTTON) == LOW) {
if (duration < 60) duration++;
else duration += 10;
ShowTime(duration);
delay(250);
}
if (digitalRead(DOWN_BUTTON) == LOW) {
if (duration > 60) duration -= 10;
else if(duration > 0) duration--;
ShowTime(duration);
delay(250);
}
if ((key - '0' >= 0) && (key - '0' <= 9)) {
lcd.clear();
enteredVal = (enteredVal * 10) + (key - '0');
dispString += "*";
lcd.setCursor(6, 0); lcd.print(dispString);
if(dispString.length()>=4){
if(enteredVal== armCode) {
isArmed = 1;
tone(BUZZER, 1200, 550);
lcd.clear();
lcd.print(" Bomb Armed ");
delay(1000);
lcd.clear();
}
else{
lcd.clear();
lcd.print(" Invalid Code ");
tone(BUZZER, 600, 250);
delay(3000);
lcd.clear();
}
dispString="";
enteredVal=0;
ShowTime(duration);
}
}
}
void TimeDuration(char key) {
// While loop will continue until time up
unsigned long startTime = millis(), oneSecStartTime = millis();
unsigned long timer = 1000ul * duration;
// Repeatedly check if time is up
while (isArmed && !instant_detonation && ((millis() - startTime) <= timer)) {
// Calculate time elapsed in seconds
int elapsed = int((millis() - startTime) / 1000);
// Only start to display countdown after 3 seconds
if ((millis() - oneSecStartTime) >= 1000) {
ShowTime(duration - elapsed);
tone(BUZZER, 1300, 150);
oneSecStartTime=millis();
}
key = keypad.getKey();
if ((key - '0' >= 0) && (key - '0' <= 9)) {
lcd.clear();
enteredVal = (enteredVal * 10) + (key - '0');
dispString += "*";
lcd.setCursor(6, 0); lcd.print(dispString);
if(dispString.length()>=4){
if(enteredVal== disarmCode) {
isArmed = 0;
tone(BUZZER, 1200, 550);
lcd.clear();
lcd.print(" Bomb Disarmed ");
delay(1000);
lcd.clear();
}
else{
lcd.clear();
lcd.print(" Invalid Code ");
lcd.setCursor(0,1);
lcd.print("Bomb Detonating");
tone(BUZZER, 600, 250);
delay(3000);
instant_detonation=1;
lcd.clear();
}
dispString="";
enteredVal=0;
ShowTime(duration);
}
}
}
if(isArmed){
lcd.clear();
if(!instant_detonation) lcd.print(" Time is Up ");
// Time up
tone(BUZZER, 250, 500);
delay(500);
tone(BUZZER, 125, 500);
delay(500);
tone(BUZZER, 250, 500);
delay(500);
tone(BUZZER, 125, 500);
delay(500);
tone(BUZZER, 250, 500);
delay(500);
tone(BUZZER, 125, 500);
delay(500);
tone(BUZZER, 250, 500);
}
//display.clear();
//display.setSegments(seg_end);
// Wait 5 seconds and reset display
delay(5000);
// Show duration for next player
isArmed=0;
instant_detonation=0;
ShowTime(duration);
}
void ShowTime(int value) {
static int lastTime;
// Update the display if time has changed
if (1){//lastTime != value) {
lastTime = value;
int iMinutes = value / 60;
int iSeconds = value - (iMinutes * 60);
// Show on LCD display
lcd.setCursor(6,1);
if(iMinutes<10) lcd.print("0");
lcd.print(iMinutes);
lcd.print(":");
if(iSeconds<10) lcd.print("0");
lcd.print(iSeconds);
lcd.setCursor(0,0);
if(isArmed) lcd.print(" Bomb Armed ");
else lcd.print(" Not Armed ");
}
}