Use Simple Timer to turn a buzzer on and off

Hi,

I a have a small problem. I am working on a project that needs to beep 4 times to notify a task is done. Now my problem is that it is not working as I want it to. This is just a small part of the code. It is supposed to turns on the buzzer on and off 4 times every time the sensor goes LOW. But the led just comes and and does not blink. I cant use delay in the final project because of the timing. I have studied the Simple Timer Library but couldnt understand.

#include <SimpleTimer.h>

int buzzer = 6;
int sensor = 3;
SimpleTimer timer;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(buzzer, OUTPUT);
  pinMode(sensor, INPUT);

}


void buzzerOn() {
  digitalWrite(buzzer, HIGH);
  timer.setTimer(1000, buzzerOff, 1); // turn off after 1min
}

void buzzerOff() {
  digitalWrite(buzzer, LOW);
}


// the loop function runs over and over again forever
void loop() {

  if (digitalRead (sensor) == 0) {
    timer.setTimer(1000, buzzerOn, 4);  // Pulse Relay ON routine three times in 500ms
  }
  else {
    buzzerOff();
  }
  timer.run();                    // wait for a second
}

Thanks in Advance

Hi,
Look in the IDE Examples for "Blink without Delay"
It will show you how to flash an LED and not use delays, so not blocking your code.

Tom... :slight_smile:

    timer.setTimer(1000, buzzerOn, 4);  // Pulse Relay ON routine three times in 500ms

Which of those arguments means three times?
Which of those arguments means 500 milliseconds?
Which of those arguments means pulse a relay?

The comment is just plain wrong.

The use of the SimpleTimer class is, too.

Does the class keep track of how many times to do something? Why would it? If it doesn't, you need to, and you need to stop doing it when it has been done the required number of times.

If buzzerOn() sets up to call buzzerOff() later, shouldn't buzzerOff() set up to call buzzerOn() later?

Your timing is out. The code calls buzzerOn() 4 times in a row once a second. In buzzerOn() you appear to switch the buzzer off after a second (not a minute as the comment says). So it's on for a second, off, then instantly back on for the next second etc.

If you want to see/hear the on/off effect then likely the time between buzzerOn() calls must be longer than the switch off time!

Mind you, I'm only guessing from the documentation, I've never actually used SimpleTimer.

Steve

TomGeorge:
Hi,
Look in the IDE Examples for "Blink without Delay"
It will show you how to flash an LED and not use delays, so not blocking your code.

Tom... :slight_smile:

I have considered this but I thought simple timer is less complicated.

PaulS:

    timer.setTimer(1000, buzzerOn, 4);  // Pulse Relay ON routine three times in 500ms

Which of those arguments means three times?
Which of those arguments means 500 milliseconds?
Which of those arguments means pulse a relay?

The comment is just plain wrong.

The use of the SimpleTimer class is, too.

Does the class keep track of how many times to do something? Why would it? If it doesn't, you need to, and you need to stop doing it when it has been done the required number of times.

If buzzerOn() sets up to call buzzerOff() later, shouldn't buzzerOff() set up to call buzzerOn() later?

Oh I got parts of the code from other websites and forgot to change the comments. I have changed the code and got the buzzer beeping on and off but how can I make it to repeat only 4 times and not forever. Also how do you stop the buzzer on , off loop?

#include <SimpleTimer.h>

int buzzer = 6;
int sensor = 3;
SimpleTimer timer;


void setup() {

  pinMode(buzzer, OUTPUT);
  pinMode(sensor, INPUT);

}


void buzzerOn() { 
  digitalWrite(buzzer, HIGH); //tun buzzer 
  timer.setTimeout(1000, buzzerOff); // turn off after 1sec
}

void buzzerOff() {
  digitalWrite(buzzer, LOW);
  timer.setTimeout(1000, buzzerOn); // turn on after 1sec
}


void loop() {

  if (digitalRead (sensor) == 0) { //If sensor is low
   timer.setTimeout(1000, buzzerOn); // turn buzzer on and off
  } else {
    // stop the loop
  }
  
  
  timer.run();                   
}

slipstick:
Your timing is out. The code calls buzzerOn() 4 times in a row once a second. In buzzerOn() you appear to switch the buzzer off after a second (not a minute as the comment says). So it's on for a second, off, then instantly back on for the next second etc.

If you want to see/hear the on/off effect then likely the time between buzzerOn() calls must be longer than the switch off time!

Mind you, I'm only guessing from the documentation, I've never actually used SimpleTimer.

Steve

My knowledge is limited with arduino. I only know the very basics. I do know something about Simple Timer but very little. Simple time is very useful in many cases but you need to know the library and how it works unlike me. I understood when you suggested but its a little complicated then I would have thought. Yes the comments are off. I got the code from different websites and didnt change the comments. My bad.

how can I make it to repeat only 4 times and not forever. Also how do you stop the buzzer on , off loop?

When the need to make the cycle start arises, set a counter to 0. Each time buzzerOn() is called, increment the counter.

In the buzzerOff() function, disable the timer when the counter gets to 4. That is, don't set the timer up again to call the other function.

I needed multiple non-blocking buzzer beeps for my project as well. I ended up writing a small class with a FIFO buffer.
You can add beeps to the queue, and (if you refresh the loop regularly) it will play them at the right time. Each beep has a certain length, and a certain time of silence afterwards.
For example, to play the iconic Nokia SMS beep ( ... -- ... ), you would use the following code:

void loop() {
  if (button.isPressed()) {
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 280);
    buzzer.queueBeep(320, 80);
    buzzer.queueBeep(320, 280);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 1600);
  }
  buzzer.refresh();
}

The source code can be found here:
https://github.com/tttapa/Projects/tree/master/Arduino/LEDs, Buttons, etc./Buzzer-Queue

Pieter

PieterP:
I needed multiple non-blocking buzzer beeps for my project as well. I ended up writing a small class with a FIFO buffer.
You can add beeps to the queue, and (if you refresh the loop regularly) it will play them at the right time. Each beep has a certain length, and a certain time of silence afterwards.
For example, to play the iconic Nokia SMS beep ( ... -- ... ), you would use the following code:

void loop() {

if (button.isPressed()) {
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 280);
    buzzer.queueBeep(320, 80);
    buzzer.queueBeep(320, 280);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 80);
    buzzer.queueBeep(115, 1600);
  }
  buzzer.refresh();
}



The source code can be found here:
[https://github.com/tttapa/Projects/tree/master/Arduino/LEDs, Buttons, etc./Buzzer-Queue](https://github.com/tttapa/Projects/tree/master/Arduino/LEDs%2C%20Buttons%2C%20etc./Buzzer-Queue)

Pieter

Hi I tried your library and I found it helpful. I tried the example given but when I but it in my code the beeping wouldn`t stop and when the sensor goes HIGH the buzzer does not stop.

claytoncamilleri100:
Hi I tried your library and I found it helpful. I tried the example given but when I but it in my code the beeping wouldn`t stop and when the sensor goes HIGH the buzzer does not stop.

That's very strange, I just tried it here, and it works without any problems.
Could you post your exact code and circuit?

Pieter

Oh sorry forgot the code. I am 100% I am doing something wrong.

#include "Buzzer.h"
#include "PushButton.h"

const uint8_t buzzerPin = 6;
int Pin;
const uint8_t sensor = 3;

Buzzer buzzer = {buzzerPin};

void setup() { 
  pinMode(sensor, INPUT);
  }

void loop() {

if (digitalRead(sensor) == 0) {
  Pin = HIGH;
} else {
  Pin = LOW;
}
  
  if (Pin == HIGH) {
    buzzer.queueBeep(500, 500);
    buzzer.queueBeep(500, 500);
    buzzer.queueBeep(500, 500);
    buzzer.queueBeep(500, 500);
  }
  buzzer.refresh();
}

When digitalRead(sensor) == 0, and Pin == HIGH, you keep on adding beeps to the queue. The loop repeats many thousands of times per second, so as long as the condition is met, it keeps on adding them. The example I posted uses the PushButton class to debounce the button and to detect a falling edge. It only adds a beep to the queue when the button goes from the "not-pressed" to the "pressed" state, and it doesn't add more beeps while it is in the "pressed" state, only on the transition.

Pieter

PieterP:
When digitalRead(sensor) == 0, and Pin == HIGH, you keep on adding beeps to the queue. The loop repeats many thousands of times per second, so as long as the condition is met, it keeps on adding them. The example I posted uses the PushButton class to debounce the button and to detect a falling edge. It only adds a beep to the queue when the button goes from the "not-pressed" to the "pressed" state.

Pieter

So how should I write the code to activate with the sensor going HIGH and Low?

So how should I write the code to activate with the sensor going HIGH and Low?

First, you decide whether the sensor going HIGH is important, or if the sensor going LOW is important...

Beeping and buzzing on every change would get your device an introduction to a sledge hammer if it were around me.

Ok let me explain. I just need the buzzer to beep 4 times when the sensor is HIGH and when the sensor if LOW the buzzer stays off. Sorry if I was not clear before.

claytoncamilleri100:
Ok let me explain. I just need the buzzer to beep 4 times when the sensor is HIGH and when the sensor if LOW the buzzer stays off. Sorry if I was not clear before.

What if the sensor goes low while it's still beeping? (e.g. after two beeps) Should it stop beeping immediately, or should it finish the last two beeps first?

If you want it to stop immediately, you could add an "off" method to the buzzer class, that clears the buffer and turns off the buzzer:

    void off() {
      digitalWrite(pin, LOW); // disable the buzzer
      offDelay = 0;           // no delay before executing the next beep
      beepsInQueue = 0;       // no more beeps in the queue
      index = writeIndex;     // start reading beeps from the index where a new one will be written
      beeping = false;        // remember that the buzzer is off
    }

What kind of sensor are we talking about? Does it need software debouncing?

Pieter

PieterP:
What if the sensor goes low while it's still beeping? (e.g. after two beeps) Should it stop beeping immediately, or should it finish the last two beeps first?

If you want it to stop immediately, you could add an "off" method to the buzzer class, that clears the buffer and turns off the buzzer:

    void off() {

digitalWrite(pin, LOW); // disable the buzzer
      offDelay = 0;          // no delay before executing the next beep
      beepsInQueue = 0;      // no more beeps in the queue
      index = writeIndex;    // start reading beeps from the index where a new one will be written
      beeping = false;        // remember that the buzzer is off
    }



What kind of sensor are we talking about? Does it need software debouncing?

Pieter

The sensor is just a float sensor with a reed switch inside. It has a pull-up so the arduino sees High and Low. Actually in my final project I will be using a switch case to turn the buzzer on. Example when mode is 2, activate the buzzer.

claytoncamilleri100:
The sensor is just a float sensor with a reed switch inside. It has a pull-up

Why aren't you using the internal pull-up?

Try using the original code I posted with your reed switch, invert the input in PushButton.h if necessary.

Pieter

I am using an external pull-up because I designed the pcb before I knew the Arduino had pullups. :astonished:

And how can I activate the relay from a switch case?

What relay?

Have you tried using the PushButton example to detect a rising or a falling edge?

Pieter