#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); // use correct address from I2C scanner
// Keypad
const byte ROWS = 4; //rows
const byte COLS = 3; //columns
byte rowPins[ROWS] = {1, 2, 42, 41}; // R1-R4
byte colPins[COLS] = {40, 39, 38}; // C1-C3
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// Create keypad object
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// LED
const int redLED = 6;
// Buzzer
const int buzzer = 7;
// variables
int gamemode = 1;
int preparationTime = 1;
int plantTime = 1;
int defuseTime = 1;
int plantMode = 0;
int plantHold = 0;
int plantCode = 0;
int defuseMode = 0;
int defuseHold = 0;
int defuseCode = 0;
bool bombPlanted = false;
//tones
const int enterToneFreq = 800;
const int enterBeepTime = 500;
const int removeToneFreq = 1000;
const int removeBeepTime = 200;
const int clickToneFreq = 1000;
const int clickBeepTime = 50;
//
const int scrollTextSpeed = 1200;
void setup() {
Serial.begin(115200);
Wire.begin(17, 18); // SDA=17, SCL=18
//LCD initialization
lcd.init();
lcd.backlight();
//LED
pinMode(redLED, OUTPUT); // Set pin as output
gamemodeSelection();
}
void loop() {
}
void gamemodeSelection(){
unsigned long lastScroll = 0;
bool showBomb = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Gamemode: ");
while(gamemode == 0){
char key = keypad.getKey();
if (key == '1') {
Serial.println("Bomb mode");
gamemode = 1;
break;
}
else if (key == '2'){
Serial.println("Dominator mode");
gamemode = 2;
break;
}
// Scroll text without blocking
if (millis() - lastScroll > scrollTextSpeed) { // 1.2 second interval
lastScroll = millis();
lcd.setCursor(0,1);
if (showBomb) {
lcd.print("Bomb: 1 ");
} else {
lcd.print("Detonator: 2 ");
}
showBomb = !showBomb;
}
}
preparation();
}
void preparation() {
String preparationString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Prep Time:");
lcd.setCursor(13, 1);
lcd.print("(s)");
lcd.setCursor(0, 1);
while(preparationTime == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Append digit to input string
preparationString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(preparationString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
preparationTime = preparationString.toInt();
Serial.println("Preparation Time:" + String(preparationTime));
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
preparation();
}
}
}
plantTimeSelection();
}
void plantTimeSelection() {
String gameTimeString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Time To Plant:");
lcd.setCursor(0, 1);
while (plantTime == 0){
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Append digit to input string
gameTimeString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(gameTimeString);
}
else if (key == '*') {
tone(buzzer, removeToneFreq);
delay(removeBeepTime);
noTone(buzzer);
// Convert to integer
plantTime = gameTimeString.toInt();
Serial.println("Time To Plant: " + String(plantTime));
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
}
}
}
defuseTimeSelection();
}
void defuseTimeSelection(){
String defuseTimeString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Time To Defuse:");
lcd.setCursor(0, 1);
//boom time
while(defuseTime == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Append digit to input string
defuseTimeString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(defuseTimeString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
defuseTime = defuseTimeString.toInt();
Serial.println("Time to defuse:" + String(defuseTime));
break;
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
defuseTimeSelection();
}
}
}
plantModeSelection();
}
void plantModeSelection(){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Plant Mode:");
lcd.setCursor(0, 1);
unsigned long lastScroll = 0;
bool showFirst = true;
while(plantMode == 0){
char key = keypad.getKey();
if (key == '1') {
Serial.println("plantMode: [Hold]");
plantMode = 1;
plantModeHold();
break;
}
else if (key == '2'){
Serial.println("plantMode: [Enter Code]");
plantMode = 2;
plantModeCode();
break;
}
// Scroll text without blocking
if (millis() - lastScroll > scrollTextSpeed) { // 1.2 second interval
lastScroll = millis();
lcd.setCursor(0,1);
if (showFirst) {
lcd.print("Hold: 1 ");
} else {
lcd.print("Enter code: 2 ");
}
showFirst = !showFirst;
}
}
}
void plantModeHold(){
String plantHoldString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hold Time:");
lcd.setCursor(13, 1);
lcd.print("(s)");
lcd.setCursor(0, 1);
while(plantHold == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Append digit to input string
plantHoldString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(plantHoldString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
defuseTime = plantHoldString.toInt();
Serial.println("Plant Hold:" + String(plantHold));
break;
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
plantModeHold();
}
}
}
defuseModeSelection();
}
void plantModeCode(){
String plantCodeString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Plant Digits:");
lcd.setCursor(11, 1);
lcd.print("(1-8)");
lcd.setCursor(0, 1);
while(plantCode == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '1' && key <= '8') {
// Append digit to input string
plantCodeString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(plantCodeString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
plantCode = plantCodeString.toInt();
Serial.println("Plant Digits:" + String(plantCodeString));
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
plantModeCode();
}
}
}
defuseModeSelection();
}
void defuseModeSelection(){
unsigned long lastScroll = 0;
int currentMessage = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Defuse Mode:");
lcd.setCursor(0, 1);
while(defuseMode == 0){
char key = keypad.getKey();
if (key == '1') {
Serial.println("defuseMode: [Hold]");
defuseMode = 1;
defuseModeHold();
break;
}
else if (key == '2'){
Serial.println("defuseMode: [Enter Code]");
defuseMode = 2;
defuseModeCode();
break;
}
else if (key == '3'){
Serial.println("defuseMode: [repeat]");
defuseMode = 3;
defuseModeRepeat();
break;
}
if (millis() - lastScroll > scrollTextSpeed) {
lastScroll = millis();
lcd.setCursor(0, 1);
switch (currentMessage) {
case 0:
lcd.print("Hold: 1 ");
break;
case 1:
lcd.print("Enter code: 2 ");
break;
case 2:
lcd.print("Repeat: 3 ");
break;
}
currentMessage++;
if (currentMessage > 2) currentMessage = 0;
}
}
}
void defuseModeHold(){
String defuseHoldString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hold Time:");
lcd.setCursor(13, 1);
lcd.print("(s)");
lcd.setCursor(0, 1);
while(plantHold == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
// Append digit to input string
defuseHoldString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(defuseHoldString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
defuseTime = defuseHoldString.toInt();
Serial.println("Defuse Hold:" + String(defuseHold));
break;
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
defuseModeHold();
}
}
}
bombGameStart();
}
void defuseModeCode(){
String defuseCodeString = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Defuse Digits:");
lcd.setCursor(11, 1);
lcd.print("(1-8)");
lcd.setCursor(0, 1);
while(plantCode == 0) {
char key = keypad.getKey();
if (key) {
if (key >= '1' && key <= '8') {
// Append digit to input string
defuseCodeString += key;
tone(buzzer, clickToneFreq); // 1000 Hz tone
delay(clickBeepTime);
noTone(buzzer); // stop sound
// Show it on LCD
lcd.setCursor(0, 1);
lcd.print(defuseCodeString);
}
else if (key == '*') {
tone(buzzer, enterToneFreq);
delay(enterBeepTime);
noTone(buzzer);
// Convert to integer
plantCode = defuseCodeString.toInt();
Serial.println("Defuse Digits:" + String(defuseCodeString));
}
else if (key == '#') {
tone(buzzer, removeToneFreq); // 1000 Hz tone
delay(removeBeepTime);
noTone(buzzer);
defuseModeCode();
}
}
}
bombGameStart();
}
void defuseModeRepeat(){
if (plantMode == 1){
defuseHold = plantHold;
Serial.println("DefuseHold:" + String(defuseHold));
}
bombGameStart();
}
void bombGameStart(){
unsigned long lastUpdate = 0;
const unsigned long interval = 1000; // 1 sekunda
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Game Starting!");
int totalSeconds = preparationTime * 60;
while(preparationTime != 0){
unsigned long now = millis();
if (now - lastUpdate >= interval) {
lastUpdate = now;
if (totalSeconds > 0) {
totalSeconds--;
displayTime(totalSeconds);
} else {
lcd.setCursor(0, 1);
break;
}
}
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Type ");
lcd.print(plantCode);
lcd.print(" digits:");
char inputBuffer[plantCode + 1];
int inputIndex = 0;
totalSeconds = plantTime * 60;
while(bombPlanted == false){
unsigned long now = millis();
if (now - lastUpdate >= interval) {
lastUpdate = now;
if (totalSeconds > 0) {
totalSeconds--;
displayTime(totalSeconds);
} else {
lcd.setCursor(0, 1);
break;
}
}
if(plantMode == 1){
// Implement hold to plant logic here
// For example, check if a specific button is held down for 'plantHold' seconds
// If held long enough, set bombPlanted = true;
}
else if(plantMode == 2){
char key = keypad.getKey();
if (key != NO_KEY) {
// only accept digits 0-9
if (key >= '0' && key <= '9' && inputIndex < plantCode) {
inputBuffer[inputIndex] = key;
inputIndex++;
// display entered digits
lcd.setCursor(0, 1);
for (int i = 0; i < inputIndex; i++) lcd.print(inputBuffer[i]);
// check if input is complete
if (inputIndex == plantCode) {
inputBuffer[inputIndex] = '\0'; // terminate string
int defuseCode = atol(inputBuffer); // convert to integer
bombPlanted = true;
Serial.print("Bomb Planted with code: ");
Serial.println(defuseCode);
}
}
// optional small delay to prevent multiple reads
delay(200);
}
}
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Bomb Planted");
totalSeconds = defuseTime * 60;
while(bombPlanted == true){
unsigned long now = millis();
if (now - lastUpdate >= interval) {
lastUpdate = now;
if (totalSeconds > 0) {
totalSeconds--;
displayTime(totalSeconds);
} else {
lcd.setCursor(0, 1);
lcd.print("BOOM! ");
}
}
}
}
void displayTime(int secondsLeft) {
int minutes = secondsLeft / 60;
int seconds = secondsLeft % 60;
lcd.setCursor(11, 1);
// formát MM:SS
if (minutes < 10) lcd.print('0');
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) lcd.print('0');
lcd.print(seconds);
}
Loading
esp32-s3-devkitc-1
esp32-s3-devkitc-1