Need Help with Piezo Buzzer and Ultrasonic Sensor code

I did not have a sensor so I used a POT.
Add/delete/change lines as needed.
You should be able to modify the code to your ultrasonic application.
Change hysteresis as needed.

int duration;
int distance;
int hysteresis = 5;       // minimum acceptable change
boolean buzzState = false;  // false = buzzer is off
unsigned long buzzDelay;  //Time the buzzer will be On
unsigned long buzzMilli;  //Time the buzzer went On
int lastDistance;  // = the last read distance value

void setup() 
{
  Serial.begin (9600);
  buzzState = false;
  pinMode(4,OUTPUT);
}

void loop()
{
  duration = analogRead(A0);
  distance = (duration);
  if (distance >= 200 || distance <= 0)
  {
    Serial.println("Out of range");
  }
  else
  {
    Serial.print(distance);
    Serial.println(" cm");
  }

  // Has the distance changed significantly?
  if ((lastDistance + hysteresis) < distance || (lastDistance - hysteresis) > distance)
  {
    lastDistance = distance;
    buzzDelay = distance;
    buzzMilli = millis();
    buzzState = true; // indicate the buzzer is now on
    digitalWrite(4,HIGH);  //turn on the buzzer
  }

  if (buzzState == true && (millis() - buzzMilli >= buzzDelay))    //is time left and is the buzzer ON?
  {
    digitalWrite(4,LOW); //turn off the buzzer
    buzzState = false;  //indicate the buzzer is now off
  }
}   
   // END of loop()

This is what I came up with. According to the serial monitor the sensor is working just fine, but the buzzer is not buzzing, ever. Where did I go wrong editing the code? Thank you, I do appreciate your time.

/*
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 13 Trig to Arduino pin 12
 More info at: http://goo.gl/kJ8Gl
*** edited by LarryD and KalELonRedKryptonite  ***
 */

#define trigPin 12
#define echoPin 13


void setup() {

  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(4,OUTPUT);
  
}

void loop() {

	int duration, distance;
	int hysteresis = 5;       // minimum acceptable change
	boolean buzzState = false;  // false = buzzer is off
	unsigned long buzzDelay;  //Time the buzzer will be On
	unsigned long buzzMilli;  //Time the buzzer went On
	int lastDistance;  // = the last read distance value


	digitalWrite(trigPin, HIGH);
	delayMicroseconds(1000);
	digitalWrite(trigPin, LOW);
	duration = pulseIn(echoPin, HIGH);
	distance = (duration/2) / 29.1;
  
  
  
  if (distance >= 200 || distance <= 0)
  {
    Serial.println("Out of range");
  }
  else
  {
    Serial.print(distance);
    Serial.println(" cm");
  }

  // Has the distance changed significantly?
  if ((lastDistance + hysteresis) < distance || (lastDistance - hysteresis) > distance)
  {
    lastDistance = distance;
    buzzDelay = distance;
    buzzMilli = millis();
    buzzState = true; // indicate the buzzer is now on
    digitalWrite(4,HIGH);  //turn on the buzzer
  }

  if (buzzState == true && (millis() - buzzMilli >= buzzDelay))    //is time left and is the buzzer ON?
  {
    digitalWrite(4,LOW); //turn off the buzzer
    buzzState = false;  //indicate the buzzer is now off
  }
}   
   // END of loop()

Move these under the #defines area, the report back.
int duration, distance;
int hysteresis = 5; // minimum acceptable change
boolean buzzState = false; // false = buzzer is off
unsigned long buzzDelay; //Time the buzzer will be On
unsigned long buzzMilli; //Time the buzzer went On
int lastDistance; // = the last read distance value

I put the

delay(500);

back at the bottom and the buzzer now works, but it is a constant buzz instead of being interrupted no matter what I point the sensor at.

EDIT: ignore this post, pretty sure on this specific test I put the wire in the power rail instead of the signal rail. But all other tests I double and triple checked my wires were correct.

Did you move those lines out of the loop().
Are the distances printed to the serial monitor?

I tried all combinations of inside the loop and outside the loop, with the delay statement and without, none work, all have silent buzzer. Yes, sensor is working according to serial monitor.

What is printed on the serial monitor?

This works, here, with a DC-SR04 ultra sonic transducer and a piezo speaker like yours.

EDIT: Added code to run the task every 1/2 second to slow things down and let the speaker/buzzer time out

/*
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 13 Trig to Arduino pin 12
 More info at: http://goo.gl/kJ8Gl
 *** edited by LarryD and KalELonRedKryptonite  ***
 */

#define trigPin 12
#define echoPin 13

unsigned long duration, distance;
int hysteresis = 2;       // minimum acceptable change
boolean buzzState = false;  // false = buzzer is off
unsigned long buzzDelay;  //Time the buzzer will be On
unsigned long buzzMilli;  //Time the buzzer went On
int lastDistance;  // = the last read distance value

const unsigned long TaskAtime  = 500UL;  //Runs TaskA every 1/2 second
unsigned long TimeA;                     //Times up, Task A time

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(4,OUTPUT);
}

void loop()
{
  unsigned long millisNow = millis();
 
 if (millisNow - TimeA >= TaskAtime) //Is it time to run Task A?
  {
    TimeA = millis();      //Re-initialize
    TaskA();                    // go and execute this code
  } 

// Check to see if its time to turn off the buzzer, IF, it's on
  if (buzzState == true && (millis() - buzzMilli >= buzzDelay))    //is time left and is the buzzer ON?
  {
    digitalWrite(4,LOW); //turn off the buzzer
    buzzState = false;  //indicate the buzzer is now off
  }
}   
// END of loop()

// FUNCTIONS
//========================================================== 
void TaskA()
{
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;

//Don't accept too large/small of a range  
 if (distance >= 200 || distance <= 0)
  {
    Serial.println("Out of range");
    return;  // invalid distance, go back
  }
  else
  {
    Serial.print(distance);
    Serial.println(" cm");
  }

// Has the distance changed significantly?
  if ((lastDistance + hysteresis) < distance || (lastDistance - hysteresis) > distance)
  {
    lastDistance = distance;   // update to the current distance
    buzzDelay = distance;      // time in milliseconds the buzzer will be on
    buzzMilli = millis();           // the time the buzzer was turned on
    buzzState = true;              // indicate the buzzer is now on
    digitalWrite(4,HIGH);        //turn on the buzzer
  }
}

Try replacing the speaker with a LED + 220 ohm resistor.
what happens with the LED?

Okay it's working, both the LED and buzzer with the new code.

It only beeps once in awhile though, so I think some tweaking of the numbers is in order.

I'm going to try the older version of the code and see if it works now too. I tore it down and rebuilt it so maybe I had something wrong yesterday that I kept missing, I'll post back here shortly and let you know.

Well that figures, the old code works now too, even better than the new code haha :blush:

Clearly I had something wrong yesterday and repeatedly missed it.

EDIT:
This code works, mostly, and buzzes AND flashes an LED though it could be tweaked to be more accurate I think.

/*
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 13 Trig to Arduino pin 12
 More info at: http://goo.gl/kJ8Gl
***  edited by LarryD and KalELonRedKryptonite ***
 */


#define trigPin 12
#define echoPin 13

  int duration, distance;
  int hysteresis = 5;       // minimum acceptable change
  boolean buzzState = false;  // false = buzzer is off
  unsigned long buzzDelay;  //Time the buzzer will be On
  unsigned long buzzMilli;  //Time the buzzer went On
  int lastDistance;  // = the last read distance value


void setup() {

  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(4,OUTPUT);
  pinMode(6,OUTPUT);
  
}

void loop() {
  
  
	digitalWrite(trigPin, HIGH);
	delayMicroseconds(1000);
	digitalWrite(trigPin, LOW);
	duration = pulseIn(echoPin, HIGH);
	distance = (duration/2) / 29.1;
  
  
  
  if (distance >= 200 || distance <= 0)
  {
    Serial.println("Out of range");
  }
  else
  {
    Serial.print(distance);
    Serial.println(" cm");
  }

  // Has the distance changed significantly?
  if ((lastDistance + hysteresis) < distance || (lastDistance - hysteresis) > distance)
  {
    lastDistance = distance;
    buzzDelay = distance;
    buzzMilli = millis();
    buzzState = true; // indicate the buzzer is now on
    digitalWrite(4,HIGH);  //turn on the buzzer
    digitalWrite(6,HIGH);  //turn on the LED
  }

  if (buzzState == true && (millis() - buzzMilli >= buzzDelay))    //is time left and is the buzzer ON?
  {
    digitalWrite(4,LOW); //turn off the buzzer
    digitalWrite(6,LOW); //turn off the LED
    buzzState = false;  //indicate the buzzer is now off
  }
  

}   
   // END of loop()

I haven't done functions yet, so I'm going to read up on them first before I attempt to do the same with the newer code.

Test time.
What does hysteresis do in the code?

I actually had to Google the word yesterday.

It's a relationship of two things changing and affecting each other, and I think in a proportional or ratio kind of way. As for what it does in the code, I'm not 100% sure, but it has to do with the relationship between distance and the buzzer/LED activating or not. I have to go soon so I don't have time to test it right now, but I'm going to raise and lower the number and see what happens.

When you come to a understanding of it does, report back.

What happens when it is set to zero?

Nevermind about distance vs lastDistance, I was confusing myself because I realized on the very first reading lastDistance would have no value, but every reading after that it would be different or the same from the distance value.

The Hysteresis variable makes it so it only triggers the loop if the distance has changed 'x' amount. What's perplexing though, is values of 1 or 10 for hysteresis seem to do the same thing and maybe it's just a crap sensor but it doesn't seem to respond when it should and it goes crazy beeping and flashing unexpectedly.

The serial monitor works, here is an example with Hysteresis set at 10:

5 cm
7 cm
6 cm
6 cm
6 cm
6 cm
6 cm
6 cm
6 cm
6 cm
Out of range
6 cm
6 cm
Out of range
6 cm

distance is the value that is measured EACH time trough the loop() this can be update thousands of times in a second.
lastDistance is the value you measured in a PRIOR loop (in a past ).
lastDistance is only update to the new value if there has been SIGNIFICANT movement.

What you are doing is comparing the current distance to a previous distance and, only if, they are different are you going to turn on the speaker. If they are the same (within a range+-) the speaker is quiet.

So in essence, the speaker will only beep if, A SIGNIFICANT CHANGE HAS BEEN DETECTED.
hysteresis is the variable that defines HOW MUCH you have to move towards OR away from the sensor before this can be called significant.

Make hysteresis = 0, what happens?
Make hysteresis = 10, what happens?

This could be referred to as sensitivity.

Haha, hysteresis set to zero is pretty funny, it goes off very often, rapidly at times. Now the hysteresis value is in CM correct? I guess it would have to be, since the rest is in CM, and it's just basic math.

If I wanted to mount this sensor to a servo and use it for obstacle detection for a robot, then in your opinion what type of sensitivity would I need so the robot has time to properly maneuver?
I guess that would depend on how fast or slow it is, but mine won't move that fast as it is just powered by dual Tamiya motors (#70168).

I have the chassis built and it will probably end up around 20x15x15 CM in area/dimension when it's all put together. I've been planning it and acquiring parts the last couple months but decided it would be best to learn how each component works by itself before I try to put it all together into one machine. That and learning a new programming language.

If I wanted to mount this sensor to a servo and use it for obstacle detection for a robot, then in your opinion what type of sensitivity would I need so the robot has time to properly maneuver?

Just have to experiment.

Good luck with your project.