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

I solved it!

External power is needed to the Arduino, i.e. just powering via USB is not enough to get good results when multiple ping sensors and an Ethernet shield are used.
This is regardless if an Mega or an Uno are used, or if the PC have 1 or 2 PSUs.

//Magnus

Hi everyone! I have a question... if I use 4 ultrasonic sensors and I want to send the data to Processing for transforming the data to OSC, can I use the 15 sensors sketch but with 4?? I don't know how can i do it...

oigres666:
Hi everyone! I have a question... if I use 4 ultrasonic sensors and I want to send the data to Processing for transforming the data to OSC, can I use the 15 sensors sketch but with 4?? I don't know how can i do it...

#define SONAR_NUM       4 // Number of sensors.

gandalf50:
I solved it!

External power is needed to the Arduino, i.e. just powering via USB is not enough to get good results when multiple ping sensors and an Ethernet shield are used.
This is regardless if an Mega or an Uno are used, or if the PC have 1 or 2 PSUs.

//Magnus

Interesting! My ultrasonic sensors only use a couple mA each, while the Arduino Uno uses 60 mA (I'd guess the Mega uses more). I wouldn't think that just the sensors would put your USB or the voltage regulator over the top. Have you measured what kind of current it's using? It just seems very unlikely that it's within a couple mA of going over the top and the sensors draw enough current to do it. I guess it's possible, just doesn't seem likely.

Tim

cyclegadget:

oigres666:
Hi everyone! I have a question... if I use 4 ultrasonic sensors and I want to send the data to Processing for transforming the data to OSC, can I use the 15 sensors sketch but with 4?? I don't know how can i do it...

#define SONAR_NUM       4 // Number of sensors.

yeah, I know that, but i want to know how to send to processing, How can processing read this data???.... coz from processing i can transform the data to OSC...or am I wrong?? :cold_sweat:
Thank u!

oigres666:

cyclegadget:

oigres666:
Hi everyone! I have a question... if I use 4 ultrasonic sensors and I want to send the data to Processing for transforming the data to OSC, can I use the 15 sensors sketch but with 4?? I don't know how can i do it...

#define SONAR_NUM       4 // Number of sensors.

yeah, I know that, but i want to know how to send to processing, How can processing read this data???.... coz from processing i can transform the data to OSC...or am I wrong?? :cold_sweat:
Thank u!

What do you mean by "i want to know how to send to processing"? What is "processing"? What is "OSC"?

The sketch pings the sensors and stores the values in the cm[] array. In the pingResult() function the contents of the cm[] array are output via serial. If you want to send that data to something else, whatever "processing" and "OSC" is, you would simply replace the contents of the pingResults() function with whatever you wanted to do with the results. We have no idea what you want to do with the results, but the data is there for you to do whatever you want with it. The pingResults() function is where you should do your magic with the results.

I have a post with help and alternative code for the 15 sensor sketch.

Tim

Just used this on a project I was building against my digispark. I removed the timer stuff since I didn't need them and it wouldn't compile against it. But anyway. worked great and was better than me trying to futz with timing all day long. Thanks!!

DigiStump's forum post for the project: RGB Shield used to "output" range

Youtube of it running: HC-SR04 on a digispark w/ RGB shield - YouTube

rainierez:
Just used this on a project I was building against my digispark. I removed the timer stuff since I didn't need them and it wouldn't compile against it. But anyway. worked great and was better than me trying to futz with timing all day long. Thanks!!

I think the digispark uses the ATtiny85, that would make sense that it wouldn't work with the timer stuff. I believe I've modified my development code to detect the ATtiny processors and not use the timer interrupt stuff. The standard ping(), ping_cm(), ping_in(), ping_median() methods should still work just fine on the ATtiny.

If program space is also a problem with the limited memory on the ATtiny, you could reduce the compiled size by optimizing your sketch a little. Here's a suggestion:

#include <NewPing.h>

#define TRIGGER_PIN 3
#define ECHO_PIN 5
#define RED_PIN 0
#define GREEN_PIN 1
#define BLUE_PIN 4
#define MAX_DISTANCE 60

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

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
}

void loop() {
  uint8_t distance = sonar.ping_cm();
  
  if (distance) {
    uint8_t greenValue = map(distance, 1, MAX_DISTANCE, 0, 255);  //Map the distance range to a range of 0 to 255 to the pwm value for the Green LED
    uint8_t redValue = 255 - greenValue;
    analogWrite(GREEN_PIN, greenValue);
    analogWrite(RED_PIN, redValue);
    digitalWrite(BLUE_PIN, LOW);
  } else {
    //Out of range, turn the LED blue
    digitalWrite(GREEN_PIN, LOW);
    digitalWrite(RED_PIN, LOW);    
    digitalWrite(BLUE_PIN, HIGH);
  }
  delay(50);
}

This would use quite a bit less sketch size and reduce the memory usage as well by using defines and right-sized variables.

On a side note, the digispark is under-powered and overpriced. For a couple dollars more you can get a Teensy 2.0 which is practically the same size and a full ATmega microcontroller so you have a ton of available pins (actually, it has more pins than an Arduino Uno). For just $3 more you can also get the Teensy 3.0 which is a 96 MHz 32-bit microcontroller, but still works with Arduino IDE.

Tim

teckel:

oigres666:

cyclegadget:

oigres666:
Hi everyone! I have a question... if I use 4 ultrasonic sensors and I want to send the data to Processing for transforming the data to OSC, can I use the 15 sensors sketch but with 4?? I don't know how can i do it...

#define SONAR_NUM       4 // Number of sensors.

yeah, I know that, but i want to know how to send to processing, How can processing read this data???.... coz from processing i can transform the data to OSC...or am I wrong?? :cold_sweat:
Thank u!

What do you mean by "i want to know how to send to processing"? What is "processing"? What is "OSC"?

The sketch pings the sensors and stores the values in the cm[] array. In the pingResult() function the contents of the cm[] array are output via serial. If you want to send that data to something else, whatever "processing" and "OSC" is, you would simply replace the contents of the pingResults() function with whatever you wanted to do with the results. We have no idea what you want to do with the results, but the data is there for you to do whatever you want with it. The pingResults() function is where you should do your magic with the results.

I have a post with help and alternative code for the 15 sensor sketch.

Tim

First of all, thank you for answering Tim! Processing is a language like, java, C++, etc... and OSC it's a protocol like MIDI for controlling a virtual instrument or whatever in your computer... My project is with 4 ultrasonic sensors to get the results and transform them into OSC so you can control eg. Ableton Live or whatever, moving your hands you can change a synth's parameters in real time.... Your code works perfectly for my 4 sensors! Now with your advice I'm going to try "play" with the data... Maybe I could obviate "Processing" and finding a library for Arduino which I can handle OSC... hahahaha sorry I'm rambling...
Anyway Thanks for ur code again!!!

I think the digispark uses the ATtiny85, that would make sense that it wouldn't work with the timer stuff. I believe I've modified my development code to detect the ATtiny processors and not use the timer interrupt stuff. The standard ping(), ping_cm(), ping_in(), ping_median() methods should still work just fine on the ATtiny.

If program space is also a problem with the limited memory on the ATtiny, you could reduce the compiled size by optimizing your sketch a little. Here's a suggestion:

#include <NewPing.h>

#define TRIGGER_PIN 3
#define ECHO_PIN 5
#define RED_PIN 0
#define GREEN_PIN 1
#define BLUE_PIN 4
#define MAX_DISTANCE 60

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

void setup() {
 pinMode(RED_PIN, OUTPUT);
 pinMode(GREEN_PIN, OUTPUT);
 pinMode(BLUE_PIN, OUTPUT);
}

void loop() {
 uint8_t distance = sonar.ping_cm();
 
 if (distance) {
   uint8_t greenValue = map(distance, 1, MAX_DISTANCE, 0, 255);  //Map the distance range to a range of 0 to 255 to the pwm value for the Green LED
   uint8_t redValue = 255 - greenValue;
   analogWrite(GREEN_PIN, greenValue);
   analogWrite(RED_PIN, redValue);
   digitalWrite(BLUE_PIN, LOW);
 } else {
   //Out of range, turn the LED blue
   digitalWrite(GREEN_PIN, LOW);
   digitalWrite(RED_PIN, LOW);    
   digitalWrite(BLUE_PIN, HIGH);
 }
 delay(50);
}




This would use quite a bit less sketch size and reduce the memory usage as well by using defines and right-sized variables.

On a side note, the digispark is under-powered and overpriced. For a couple dollars more you can get a Teensy 2.0 which is practically the same size and a full ATmega microcontroller so you have a ton of available pins (actually, it has more pins than an Arduino Uno). For just $3 more you can also get the Teensy 3.0 which is a 96 MHz 32-bit microcontroller, but still works with Arduino IDE.

Tim

Great stuff, I'm a hardware junky that knows enough code to be stupid with it. so seeing someone that knows how to make it effecient is alway a bonus. Thanks for cleaning that up a ton. I will have a go with that and let you know.

Again Thanks!

The new code you updated works great but if I leave the timer functions in the cpp then it won't compile. :confused: I get this in the IDE

...\Arduino\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_us(unsigned int, void (*)())':
...\Arduino\libraries\NewPing\NewPing.cpp:151: error: 'OCR2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:152: error: 'TIMSK2' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:152: error: 'OCIE2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_ms(long unsigned int, void (*)())':
...\Arduino\libraries\NewPing\NewPing.cpp:167: error: 'OCR2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:168: error: 'TIMSK2' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:168: error: 'OCIE2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_stop()':
...\Arduino\libraries\NewPing\NewPing.cpp:177: error: 'TIMSK2' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:177: error: 'OCIE2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_setup()':
...\Arduino\libraries\NewPing\NewPing.cpp:195: error: 'ASSR' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:195: error: 'AS2' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:196: error: 'TCCR2A' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:196: error: 'WGM21' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:197: error: 'TCCR2B' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:197: error: 'CS22' was not declared in this scope
...\Arduino\libraries\NewPing\NewPing.cpp:198: error: 'TCNT2' was not declared in this scope

rainierez:
The new code you updated works great but if I leave the timer functions in the cpp then it won't compile. :confused: I get this in the IDE

Yes, v1.5 of NewPing that you're running is not designed for the ATtiny. My development version now detects the ATtiny and automatically removes the timer stuff. In other words, you'll need to comment out the timer stuff in the library till I release version 1.6 of NewPing.

Tim

Hello,

I would like to ask if it is possibly to read the cm with decimal like 10.4 cm e.t.c.

Thank in advance.

Best regards,
Tasos

tasosstr:
Hello,

I would like to ask if it is possibly to read the cm with decimal like 10.4 cm e.t.c.

Thank in advance.

Best regards,
Tasos

Yes, simply use ping() which will return the milliseconds and then divide by whatever number you want to convert ms to cm (defaults to 57). The library uses integers to save program space (saves about 1k by avoiding floating point). Also, the accuracy isn't really better than a cm and there's other variables like temperature that will change the speed of sound and mess up your calculations.

However, keep in mind that doing any of this will really be of no good as the sensor is not accurate enough to actually give you a consistent reading of 10.4. If you did use a floating point number for ms to cm conversion, the ping results would probably jump around from 10.9 to 10.1, with everything still. So, I'm sure sure what use you'd really get from it. All you'd really be doing is wasting 1k of program space and getting a bunch of different readings and not knowing which one was right.

Basically, I'd suggest leaving it as-is and accepting that the sensor is really only accurate to 1cm or 1in. And, enjoy the extra speed and 1k of program space you saved by not using floating point calculations on things that are not accurate below an integer anyway. NewPing is designed to be small, fast, and accurate. Making it floating point would not help the accuracy and it would make it slower and larger. So, it would hurt the library in every way. But, you're free to use floating point if you wish by using the ping() method along with your own conversion (after also monitoring the temperature).

Let me know if you actually find this useful, I've yet to hear of it being at all useful or more accurate.

Tim

Well that's a good point, but it is still likely to jump around between 10 and 11 cm.

teckel:
Interesting! My ultrasonic sensors only use a couple mA each, while the Arduino Uno uses 60 mA (I'd guess the Mega uses more). I wouldn't think that just the sensors would put your USB or the voltage regulator over the top. Have you measured what kind of current it's using? It just seems very unlikely that it's within a couple mA of going over the top and the sensors draw enough current to do it. I guess it's possible, just doesn't seem likely.

Tim

Well it did it for me at least. Hopefully it helps someone else as well.

The operating voltage for the HC-SR04 should apperently be 4.50 to 5.0V. But I did some quick measurements which shows that that's not the case for my sensors:

With Ethernet shield:

  1. Power via USB port
    1.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.55 V
    1.2. Without LCD Screen: 4.60 V

  2. Power from power outlet
    2.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.98 V
    2.2. Without LCD Screen: 4.98 V

Without Ethernet shield:
3. Power via USB port
3.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.76 V
3.2. Without LCD Screen: 4.82 V

  1. Power from power outlet
    4.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.98 V
    4.2. Without LCD Screen: 4.98 V

i.e. since it doesn't work properly for me with just the sensors and the Ethernet shield connected (using just USB), over 4.60V seems to be needed.

michinyon:
Well that's a good point, but it is still likely to jump around between 10 and 11 cm.

Not if you turn off rounding. But, you are right, it can bounce between to different integers as well. However, that's because the sensor is not accurate to a fraction of a cm. It's not because the library doesn't do floating point. Basically, it's not helpful to do floating point math. But, feel free to do it. Replace "ping_cm()" with "ping()/57.0" and you'll get a decimal result. If you find this useful I'd really be amazed, but the library is designed so you can do it as shown.

Tim

gandalf50:

teckel:
Interesting! My ultrasonic sensors only use a couple mA each, while the Arduino Uno uses 60 mA (I'd guess the Mega uses more). I wouldn't think that just the sensors would put your USB or the voltage regulator over the top. Have you measured what kind of current it's using? It just seems very unlikely that it's within a couple mA of going over the top and the sensors draw enough current to do it. I guess it's possible, just doesn't seem likely.

Tim

Well it did it for me at least. Hopefully it helps someone else as well.

The operating voltage for the HC-SR04 should apperently be 4.50 to 5.0V. But I did some quick measurements which shows that that's not the case for my sensors:

With Ethernet shield:

  1. Power via USB port
    1.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.55 V
    1.2. Without LCD Screen: 4.60 V

  2. Power from power outlet
    2.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.98 V
    2.2. Without LCD Screen: 4.98 V

Without Ethernet shield:
3. Power via USB port
3.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.76 V
3.2. Without LCD Screen: 4.82 V

  1. Power from power outlet
    4.1. With LCD screen connected as well, at 3 HC-SR04 ultrasonic sensors: 4.98 V
    4.2. Without LCD Screen: 4.98 V

i.e. since it doesn't work properly for me with just the sensors and the Ethernet shield connected (using just USB), over 4.60V seems to be needed.

I've ran ultrasonic sensors down to 3.3 volts and they still work. I forgot I have an Internet shield, I'll see what kind of milliamps it uses.

Tim

teckel:

tasosstr:
Hello,

I would like to ask if it is possibly to read the cm with decimal like 10.4 cm e.t.c.

Thank in advance.

Best regards,
Tasos

Yes, simply use ping() which will return the milliseconds and then divide by whatever number you want to convert ms to cm (defaults to 57). The library uses integers to save program space (saves about 1k by avoiding floating point). Also, the accuracy isn't really better than a cm and there's other variables like temperature that will change the speed of sound and mess up your calculations.

However, keep in mind that doing any of this will really be of no good as the sensor is not accurate enough to actually give you a consistent reading of 10.4. If you did use a floating point number for ms to cm conversion, the ping results would probably jump around from 10.9 to 10.1, with everything still. So, I'm sure sure what use you'd really get from it. All you'd really be doing is wasting 1k of program space and getting a bunch of different readings and not knowing which one was right.

Basically, I'd suggest leaving it as-is and accepting that the sensor is really only accurate to 1cm or 1in. And, enjoy the extra speed and 1k of program space you saved by not using floating point calculations on things that are not accurate below an integer anyway. NewPing is designed to be small, fast, and accurate. Making it floating point would not help the accuracy and it would make it slower and larger. So, it would hurt the library in every way. But, you're free to use floating point if you wish by using the ping() method along with your own conversion (after also monitoring the temperature).

Let me know if you actually find this useful, I've yet to hear of it being at all useful or more accurate.

Tim

Hello Dear Tim,

Thank you very much for the reply and for the help ! ! !

You have make amazing work well done ! ! !

I was try the bellow example:

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 500 // 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(115200); // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  float uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}

and working perfect ! ! !

I need this because i want to get the height of a petrol tank, so now i can have more better results because of you :slight_smile:

Again Thank you Very Much ! ! !

Best Regards,
Tasos

THANKS FOR THIS NEW SONIC LIBRARY! GREAT WORK !!!!!!!!!!!!!!!!!!!