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

cyclegadget:

matt121187: can someone help me... =(

First step, make Arduino work with basic code for NewPing.

After you understand how the sketch works you can use variables to calculate speed.

Quoted from this link http://www.unitarium.com/speed-calculator

Assume, V - stands for average speed (velocity), T - stands for traveling time and D - stands for traveled distance.

Average Speed can be calculated by using the formula: V = D/T Traveled distance can be calculated as: D = V*T Traveling time can be calculated using: T = D/V

Using the formulas remember about the units. For example, if the distance is given in meters and the time is given in seconds, calculated average speed is given in meters per second.

sorry, im new with arduino..what do u mean by " First step, make Arduino work with basic code for NewPing."? from the ping sensor coding, i can get the distance, but how to get the value of times?

Assume, V - stands for average speed (velocity), T - stands for traveling time and D - stands for traveled distance.

Average Speed can be calculated by using the formula: V = D/T Traveled distance can be calculated as: D = V*T Traveling time can be calculated using: T = D/V

You may want to start a thread in the programming questions area for your project. Below, is some help to get you started. You have a sensor that can provide distance information. This is your "D" variable.

You can use millis() or micros() to measure your time between distance checks. This is your "T" variable. FirstMillis() - SecondMillis() = time between distance checks.

V = D/T......."V" velocity, = "D" distance / "T" time.

Before you ask more questions, you need to read this thread so that you will get the best help possible. http://arduino.cc/forum/index.php/topic,97455.0.html

Good luck, your project is easily possible but, you need to put in some time to make it happen.

matt121187:
sorry, im new with arduino…what do u mean by " First step, make Arduino work with basic code for NewPing."? from the ping sensor coding, i can get the distance, but how to get the value of times?

You create a time stamp for each ping. Then, looking at multiple ping times, and the comparison to the ping time stamp, you can easily calculate the speed (also if it’s getting closer or further away). For example, you have two pings like the following:

Ping 1: Timestamp 50,000uS - Ping time 8,000uS
Ping 2: Timestamp 100,000uS - Ping time 7,000uS

So, two pings that are 50ms apart, the first distance is 8000uS (140cm), sencond ping is 7,000uS (123cm). So, in 50ms, it got 17cm closer (140-123). 17cm/50ms = .17/0.05 m/s or 3.4 m/s or 7.6 miles/hour.

Only the previous and current ping timestamp and distance are needed. If you use scheduled polling so you always know exactly how far apart each ping is (for example, exactly 50,000uS) then you don’t even need to know the timestamp, just the current and previous ping distance. Just don’t use delay(50) to make them 50ms apart, that won’t be accurate. You’ll need to either use an interrupt timer or polling to keep things accurate. Interrupt timer would be ideal but more complicated unless you used a timer library would would greatly simplify things.

I’ve written a little sketch for you that uses the NewPing and TimerOne library that outputs the speed via serial and uses the timer interrupt to make the ping timing very accurate. I added lots of comments so you should be able to follow along. Speed values are in meters per second, with positive values coming at you and negative moving away. Anyway, here’s the sketch:

#include <TimerOne.h>
#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.

NewPing sonar(TRIGGER_PIN, ECHO_PIN); // NewPing setup of pins.

volatile int previous = 0, current = 0; // Must be volatile because these change inside the interrupt code.
volatile float mps = 0.0;
volatile boolean newping = false;

void setup() {
  delay(1000);                        // Wait a second before we start.
  Timer1.initialize(50000);           // 50000uS = 50ms.
  Timer1.attachInterrupt(pingSensor); // pingSensor to run every 50ms.
  Serial.begin(115200);               // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
  if (newping) { // There a new ping, print speed.
    /* START - This section would be replaced with code that would do something with the result other than just output to serial. */
    if (mps) {   // Non-zero speed, show result.
      Serial.print(mps);
      Serial.println(" m/s");
    } else Serial.println("-"); // Can't determine speed, output "-" instead of speed.
    /* END */
    newping = false; // Set to false till next ping.
  }
}

void pingSensor() {
  previous = current;
  current = sonar.ping_cm(); // Send out a ping and get the results in CM.
  if (previous && current) { // If either are zero, we had a no-ping result or on the first ping.
    mps = (float) (previous - current) * 0.2; // Calculate speed in m/s (positive values are coming at you, negative moving away).
  } else mps = 0; // Can't calculate speed.
  newping = true; // Flag that there's a new ping.
}

Hope this helps!

Tim

Hi,

First of all THANK YOU TIM for this library!!!
And thank you to all the enthusiasts who have been posting here!

I have been running into a slight problem that I have not been able to fix, despite dowloading the lib again, googling it a million times, etc. I am trying to get readings from a PING))) sensor and from a maxbotic MAX SONAR (which can be PWM, An or BW, I have it as PWM) and arduino throws the same error:
‘NewPing’ does not name a type

sketch_jan06a:3: error: ‘NewPing’ does not name a type
sketch_jan06a:4: error: ‘NewPing’ does not name a type
sketch_jan06a.cpp: In function ‘void loop()’:
sketch_jan06a:19: error: ‘sonar1’ was not declared in this scope
sketch_jan06a:23: error: ‘sonar2’ was not declared in this scope

The code I used is the modified sample one provided:

#include <NewPing.h>
//barely modified sketch from Tim Eckel's original sketch

NewPing sonar1(11, 12, 200); // Sensor 1: trigger pin, echo pin, maximum distance in cm
NewPing sonar2(9, 10, 200); // Sensor 2: same stuff

#define pingSpeed 100 // Ping frequency (in milliseconds), fastest we should ping is about 35ms per sensor
unsigned long pingTimer1, pingTimer2;

void setup() {
  Serial.begin(9600);
  // Do other stuff here
  pingTimer1 = millis() + pingSpeed; // Sensor 1 fires after 100ms (pingSpeed)
  pingTimer2 = pingTimer1 + (pingSpeed / 2); // Sensor 2 fires 50ms later
}

void loop() {
  if (millis() >= pingTimer1) {
    pingTimer1 += pingSpeed; // Make sensor 1 fire again 100ms later (pingSpeed)
    int in1 = sonar1.ping_in();
  }
  if (millis() >= pingTimer2) {
    pingTimer2 = pingTimer1 + (pingSpeed / 2); // Make sensor 2 fire again 50ms after sensor 1 fires
    int in2 = sonar2.ping_in();
    // Both sensors pinged, process results here
  }
  // Do other stuff here, notice how there's no delays in this sketch, so you have processing cycles to do other things :)
}

Any suggestions would be greatly greatly appreciated… Thank you!!!

teckel:

matt121187:
sorry, im new with arduino…what do u mean by " First step, make Arduino work with basic code for NewPing."? from the ping sensor coding, i can get the distance, but how to get the value of times?

You create a time stamp for each ping. Then, looking at multiple ping times, and the comparison to the ping time stamp, you can easily calculate the speed (also if it’s getting closer or further away). For example, you have two pings like the following:

Ping 1: Timestamp 50,000uS - Ping time 8,000uS
Ping 2: Timestamp 100,000uS - Ping time 7,000uS

So, two pings that are 50ms apart, the first distance is 8000uS (140cm), sencond ping is 7,000uS (123cm). So, in 50ms, it got 17cm closer (140-123). 17cm/50ms = .17/0.05 m/s or 3.4 m/s or 7.6 miles/hour.

Only the previous and current ping timestamp and distance are needed. If you use scheduled polling so you always know exactly how far apart each ping is (for example, exactly 50,000uS) then you don’t even need to know the timestamp, just the current and previous ping distance. Just don’t use delay(50) to make them 50ms apart, that won’t be accurate. You’ll need to either use an interrupt timer or polling to keep things accurate. Interrupt timer would be ideal but more complicated unless you used a timer library would would greatly simplify things.

I’ve written a little sketch for you that uses the NewPing and TimerOne library that outputs the speed via serial and uses the timer interrupt to make the ping timing very accurate. I added lots of comments so you should be able to follow along. Speed values are in meters per second, with positive values coming at you and negative moving away. Anyway, here’s the sketch:

#include <TimerOne.h>

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

NewPing sonar(TRIGGER_PIN, ECHO_PIN); // NewPing setup of pins.

volatile int previous = 0, current = 0; // Must be volatile because these change inside the interrupt code.
volatile float mps = 0.0;
volatile boolean newping = false;

void setup() {
 delay(1000);                        // Wait a second before we start.
 Timer1.initialize(50000);           // 50000uS = 50ms.
 Timer1.attachInterrupt(pingSensor); // pingSensor to run every 50ms.
 Serial.begin(115200);               // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
 if (newping) { // There a new ping, print speed.
   /* START - This section would be replaced with code that would do something with the result other than just output to serial. /
   if (mps) {   // Non-zero speed, show result.
     Serial.print(mps);
     Serial.println(" m/s");
   } else Serial.println("-"); // Can’t determine speed, output “-” instead of speed.
   /
END */
   newping = false; // Set to false till next ping.
 }
}

void pingSensor() {
 previous = current;
 current = sonar.ping_cm(); // Send out a ping and get the results in CM.
 if (previous && current) { // If either are zero, we had a no-ping result or on the first ping.
   mps = (float) (previous - current) * 0.2; // Calculate speed in m/s (positive values are coming at you, negative moving away).
 } else mps = 0; // Can’t calculate speed.
 newping = true; // Flag that there’s a new ping.
}




Hope this helps!

Tim

tq so much eckel!!its work for me…i using parallax ping ultrasonic sensor and add some more coding…later i post here what ive done…tq so much!!

notsoyyo:
Hi,

First of all THANK YOU TIM for this library!!!
And thank you to all the enthusiasts who have been posting here!

I have been running into a slight problem that I have not been able to fix, despite dowloading the lib again, googling it a million times, etc. I am trying to get readings from a PING))) sensor and from a maxbotic MAX SONAR (which can be PWM, An or BW, I have it as PWM) and arduino throws the same error:
‘NewPing’ does not name a type

sketch_jan06a:3: error: ‘NewPing’ does not name a type
sketch_jan06a:4: error: ‘NewPing’ does not name a type
sketch_jan06a.cpp: In function ‘void loop()’:
sketch_jan06a:19: error: ‘sonar1’ was not declared in this scope
sketch_jan06a:23: error: ‘sonar2’ was not declared in this scope

Any suggestions would be greatly greatly appreciated… Thank you!!!

Your exact sketch compiled fine here. But, I can get it to fail and give the above errors by removing the #include <NewPing.h> line. This means that while you’re telling it to load NewPing.h, it can’t find it. Most of the time, this means that you didn’t install NewPing properly to the correct directory. Libraries are installed inside your “Arduino” library in a subdirectory named “libraries”. Inside “libraries” you would create a new directory named “NewPing” with the files in the NewPing zip file in the NewPing directory. See the other directories inside “libraries” for examples of how it should look. The only instructions I have for installing a library with Arduino is:

Put the “NewPing” folder in “libraries”.

If you can’t figure out how to correctly install a library, do a web search for how to install an Arduino library, maybe someone else has a better way of describing it.

Tim

alegiaco: Very good job, man!!!! Two questions: - is it possible to use multiple ultrasonic sensors? i.e 4 sensors? - with multiple sensors and a distance between 10 and 20 cm how fast can be the readings? Thanks

For my HC-SR04 app, I use a common trigger signal (to all 8 sensors), then pin-change interrupts to read pulse time. I went outside the libraries to do this. Haven't tried to see how fast I can ping, but they all share the same timeout, currently at .030 sec (30ish Hz max). They don't seem to work for distances longer than about .020 ping time, so I'd think that a max rate of around 40 Hz should be achievable... for full 2+m range.

I don't know how much faster you could go at max 20cm, since subsequent pulses might give false readings from objects around 2-2.5m away.

See http://arduino.cc/forum/index.php/topic,141363.0.html for my test code.

terryking228: I'm writing a library for these: http://goo.gl/FWMjI and I'd love to try some cool mapping ideas with your code...

I'm writing my own too. My test code is posted at http://arduino.cc/forum/index.php/topic,141363.0.html. The big difference for my code is that an array of HC-SR04's all share the same trigger, then read pulse time using pin-change interrupts (on mega).

It is kind of hard for me to generalize pin-change interrupts, so it is somewhat hard-coded. more of an example than a good general-purpose library.

Mr-What:

terryking228: I'm writing a library for these: http://goo.gl/FWMjI and I'd love to try some cool mapping ideas with your code...

I'm writing my own too. My test code is posted at http://arduino.cc/forum/index.php/topic,141363.0.html. The big difference for my code is that an array of HC-SR04's all share the same trigger, then read pulse time using pin-change interrupts (on mega).

It is kind of hard for me to generalize pin-change interrupts, so it is somewhat hard-coded. more of an example than a good general-purpose library.

The problem with pin-change interrupts is that it's not even tested on the Uno, only Mega. It's a little ridged for a general-purpose library. The next release of NewPing should have a pin interrupt-based method. I've expanded my required compatibility to include the Uno, Teensy 2.0, and Teensy 3.0. So, it's a little more challenging at times.

I do have a question for you. How do you deal with pings that don't return? Waiting for the interrupt doesn't work as sometimes there isn't a ping return. I'm building an ultra-low-powered system currently and because I can't rely on getting a ping result, I can't do what I wanted, which is to put the ATmega to sleep while waiting for the pin interrupt. Still got it down to using only 1.27mA, but even lower would be better.

Tim

I have run the pin-change interrupts on UNO... the official pin-change interrupt libraries are tested for UNO, NOT mega.

Either way, you will see that this is kind of hard-coded to my app. It gets very tricky when you want to use specific pins so they share the same interrupt vector. So tricky that I gave up on "proper" programming, and kind of hard-coded pin assignments and interrupts.

My application runs on a constant poll, and will call .timeout() when more than about 20000us have passed. That is not shown... since I just posted my original test script demonstrating use of pin-change interrupts for a sonar array.

Mr-What: I have run the pin-change interrupts on UNO... the official pin-change interrupt libraries are tested for UNO, NOT mega.

Either way, you will see that this is kind of hard-coded to my app. It gets very tricky when you want to use specific pins so they share the same interrupt vector. So tricky that I gave up on "proper" programming, and kind of hard-coded pin assignments and interrupts.

My application runs on a constant poll, and will call .timeout() when more than about 20000us have passed. That is not shown... since I just posted my original test script demonstrating use of pin-change interrupts for a sonar array.

My bad, pinchangeint supports Uno with partial Mega compatibility.

Don't you have to wait at least 29 to 35ms? The sensors work at up to 500cm, which means the pings are still bouncing around for up to 28,500uS.

Also, when I've tried to fire multiple sensors simultaneously, it really only worked well in wide-open spaces. In more closed environments, I'd get cross-sensor echos at times making it unreliable.

With this said, using the Teensy 3.0 is really nice as every pin can be an interrupt. You may want to consider this as it would make things a lot easier. Not to mention the extra horsepower the microcontroller will give you.

Tim

You are right. I need to revisit that. I might need to extend that timeout. I have seen these specific sensors work over 2m (to a flat wall).

Haven't seen cross-talk in my testing yet, but I haven't done anything too stressing. This is for a large robot, so the sensors will be about 20-50 cm apart, more or less radially pointing outward.

For collision avoidance I am hoping that a false positive from a simultaneous ping would not necessarily be a bad thing. If I receive my neighbor's ping from a tilted surface nearby (which I still need to avoid), that is better than not seeing anything. I hope that the first echo sensed causes the pin to go low, and I get the "conservative" estimate of distance to a nearby obstacle.

Teckel, I’ve received a Due and downloaded NewPing (you asked earlier in the thread). The immediate issues are that it includes “avr/io.h” and “avr/interrupt.h”, neither of which seem to have obvious counterparts for the ARM due.

With those headers missing, the following lines become issues:

C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In constructor 'NewPing::NewPing(uint8_t, uint8_t, int)':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:19: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:20: error: cannot convert 'volatile RoReg*' to 'volatile uint8_t*' in assignment
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:22: error: 'portModeRegister' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_us(unsigned int, void (*)())':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:151: error: 'OCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:152: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:152: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_ms(long unsigned int, void (*)())':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:167: error: 'OCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:168: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:168: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_stop()':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:177: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:177: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_setup()':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:195: error: 'ASSR' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:195: error: 'AS2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:196: error: 'TCCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:196: error: 'WGM21' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:197: error: 'TCCR2B' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:197: error: 'CS22' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:198: error: 'TCNT2' was not declared in this scope

jmXCA:
Teckel, I’ve received a Due and downloaded NewPing (you asked earlier in the thread). The immediate issues are that it includes “avr/io.h” and “avr/interrupt.h”, neither of which seem to have obvious counterparts for the ARM due.

With those headers missing, the following lines become issues:

C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In constructor 'NewPing::NewPing(uint8_t, uint8_t, int)':

SNIP

Ok, so in a pinch I quickly hacked this to work on the DUE (NO TIMERS YET). I’m new to Arduino so these changes probably have some side effect I’m not aware of (ie, I’m not sure why digitalWrite and pinMode functions weren’t used in the first place - maybe just to avoid function calls?)
1) In NewPing.h:
-if’defd the AVR includes
#ifndef arm
#include <avr/io.h>
#include <avr/interrupt.h>
#ifndef arm

-added 2 members to NewPing class
uint8_t _triggerPin;
uint8_t _echoPin;

2) In NewPing.cpp:
-Added these 2 lines in the constructor
_triggerPin = trigger_pin;
_echoPin = echo_pin;

-Commented out the portModeRegister line

-Change any lines like “*_triggerMode |= _triggerBit; // Set trigger pin to output.”
to: pinMode(_triggerPin,OUTPUT);

-And finally a new ping_trigger()
#ifdef arm
boolean NewPing::ping_trigger() {
#if DISABLE_ONE_PIN != true
pinMode(_triggerPin, OUTPUT);
#endif
digitalWrite(_triggerPin, LOW);
delayMicroseconds(4); // Wait for pin to go low, testing shows it needs 4uS to work every time.
digitalWrite(_triggerPin, HIGH);
delayMicroseconds(10); // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS.
digitalWrite(_triggerPin, LOW);

#if DISABLE_ONE_PIN != true
pinMode(_triggerPin, INPUT);
#endif

_max_time = micros() + MAX_SENSOR_DELAY; // Set a timeout for the ping to trigger.
while ((digitalRead(_echoPin) == HIGH) && (micros() <= _max_time)) {}
while (!(digitalRead(_echoPin) == HIGH)) // Wait for ping to start.
if (micros() > _max_time) return false; // Something went wrong, abort.

_max_time = micros() + _maxEchoTime; // Ping started, set the timeout.
return true; // Ping started successfully.
}
#else
//old ping_trigger() goes here
#endif

jmXCA: Teckel, I've received a Due and downloaded NewPing (you asked earlier in the thread). The immediate issues are that it includes "avr/io.h" and "avr/interrupt.h", neither of which seem to have obvious counterparts for the ARM due.

With those headers missing, the following lines become issues:

C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In constructor 'NewPing::NewPing(uint8_t, uint8_t, int)':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:19: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:20: error: cannot convert 'volatile RoReg*' to 'volatile uint8_t*' in assignment
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:22: error: 'portModeRegister' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_us(unsigned int, void (*)())':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:151: error: 'OCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:152: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:152: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_ms(long unsigned int, void (*)())':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:167: error: 'OCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:168: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:168: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_stop()':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:177: error: 'TIMSK2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:177: error: 'OCIE2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp: In static member function 'static void NewPing::timer_setup()':
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:195: error: 'ASSR' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:195: error: 'AS2' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:196: error: 'TCCR2A' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:196: error: 'WGM21' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:197: error: 'TCCR2B' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:197: error: 'CS22' was not declared in this scope
C:\arduino-1.5.1r2\hardware\arduino\sam\libraries\NewPing\NewPing.cpp:198: error: 'TCNT2' was not declared in this scope

The Due will not currently work with the NewPing library. NewPing uses all low-level port register calls which are specific to the 8 bit ATmega processors. I've been working on a new version that will work with the Teensy 3.0 that's similar to the Due as they both use 32 bit microcontrollers. I don't plan on getting a Due as the Teensy 3.0 offers similar capability but in a MUCH smaller size and only costs $19. But, this update should also work with the Due in the basic non-timer interrupt methods.

The code you listed in your following post is similar to my development library for the non-8-bit ATmega microcontrollers. Instead of timer interrupt methods, pin interrupt should be the method of choice for the Due. I know for the Teensy 3.0 every pin can be an external pin interrupt, which makes it ULTRA convenient . I think the Due isn't quite as advanced in this area, which makes it a little more of an issue to implement, or will be somewhat limited.

You'll soon find that most advanced libraries won't work with the Due. Only simple libraries that don't do any lower-level commands will work. For size and speed, many libraries have adopted very specific 8 bit ATmega compatibility. So, expect to find many libraries that won't work with the Due.

Tim

Hi Tim.

Thanks for a great library!

I have a problem though that you might have some ideas on what I've done wrong. When using your lib (v1.5) together with an Ethernet shield, I can't get 3 sensors to work properly.

E.g: - If I use 3 HC-SR04 sensors and a Mega 2560 with your example code with an sonar array, they all work fine, but if I just add an Ethernet shield to the Mega, 2 of the sensors give bad readings (like 4 cm instead of 90-150cm). The same wiring is used and no code is changed, just added the Ethernet shield (i.e. not messed with Timer2 and don't use the tone lib)

  • The Ethernet shield works, e.g. can just load other code (e.g. web server code, NTP client etc) without even removing the connected sensors and it works fine, i.e. it's not the Ethernet shield itself (have also tried with another Ethernet shield with same result)

  • I've stayed away from the 50-53 pins (used by Ethernet shield+HW ss pin) and the PWM pins. Currently using pin 30-35 (it's the middle HC-SR04 that gives OK readings when Ethernet shield is connected)

  • Tried with stuff like disabling SD SPI interface, pin 4, and setting pin 53 to output without any luck.

  • Using Arduino 1.0.2 IDE

Any ideas?

Thanks in advance!! /Magnus

gandalf50: Hi Tim.

Thanks for a great library!

I have a problem though that you might have some ideas on what I've done wrong. When using your lib (v1.5) together with an Ethernet shield, I can't get 3 sensors to work properly.

E.g: - If I use 3 HC-SR04 sensors and a Mega 2560 with your example code with an sonar array, they all work fine, but if I just add an Ethernet shield to the Mega, 2 of the sensors give bad readings (like 4 cm instead of 90-150cm). The same wiring is used and no code is changed, just added the Ethernet shield (i.e. not messed with Timer2 and don't use the tone lib)

  • The Ethernet shield works, e.g. can just load other code (e.g. web server code, NTP client etc) without even removing the connected sensors and it works fine, i.e. it's not the Ethernet shield itself (have also tried with another Ethernet shield with same result)

  • I've stayed away from the 50-53 pins (used by Ethernet shield+HW ss pin) and the PWM pins. Currently using pin 30-35 (it's the middle HC-SR04 that gives OK readings when Ethernet shield is connected)

  • Tried with stuff like disabling SD SPI interface, pin 4, and setting pin 53 to output without any luck.

  • Using Arduino 1.0.2 IDE

Any ideas?

Thanks in advance!! /Magnus

First, try using different pins for the sensors that are not working. It sounds like a conflict. If that doesn't work, you're going to need to provide some code so I know exactly how you're using NewPing. Not even sure what method of NewPing you're using, timer interrupt method or standard? At least part of the code would be helpful (maybe all of it).

Tim

Sounds good, I’ll try some more with other pin configs.

I didn’t provide the code since I have this problem with e.g. your example code with the sonar array and 3 sensors. I.e. your code with “This example code was used to successfully communicate with 15 ultrasonic sensors”. Let me know if you still want the code (only updated the SONAR_NUM and objects in the sonar array).

Do you know if someone got multiple sensor working together with an Ethernet shield on the Mega 2560?

Brg,
/Magnus

gandalf50: Sounds good, I'll try some more with other pin configs.

I didn't provide the code since I have this problem with e.g. your example code with the sonar array and 3 sensors. I.e. your code with "This example code was used to successfully communicate with 15 ultrasonic sensors". Let me know if you still want the code (only updated the SONAR_NUM and objects in the sonar array).

Do you know if someone got multiple sensor working together with an Ethernet shield on the Mega 2560?

Brg, /Magnus

The code is always helpful, even if it's basically the same as the sample. I've seen several times that a little change was made and that was causing the problem.

Tim

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*_