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

teckel:

Stanley:
Dear Tim,

Are you able to add the option to have the distance measurement/pulse width based on LOW signal instead of HIGH signal ? With this, the URM37 passive PWM mode should work with the NewPing library...

Thanks

It would be possible. But would be like shooting in the dark without an actual sensor to test with. There could be a host of other problems. From your testing, is it sending out a single low pulse or is it pulses as the documentation states?

Tim

From my observation on the scope, it is sending multiple pulses based on the returned ping timing/distance..

I'm not sure what the NewPing does on the trigger pins but it surely trigger the PWM pins to send a LOW pulse per trigger on a constant basis...

I thought if the library read a high pulse whereas the URM37 reads a low pulse, a "simple" #if define URM37 would change the codes whereas all the other codes and timing would remain the same...

*** I could be wrong or it just sounded too simplified...

Stanley:
I thought if the library read a high pulse whereas the URM37 reads a low pulse, a "simple" #if define URM37 would change the codes whereas all the other codes and timing would remain the same...

*** I could be wrong or it just sounded too simplified...

You're right, that would be all that's required to read a LOW pulse instead of a HIGH pulse. It's a little more complicated as it waits and makes sure the signal is LOW before it times the HIGH pulse. But, it's still shooting in the dark without the sensor in front of me.

You can try the following changes to NewPing.cpp, which just changes the pulse measurement from HIGH to LOW:

	while (!(*_echoInput & _echoBit))                   // Wait for the ping echo.
	while (!(*_echoInput & _echoBit) && micros() <= _max_time) {} // Wait for echo pin to clear.
	while (*_echoInput & _echoBit)                                // Wait for ping to start.
	if (*_echoInput & _echoBit) {    // Ping echo received.

Give it a go. Keep in mind that this is just a guess, and we're still assuming a lot. But, it's a simple thing to try. There's other issues as well, like this could give a reading, but it may not be consistent or accurate due to timing issues.

Let me know what happens.

Tim

teckel:
You're right, that would be all that's required to read a LOW pulse instead of a HIGH pulse. It's a little more complicated as it waits and makes sure the signal is LOW before it times the HIGH pulse. But, it's still shooting in the dark without the sensor in front of me.

You can try the following changes to NewPing.cpp, which just changes the pulse measurement from HIGH to LOW:

	while (!(*_echoInput & _echoBit))                   // Wait for the ping echo.
	while (!(*_echoInput & _echoBit) && micros() <= _max_time) {} // Wait for echo pin to clear.
while (*_echoInput & _echoBit)                                // Wait for ping to start.





if (*_echoInput & _echoBit) {    // Ping echo received.




Tim

Dear Tim,

I made the changes to the suggested codes and it WORKS on the URM37 using the Examples codes...

I'm using Pin4 for PWM & Pin5 for Trigger...

I also tried with TWO sensors and it is still working without any delays between reading the sensors...

Let me capture a scope output and post it here later...

Thanks a lot!!!

Stanley

Stanley:
I made the changes to the suggested codes and it WORKS on the URM37 using the Examples codes...

I'm using Pin4 for PWM & Pin5 for Trigger...

I also tried with TWO sensors and it is still working without any delays between reading the sensors...

Let me capture a scope output and post it here later...

Thanks a lot!!!

Stanley

We got lucky for sure. Is it reading accurate distances? 3 distances are a good test (10cm, 50cm and 200cm) something like that. It probably won't be prefect, but within about 1cm is about the best you can hope for with ultrasonic sensors. As it is now, we're assuming 50uS is really 1cm. Also, you should probably try to test the ping_in() method to make sure the inches are also correct.

I've implemented changes to the NewPing Library to a allow support for the URM37 sensor in PWM mode. v1.6 will include this support. There's a URM37_ENABLED define you set to "true" to enable support (which measures the low signal length instead of the high and adjusts the length so each 50uS is 1cm).

Tim

teckel:
We got lucky for sure. Is it reading accurate distances? 3 distances are a good test (10cm, 50cm and 200cm) something like that. It probably won't be prefect, but within about 1cm is about the best you can hope for with ultrasonic sensors. As it is now, we're assuming 50uS is really 1cm. Also, you should probably try to test the ping_in() method to make sure the inches are also correct.

I've implemented changes to the NewPing Library to a allow support for the URM37 sensor in PWM mode. v1.6 will include this support. There's a URM37_ENABLED define you set to "true" to enable support (which measures the low signal length instead of the high and adjusts the length so each 50uS is 1cm).

Tim

I did some measurements, the distance of the following looks good :-

10cm - ok
50cm - ok
100cm - ok
150cm - ok
200cm - ok

With +/- 1 to 2cm variance for distance above 100cm...

I have a strange issues, one of the URM37 sensors, after operating for 7-9 hours, it just stop working... ( I think this is related to the sensors and nothing to do with the NewPing lib ), even after I do multiple reset, it is still not responding and gives a 50,000us ( means reading is invalid )...

I'll report this issue back to DFRobot for this...

Hello, I have a big problem and I need help. I'm trying to use the Ultrasonic Sensor HC-SR04 to make a project, I have this sensor connected to the arduino via USB and the problem is that i get multiple values of 0cm. For example i mesure 3cm, 4cm, 4cm, 5cm, 0cm,0cm,0cm,0cm, 6cm, 0cm,0cm,0cm, 8cm. I tried with the Newping library and with another library called Ultrasonic but it was the same. Something awkward is that when i use the Ultrasonic Library with the example code, it works great. But when i upload my example the problem starts.

This is my code:


#include <Ultrasonic.h>
const int alarmPin = 7;
const int alarm2Pin = 6;
Ultrasonic ultrasonic(9,8,5000); // (Trig PIN,Echo PIN, Max.TimeOut in µsec )

void setup() {
Serial.begin(9600);
pinMode(alarmPin, OUTPUT);
pinMode(alarm2Pin, OUTPUT);
}

void loop()
{
if (ultrasonic.Ranging(CM) >= 10)
{
digitalWrite(alarmPin, HIGH);
}
else
{
digitalWrite(alarmPin, LOW);
}
if (ultrasonic.Ranging(CM) < 10 && ultrasonic.Ranging(CM) > 5)
{
digitalWrite(alarm2Pin, HIGH);
}
else
{
digitalWrite(alarm2Pin, LOW);
}
Serial.print(ultrasonic.Ranging(CM));
Serial.println(" cm" );
delay(100);
}

Thanks for your help, and sry for my grammar.

Neonz:
Hello, I have a big problem and I need help. I'm trying to use the Ultrasonic Sensor HC-SR04 to make a project, I have this sensor connected to the arduino via USB and the problem is that i get multiple values of 0cm. For example i mesure 3cm, 4cm, 4cm, 5cm, 0cm,0cm,0cm,0cm, 6cm, 0cm,0cm,0cm, 8cm. I tried with the Newping library and with another library called Ultrasonic but it was the same. Something awkward is that when i use the Ultrasonic Library with the example code, it works great. But when i upload my example the problem starts.

I can't really help with someone else's library, but I do see why it's not working for you. Use the following script with my NewPing library and then if there's still a problem I can diagnose it for you:

#include <NewPing.h>

#define alarmPin 7
#define alarm2Pin 6

#define TRIGGER_PIN   9  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN      8  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(9600);
  pinMode(alarmPin, OUTPUT);
  pinMode(alarm2Pin, OUTPUT);
}

void loop() {
  unsigned int cm = sonar.ping_cm(); // Send ping, get ping distance in cm.
  Serial.print(cm);
  Serial.println(" cm");
  if (cm >= 10) { 
    digitalWrite(alarmPin, HIGH); 
  } else {
    digitalWrite(alarmPin, LOW); 
  }
  if (cm < 10 && cm > 5)  { 
    digitalWrite(alarm2Pin, HIGH); 
  } else {
    digitalWrite(alarm2Pin, LOW); 
  }
  delay(100);
}

That script should be a drop-in replacement using NewPing for your defective script. Let me know what happens.

Tim

Unfortunately for me, I am using the tone library and wanted to use the NewPing library too.
Do you know any way around the conflict?
It can be also a new tone library (or a modified one) or another way of playing a tone without the usage of the Timer2

TIA,
basile

basile-laderchi:
Unfortunately for me, I am using the tone library and wanted to use the NewPing library too.
Do you know any way around the conflict?
It can be also a new tone library (or a modified one) or another way of playing a tone without the usage of the Timer2

TIA,
basile

NewPing only uses a timer interrupt when using the event-driven ping method "ping_timer". The standard "ping" method as in the example sketch that starts this thread doesn't use any timer interrupts at all.

Do you need to use the event-driven ping method? Or, do you somehow believe that NewPing always uses a timer interrupt? If you believe NewPing always uses a timer interrupt, maybe you could explain why you believed this so I can make this more clear to other users.

Tim

This is part of the sketch I am using:

#include <NewPing.h>

NewPing sonar = NewPing(A4, A4, 300);

void setup() {
}

void loop() {
  tone(12, 2999, 3000);
}

When I try to verify the sketch I always get this error:

core.a(Tone.cpp.o): In function `__vector_7':
C:\...\arduino-1.0\hardware\arduino\cores\arduino/Tone.cpp:523: multiple definition of `__vector_7'
NewPing\NewPing.cpp.o:C:\...\Documents\Arduino\libraries\NewPing/NewPing.cpp:214: first defined here

Even when I comment out or delete the 3rd line ("NewPing sonar = ...") I still get the same error.

basile

P.S.: I am using a Parallax PING))) sensor on an Arduino UNO board and I think (I am not sure because the test has been performed by a friend) that when it is connected to A4 (as in the example) it doesn't work. Unfortunately right now there are no digital ports available.

This is part of the sketch I am using:

This is part of an answer I am giving: tone.

AWOL:

basile-laderchi:
This is part of the sketch I am using:

This is part of an answer I am giving: tone.

That's exactly why I replaced the tone function with this function:

void toneWorkaround(byte tonePin, int frequency, int duration) {
  int period = 1000000L / frequency;
  int pulse = period / 2;
  for (long i = 0; i < duration * 1000L; i += period) {
    digitalWrite(tonePin, HIGH);
    delayMicroseconds(pulse);
    digitalWrite(tonePin, LOW);
    delayMicroseconds(pulse);
  }
}

Even after this modification to my code though the Parallax PING))) refuses to work when using the NewPing library.

Right now the Parallax PING))) is working and returning correct values with this code:

long ping(byte pingPin) {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  pinMode(pingPin, INPUT);
  long duration = pulseIn(pingPin, HIGH);
  return duration;
}

basile

P.S.: robot's full code as is right now: Wheeled-Robot Arduino Code - Pastebin.com

basile-laderchi:
This is part of the sketch I am using:

#include <NewPing.h>

NewPing sonar = NewPing(A4, A4, 300);

void setup() {
}

void loop() {
  tone(12, 2999, 3000);
}




When I try to verify the sketch I always get this error:


~~~
core.a(Tone.cpp.o): In function `__vector_7':

C:...\arduino-1.0\hardware\arduino\cores\arduino/Tone.cpp:523: multiple definition of `__vector_7'
NewPing\NewPing.cpp.o:C:...\Documents\Arduino\libraries\NewPing/NewPing.cpp:214: first defined here




Even when I comment out or delete the 3rd line ("NewPing sonar = ...") I still get the same error.

basile

P.S.: I am using a Parallax PING))) sensor on an Arduino UNO board and I think (I am not sure because the test has been performed by a friend) that when it is connected to A4 (as in the example) it doesn't work. Unfortunately right now there are no digital ports available.

Just comment out line 214, 216, and 217 in NewPing.cpp if you're not using the interrupt method of NewPing. Commenting out the "NewPing sonar=" line won't help as the library files are loaded via the #include <NewPing.h>

Not sure what can be done to fix this without manually commenting out the lines. If anyone has any suggestions I'd appreciate it. At least the solution is very straight-forward and simple.

Tim

For this line in the example:
Serial.print(uS / US_ROUNDTRIP_IN); // Convert ping time to distance in cm and print result (0 = outside set distance range)

Is there a way to have "outside distance range" read the MAX_DISTANCE value instead of 0?

caseyd:
For this line in the example:
Serial.print(uS / US_ROUNDTRIP_IN); // Convert ping time to distance in cm and print result (0 = outside set distance range)

Is there a way to have "outside distance range" read the MAX_DISTANCE value instead of 0?

First, that would probably be a bad idea because a value of MAX_DISTANCE would indicate there was something there. In other words, you wouldn't know if there was actually something exactly at 200cm away or if there was no ping echo if MAX_DISTANCE was set to 200.

With that said, you can easily do what you want. See the following code snippet:

  long uS = sonar.ping();
  if (uS == NO_ECHO) uS = MAX_DISTANCE;
  Serial.print(uS);

Tim

Hi Tim,

I want to use 12 sensors, which is obviously achievable with your code, I have got 6 working really well so far so thank you.... however there are only 12 pins on the arduino uno, so I can only use 6 sensors (obviously 2pins per sensor). I see you can buy a Mux shield to add more inputs. Would this shield work with your code? (I'm very new to code). Would I need to change the code much to make it work? or is there a better / easier option?

Thanks again

@ bassmagnetic

Some time in the earlier pages, Tim made it possible to run each sensor from one digital pin, +5, and GND. So, the result is that 12 sensors require 12 digital pins.

Check the examples with his library.

EDIT: his discovery of the one pin method was reported on page 7 of this thread. I am not sure what page the addition was made to the examples.

bassmagnetic:
Hi Tim,

I want to use 12 sensors, which is obviously achievable with your code, I have got 6 working really well so far so thank you.... however there are only 12 pins on the arduino uno, so I can only use 6 sensors (obviously 2pins per sensor). I see you can buy a Mux shield to add more inputs. Would this shield work with your code? (I'm very new to code). Would I need to change the code much to make it work? or is there a better / easier option?

Thanks again

cyclegadget is quite right, I've written the NewPing library to work using only one one pin for both trigger and echo. So, with even the Uno you can connect 12 ping sensors using the NewPing library. Basically, the library sets the pin to output, initiates the ping, quickly switches the same pin to input, and waits for the ping echo. The syntax is just to specify the same pin for both trigger and echo. Below is an example sketch as well as a schematic of how you connect the sensor. You simply tie the pin to trigger and then jumper trigger to echo.

http://code.google.com/p/arduino-new-ping/wiki/NewPing_Single_Pin_Sketch

Before you rip your project apart and use the one pin method I would suggest doing just one sensor first. The reason is that for some sensors this one pin technique doesn't work. If you're using the HC-SR04, you should be good to go. Others may need a little capacitor instead of the jumper. I believe I docucmented in the release notes in NewPing.h exactly which sensors worked without the cap and those that needed the cap. Check the release notes in NewPing.h for details.

Also, I'm always interested to see what multi ping sensor projects people are using with NewPing. Once you get things working, post a pic.

Tim

Brilliant, thanks Tim, just tried that and it works fine with 1 sensor, I am using HC-SR04's.... much better than buying more bits!!

Now I just need to figure out how to combine this code with the NewPing15sensor code to make it work with more sensors, any ideas, is it easy to do?

I am needing to increase the number of sensors as I want to make sure that proximately to the speakers does not trigger sounds (so no one goes deaf!)

I am making an installation as part of a final piece for an MA, i'd be happy to send details and photos when its all up and running...

thanks again

andre

bassmagnetic:
Brilliant, thanks Tim, just tried that and it works fine with 1 sensor, I am using HC-SR04's.... much better than buying more bits!!

Now I just need to figure out how to combine this code with the NewPing15sensor code to make it work with more sensors, any ideas, is it easy to do?

I am needing to increase the number of sensors as I want to make sure that proximately to the speakers does not trigger sounds (so no one goes deaf!)

I am making an installation as part of a final piece for an MA, i'd be happy to send details and photos when its all up and running...

thanks again

andre

Just take the 15 sensor sketch and for each sensor use the same trigger and echo pin. For example, the first part of your sketch would look something like this:

#include <NewPing.h>

#define SONAR_NUM     12 // 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(2, 2, MAX_DISTANCE), // Using same pin for trigger and echo.
  NewPing(3, 3, MAX_DISTANCE),
  NewPing(4, 4, MAX_DISTANCE),
  NewPing(5, 5, MAX_DISTANCE),
  NewPing(6, 6, MAX_DISTANCE),
  NewPing(7, 7, MAX_DISTANCE),
  NewPing(8, 8, MAX_DISTANCE),
  NewPing(9, 9, MAX_DISTANCE),
  NewPing(10, 10, MAX_DISTANCE),
  NewPing(11, 11, MAX_DISTANCE),
  NewPing(12, 12, MAX_DISTANCE),
  NewPing(13, 13, MAX_DISTANCE)
};

Tim