Turning Buzzer On Whilst Certain Condition Is Met

Hello! I'm trying to have an active buzzer sound only when the ultrasonic sensor detects an object from a certain distance. Therefore, it should produce a sound the entire time that the object is within that distance and stop producing a sound when no object is detected in that range.

However, it is difficult for me to sound the buzzer whilst continuously checking the distance using the sensor. Either the buzzer continues to produce a sound and stops the sensor code from running (it can't check the distance once the buzzer is on), or it takes too long to check if the buzzer should not ring between intervals.

I have tried using the millis() method from a source I found online:

void alarm( )
{
    static unsigned long startMs = 0;
    static unsigned long intervalMs = 40;    
    static byte buzz = 0;
    static byte alarmOn = 0;

    if ( alarmBeeps > 0 )
    {
        if ( millis() - startMs < intervalMs )    return;     // time is not up, do something else

        if ( alarmOn == 0 )
        {
            startMs = millis();
            alarmOn = 1;
        }
        else     startMs += intervalMs;

        buzz ^= 1;         // toggles bit 0  
        if ( buzz > 0 )    // start of sound pulse
        {
            digitalWrite(buzzer,HIGH);
            alarmBeeps--;
        }
        else
        {
            digitalWrite(buzzer,LOW);
        }
     }
    else    //  alarmBeeps == 0
    {
        digitalWrite(buzzer,LOW);
        alarmOn = 0;
        buzz = 0;
    }
}

It kind of works but erratically. It does stop but only once it's gone through the 5, long beeps. I do not want a set number of beeps - I just want it to stop once the object moves out of that range. This is probably a simple task but I have trouble understanding state changes and executing two tasks at once as a beginner. Any help would be appreciated!

We need to see the complete sketch.

We need to see your proposed schematic.

The only information that you gave in your post is
image

If you code a while loop like this

while (distance < q) {
  digitalWrite(buzzer, HIGH);

this means the code stays forever inside this while-loop
because you do not update variable "q"

Though I guess this does not come close to your real code.
And this is the reason why

best regards Stefan

Thank you so much for the quick reply! You are right - I did not provide the complete code. This is what I have so far:


#include <NewPing.h>

#define TRIGGER_PIN A0

#define ECHO_PIN A1

#define MAX_DISTANCE 200

int buzzer = 11;
byte  alarmBeeps  = 0;  

unsigned int duration = 0;
float distance = 0;


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void measure(){
  
  distance = sonar.ping();
  pinMode(ECHO_PIN,OUTPUT);
  digitalWrite(ECHO_PIN,LOW);
  pinMode(ECHO_PIN,INPUT);
  distance = distance/ US_ROUNDTRIP_CM; }
  

void alarm( )
{
    static unsigned long startMs = 0;
    static unsigned long intervalMs = 40;    
    static byte buzz = 0;
    static byte alarmOn = 0;

    if ( alarmBeeps > 0 )
    {
        if ( millis() - startMs < intervalMs )    return;     // time is not up, do something else

        if ( alarmOn == 0 )
        {
            startMs = millis();
            alarmOn = 1;
        }
        else     startMs += intervalMs;

        buzz ^= 1;         // toggles bit 0  
        if ( buzz > 0 )    // start of sound pulse
        {
            digitalWrite(buzzer,HIGH);
            alarmBeeps--;
        }
        else
        {
            digitalWrite(buzzer,LOW);
        }
     }
    else    //  alarmBeeps == 0
    {
        digitalWrite(buzzer,LOW);
        alarmOn = 0;
        buzz = 0;
    }
}



void setup() {

  pinMode(buzzer,OUTPUT);
  Serial.begin(9600);}

void loop() {

delay(500);
measure();

duration = duration + 1;

Serial.print(distance);
Serial.println("cm");
Serial.println(" ");
Serial.print(duration);

 if(distance>20.00) {
  alarmBeeps = 0;}
 
 else if(distance>9.00){
  alarmBeeps = 0;}

 else if(distance>2.00){
  alarmBeeps = 5;}

 else {
  Serial.println("Outlier");}
  
  alarm();
}

Suggest you slow things down a bit.

How fast do you really need to sample the distance ?

When a valid distance is detected, and the beeping is happening, do not need to keep reading the distance ?

What does this do for you ?
duration = duration + 1;

Show us a schematic.

Give us a Link to the buzzer.

The schematic is extremely basic - please ignore the horrible lines crossing (I am not using a breadboard).
This is the link to the buzzer:Buzzer

Some extra info: I am using the ultrasonic sensor as water level indicator for a visually impaired client. Once the water reaches a certain distance from the sensor, it needs to beep to tell the client that his container is almost full. It needs to keep reading the distance because once he removes the device with the sensor or places it on another empty pot, it should stop beeping entirely.

duration = duration + 1 was used solely for counting how many times the sensor took readings and is not useful to my current issue.

What is the resistance of the buzzer ?

THX.

So the beeping is 40 ms on, 40 ms off gotta say that would be very annoying!

a7

If the buzzer only takes 10mA you should be okay.

You should be able to build on this sketch.

This will not be exactly what you want but try it out and report back.



//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       23/04/01    Running code, to be tested
//
//

#include <NewPing.h>

#define ENABLED                  true
#define DISABLED                 false

#define STARTbeep                HIGH
#define STOPbeep                 LOW


//********************************************^************************************************
const byte TRIGGER_PIN         = A0;
const byte ECHO_PIN            = A1;

const byte heartbeatLED        = 13;
const byte buzzerPin           = 11;

byte alarmBeeps                = 0;

const int MAX_DISTANCE         = 200;

unsigned int duration;

float distance;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

//timing stuff
unsigned long heartbeatTime;
unsigned long beepTime;
unsigned long distanceTime;


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(buzzerPin, OUTPUT);

} //END of   setup()


//                                       l o o p ( )
//********************************************^************************************************
void loop()
{
  //**********************************************                h e a r t b e a t   T I M E R
  //is it time to toggle the heartbeatLED ?
  if (millis() - heartbeatTime > 250)
  {
    //restart this TIMER
    heartbeatTime = millis();

    //toggle LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }

  //**********************************************                d i s t a n c e   T I M E R
  //if we are not beeping, is it time to check the distance ?
  if (alarmBeeps == 0 && millis() - distanceTime > 500ul)
  {
    //restart this TIMER
    distanceTime = millis();

    checkDistance();
  }

  //**********************************************                b e e p i n g   T I M E R
  //if enabled, is it time to toggle the buzzer pin ?
  if (alarmBeeps > 0 && millis() - beepTime > 1000)
  {
    //restart this TIMER
    beepTime = millis();

    alarmBeeps = alarmBeeps - 1;

    //are we finished ?
    if (alarmBeeps <= 0)
    {
      digitalWrite(buzzerPin, STOPbeep);
    }

    else
    {
      //toggle the pin
      digitalWrite(buzzerPin, digitalRead(buzzerPin) == HIGH ? LOW : HIGH);
    }
  }

  //**********************************************
  //Other non blocking code goes here
  //**********************************************

} //END of   loop()


//                              c h e c k D i s t a n c e ( )
//********************************************^************************************************
void checkDistance()
{
  duration = duration + 1;
  Serial.print(duration);

  measure();
  Serial.print("\tcm =  ");
  Serial.println(distance);

  //***************************************
  if (distance >= 20.00)
  {
    alarmBeeps = 0;
  }

  //***************************************
  else if (distance >= 9.00)
  {
    alarmBeeps = 0;
  }

  //***************************************
  else if (distance >= 2.00)
  {
    alarmBeeps = 7;

    digitalWrite(buzzerPin, STARTbeep);

    beepTime = millis();
  }

  //***************************************
  else
  {
    Serial.println("Outlier");
  }

} //END of   checkDistance()


//                                     m e a s u r e ( )
//********************************************^************************************************
void measure()
{
  distance = sonar.ping_cm();

} //END of   measure()


//********************************************^************************************************

I tried this! It does about the same as my old alarm function. I've been trying to take out the long pauses between the beeps because once the device is removed, it still beeps the entire 4 times. Is there a way around this to have the beeps be continuous?

I was also going to change the tone using the NewTone library for different distances measured but that is once I get at least one to work.

1 Like

It does not specify - I had initially attached a 10-ohm resistor but was warned to not do.

That looks like an active (ON or OFF) buzzer, you don't need TONE.

A 10 ohm is too low for testing.

Try a series 220 ohm resistor and a LED for testing.


Your link says 3-12v operation, 10mA.


As mentioned that buzzer makes its own sound, don’t use tone()


Please explain this more:

By this, I mean that I am trying to get the buzzer to produce a sound whilst the sensor measures the full water level. As soon as it detects a distance other than the full water level, it should almost immediately stop producing any sound until it measures the full water level again. Right now, it just produces erratic beeps that continue for a while when it is not measuring the full water level.

How do I get the buzzer to beep WHILE the sensor is detecting a full water level and STOP beeping when the sensor does not detect the full water anymore (essentially, making a device that can detect max liquid levels for multiple pots without needing to be turned on/off between the measurements).

Hmm ok, I was going to use it to create a different sound because the default buzzer sound is quite unpleasant.

Is this correct ?

  • when a reservoir gets too full (let’s say level #1), the buzzer starts making sound.
  • as long as the reservoir is too full, the buzzer keeps making sound.
  • when the reservoir falls to a certain point (let’s say level #1 minus a bit), the buzzer stops making sound.

Making sound means a constant sound.
i.e. NOT ON then OFF then ON . . . etc.


Version to make sound or not make sound.

//
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       23/04/01    Running code, to be tested
//  1.10       23/04/01    Buzzer makes sound while the distance is too small
//

#include <NewPing.h>



#define ENABLED                  true
#define DISABLED                 false

#define STARTbeep                HIGH
#define STOPbeep                 LOW

//********************************************^************************************************
const byte TRIGGER_PIN         = A0;
const byte ECHO_PIN            = A1;

const byte heartbeatLED        = 13;
const byte buzzerPin           = 11;

const byte MAX_DISTANCE        = 200;
const byte levelToHigh         = 8;
const byte levelNormal         = 9;

unsigned int duration;

float distance;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

//timing stuff
unsigned long heartbeatTime;
unsigned long distanceTime;


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);

  digitalWrite(buzzerPin, STOPbeep);
  pinMode(buzzerPin, OUTPUT);

} //END of   setup()


//                                       l o o p ( )
//********************************************^************************************************
void loop()
{
  //**********************************************                h e a r t b e a t   T I M E R
  //is it time to toggle the heartbeatLED ?
  if (millis() - heartbeatTime > 250)
  {
    //restart this TIMER
    heartbeatTime = millis();

    //toggle LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }

  //**********************************************                d i s t a n c e   T I M E R
  //is it time to check the distance ?
  if (millis() - distanceTime > 500ul)
  {
    //restart this TIMER
    distanceTime = millis();

    checkDistance();
  }

  //**********************************************
  //Other non blocking code goes here
  //**********************************************

} //END of   loop()


//                              c h e c k D i s t a n c e ( )
//********************************************^************************************************
void checkDistance()
{
  duration = duration + 1;
  Serial.print(duration);

  distance = sonar.ping_cm();

  Serial.print("\tcm =  ");
  Serial.println(distance);

  //***************************************
  //is the water level too HIGH ?
  if (distance <= levelToHigh)
  {
    digitalWrite(buzzerPin, STARTbeep);
  }

  else if (distance >= levelNormal)
  {
    //the water level is okay

    digitalWrite(buzzerPin, STOPbeep);
  }

} //END of   checkDistance()


//********************************************^************************************************

Yes, very close! In this case, I am also fabricating a box to encase the arduino and sensor and the device will attach onto pots. When the device is removed from the pot, it should immediately stop beeping. When it attaches onto the pot and the pot is filled with water, it starts and continues to beep until the device is taken off the pot.

The sound should be constant as you mentioned (or very frequent beeps). I will try the code you sent and give updates :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.