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!
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.
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.
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).
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