Go Down

Topic: NewPing Library: HC-SR04, SRF05, SRF06, DYP-ME007, Parallax PING))) - v1.5 (Read 128 times) previous topic - next topic

Human

The test run I did earlier today isn't valid because I didn't notice the pin changes between the last test sketch and this one. (echo pin changed from 13 to 11).  After making that change, I am seeing distances being reported in the test library versions that I tried.  I wonder if there's a problem using pin 13 because it's also for the built-in LED.

I have to stop for today, but I tried NewPing 1.3 with this configuration, and I'm seeing distances there, too. I need to make sure I can consistently get results, but in the meantime, I'll investigate and see if I can try to make it fail again.

Human

I think I have good news, but it's not what either of us expected.

The "0cm" problem with the Duemilanove seems to be because of pin 13. The Duemilanove can't use pin 13 as the echoPin. It works fine on the Uno R3, but the Duemilanove doesn't like it. Changing it from pin 13 to pin 11 (and probably any other appropriate pin) makes NewPing work on the Duemilanove back to v1.3 and with the test versions you sent (at least the ones I re-tested).

I believe the previous example sketch version used pin 13, and you've changed it to be pin 11. If I had to guess, I'd say that the "0cm" bug was people on a Duemilanove (or similar) board using the example sketch and the example pins.

What do you think?

Human

Assuming that pin 13 really is the reason why the Duemilanove wasn't working with NewPing, I wanted to work on a contribution to the project. Everyone's experiences with the HC-SR* family of sensors is that they're *mostly* reliable, but they occasionally throw out a false positive or false negative. I've put digital filters in my code so that I don't trust readings until they remain consistent for a window of time or number of pings. It occurs to me that this would be of general utility, as an optional way of using NewPing objects.

Some ideas of how I'd do this:

  • 1) Sliding scale between responsive and trustworthy: Max responsiveness would provide no filter. Max trustworthiness would only trust a reading if there are no incompatible readings over a period of time, depending on whether we're trying to eliminate false positives or false negatives.

  • 2) "Best result in N ms": Similar to the above, except it only examines as many pings as it can in an N ms window. Should ensure that a filtered ping comes through in N ms, +/- some inherent latency

  • 3) Parameter-level tweaking: Open up all the configuration options to advanced users. They could specify a time-based filter or a filter that waits for N compatible pings in a row before believing the results.



I think I'd start with #1 and see how it's received.

Would you like me to have a go at coding this up? Would you prefer that I subclass NewPing or extend NewPing with additional methods that enable/configure the digital filter option? My intent is to not change the existing API so as not to break any legacy code, and I think either approach could facilitate that.

Human

(I couldn't decide if I should post a new topic for this.  It's only of value to people who use NewPing with the HC-SR04 / SRF05 family of sensors.)

I have a pre-alpha, proof of concept class called ConsensusDistance that takes a pointer to a NewPing object and acts as a wrapper for it, returning distance values that are likely to be trustworthy and not anomalous. Currently, you can define how long of a "streak" you choose to trust for in-range and out-of-range readings, in milliseconds. If the sensor reads a streak of in-range values for the appropriate time, it returns the last distance read. Similarly, if the sensor reads a streak of out-of-range values (0), it returns a 0. There's also a setting for tolerance of distance between streaks. (A sufficiently recent streak of in-range values means that reading a single new in-range value is vetted by the previous streak.)

Is anyone interested in trying it out?


teckel


Assuming that pin 13 really is the reason why the Duemilanove wasn't working with NewPing,


Pin 13 was my first guess as to the cause of the problem as there's an LED attached to it.  I've been suggesting to people to try different pin assignments and changed the default sketch to use pin 12 and 11 for a few weeks now.

With that said, I didn't ask you specifically not to use pin 13 for two reasons.  First, pin 13 works fine on the Uno and we both assumed you were using the Uno at the begining.  Secondly, the sketch you linked to at http://trollmaker.com/article3/arduino-and-hc-sr04-ultrasonic-sensor also uses pins 12 and 13.  So, to totally close this case, were you using the exact trollmaker sketch including using pins 12 and 13 or did you use that sketch but with different pins?  The TestF library is basically exactly the same as the trollmaker sketch.  If the Duemilanove really can't use pin 13 as a input, it shouldn't be able to with either the NewPing library or the trollmaker sketch (as it uses pin 13 for input).


I wanted to work on a contribution to the project. Everyone's experiences with the HC-SR* family of sensors is that they're *mostly* reliable, but they occasionally throw out a false positive or false negative. I've put digital filters in my code so that I don't trust readings until they remain consistent for a window of time or number of pings. It occurs to me that this would be of general utility, as an optional way of using NewPing objects.

Some ideas of how I'd do this:

  • 1) Sliding scale between responsive and trustworthy: Max responsiveness would provide no filter. Max trustworthiness would only trust a reading if there are no incompatible readings over a period of time, depending on whether we're trying to eliminate false positives or false negatives.

  • 2) "Best result in N ms": Similar to the above, except it only examines as many pings as it can in an N ms window. Should ensure that a filtered ping comes through in N ms, +/- some inherent latency

  • 3) Parameter-level tweaking: Open up all the configuration options to advanced users. They could specify a time-based filter or a filter that waits for N compatible pings in a row before believing the results.



I think I'd start with #1 and see how it's received.

Would you like me to have a go at coding this up? Would you prefer that I subclass NewPing or extend NewPing with additional methods that enable/configure the digital filter option? My intent is to not change the existing API so as not to break any legacy code, and I think either approach could facilitate that.


I don't ever remember seeing false positives or false negatives.  For example, if I put an object a foot away from the sensor it will show a distance every time.  It may fluctuate a bit as far as the distance, but will never give a 0 reading.  Likewise, if I set the maximum distance at 200cm and have it ping out at a wall that's 15 feet away, it will always get a 0 reading.  Some, have incorrectly interpreted this as incorrect.  But, this is the correctly designed behavior.  You wouldn't want the sensor to report back 200cm when there was something 400cm away as you've set the sensor to only listen for objects 200cm away or closer.  A reading of 200cm would tell you that something is 200cm away, when there is not.  Any object beyond the specified maximum distance is returned as 0, which means "all clear".  It's slightly different with the timer interrupt method as we don't create an event unless there's something in-range.

I used the below sketch with your HC-SR04 sensor.  It does VERY fast pings and displays a "." if it gets a ping within 200cm or an "0" if it gets no ping (zero).  It displays it in 80 columns so a lot of data can quickly be looked after the test is complete.  Each line ends with the ping microseconds for the final ping (kind of a test to make sure you're understanding what it's showing).

Code: [Select]
#include <NewPing.h>
#define trigPin 12
#define echoPin 11
NewPing sonar(trigPin, echoPin, 200);
byte i = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  unsigned int us = sonar.ping();
  if (us==0) {
    Serial.print("0");
  } else {
    Serial.print(".");
  }
  i++;
  if (i==80) {
    Serial.print(" ");
    Serial.println(us);
    i=0;
  }
  delay(10);
}


I ran it for an hour pointing in the general area of my coffee cup and monitor sitting on my desk about 18 inches away and I got all periods, not a single "0".  A ping every 10ms for an hour is around 360,000 pings.  For the next test I turned the sensor around and pointed it towards a wall that was about 10 feet away.  I started the test and let it run for another hour and got nothing but zeros with no periods.

So, you may want to try the above sketch and a similar test before we try to filter false positives or false negatives that I can't even duplicate.  What I could see as useful is averaging.  Either a simple multi-sample average or a more complex standard deviation type calculation.  But, I question if this type of calculation is really outside the scope of an ultrasonic library as one could simply take the ping results and feed them to a standard deviation library to do the calculation.

Tim
Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

Go Up