/*
Wokwi | projects & Wokwi | questions
Wide Game Bomb Sim Box & Help with timer key pad coding &
Help with timer keypad code Wide Game Sim Box
AHARRIS22 OP — 9/9/24 at 4:26 AM
Hi I M working on a bomb sim for my Explorer Scouts.
I have partly got it working but I would like to add the following.
-Set the timer for the game at the start before setting the code.
if the code is entered incorrectly then the timer to reduce by 30s
(3 try’s then it’s activates)
Here is the link to my project:
https://wokwi.com/projects/408486978717258753
Any help would be appreciated thanks
A = All clear, B = Time clear, C = Pass clear, D = Detonate
*/
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include "pitches.h"
// user constants
const unsigned long CNT_DOWN_TIME = 1000;
const unsigned long LED_CYCLE_TIME = 100;
const int CODE_LENGTH = 4;
const int PENALTY = 30;
// pin definitions
const int BUZZ_PIN = A1;
const int RELAY_PIN = A0;
const int LED_PINS[] = {3, 4, 5}; // red, yel, grn
// Keypad setup
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {13, 12, 11, 10};
byte colPins[COLS] = {9, 8, 7, 6};
// timer variables
unsigned long prevCntTime = 0;
unsigned long prevLedTime = 0;
// variables for password entry
char code[CODE_LENGTH + 1]; // user input
char userCode[CODE_LENGTH + 1]; // user password
char* passCode; // system password
// system var
long defuseTime = 0; // number of seconds
bool isReset = false;
LiquidCrystal_I2C lcd(0x27, 16, 2);
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void allReset() {
code[0] = '\0';
userCode[0] = '\0';
passCode[0] = '\0';
defuseTime = 0;
isReset = true;
digitalWrite(RELAY_PIN, LOW);
noTone(BUZZ_PIN);
// get defuse time
defuseTime = getTime();
// get unlock code
passCode = getCode();
// init LCD
initTimerDisplay();
}
void userCodeError() {
static int errCount = 0;
Serial.println("Code <ERROR>");
defuseTime = defuseTime - PENALTY;
tone(BUZZ_PIN, NOTE_A3, 500);
errCount++;
if (errCount == 3) {
errCount = 0;
lcd.clear();
isReset = false;
detonate();
}
}
void detonate() { // do crazy detonated stuff here
Serial.println("BOOM!");
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("Device");
lcd.setCursor (0, 1);
lcd.print("***DETONATED!***");
digitalWrite(RELAY_PIN, HIGH);
tone(BUZZ_PIN, NOTE_A2);
while (!isReset) {
char cmd = getKeys();
ledCycle();
}
}
void disarmed() { // do "you win!" here
Serial.println("Code <Match>");
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("Weapon");
lcd.setCursor(3, 1);
lcd.print("*DISARMED*");
tone(BUZZ_PIN, NOTE_D7, 1000);
digitalWrite(LED_PINS[2], HIGH);
delay(3000);
lcd.clear();
lcd.setCursor(6, 0);
lcd.print("Core");
lcd.setCursor(3, 1);
lcd.print("Power Down");
delay(3000);
digitalWrite(LED_PINS[2], LOW);
digitalWrite(LED_PINS[0], HIGH);
while (!isReset) {
char cmd = getKeys();
}
}
char getKeys() {
char key = keypad.getKey();
if (key != NO_KEY) {
// key press feedback
tone(BUZZ_PIN, NOTE_D7, 30);
digitalWrite(LED_PINS[0], HIGH);
delay(20);
digitalWrite(LED_PINS[0], LOW);
if (key == '*') {
Serial.println("Entry reset");
}
else if (key == '#') {
Serial.println("Enter");
}
else if (key == 'A') {
Serial.println("All reset");
allReset();
}
else if (key == 'B') {
Serial.println("Time reset");
}
else if (key == 'C') {
Serial.println("Code reset");
}
else if (key == 'D') {
Serial.println("Detonate");
detonate();
} else {
// digit - display value in calling function
//lcd.print(key);
}
}
return key;
}
long getTime() {
char defuseInput[6];
int index = 0;
int posIndex = 4;
long defuse = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set defuse time:");
lcd.setCursor(4, 1);
lcd.print(" : : ");
lcd.setCursor(4, 1);
lcd.blink();
while (index < 6) {
char key = getKeys();
if (key != '\0') {
if (key == '*') {
lcd.setCursor(posIndex - 1, 1);
lcd.print('*');
lcd.setCursor(posIndex - 1, 1);
index--;
} else {
defuseInput[index] = key;
lcd.print(key);
//Serial.print(key);
posIndex++;
if (index == 1 || index == 3) {
lcd.print(':');
posIndex++;
}
index++;
}
if (index == 6) {
int t10Hour = int(defuseInput[0] - 48);
int t01Hour = int(defuseInput[1] - 48);
defuse = defuse + (t10Hour * 36000) + (t01Hour * 3600);
int t10Min = int(defuseInput[2] - 48);
int t01Min = int(defuseInput[3] - 48);
defuse = defuse + (t10Min * 600) + (t01Min * 60);
int t10Sec = int(defuseInput[4] - 48);
int t01Sec = int(defuseInput[5] - 48);
defuse = defuse + (t10Sec * 10) + t01Sec;
}
}
}
lcd.noBlink();
lcd.setCursor(0, 0);
lcd.print(" Timer set to ");
Serial.print("Defuse time: ");
//Serial.println(defuse);
writeTimer(defuse, true); // formats seconds
delay(2000);
return defuse;
}
char* getCode() {
int index = 0;
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Set password:");
lcd.setCursor(6, 1);
lcd.blink();
while (index < CODE_LENGTH) {
char key = getKeys();
if (key != '\0') {
code[index] = key;
lcd.print(key);
//Serial.print(key);
index++;
}
}
code[CODE_LENGTH] = '\0';
lcd.noBlink();
lcd.setCursor(0, 0);
lcd.print("Passcode set to ");
Serial.print(" Pass code: ");
Serial.println(code);
delay(2000);
return code;
}
void initTimerDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Time remaining ");
}
void ledCycle() {
static int ledState = LOW;
static int ledIdx = 0;
if (millis() - prevLedTime >= LED_CYCLE_TIME) {
prevLedTime = millis();
ledState = !ledState;
digitalWrite(LED_PINS[ledIdx], ledState);
if (ledState == LOW) ledIdx++;
if (ledIdx == 3) ledIdx = 0;
}
}
void timer() {
if (millis() - prevCntTime >= CNT_DOWN_TIME) {
prevCntTime = millis();
tone(BUZZ_PIN, NOTE_C8, 100);
digitalWrite(LED_PINS[1], HIGH);
delay(50);
digitalWrite(LED_PINS[1], LOW);
writeTimer(defuseTime, false);
defuseTime--;
}
}
void writeTimer(long numSecs, bool serial) {
char timeBuff[16];
int tHour = (numSecs / 3600);
int tMin = (numSecs / 60) % 60;
int tSec = numSecs % 60;
snprintf(timeBuff, 16, "%02d:%02d:%02d", tHour, tMin, tSec);
lcd.setCursor(4, 1);
lcd.print(timeBuff);
if (serial) {
Serial.println(timeBuff);
}
}
void getUserCode() {
static int userIdx = 0;
char key = getKeys();
if (key != '\0') {
userCode[userIdx] = key;
userIdx++;
if (userIdx == CODE_LENGTH) {
userIdx = 0;
Serial.print("User code: ");
Serial.println(userCode);
if (strcmp(userCode, passCode) == 0) {
disarmed();
} else {
userCodeError();
}
}
}
}
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(BUZZ_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
for (int ledCnt = 0; ledCnt < 3; ledCnt++) {
pinMode(LED_PINS[ledCnt], OUTPUT);
}
Serial.println("System starting\n");
// splash screen
lcd.setCursor(2, 0);
lcd.print("Defuse Timer");
lcd.setCursor(5, 1);
lcd.print("V1.00");
delay(2000);
// get defuse time
defuseTime = getTime();
// get unlock code
passCode = getCode();
// init LCD
initTimerDisplay();
// setup complete message
Serial.println("System initialized\n");
}
void loop() {
timer();
if (defuseTime < 0 ) {
delay(500);
isReset = false;
lcd.clear();
detonate();
}
getUserCode();
}