Something is wrong with my buzzer and/or IR sensor

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
}
  • In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
    Use the < CODE / > icon from the ‘posting menu’ to attach the copied sketch.

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

  • Where are your meaningful comments in the sketch ? :thinking:

  • Exactly what is not working, how should it work ?

What piezo buzzer. Active or passive.
Only passive buzzers can be used with "tone".

Test your piezo by directly connecting it to 5volt and ground.
If it makes a sound, then you have an active buzzer.
They can only be controlled by setting the pin High or Low.
Leo..

It's passive.

Both irremote and tone() use timer2 on uno.
Either setup irremote to use timer1

#define IR_USE_AVR_TIMER1

or use them sequentially.

    IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
    tone(TONE_PIN, 2200, 8);
    delay(8);
    IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.

Thanks, this worked perfectly.