Go Down

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

teckel


First, thank you for this valuable Ping Library,

I am attempting to use the same trigger ping for three HC-SR04 sensor on a Pro-Mini Arduino and so far, things appear to be working fine on the bench. My question is, are there any know issues with using the same trigger pin for two or more sensors?

Thank you.


I've never tried using the same trigger pin for multiple sensors nor is the library designed to work this way.  What NewPing would do would be to actually try to initiate a ping three times each sensor.  The sensor would probably ignore this, but there's no guarantee.  Also, I would be concerned with the higher likelihood of echos giving bad results or the pulsing from multiple sensors confusing the sensors.

It would be better (avoiding echos and cross-talk issues) and use fewer pins to just wire a single pin to each sensor's trigger and echo pin.  In other words, you would use 3 pins, each pin going to each sensor's trigger and echo pins.  This would use 3 pins instead of (I assume) the 4 pins you're currently using.  Yes, you would need to ping each sensor individually, but using the non-blocking ping_timer() method your microcontroller could be doing other things while the ping sound is traveling.  I would consider this a more "sound" way to implement 3 sensors.

May I ask, why do you want to ping all three at the same time?  Would it really matter if each ping was 30ms apart?  You could still ping 3 sensors 10 times a second while still "multi-tasking" and doing other processes in your sketch.  Insight on your project and the reasoning would be helpful.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

reverendrichie



I've never tried using the same trigger pin for multiple sensors nor is the library designed to work this way.  What NewPing would do would be to actually try to initiate a ping three times each sensor.  The sensor would probably ignore this, but there's no guarantee.  Also, I would be concerned with the higher likelihood of echos giving bad results or the pulsing from multiple sensors confusing the sensors.

It would be better (avoiding echos and cross-talk issues) and use fewer pins to just wire a single pin to each sensor's trigger and echo pin.  In other words, you would use 3 pins, each pin going to each sensor's trigger and echo pins.  This would use 3 pins instead of (I assume) the 4 pins you're currently using.  Yes, you would need to ping each sensor individually, but using the non-blocking ping_timer() method your microcontroller could be doing other things while the ping sound is traveling.  I would consider this a more "sound" way to implement 3 sensors.

May I ask, why do you want to ping all three at the same time?  Would it really matter if each ping was 30ms apart?  You could still ping 3 sensors 10 times a second while still "multi-tasking" and doing other processes in your sketch.  Insight on your project and the reasoning would be helpful.

Tim


Thank you for the very quick response Tim,

The primary reason is the limitation of available pins on the Pro-Mini. I have each sensor angled outside of each others echo zone. so there is little or no interferences that I can detect at this point. I may have to upgrade to a Arduino mega before this project is finish.

teckel




I've never tried using the same trigger pin for multiple sensors nor is the library designed to work this way.  What NewPing would do would be to actually try to initiate a ping three times each sensor.  The sensor would probably ignore this, but there's no guarantee.  Also, I would be concerned with the higher likelihood of echos giving bad results or the pulsing from multiple sensors confusing the sensors.

It would be better (avoiding echos and cross-talk issues) and use fewer pins to just wire a single pin to each sensor's trigger and echo pin.  In other words, you would use 3 pins, each pin going to each sensor's trigger and echo pins.  This would use 3 pins instead of (I assume) the 4 pins you're currently using.  Yes, you would need to ping each sensor individually, but using the non-blocking ping_timer() method your microcontroller could be doing other things while the ping sound is traveling.  I would consider this a more "sound" way to implement 3 sensors.

May I ask, why do you want to ping all three at the same time?  Would it really matter if each ping was 30ms apart?  You could still ping 3 sensors 10 times a second while still "multi-tasking" and doing other processes in your sketch.  Insight on your project and the reasoning would be helpful.

Tim


Thank you for the very quick response Tim,

The primary reason is the limitation of available pins on the Pro-Mini. I have each sensor angled outside of each others echo zone. so there is little or no interferences that I can detect at this point. I may have to upgrade to a Arduino mega before this project is finish.


How many pins are you using?  4?  One pin for triggers on all sensors and 3 pins to get the results from each sensor?  If so, you could just use 3 pins by using the method I describe.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

reverendrichie




How many pins are you using?  4?  One pin for triggers on all sensors and 3 pins to get the results from each sensor?  If so, you could just use 3 pins by using the method I describe.

Tim


Please forgive me Tim, I am not understanding, I am using four pins as you have stated but I don't understand how to wire the sensor to only use three pins. This surely would be better because I can add a forth sensor pointing to the rear.

Here is the setup code I am presently using.

Code: [Select]

#define LED_STATUS_PIN 13
#define SONAR_NUM     3 // Number or sensors.
#define MAX_DISTANCE 300 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 66 // 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.
byte currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
NewPing(7, 10, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(7, 11, MAX_DISTANCE),
NewPing(7,  5, MAX_DISTANCE),
...
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();
          serialCom();
      }          // 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] = 999;                      // 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).
    }
  }


teckel





How many pins are you using?  4?  One pin for triggers on all sensors and 3 pins to get the results from each sensor?  If so, you could just use 3 pins by using the method I describe.

Tim


Please forgive me Tim, I am not understanding, I am using four pins as you have stated but I don't understand how to wire the sensor to only use three pins. This surely would be better because I can add a forth sensor pointing to the rear.

Here is the setup code I am presently using.

Code: [Select]

#define LED_STATUS_PIN 13
#define SONAR_NUM     3 // Number or sensors.
#define MAX_DISTANCE 300 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 66 // 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.
byte currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
NewPing(7, 10, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(7, 11, MAX_DISTANCE),
NewPing(7,  5, MAX_DISTANCE),
...
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();
          serialCom();
      }          // 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] = 999;                      // 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).
    }
  }




NewPing supports the ability to use one pin per sensor.  You simply wire a single pin to the trigger and the echo pins on the sensor.  That's it!  In your sketch, you would set the trigger and echo pin as the same pin.  The magic all happens in the library.  It would look something like this:

Code: [Select]

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


This would ping each device independently, and not all at once like you're doing now.  The way you're doing it could cause bad echo problems.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

reverendrichie



NewPing supports the ability to use one pin per sensor.  You simply wire a single pin to the trigger and the echo pins on the sensor.  That's it!  In your sketch, you would set the trigger and echo pin as the same pin.  The magic all happens in the library.  It would look something like this:

Code: [Select]

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


This would ping each device independently, and not all at once like you're doing now.  The way you're doing it could cause bad echo problems.

Tim


Absolutely Fantastic!!!

Thank you Tim.

phamtuan1151

I used newping libray but It error compiling...

sketch_may15a.cpp.o: In function `__static_initialization_and_destruction_0':
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
sketch_may15a.cpp.o: In function `loop':
C:\Program Files\Arduino/sketch_may15a.ino:18: undefined reference to `NewPing::ping_cm()'

Please hlep me!

teckel


I used newping libray but It error compiling...

sketch_may15a.cpp.o: In function `__static_initialization_and_destruction_0':
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
C:\Program Files\Arduino/sketch_may15a.ino:10: undefined reference to `NewPing::NewPing(unsigned char, unsigned char, int)'
sketch_may15a.cpp.o: In function `loop':
C:\Program Files\Arduino/sketch_may15a.ino:18: undefined reference to `NewPing::ping_cm()'

Please hlep me!


Sounds like you didn't install the library correctly.  Did you decompress it (keeping the directory structure in tact) and put it in your arduino's libraries folder?  I believe there's now also an option in Arduino 1.0.5 to import a library.

Also, you should really always provide your sketch (or mention if you're using an example sketch).  But, these errors are basically saying that it can't find the library AT ALL.  So, you didn't install it correctly (or you just need to close Arduino and open it again).  If you do this and verify the library is installed correctly in your libraries folder like the rest of your libraries and you still have a problem, please indicate the sketch you're using or paste the sketch to your reply.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

terryking228

Regards, Terry King terry@yourduino.com  - Check great prices, devices and Arduino-related boards at http://YourDuino.com
HOW-TO: http://ArduinoInfo.Info

fernandossala

#474
May 20, 2014, 11:57 pm Last Edit: May 21, 2014, 12:01 am by fernandossala Reason: 1
I am doing an installation that works with two sr04, and I am quite satisfied with the results I am achieving so far.
The code I am using is this:
Code: [Select]
#include <NewPing.h>

#define SONAR_NUM      2
#define MAX_DISTANCE 350
#define PING_INTERVAL 33

int rele1 = 7;
int rele2 = 8;


unsigned long pingTimer[SONAR_NUM];
uint8_t currentSensor = 0;

NewPing sonar[SONAR_NUM] = {
  NewPing(13, 12, MAX_DISTANCE),

  NewPing(4, 2, MAX_DISTANCE)
};

void setup() {
  pinMode (rele1, OUTPUT);
  pinMode (rele2, OUTPUT);
 
  Serial.begin(115200);
  pingTimer[0] = millis() + 75;
  for (uint8_t i = 1; i < SONAR_NUM; i++)
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    if (millis() >= pingTimer[i]) {
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;
      sonar[currentSensor].timer_stop();
      currentSensor = i;
      sonar[currentSensor].ping_timer(echoCheck);
    }
  }
  // Other code that *DOESN'T* analyze ping results can go here.
}

void echoCheck() {
  if (sonar[currentSensor].check_timer())
    pingResult(currentSensor, sonar[currentSensor].ping_result / US_ROUNDTRIP_CM);
}

void pingResult(uint8_t sensor, int cm){
// The following code would be replaced with your code that does something with the ping result.

int i;
float f;
f = cm;

i = (int) f/2;

if ( i > 10)
{ digitalWrite (rele1, HIGH);
digitalWrite (rele2, HIGH);
}else{
i = 0;
digitalWrite (rele1, LOW);
digitalWrite (rele2, LOW);


Serial.println(i);

}
}



and I just wanted to turn on a pair of relays based on the sensors activity, and so far i got it to work almost the way i want, the sensors will work almost in parallel (slightly different angles to give'em more viewing angle).  I found the cast operator to be more friendly to deal with the cm array, but I am not sure if its the proper way of doing it.

as of the relays, i want them to turn on when there's somebody in the range of the sensors, otherwise it must be turned off, any advice or suggestion will be much apreciated, and what I got so far is, they turn on on presence, but turn off only when somebody is 10 cm or closer, but not when out of range, i tried to stop and turn the ping on again as suggested on page 19, but I'm not achieving the results I seek

and Teckel, excelent job, and thanks a bunch for your activity in this thread, as an arduino lover and a maker, I am obliged to thank people like you!

teckel


I am doing an installation that works with two sr04, and I am quite satisfied with the results I am achieving so far.

and I just wanted to turn on a pair of relays based on the sensors activity, and so far i got it to work almost the way i want, the sensors will work almost in parallel (slightly different angles to give'em more viewing angle).  I found the cast operator to be more friendly to deal with the cm array, but I am not sure if its the proper way of doing it.

as of the relays, i want them to turn on when there's somebody in the range of the sensors, otherwise it must be turned off, any advice or suggestion will be much apreciated, and what I got so far is, they turn on on presence, but turn off only when somebody is 10 cm or closer, but not when out of range, i tried to stop and turn the ping on again as suggested on page 19, but I'm not achieving the results I seek

and Teckel, excelent job, and thanks a bunch for your activity in this thread, as an arduino lover and a maker, I am obliged to thank people like you!


I'm not sure why you're creating the floating variable "f" and why you're then dividing the distance by two.  That will just add a lot of overhead to your code.  But, a distance of "0" means out of range.  So, if you want to turn something on when in rage and off when out of range your code would look something like this (I cleaned it up a bit too):

Code: [Select]
#include <NewPing.h>

#define SONAR_NUM      2
#define MAX_DISTANCE 350
#define PING_INTERVAL 33

#define RELE1 7
#define RELE2 8

unsigned long pingTimer[SONAR_NUM];
uint8_t currentSensor = 0;

NewPing sonar[SONAR_NUM] = {
  NewPing(13, 12, MAX_DISTANCE),
  NewPing(4, 2, MAX_DISTANCE)
};

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

    pinMode (RELE1, OUTPUT);
    pinMode (RELE2, OUTPUT);
    pingTimer[0] = millis() + 75;
    for (uint8_t i = 1; i < SONAR_NUM; i++)
      pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    if (millis() >= pingTimer[i]) {
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;
      sonar[currentSensor].timer_stop();
      currentSensor = i;
      sonar[currentSensor].ping_timer(echoCheck);
    }
  }
  // Other code that *DOESN'T* analyze ping results can go here.
}

void echoCheck() {
  if (sonar[currentSensor].check_timer())
    pingResult(currentSensor, sonar[currentSensor].ping_result / US_ROUNDTRIP_CM);
}

void pingResult(uint8_t sensor, int cm){
  if ( cm == 0 ) {
    digitalWrite (RELE1, LOW);
    digitalWrite (RELE2, LOW);
  } else {
    digitalWrite (RELE1, HIGH);
    digitalWrite (RELE2, HIGH);
  }

  Serial.println(cm);
}


The problem with this code however is that you have two sensors.  One may detect an object and the other may not.  So, it could turn on and off so quickly you can't even tell.  You probably need to use the original multi-sensor sketch that stores the results in the array and then process the results where you can make logic decisions based upon results of maybe one sensor detecting an object and the other not, or distances that are wildly different.

Basically, while my above sketch will work the way you asked, it won't really work the way you want.  Going back to the original sketch and storing the results in the array and then using different logic is probably what you really want.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

fernandossala

When I first tried the example sketches, I printed every single piece of code I found could be handy to work with, the objects in the array cm
  • and cm [1] where the variables I found most important (all other I just couldn't print), but, again I couldn't do much with them as I have poor code skills, I was looking for some piece of code that could convert whatever I was looking at to something I could do some math with , later I found I was merging the results into one, so I decided I needed to divide the result by two. Ok, not a smart decision, I know...

    And with your sketch, I did came to similar results as yours before, and what happens is, when something approaches to the sensor, it turns on, but never turns off, therefore, there's no 0 coming out when there's no activity. I thought this was a good approuch to achieve my goal, which is, when there's activity on the sensor, turn on, else, turn off
    thanks

    Fernando

teckel


When I first tried the example sketches, I printed every single piece of code I found could be handy to work with, the objects in the array cm
  • and cm [1] where the variables I found most important (all other I just couldn't print), but, again I couldn't do much with them as I have poor code skills, I was looking for some piece of code that could convert whatever I was looking at to something I could do some math with , later I found I was merging the results into one, so I decided I needed to divide the result by two. Ok, not a smart decision, I know...

    And with your sketch, I did came to similar results as yours before, and what happens is, when something approaches to the sensor, it turns on, but never turns off, therefore, there's no 0 coming out when there's no activity. I thought this was a good approuch to achieve my goal, which is, when there's activity on the sensor, turn on, else, turn off
    thanks

    Fernando


Without totally writing the sketch for you (what fun would that be?) I can suggest that you start again with the standard 15 sensor sample sketch that puts the results in an array.  Then, analyze the results in the array and decide what you want to do with the data.  The distance variables are simply cm[0] and cm[1].  You wouldn't want to add them and divide by two, as that would not give accurate results.  Instead, you would need some better logic.  For example, maybe one OR the other needs to be a positive value to consider something in range.  So, you would do something like:

Code: [Select]
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  // The following code would be replaced with your code that does something with the ping results.
  if (cm[0] || cm[1]) {  // At least one sensor detected something in range, activate relays.
    digitalWrite (RELE1, HIGH);
    digitalWrite (RELE2, HIGH);
  } else {  // Both sensors can't detect anything, turn relays off.
    digitalWrite (RELE1, LOW);
    digitalWrite (RELE2, LOW);
  }
}


Hope that helps!

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

fernandossala



When I first tried the example sketches, I printed every single piece of code I found could be handy to work with, the objects in the array cm
  • and cm [1] where the variables I found most important (all other I just couldn't print), but, again I couldn't do much with them as I have poor code skills, I was looking for some piece of code that could convert whatever I was looking at to something I could do some math with , later I found I was merging the results into one, so I decided I needed to divide the result by two. Ok, not a smart decision, I know...

    And with your sketch, I did came to similar results as yours before, and what happens is, when something approaches to the sensor, it turns on, but never turns off, therefore, there's no 0 coming out when there's no activity. I thought this was a good approuch to achieve my goal, which is, when there's activity on the sensor, turn on, else, turn off
    thanks

    Fernando


Without totally writing the sketch for you (what fun would that be?) I can suggest that you start again with the standard 15 sensor sample sketch that puts the results in an array.  Then, analyze the results in the array and decide what you want to do with the data.  The distance variables are simply cm[0] and cm[1].  You wouldn't want to add them and divide by two, as that would not give accurate results.  Instead, you would need some better logic.  For example, maybe one OR the other needs to be a positive value to consider something in range.  So, you would do something like:

Code: [Select]
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  // The following code would be replaced with your code that does something with the ping results.
  if (cm[0] || cm[1]) {  // At least one sensor detected something in range, activate relays.
    digitalWrite (RELE1, HIGH);
    digitalWrite (RELE2, HIGH);
  } else {  // Both sensors can't detect anything, turn relays off.
    digitalWrite (RELE1, LOW);
    digitalWrite (RELE2, LOW);
  }
}


Hope that helps!

Tim


It works like a champion!
Thanks a bunch, next time, i will send pictures and videos of the final project!
Best Regards,
Fernando

teckel


It works like a champion!
Thanks a bunch, next time, i will send pictures and videos of the final project!
Best Regards,
Fernando


Glad I could help!  Would love to see the final project.  I hope it's something fast-moving that chases your cat around the house or something cool like that.

Tim
My platforms Arduino, Teensy 3.2, Arduino Pro Mini, ATmega328
My libraries: NewPing, LCDBitmap, toneAC, toneAC2, NewTone, TimerFreeTone
My projects: https://dogblocker.com & https://baconorbeer.com
My beer: Great Lakes Brewing Co. Lake Erie Monster

Go Up