NewPing Library: HC-SR04, SRF05, SRF06, DYP-ME007, Parallax PING))) - v1.7

I would also suggest a float because then the electronics can be placed outside the tank with only the float on the inside. Putting electronics inside fuel vapor doesn't sound like a good ideal. Actually, it sounds like a very bad idea. A short could result in a spark which results in a very bad day.

Tim

Hi everyone, I would like to ask if it's possible to hold a value, I mean, if I remove my hand from the sensor, then the sensor measure out of range, I would like that the last value sent for serial (usb) was the measure from my hand to the sensor before remove... This is my sketch which I found in this post, BTW really useful!!!

#include <NewPing.h>

#define SONAR_NUM     4 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(12, 11, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(10, 9, MAX_DISTANCE),
  NewPing(8, 7, MAX_DISTANCE),
  NewPing(6, 5, MAX_DISTANCE) 
};

void setup() {
  Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  // The rest of your code would go here.
  
}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
      Serial.print(cm[i]);
}

oigresUPM:
Hi everyone, I would like to ask if it's possible to hold a value, I mean, if I remove my hand from the sensor, then the sensor measure out of range, I would like that the last value sent for serial (usb) was the measure from my hand to the sensor before remove... This is my sketch which I found in this post, BTW really useful!!!

You would write your sketch to hold a value. Once one cycle of pinging all the sensors is complete, it goes to the oneSensorCycle() function. This is where you would analyze the results. If you wanted to hold those results and stop pinging, this is where you would do it. The 15 sensor sketch help post shows how you would stop the ping process and resume. If you only want to know when something is in the way of one of the sensors and then hold those results. In the oneSensorCycle() function you would detect something was in the way, stop the pings, and do whatever you wanted with that information. When you wanted to restart the pings, you would use the restart code.

That's about the best I can do shy of writing your script for you, and what fun would that be?

Tim

teckel:

oigresUPM:
Hi everyone, I would like to ask if it's possible to hold a value, I mean, if I remove my hand from the sensor, then the sensor measure out of range, I would like that the last value sent for serial (usb) was the measure from my hand to the sensor before remove... This is my sketch which I found in this post, BTW really useful!!!

You would write your sketch to hold a value. Once one cycle of pinging all the sensors is complete, it goes to the oneSensorCycle() function. This is where you would analyze the results. If you wanted to hold those results and stop pinging, this is where you would do it. The 15 sensor sketch help post shows how you would stop the ping process and resume. If you only want to know when something is in the way of one of the sensors and then hold those results. In the oneSensorCycle() function you would detect something was in the way, stop the pings, and do whatever you wanted with that information. When you wanted to restart the pings, you would use the restart code.

That's about the best I can do shy of writing your script for you, and what fun would that be?

Tim

Thank you Tim!!! I'm going to work with these advices!!

Would NewPing work with a SRF08?

I've been using a HC-SR04 but I've looking for something more accurate at longer distances, to sense body movement accurately up to 3m, is the SRF08 much better?

Or any other suggestions?

The HC-SR04 recognises a body up till about 1.2m, then further away the sensor reports 0, as I guess its sending out a signal but not receiving it back.... but if I hold up a board of wood it sends back an accurate reading up to about 3m

bassmagnetic:
Would NewPing work with a SRF08?

I've been using a HC-SR04 but I've looking for something more accurate at longer distances, to sense body movement accurately up to 3m, is the SRF08 much better?

Or any other suggestions?

The HC-SR04 recognises a body up till about 1.2m, then further away the sensor reports 0, as I guess its sending out a signal but not receiving it back.... but if I hold up a board of wood it sends back an accurate reading up to about 3m

All the sensors are basically the same, with the same transducers and amps in most cases. There's just slight differences (like timeouts). I have several kinds and I would consider most to be almost identical. Also, keep in mind that the HC-RS04 is not made by one company, many make them, with slight differences. It could be that you just not one that wasn't too good.

Also, the SRF08 is not better just because the number is bigger. It's not like it's version 8 so it's better than version 4. The SRF08 is much larger, uses a lot more power, more expensive, and doesn't use the same interface at all, it uses I2C. Instead, I would opt for the SRF06 from Yourduino. There are other models of the SRF06 that have a different interface and connection header. Those won't work with NewPing as they are very rare. But, the SRF06 from YourDuino works very well with NewPing and is the best working sensor that I have. It uses the least amount of power, fastest startup time, and has the longest range of any sensor I have. The owner of YourDuino is a regular on this forum too as a bonus.

So, I would suggest either trying to buy a few additional cheapo eBay HC-RS04 sensors as you may have better luck. Or, go with the SRF06 from YourDuino (4 pins). Keep in mind that ultrasonic sensors are affected by sound absorbing materials, like clothing. It won't work as well detecting detecting a dog as it will a flat board. But, keep in mind that this still may give you what you want. For example, having the sensor hit a far wall and get the distance (say 300cm). When someone walks in front of the sensor, it will either bounce off and give a distance reading of say 150cm. Or, maybe all the sound is absorbed so it gives a reading of zero. That too could be used as a detection trigger, as normally it reads 300cm. So, whenever there's a reading of anything less than say 280cm (all the way to 0) would mean something was in the way of the sensor. This may not work in your situation, but it does in some (if the far wall is within the sensor range).

Tim

Thanks so much Tim for your reply....

I'm in the UK so I think ordering from Yourduino is a little far... I was also looking at the http://www.maxbotix.com/ Maxbotix sensors, have you any experience of these? Prices seem wildly different but can't tell if that means a more accurate sensor?

I have taken your advice and changed my current patch to take into account 0 readings for non-distance people detection, but would really like to try to get accurate distance reading of people up to 3m... especially as the sensors throw out quite a few false 0 readings when there is not a person there....

Also before I said I would post the installation that I am using the sensors for, its here: http://www.apbsound.com/2013/drone/

All the best

bassmagnetic:
Thanks so much Tim for your reply....

I'm in the UK so I think ordering from Yourduino is a little far... I was also looking at the http://www.maxbotix.com/ Maxbotix sensors, have you any experience of these? Prices seem wildly different but can't tell if that means a more accurate sensor?

I have taken your advice and changed my current patch to take into account 0 readings for non-distance people detection, but would really like to try to get accurate distance reading of people up to 3m... especially as the sensors throw out quite a few false 0 readings when there is not a person there....

Also before I said I would post the installation that I am using the sensors for, its here: http://www.apbsound.com/2013/drone/

All the best

Yourduino is far, but the sensors are cheaper and shipping low so it's not bad at all. maxbotix.com makes some good sensors. But, you need to use their libraries or make your own as they do things totally different than all the other ultrasonic sensors.

You can use the ping_median() method if you're not already to get a few readings which could weed out erroneous "no ping" readings. Looking at the installation, it would seem that would work very well for ultrasonic sensors. The far wall seems to be within 15 feet and it's a nice big flat wall. But, maybe it's not working as well as you hoped for another reason. For example, too much ambient noise or maybe because the sensors are hidden in the wall so the echo isn't as effective returning to the sensor. I'd be curious how well it works if you placed the sensors outside the wall and there was no other noise in the room. I know that doesn't help with your goal, but it could be useful for tracking down the problem. Or, maybe it's the length of the wires you have running to the sensor?

Tim

Is there a way to adjust the sensitivity or have a minimum size of object/return to be used for the result? I ask because if you look at the attached picture you will see the HC-SR04 mounted tipped up at 10 degrees. It will always return the distance to the 1.3" x 2.5" rectangle of cardboard and will never return the distance to the wood door (I like that it does this). However, if I put the 1/16" hex key in the path like in the picture, the sensor will return this shorter distance once in a while. A larger .090" hex key will cause most all returns to be the hex key distance.
I have read to get the sensor well off of the floor, but I don't really have that option. I don't have hex keys in the path, but I used this as an example. Many real world surfaces can cause returns it seems.
Your very good median can be used for a small amount of stray results, but I have found that sometimes the extremely small object returns can be consecutive at times and bad numbers will get through the median. The oscilloscope shows that it must be very difficult to pick out the closest object, but I was hoping to have the ultrasonic ignore the very small returns. I know that this is not in NewPing, but I just wondered if anyone had changed what must be the firmware on the sensor itself.
Thank you.

@CyklKent

I have seen some videos where people have put tubing, or short pipe over each half of the sensor. The result looked like binoculars. I think the reason was to make a the sensor's "vision" narrower and allow the sensor to only focus on a smaller area.

CyklKent:
Is there a way to adjust the sensitivity or have a minimum size of object/return to be used for the result? I ask because if you look at the attached picture you will see the HC-SR04 mounted tipped up at 10 degrees. It will always return the distance to the 1.3" x 2.5" rectangle of cardboard and will never return the distance to the wood door (I like that it does this). However, if I put the 1/16" hex key in the path like in the picture, the sensor will return this shorter distance once in a while. A larger .090" hex key will cause most all returns to be the hex key distance.
I have read to get the sensor well off of the floor, but I don't really have that option. I don't have hex keys in the path, but I used this as an example. Many real world surfaces can cause returns it seems.
Your very good median can be used for a small amount of stray results, but I have found that sometimes the extremely small object returns can be consecutive at times and bad numbers will get through the median. The oscilloscope shows that it must be very difficult to pick out the closest object, but I was hoping to have the ultrasonic ignore the very small returns. I know that this is not in NewPing, but I just wondered if anyone had changed what must be the firmware on the sensor itself.
Thank you.

As cyclegadget stated, putting the transmitting and/or receiving sensor(s) in a tube can focus the detection to a smaller range. You can try different length tubes which will give different results.

Also, if you just want to block the ground, tilting it up slightly as you have done is a good method. If that still doesn't give the desired results, you can add a shield below the sensors. This is the same concept as the tube, but only blocks stray echos from below, not above.

Other than this, I haven't seen any ultrasonic sensor with any type of sensor adjustability.

Tim

hi im building obstacle avoidance robot using two hs-o4 sensor and two dc motor. im using following code

#include <NewPing.h>
#define lp 9// left side motor l293
#define ln 8// left side motor l293
#define rp 7// right side motor l293
#define rn 6// right side motor l293

#define SONAR_NUM     2 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.
int leftsensor, rightsensor;
NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(13, 12, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(11, 10, MAX_DISTANCE),
 
};

void setup() {
  Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) 
      {
 leftsensor =cm[0];
rightsensor =cm[1]; 
if ((leftsensor >=10) && (rightsensor >=10))
{
  digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rp, HIGH);
digitalWrite(rn, LOW);
Serial.println(" go straight");
Serial.println(cm[0]);
Serial.println(cm[1]);
}

if ((leftsensor <=10) && (rightsensor >=10))
{
digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" right turn");
Serial.println(cm[0]);
Serial.println(cm[1]);
}

if ((leftsensor <=10)&& (rightsensor >=10))
{
digitalWrite(ln, HIGH);
digitalWrite(lp, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println("left turn ");
Serial.println(cm[0]);
Serial.println(cm[1]);

}
if ((leftsensor <=10) && (rightsensor <=10))
{
digitalWrite(lp,  LOW);
digitalWrite(ln, HIGH);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println("back");
Serial.println(cm[0]);
Serial.println(cm[1]);




}

if ((leftsensor =0) && (rightsensor =0))
{digitalWrite(lp,  HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, LOW);
digitalWrite(rp, HIGH);
Serial.println("go stright");
Serial.println(cm[0]);
Serial.println(cm[1]);
  
}
if ((leftsensor =0) && (rightsensor >=10))
{digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" right turn");
Serial.println(cm[0]);
Serial.println(cm[1]);
  
}
if ((leftsensor =0) && (rightsensor >=10))
{digitalWrite(ln, HIGH);
digitalWrite(lp, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" left turn");
Serial.println(cm[0]);
Serial.println(cm[1]);


      }
     
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
  // The rest of your code would go here.

}
}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

by using this the robot is not moving straight but it is rotating in same place slowly and if try to use serial monitor it is not printing any thing

then i tried normal code

#define ta 13// trigger
#define ea 12// eco
#define tb 11 // trigger
#define eb 10// eco
#define lp 9// left side motor l293
#define ln 8// left side motor l293
#define rp 7// right side motor l293
#define rn 6// right side motor l293

#define TIMEOUT 40000 // 40ms timeout (the HC-sr04 has 38 ms timeout)

void setup()
{
Serial.begin (19200);
pinMode(lp, OUTPUT);
pinMode(ln, OUTPUT);
pinMode(rp, OUTPUT);
pinMode(rn, OUTPUT);
pinMode(ta, OUTPUT);
pinMode(ea, INPUT);
pinMode(tb, OUTPUT);
pinMode(eb, INPUT);
digitalWrite(ta, LOW); // Ensure triger is starting with low before any pulse
delayMicroseconds(20);// Delay before first pulse
digitalWrite(tb, LOW);
delayMicroseconds(20);
}

void loop()
{
long dua, da,dub,db;

digitalWrite(ta, HIGH); // Start the a  High Pulse

delayMicroseconds(10); // Delay 10 micros

digitalWrite(ta, LOW); // End the Pulse
dua = pulseIn(ea, HIGH, TIMEOUT);
da = (dua/2) / 29.1;

digitalWrite(tb, HIGH); // Start the b High Pulse

delayMicroseconds(10); // Delay 10 micros
digitalWrite(tb, LOW); // End the Pulse
dub = pulseIn(eb, HIGH, TIMEOUT);
db = (dub/2) / 29.1;
if ((da >=10) && (db >=10))
{
  
digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rp, HIGH);
digitalWrite(rn, LOW);
Serial.println(" go straight");
Serial.println(da);
Serial.println(db);
}

if ((da <=10) && (db >=10))
{
digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" right turn");
Serial.println(da);
Serial.println(db);
}

if ((db <=10)&& (da >=10))
{
digitalWrite(ln, HIGH);
digitalWrite(lp, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println("left turn ");
Serial.println(da);
Serial.println(db);

}
if ((da <=10) && (db <=10))
{
digitalWrite(lp,  LOW);
digitalWrite(ln, HIGH);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println("back");
Serial.println(da);
Serial.println(db);




}

if ((da =0) && (db =0))
{digitalWrite(lp,  HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, LOW);
digitalWrite(rp, HIGH);
Serial.println("go stright");
Serial.println(da);
Serial.println(db);
  
}
if ((da =0) && (db >=10))
{digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" right turn");
Serial.println(da);
Serial.println(db);
  
}
if ((db =0) && (da >=10))
{digitalWrite(ln, HIGH);
digitalWrite(lp, LOW);
digitalWrite(rn, HIGH);
digitalWrite(rp, LOW);
Serial.println(" left turn");
Serial.println(da);
Serial.println(db);
  
}
delay(50);
}

it is behaving good in serial monitor that is print turn right when blocked in left and in vice versa...
but in real robot it is rotating in clock wise not moving forward..help me to resolve it

Each movement decision is based on an "if" statement similar to this:

if ((da <=10) && (db >=10)

I recommend printing "da = " da ........and print "db = " db....... this will show what those numbers are and if they are changing. There must be a problem related to those two number results.

most of the time it show zero in one sensor but zero may denote out of range or object very near..and i think taking mean of ping is good idea but dono how to use that method sonar.mean() and new ping is not working good in my program even serial monitor and that is not show any word tx light in uno is not glowing when i use new ping program

Put "0" in the integer postions of this "if" statement.

if ((da >=10) && (db >=10))
{
  
digitalWrite(lp, HIGH);
digitalWrite(ln, LOW);
digitalWrite(rp, HIGH);
digitalWrite(rn, LOW);
Serial.println(" go straight");
Serial.println(da);
Serial.println(db);
}

If the either sensor output results as "0" you will not go straight.

for zero this will work, in that program

if ((da =0) && (db =0))
{
digitalWrite(lp,  HIGH);
digitalWrite(ln, LOW);
digitalWrite(rn, LOW);
digitalWrite(rp, HIGH);
Serial.println("go stright");
Serial.println(da);
Serial.println(db);
  
}
if ((da == 0) && (db == 0)||(da >=10) && (db >=10))

Don't forget TWO == signs when doing a check with an "if" statement.

One = sign is used for setting a variable to a value.

You could add a "or' ||, to add another check. This would say if either number is NOT = 0 and is not greater than 10....go straight.

Hi Tim,

In the end I brought some Yourdunino SRF06's. They are accurate at their distance measurements but unfortunately their distance max's out at about 200cm, beyond that they return 0's. I was looking for something which would hopefully be accurate to about 350cm.... I have gone ahead and bought a few of Maxbotix XL EZ0 sensors. Do you think that I could modify your New Ping code to work with these sensors or would I need to start from scratch?

bassmagnetic:
Hi Tim,

In the end I brought some Yourdunino SRF06's. They are accurate at their distance measurements but unfortunately their distance max's out at about 200cm, beyond that they return 0's. I was looking for something which would hopefully be accurate to about 350cm.... I have gone ahead and bought a few of Maxbotix XL EZ0 sensors. Do you think that I could modify your New Ping code to work with these sensors or would I need to start from scratch?

Did you set the maximum distance to higher than 200cm? Mine work well to easily over 400cm. Maybe it's the size of the object or how sonically reflective it is? Try using a wall as your maximum distance measurements, that's what the distance specs use.

Tim

Yes, I set the maximum distance at 300 but then the sensors return 0's. All the sensors are pointing at a solid wall 250cm away, but the sensors are returning 0's rather than seeing the wall, thus I'm assuming out of their range. I thought it strange as the Hr04's measured/worked fine over this distance. I've tried different delay times to see if there is any interference, up to 100ms but it makes no difference to the readings