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

I think this part of the code is incorrect. It will always check as true. That is all that I have found at the moment.

if (millis() >= pingTimer) {   // pingSpeed milliseconds since last ping, do another ping.
    pingTimer += pingSpeed;      // Set the next ping time.
    sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.
  }

Take a look at the blink without delay example.

 unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;  
    
    
    // run function here
    
  }

that code was taken straight from the NewPingEventTimer example code, and as far as I can tell should not always be true.

hbaxton:
I am using the new Ping library with my code and have hit a dead end. My code is running a SparkFun stepper motor in a loop where it slowly increments the RPM. I eventually want to control the speed based on the distance measurement from my Ping((( sensor, but I've dumbed it down to find the error. It's not the best code for my motor, but for example sake it works. The problem is that even though I use the ping_timer like in the example calling:

sonar.ping_timer(echoCheck);

stops the motor from moving. once I comment that line out the motor starts working again. below is the code. any ideas?

I'd start debugging this by removing the Serial.print/Serial.println stuff inside the echoCheck subroutine. This is only there for a test, you should eventually replace it with code that processes the ping result. But for now you can simply delete it. If it still doesn't work correctly, it could be that the AFMotor library is also using the same timer that NewPing is using to do the stepper motor control.

Also, cyclegadget is correct, you're not really using the pingTimer correctly. Both ping_timer() and the pingTimer variable are designed to be used WITHOUT delays. If you're using delays, it's going to not work correctly.

Basically, if you're going to use delays, you should not use any of the polling (pingTimer) stuff and shouldn't use the ping_timer() method. You should just use the standard ping() method. If you want to create a more event driven sketch, you need to be comfortable with not using delay commands.

I simplified your sketch and used the standard ping() method (well, ping_cm() which is ping that converts the result to centimeters). This may make more sense and be a closer fit to what you're trying to do.

#include <NewPing.h>
#include <AFMotor.h>

AF_Stepper motor(200, 1);
NewPing sonar(7, 7, 200); // NewPing setup of pins and maximum distance.
int rpm = 10;

void setup(){
  Serial.begin(115200);
  Serial.println("Stepper test!");
  motor.setSpeed(100);  // 100 rpm   
  motor.step(100, FORWARD, SINGLE); 
  Serial.println("step done");
  motor.release();
  delay(1000);
}

void loop(){
  int cm = sonar.ping_cm();
  Serial.print(cm);
  Serial.println(" cm");
  
  Serial.print("setting RMP = ");
  Serial.println(rpm);
  motor.setSpeed(rpm);
  Serial.println();
  Serial.println();
  motor.step(100, FORWARD, SINGLE);
  rpm += 10;
  delay(1000);
}

hbaxton:
that code was taken straight from the NewPingEventTimer example code, and as far as I can tell should not always be true.

It is always true, because you're adding delays and telling it to start right away, yet then adding a full second delay. Basically, you need to either create an event driven/polling type sketch, or one with delays. Combining the two could give you problems.

It doesn't seem you're comfortable with an event driven/polling type sketch. So, you shouldn't really try to use any example NewPing sketch that uses the ping_timer() method. Stick with ping(), ping_cm(), ping_in(), and ping_median() till you're comfortable with not using the delay() command in your sketch.

Tim

hi teckel & cyclegadget,

thank you for your response. i am new to events. so i tried taking out all the delays and also tried calling the ping function directly but i had the same results. i'm going to look into the adafruit motor library to see if it is using the timer as the new ping library.

thanks again! i'll report back.

@hbaxton

Take a look at this sketch. I reworked your sketch and put the motor running part into a function then, made it work with blink without delay style. It is untested but, I think it will work.

#include <NewPing.h>
#include <AFMotor.h>


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

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

unsigned int pingSpeed = 1000;  // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second.
unsigned long pingTimer;        // Holds the next ping time.
unsigned long motorTimer;       // Holds the place for motor speed adjusts
unsigned int adjustTime = 1000; // how often to adjust the speed of the motor
int rpm =10;

void setup(){
  Serial.begin(115200);
  pingTimer = millis(); // Start now.

  Serial.println("Stepper test!");
  motor.setSpeed(100);  // 100 rpm   
  motor.step(100, FORWARD, SINGLE); 
  Serial.println("step done");
  motor.release();
  delay(1000);
}

void loop(){
  // Notice how there's no delays in this sketch to allow you to do other processing in-line while doing distance pings.
  if (millis() >= pingTimer) // pingSpeed milliseconds since last ping, do another ping.
  {   
    pingTimer = millis() + pingSpeed;      // Set the next ping time.
    sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.
  }

////////////////////////////////////////Here is the new part that will run your motor on a timer
  if (millis() >= motorTimer)
  {
    motorrun();
    motorTimer = millis() + adjustTime;
  }
}

void motorrun()
{ // this is the function that will run your motor when called
  Serial.print("setting RMP = ");
  Serial.println(rpm);
  motor.setSpeed(rpm);
  Serial.println();
  Serial.println();
  motor.step(100, FORWARD, SINGLE);
  rpm = rpm +10;
}


void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status.
  // Don't do anything here!
  if (sonar.check_timer()) { // This is how you check to see if the ping was received.
    // Here's where you can add code.
    Serial.print("Ping: ");
    Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM.
    Serial.println("cm");
  }  
}

hbaxton:
hi teckel & cyclegadget,

thank you for your response. i am new to events. so i tried taking out all the delays and also tried calling the ping function directly but i had the same results. i'm going to look into the adafruit motor library to see if it is using the timer as the new ping library.

thanks again! i'll report back.

You can't just remove the delays and expect it to work as then you'll have other problems. Instead, try using the replacement sketch I provided in a previous post that includes delays, but does so correctly. Your sketch was a hybrid, but used bad logic. To simplify things for you, my sketch does it the standard way, with the ping() method and delays. This is how you should use NewPing unless you know what you're doing and know how to write event-driven sketches. I do highly suggest that you learn this programming paradigm as you'll have a hard time graduating beyond "hello world" tests otherwise. But, maybe try something simple at first.

Tim

Hello.. i wrote a code that uses this library, and isn't 100% reliable when debugging...
I'd be grateful if you comment it.

#include <NewPing.h>

#define BAUD 9600
#define MIN_DISTANCE 6      //Minimum distance to ping (cm)
#define MAX_DISTANCE 60     //Maximum distance to ping (cm)
#define THRESHOLD 10        //Treshold (cm)
#define HOLD_TIME 15        //Delay between each step (ms)
#define STEP_TIME 33        //Delay between ultrasonic's

//Creating ultrasonic objects
NewPing SONAR_L(TRIG_PIN_L, ECHO_PIN_L, 2000);
NewPing SONAR_R(TRIG_PIN_R, ECHO_PIN_R, 2000);

//Creating debugg function
void debugg(int val_l, int val_r)
{
  Serial.print(val_l);
  Serial.print(" ");
  Serial.print(val_r);
  Serial.println();
}

//Creating setup function
void setup() 
{
  Serial.begin(BAUD);
  
  pinMode(ECHO_PIN_L, INPUT);
  pinMode(ECHO_PIN_R, INPUT);
  pinMode(TRIG_PIN_L, OUTPUT);
  pinMode(TRIG_PIN_R, OUTPUT);
}

//Program
void loop() 
{
  //Declaring local static variables
  static bool hold = false;
  static int val_l, val_r;
  static int per_l, per_r;
  static int prev_per_l = MIN_DISTANCE, prev_per_r = MIN_DISTANCE;

  //Reading ultrasonic values
  delay(STEP_TIME);
  unsigned int uS1 = SONAR_L.ping();
  per_l = uS1 / US_ROUNDTRIP_CM;
  
  delay(STEP_TIME);
  unsigned int uS2 = SONAR_R.ping();
  per_r = uS2 / US_ROUNDTRIP_CM;
  
  //Limiting the effective range of ultrasonics
  per_l = constrain(per_l, MIN_DISTANCE, MAX_DISTANCE);
  per_r = constrain(per_r, MIN_DISTANCE, MAX_DISTANCE);
  
  //This part of code is used to save the distance of ultrasonic sensors
  //when the hand is moved away from the beam ) ) ) of the sensor
  if( (per_l - prev_per_l) > THRESHOLD )
  {
    per_l = prev_per_l;
    hold=false;
  }

  if( (per_r - prev_per_r) > THRESHOLD )
  {
    per_r = prev_per_r;
    hold=false;
  }
  
  prev_per_l = per_l;
  prev_per_r = per_r;

  //Modifying the data using linear math (used for servo motors)
  per_l = map(per_l, MIN_DISTANCE, MAX_DISTANCE, 100, 0);

  val_l = map(per_r, MIN_DISTANCE, MAX_DISTANCE, 90, 0);
  val_r = map(per_r, MIN_DISTANCE, MAX_DISTANCE, 0, 90);
  
  val_l = val_l * (per_l / 100.0);
  val_r = val_r * (per_l / 100.0);

  //Writing final data to servo motors
  servo_l.write(val_l);
  servo_r.write(val_r);
  
  //Debugging the final data
  debugg(val_l, val_r);

  //Applying the final delay (due to servo speed characteristics)
  hold=true;
  if(hold==true) delay(HOLD_TIME);
}

xvjeko:
Hello.. i wrote a code that uses this library, and isn't 100% reliable when debugging...
I'd be grateful if you comment it.

  1. TRIG_PIN_L, TRIG_PIN_R, ECHO_PIN_L and ECHO_PIN_R are never defined.
  2. No reason to set the pin modes, NewPing does that for you.
  3. You shouldn't set the maximum distance to 2000cm on the "NewPing SONAR" lines. The sensor won't work beyond 500cm and setting it to 2000 could make the time between pings from 33ms to 115ms or just cause problems in general. Just remove the ,2000 and it will default to the sensor's maximum distance, which is 500cm and will allow for 33ms between pings as you have it set.
  4. The "constrain" commands will give you problems as out of range results (which are zero) would change to 6. Out of range would typically be beyond 500cm, making it 6cm will probably not give what you're looking for. Instead, do something like "if (per_l > 0) per_l = constrain(per_l, MIN_DISTANCE, MAX_DISTANCE);" so there can still be a zero result (out of range).
  5. The rest of your code then needs to accommodate what to do with out of range results. It doesn't appear that you have considered that. If anything, a zero result should be changed to MAX_DISTANCE + 1, as that's what it means. Without considering a zero result (out of range), your sketch will probably never work.

That should give you a good start to diagnose what's going on. 1, 3, 4 & 5 are real problems that will seriously cause problems for your sketch.

Tim

teckel:

xvjeko:
Hello.. i wrote a code that uses this library, and isn't 100% reliable when debugging...
I'd be grateful if you comment it.

  1. TRIG_PIN_L, TRIG_PIN_R, ECHO_PIN_L and ECHO_PIN_R are never defined.
  2. No reason to set the pin modes, NewPing does that for you.
  3. You shouldn't set the maximum distance to 2000cm on the "NewPing SONAR" lines. The sensor won't work beyond 500cm and setting it to 2000 could make the time between pings from 33ms to 115ms or just cause problems in general. Just remove the ,2000 and it will default to the sensor's maximum distance, which is 500cm and will allow for 33ms between pings as you have it set.
  4. The "constrain" commands will give you problems as out of range results (which are zero) would change to 6. Out of range would typically be beyond 500cm, making it 6cm will probably not give you want you're looking for. Instead, do something like "if (per_l > 0) per_l = constrain(per_l, MIN_DISTANCE, MAX_DISTANCE);" so there can still be a zero result (out of range).
  5. The rest of your code then needs to accommodate what to do with out of range results. It doesn't appear that you have considered that. If anything, a zero result should be changed to MAX_DISTANCE + 1, as that's what it means. Without considering a zero result (out of range), your sketch will probably never work.

That should give you a good start to diagnose what's going on. 1, 3, 4 & 5 are real problems that will seriously cause problems for your sketch.

Tim

thank you sir

EDIT: I got everything to work now... I hope it will run flawlessly in the real life... Thanks again

xvjeko:
thank you sir

EDIT: I got everything to work now... I hope it will run flawlessly in the real life... Thanks again

Glad to help! Always satisfying when a project starts to come together. Pictures of your final project are always appreciated by the community.

Tim

hello..im using ultrasonic parallax ping))) sensor.can someone share to me coding for velocity (speed) sensor? km/h

matt121187:
hello..im using ultrasonic parallax ping))) sensor.can someone share to me coding for velocity (speed) sensor? km/h

What's the size and speed of the object you're trying to track the speed of? Will the object always be heading straight for the sensor or at an angle? If at an angle, is the angle consistent and known?

Tim

teckel:

matt121187:
hello..im using ultrasonic parallax ping))) sensor.can someone share to me coding for velocity (speed) sensor? km/h

What's the size and speed of the object you're trying to track the speed of? Will the object always be heading straight for the sensor or at an angle? If at an angle, is the angle consistent and known?

Tim

between two cars..im doing the fyp project..doing the car blind spot detection..this sensor put at the side of the car..then this sensor will measure the distance and speed between my car and side car. actually, for the speed, im not measure the speed of the side car but im measure the different speed between my car and side car..(i think this very simple compare to measure the speed of the side car)

can someone help me... =(

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

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