Go Down

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

gandalf50

Sure, here it is:
// ---------------------------------------------------------------------------
// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust
// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the
// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor
// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results
// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project
// would normally process the sensor results in this function (for example, decide if a robot needs to
// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs
// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other
// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind.
// ---------------------------------------------------------------------------
#include <NewPing.h>

#define SONAR_NUM     3 // Number of 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(22, 23, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping. // OK
  NewPing(24, 25, MAX_DISTANCE), // NOK
  NewPing(34, 35, MAX_DISTANCE)  // OK
};

  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 = pingTimer[i - 1] + PING_INTERVAL;
  }

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer) {         // Is it this sensor's time to ping?
      pingTimer += 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).
    }
  }
  // Other code that *DOESN'T* analyze ping results can 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.
  // The following code would be replaced with your code that does something with the ping results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm);
    Serial.print("cm ");
  }
  Serial.println();
}


Now two of the sensors work fine with the ethernet shield, using the pins above. Without the ethernet shield all 3 works.
I've looked at the 2560 pinout, but it didn't help figuring this out. Also tried several pin configs. I've also tried initializing the Ethernet shield (i.e. setting IP addr etc), but no luck (and tried with the 1.0 IDE as well).

Only the 3 sensors are wired to the Mega (power via USB).

I'll try with an UNO with an Ethernet shield and an Arduino Ethernet.

  /Magnus


Now two of the sensors work fine with the ethernet shield, using the pins above. Without the ethernet shield all 3 works.
I've looked at the 2560 pinout, but it didn't help figuring this out. Also tried several pin configs. I've also tried initializing the Ethernet shield (i.e. setting IP addr etc), but no luck (and tried with the 1.0 IDE as well).

Only the 3 sensors are wired to the Mega (power via USB).

I'll try with an UNO with an Ethernet shield and an Arduino Ethernet.

 /Magnus


I don't see any Ethernet code in that sketch.  Does it fail just as is?  What exactly happens?

The first thing you should ALWAYS try is to use different pins.  Also, switch the sensors to see if the problem follows the sensors or the pins.  My guess is that there's a conflict with the pins you are using.  Using different pins is so simple that you should always try this first.

Try totally different pins and see if anything changes.  If so, the conflict is with the Ethernet or SD library.

I'd also try to slow down the pings, change PING_INTERVAL 33  to PING_INTERVAL 250 and see if that does anything.

Finally, I'd try to not use a timer interrupt method of pinging as it could be just a simple timing issue with multiple libraries competing for CPU cycles.  So instead of using ping_timer() just do a convention ping of each sensor.  Here's a sketch that does just that to your 3 sensors:

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

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

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(22, 23, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(24, 25, MAX_DISTANCE),
  NewPing(34, 35, MAX_DISTANCE)
};

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

void loop() {
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    unsigned int cm = sonar[i].ping_cm();
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm);
    Serial.print("cm ");
  }
  Serial.println();
  delay(PING_INTERVAL);
}


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

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

oigresUPM

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...

cyclegadget


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...


Code: [Select]
#define SONAR_NUM       4 // Number of sensors.
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123


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
Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

oigresUPM



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...


Code: [Select]
#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?? :smiley-roll-sweat:
Thank u!




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...


Code: [Select]
#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?? :smiley-roll-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
Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

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!!

DigiStump's forum post for the project: http://digistump.com/board/index.php/topic,299.0.html

Youtube of it running: http://www.youtube.com/watch?v=QNZyMQC3maQ


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:

Code: [Select]
#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
Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

oigresUPM





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...


Code: [Select]
#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?? :smiley-roll-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!!!

rainierez

Quote
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:

Code: [Select]
#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!

rainierez

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

Code: [Select]
...\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


The new code you updated works great but if I leave the timer functions in the cpp then it won't compile. :/ 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
Arduino - Teensy - Raspberry Pi
My libraries: NewPing - LCDBitmap - toneAC - NewTone - TimerFreeTone

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

Go Up