I'm working on an airsoft prop so I can run a gamemode where you defuse a bomb, all of the code works fine until I try plugging in the Piezo Buzzer. The code should run "Initiated()" until the timer runs out or an IR signal is received, but if I have the Buzzer plugged in, once the time has been set and the 5 second countdown finishes, it immediately starts the "Defusal()" function. Sometimes the Buzzer starts beeping before I even get to that phase and will just beep until I unplug it.
I've tried:
- Plugging both wires into separate GND ports (no difference)
- Wiggling wires to see if there is a loose connection (there is no loose connection)
- Double checking all wiring (everything is plugged in properly)
- Using different Buzzers (all are the same type and act the same)
What i'm using:
- UNO R3
- IR Receiver Module
- Joystick Module
- 4x4 Keypad
- Passive Piezo Buzzer (comment helped with specification)
- LCD Screen (not sure specification, I got it from a class for free a while back)
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ezButton.h>
#include <IRremote.h>
#include <Keypad.h>
#define VRX_PIN A0
#define VRY_PIN A1
#define SW_PIN 0
ezButton button(SW_PIN);
const byte ROWS = 4;
const byte COLUMNS = 4; // FIXED to 4 columns
char hexaKeys[ROWS][COLUMNS] = {
{ '1', '2', '3', 'a' },
{ '4', '5', '6', 'b' },
{ '7', '8', '9', 'c' },
{ '*', '0', '#', 'd' }
};
byte rowPins[ROWS] = { 2, 3, 4, 5 };
byte columnPins[COLUMNS] = { 6, 7, 8, 9 };
Keypad numPad = Keypad(makeKeymap(hexaKeys), rowPins, columnPins, ROWS, COLUMNS);
int IR = 11;
int piezo = 10;
int xValue = 0;
int yValue = 0;
int bValue = 0;
int irValue = 0;
int displayedScreenNumber = 0;
LiquidCrystal_I2C lcd(0x27, 16, 2);
int timer = 300;
bool Cancelled = false;
void setup() { // Just the setup
pinMode(piezo, OUTPUT);
pinMode(IR, INPUT);
Serial.begin(9600);
lcd.init();
lcd.backlight();
button.setDebounceTime(50);
}
String inputBuffer = ""; // move to global scope
void loop() {
button.loop();
delayMicroseconds(10);
yValue = analogRead(VRY_PIN);
bValue = button.getState();
irValue = digitalRead(IR);
// Joysticks
bool jStickU = yValue > 700;
bool jStickD = yValue < 300;
// Debugging for testing if an IR input works
if (irValue == LOW) {
tone(piezo, 5000);
delay(500);
noTone(piezo);
}
// Change LCD based on joystick movement
if (jStickU) displayedScreenNumber++;
if (jStickD) displayedScreenNumber--;
displayedScreenNumber = constrain(displayedScreenNumber, 0, 1);
lcd.setCursor(0, 0);
lcd.setCursor(0, 1);
// Set time mode, using the number matrix for custom time
if (displayedScreenNumber == 1) {
lcd.setCursor(0, 0);
lcd.print("SET TIME MMSS ");
char key = numPad.getKey();
if (key) {
if (key >= '0' && key <= '9') {
if (inputBuffer.length() < 4) {
inputBuffer += key;
}
} else if (key == '*') {
inputBuffer = ""; // Clear input
} else if (key == '#') {
if (inputBuffer.length() == 4) {
int mins = inputBuffer.substring(0, 2).toInt();
int secs = inputBuffer.substring(2, 4).toInt();
timer = mins * 60 + secs;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SETTING BOMB...");
delay(1000);
for (int i = 5; i > 0; i--) {
lcd.setCursor(0, 1);
lcd.print("00:0");
lcd.print(i);
lcd.print(" ");
delay(1000);
}
inputBuffer = "";
Initiated();
} else {
lcd.setCursor(0, 1);
lcd.print("Invalid Format");
delay(1000);
inputBuffer = "";
}
}
}
lcd.setCursor(0, 1);
lcd.print("TIME: ");
lcd.print(inputBuffer);
for (int i = inputBuffer.length(); i < 4; i++) {
lcd.print("_");
}
} else {
// if it's not in set time, just run the base mode
lcd.setCursor(0, 0);
lcd.print("BOMB: POWERED ");
lcd.setCursor(0, 1);
lcd.print("INACTIVE... ");
inputBuffer = ""; // Reset input if screen changes
}
}
void Initiated() { // Countdown process
while (timer >= 0) {
irValue = digitalRead(IR);
int seconds = timer % 60;
int minutes = (timer / 60) % 60;
if (irValue == LOW && timer != 0) {
Defusal();
return;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BOMB ONLINE");
char minBuffer[6];
sprintf(minBuffer, "%02d:%02d", minutes, seconds);
lcd.setCursor(0, 1);
lcd.print(minBuffer);
delay(800);
tone(piezo, 5000);
delay(200);
noTone(piezo);
timer--;
if (timer <= 0) {
Detonated();
return;
}
}
}
void Detonated() { // When the timer is finished, this is the "detonation"
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BOMB DETONATED");
tone(piezo, 500);
delay(500);
lcd.setCursor(0, 1);
lcd.print("FAILED DEFUSAL");
noTone(piezo);
delay(3000);
timer = 300;
while (1)
; // halt
}
void Defusal() { // If the IR sensor finds something it gets "defused"
float reps = 0;
Cancelled = false;
for (int i = 200; i > 0; i--) {
reps++;
bValue = button.getStateRaw();
if (bValue == LOW && reps != 0) {
DefusalCancelled();
return;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("DEFUSING...");
lcd.setCursor(0, 1);
lcd.print((int)(reps / 2));
lcd.print("%");
delay(50);
if (reps >= 200) {
DefuseSequence();
return;
}
}
}
void DefusalCancelled() { // If you press the joystick button in time before the defusal is finished it "cancels"
// the defusal
int time = 0;
String Str = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("OVERRIDING...");
while (time < 100) {
int RandomNum = random(0, 2);
Str += String(RandomNum);
lcd.setCursor(0, 1);
lcd.print(Str);
delay(10);
time++;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("DEFUSAL");
lcd.setCursor(0, 1);
lcd.print("CANCELLED");
timer = 300;
while (1)
; // halt
}
void DefuseSequence() { // The sequence after the time is up from the defusal
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BOMB DEFUSED");
lcd.setCursor(0, 1);
lcd.print("100.00%");
for (int i = 0; i < 3; i++) {
tone(piezo, 2000);
delay(200);
noTone(piezo);
delay(100);
}
timer = 300;
while (1)
; // halt
}