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

mimansamaheshwari: Hello,

The NewPing is amazing and it worked great with Arduino mega I used single pin of Mega for Trigger and Echo signals of Ultrasonic sensor HC-sr04 and it worked fine.

However when I try to use one pin for signals in ESP32 I get 0cm value in result everytime. If I use two pins for sensor on esp32 everything works fine but I am unable to use single pin of esp32.

Please help me in understanding what is wrong here? Are there any changes to be made in library for using one pin functionality on esp32.

I have also attached the code I am using.

It's possible that the sensor or the ESP32 isn't compatible with single pin control. This is a hardware thing that can't be resolved with software. The single pin method typically only works with an Arduino Uno and a HC-SR04 sensor. But, at the top of the single pin sketch in the comments it does give you a suggestion on how to possibly get it working with a single pin (installing a cap). If that doesn't work, you're out of luck as your hardware doesn't support it.

Tim

Hi Tim

I have been trying out some HC-SR04’s with your example codes that you have provided and everything is working quite well. I am however having trouble working out how to blend them together to achieve my goals.

My project basically has 3 sensors measuring height above ground, with one of them being a fixed reference sensor and the other 2 being separate variable height sensors.

I was trying to use the 3 sensor example and mix it with the event timer example and the timer median example to provide an average measurement for all 3 sensors 4 or 5 times a second.

Does this seem like a good idea, and do you have any suggestions about how to mix them together?

This is what i have tried so far without success

#include <NewPing.h>

#define SONAR_NUM 3
#define MAX_DISTANCE 200
#define PING_INTERVAL 33

NewPing sonar[SONAR_NUM]={
  NewPing(7,7,MAX_DISTANCE),
  NewPing(8,8,MAX_DISTANCE),
  NewPing(9,9,MAX_DISTANCE)
};

unsigned int pingSpeed = 50;
unsigned long pingTimer;

void setup() {
  Serial.begin(115200);
  pingTimer = millis();
}

void loop() {
  for (uint8_t i=0; i<SONAR_NUM; i++){
    if (millis() >= pingTimer){
    pingTimer += pingSpeed;
    sonar.ping_timer(echoCheck);
    } 
  }
  
}

void echoCheck() {
  if (sonar.check_timer()){
    Serial.print(sonar.ping_result/US_ROUNDTRIP_CM);
    Serial.println("cm");
  }
}

Thanks

Tony

Greenie-0424:
Hi Tim

I have been trying out some HC-SR04’s with your example codes that you have provided and everything is working quite well. I am however having trouble working out how to blend them together to achieve my goals.

My project basically has 3 sensors measuring height above ground, with one of them being a fixed reference sensor and the other 2 being separate variable height sensors.

I was trying to use the 3 sensor example and mix it with the event timer example and the timer median example to provide an average measurement for all 3 sensors 4 or 5 times a second.

Does this seem like a good idea, and do you have any suggestions about how to mix them together?

This is what i have tried so far without success

#include <NewPing.h>

#define SONAR_NUM 3
#define MAX_DISTANCE 200
#define PING_INTERVAL 33

NewPing sonar[SONAR_NUM]={
 NewPing(7,7,MAX_DISTANCE),
 NewPing(8,8,MAX_DISTANCE),
 NewPing(9,9,MAX_DISTANCE)
};

unsigned int pingSpeed = 50;
unsigned long pingTimer;

void setup() {
 Serial.begin(115200);
 pingTimer = millis();
}

void loop() {
 for (uint8_t i=0; i<SONAR_NUM; i++){
   if (millis() >= pingTimer){
   pingTimer += pingSpeed;
   sonar.ping_timer(echoCheck);
   }
 }
 
}

void echoCheck() {
 if (sonar.check_timer()){
   Serial.print(sonar.ping_result/US_ROUNDTRIP_CM);
   Serial.println(“cm”);
 }
}




Thanks 

Tony

You’re probably complicating things by trying to use the ping_timer() method based on the 15 sensor example. I would suggest NOT going this route if you’re having problems sorting out your logic as this is a much more complicated programming paradigm to understand. Please see the following Wiki which tries to talk you out of using the 15 sensor sketch ad nauseam:

Help with 15 Sensor Example Sketch

Instead, do what it suggests and use this sketch as a guide:
Ping 3 sensors sketch

And if you want to do averaging for each sensor, you can replace:

Serial.print(sonar[i].ping_cm());

with :

Serial.print(sonar[i].ping_median() / US_ROUNDTRIP_CM);

As I continue to get support questions from people trying to use the 15 sensor sketch that have no business trying, and I’ve tried everything to guild people in the right direction, could you let me know why you decided to use the 15 sensor sketch as a starting point instead of the MUCH more easy to understand 3 sensor sketch? Even after all the warnings and you’re still trying to use it? I’m really at a loss as to what to do other than remove the 15 sensor sketch. Even though it’s useful for the expert coders, it seems to totally wreck the minds of new coders, to a point where they don’t follow any of my warnings or suggestions. Any help would be appreciated.

Tim

quick question. why 99.99% of HC-SR04 code put trigger pin LOW for 2us-5us?

the datasheet tells to set trigger pin HIGH for 10us..100us to start measurement. why LOW?

enjoyneering: quick question. why 99.99% of HC-SR04 code put trigger pin LOW for 2us-5us?

the datasheet tells to set trigger pin HIGH for 10us..100us to start measurement. why LOW?

The sensor is triggered when trig is high for around 10us. But, in order to see that, we should first be sure the pin is low. So, it's set to low, then set to high for the required 10us to trigger the sensor. If, for example, it was already high, it would never trigger the ping.

This really shouldn't be required, as the pin should be low already. But, it's just insurance that nothing else set it high. I believe NewPing is the only library that does this (due to the single pin connection method). NewPing also does this because it can be used as a background timer so the pin may not be in the state you believe it's in at the time the ping is triggered.

Tim

So is it only for set-up where trigger & echo pins connected to one Arduino port?

enjoyneering: So is it only for set-up where trigger & echo pins connected to one Arduino port?

No, it should work with either (it works with every sensor on every system that I have). But, if you're having a problem, or running non-standard hardware, there's an option to simply disable this.

Tim

No, it should work with either (it works with every sensor on every system that I have).

So why do we need it? it just takes ram and time to execute the code.

Hey,

I just recently started using this library and noticed that when I disconnect my sensor and use ping(), instead of getting NO_ECHO (0) sometimes it reports a random number (usually 20-30cm below MAX_SENSOR_DISTANCE). Wondering if anyone else is experiencing this issue?

This is especially impacting the reliability of ping.median() as NO ECHOs are factored out, so even just 1 faulty reading is sufficient for the sensor to still report a measurement.

NewPing.h (renamed to sr4t)

#include "WProgram.h"

#define sr4t_h
#define MAX_SENSOR_DISTANCE 300
#define US_ROUNDTRIP_CM 58
#define NO_ECHO 0
#define MAX_SENSOR_DELAY 5800   // Maximum uS it takes for sensor to start the ping
#define ECHO_TIMER_FREQ 24      // Frequency to check for a ping echo
#define PING_MEDIAN_DELAY 29000
#define PING_OVERHEAD 5
#define PING_TIMER_OVERHEAD 13
#define NewPingConvert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0)))

class sr4t {
public:
sr4t(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE);
unsigned int ping(unsigned int max_cm_distance = 0);
unsigned long ping_cm(unsigned int max_cm_distance = 0);
unsigned long ping_in(unsigned int max_cm_distance = 0);
unsigned long ping_median(uint8_t it = 5, unsigned int max_cm_distance = 0);
static unsigned int convert_cm(unsigned int echoTime);
static unsigned int convert_in(unsigned int echoTime);
private:
boolean ping_trigger();
void set_max_distance(unsigned int max_cm_distance);
uint8_t _triggerPin;
uint8_t _echoPin;
unsigned int _maxEchoTime;
unsigned long _max_time;
   };

NewPing.cpp

#include "sr4t.h"

sr4t::sr4t(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance) {
    _triggerPin = trigger_pin;
    _echoPin = echo_pin;
	set_max_distance(max_cm_distance);
    }

unsigned int sr4t::ping(unsigned int max_cm_distance) {
	if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance.
	if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function.
	while (digitalRead(_echoPin))                 // Wait for the ping echo.
	    if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
	    return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead.
    }

unsigned long sr4t::ping_cm(unsigned int max_cm_distance) {
	unsigned long echoTime = sr4t::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS.
	return (echoTime / US_ROUNDTRIP_CM);              // Call the ping method and returns the distance in centimeters (no rounding).
    }

unsigned long sr4t::ping_median(uint8_t it, unsigned int max_cm_distance) {
	unsigned int uS[it], last;
	uint8_t j, i = 0;
	unsigned long t;
	uS[0] = NO_ECHO;
	while (i < it) {
		t = micros();                  // Start ping timestamp.
		last = ping(max_cm_distance);  // Send ping.
		if (last != NO_ECHO) {         // Ping in range, include as part of median.
			if (i > 0) {               // Don't start sort till second ping.
				for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop.
					uS[j] = uS[j - 1];                      // Shift ping array to correct position for sort insertion.
			    } 
			else j = 0;              // First ping is sort starting point.
			uS[j] = last;              // Add last ping to array in sorted position.
			i++;                       // Move to next ping.
		    } 
		else it--;                   // Ping out of range, skip and don't include as part of median.
		if (i < it && micros() - t < PING_MEDIAN_DELAY)
			delay((PING_MEDIAN_DELAY + t - micros()) / 1000); // Millisecond delay between pings.
	    }
	return (uS[it >> 3]); // Return the ping 12.5th percentile distance.
    }

boolean sr4t::ping_trigger() {
	pinMode(_triggerPin, OUTPUT); // Set trigger pin to output.
	digitalWrite(_triggerPin, LOW);
	delayMicroseconds(4);
	digitalWrite(_triggerPin, HIGH);
	delayMicroseconds(10);
	digitalWrite(_triggerPin, LOW);
    pinMode(_triggerPin, INPUT);  // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin).
	if (digitalRead(_echoPin)) return false;                // Previous ping hasn't finished, abort.
	_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
	while (!digitalRead(_echoPin))                          // Wait for ping to start.
	    if (micros() > _max_time) return false;             // Took too long to start, abort.
	    _max_time = micros() + _maxEchoTime; // Ping started, set the time-out.
	    return true;                         // Ping started successfully.
    }

void sr4t::set_max_distance(unsigned int max_cm_distance) {
	_maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding).
    }

unsigned int sr4t::convert_cm(unsigned int echoTime) {
	return (echoTime / US_ROUNDTRIP_CM);              // Convert uS to centimeters (no rounding).
    }

enjoyneering: So why do we need it? it just takes ram and time to execute the code.

You have the option! Turn it off and save a bit of memory, or leave it on and it works with one pin. The default "on" method works either way, which is why it's default. Also, the saved memory is VERY small, probably 8 bytes. So it's not much of a hit for 100% compatibility.

But, you have the option so I'm not sure what the issue is. 100% compatibility out of the box and a user option to save 8 bytes sounds like the only solution to me. But, make an argument if you wish.

Tim

Vitesze:
Hey,

I just recently started using this library and noticed that when I disconnect my sensor and use ping(), instead of getting NO_ECHO (0) sometimes it reports a random number (usually 20-30cm below MAX_SENSOR_DISTANCE). Wondering if anyone else is experiencing this issue?

This is especially impacting the reliability of ping.median() as NO ECHOs are factored out, so even just 1 faulty reading is sufficient for the sensor to still report a measurement.

NewPing.h (renamed to sr4t)

#include "WProgram.h"

#define sr4t_h
#define MAX_SENSOR_DISTANCE 300
#define US_ROUNDTRIP_CM 58
#define NO_ECHO 0
#define MAX_SENSOR_DELAY 5800  // Maximum uS it takes for sensor to start the ping
#define ECHO_TIMER_FREQ 24      // Frequency to check for a ping echo
#define PING_MEDIAN_DELAY 29000
#define PING_OVERHEAD 5
#define PING_TIMER_OVERHEAD 13
#define NewPingConvert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0)))

class sr4t {
public:
sr4t(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE);
unsigned int ping(unsigned int max_cm_distance = 0);
unsigned long ping_cm(unsigned int max_cm_distance = 0);
unsigned long ping_in(unsigned int max_cm_distance = 0);
unsigned long ping_median(uint8_t it = 5, unsigned int max_cm_distance = 0);
static unsigned int convert_cm(unsigned int echoTime);
static unsigned int convert_in(unsigned int echoTime);
private:
boolean ping_trigger();
void set_max_distance(unsigned int max_cm_distance);
uint8_t _triggerPin;
uint8_t _echoPin;
unsigned int _maxEchoTime;
unsigned long _max_time;
  };



NewPing.cpp


#include “sr4t.h”

sr4t::sr4t(uint8_t trigger_pin, uint8_t echo_pin, unsigned int max_cm_distance) {
    _triggerPin = trigger_pin;
    _echoPin = echo_pin;
set_max_distance(max_cm_distance);
    }

unsigned int sr4t::ping(unsigned int max_cm_distance) {
if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance.
if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function.
while (digitalRead(_echoPin))                // Wait for the ping echo.
    if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we’re beyond the set maximum distance.
    return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead.
    }

unsigned long sr4t::ping_cm(unsigned int max_cm_distance) {
unsigned long echoTime = sr4t::ping(max_cm_distance); // Calls the ping method and returns with the ping echo distance in uS.
return (echoTime / US_ROUNDTRIP_CM);              // Call the ping method and returns the distance in centimeters (no rounding).
    }

unsigned long sr4t::ping_median(uint8_t it, unsigned int max_cm_distance) {
unsigned int uS[it], last;
uint8_t j, i = 0;
unsigned long t;
uS[0] = NO_ECHO;
while (i < it) {
t = micros();                  // Start ping timestamp.
last = ping(max_cm_distance);  // Send ping.
if (last != NO_ECHO) {        // Ping in range, include as part of median.
if (i > 0) {              // Don’t start sort till second ping.
for (j = i; j > 0 && uS[j - 1] < last; j–) // Insertion sort loop.
uS[j] = uS[j - 1];                      // Shift ping array to correct position for sort insertion.
    }
else j = 0;              // First ping is sort starting point.
uS[j] = last;              // Add last ping to array in sorted position.
i++;                      // Move to next ping.
    }
else it–;                  // Ping out of range, skip and don’t include as part of median.
if (i < it && micros() - t < PING_MEDIAN_DELAY)
delay((PING_MEDIAN_DELAY + t - micros()) / 1000); // Millisecond delay between pings.
    }
return (uS[it >> 3]); // Return the ping 12.5th percentile distance.
    }

boolean sr4t::ping_trigger() {
pinMode(_triggerPin, OUTPUT); // Set trigger pin to output.
digitalWrite(_triggerPin, LOW);
delayMicroseconds(4);
digitalWrite(_triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(_triggerPin, LOW);
    pinMode(_triggerPin, INPUT);  // Set trigger pin to input (when using one Arduino pin, this is technically setting the echo pin to input as both are tied to the same Arduino pin).
if (digitalRead(_echoPin)) return false;                // Previous ping hasn’t finished, abort.
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we’ll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
while (!digitalRead(_echoPin))                          // Wait for ping to start.
    if (micros() > _max_time) return false;            // Took too long to start, abort.
    _max_time = micros() + _maxEchoTime; // Ping started, set the time-out.
    return true;                        // Ping started successfully.
    }

void sr4t::set_max_distance(unsigned int max_cm_distance) {
_maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding).
    }

unsigned int sr4t::convert_cm(unsigned int echoTime) {
return (echoTime / US_ROUNDTRIP_CM);              // Convert uS to centimeters (no rounding).
    }

I haven’t experienced this, but it could be based on the sensor and microcontroller you’re using. I would try to tweak these values higher to see if that resolves the problem:

#define MAX_SENSOR_DELAY 5800
#define PING_MEDIAN_DELAY 29000

These values worked for all of my sensors, but because they are sensor dependent, I made them easy to modify. As a starting point, double both and see if that resolves the problem. If so, it’s then just a matter of figuring out what the best value is for your microcontroller.

Tim

Vitesze: Hey,

I just recently started using this library and noticed that when I disconnect my sensor and use ping(), instead of getting NO_ECHO (0) sometimes it reports a random number (usually 20-30cm below MAX_SENSOR_DISTANCE). Wondering if anyone else is experiencing this issue?

If you leave pins floating sometimes it happens that they get sufficient noise that is evaluated as a echo.

teckel:
I haven’t experienced this, but it could be based on the sensor and microcontroller you’re using. I would try to tweak these values higher to see if that resolves the problem:

#define MAX_SENSOR_DELAY 5800

#define PING_MEDIAN_DELAY 29000




These values worked for all of my sensors, but because they are sensor dependent, I made them easy to modify. As a starting point, double both and see if that resolves the problem. If so, it's then just a matter of figuring out what the best value is for your microcontroller.

Tim

I’m using the Particle Electron, and JSN-SR04T sensor. Changing these values hasn’t worked - I tried adding a pull-up/down resistor and it also didn’t appear to help much.

So you’re saying you can use this library, leave the actual TRIG/ECHO pin unpopulated (or non-functioning sensor) and it will always return the NO ECHO value (i.e. 0)?

Vitesze:
I’m using the Particle Electron, and JSN-SR04T sensor. Changing these values hasn’t worked - I tried adding a pull-up/down resistor and it also didn’t appear to help much.

So you’re saying you can use this library, leave the actual TRIG/ECHO pin unpopulated (or non-functioning sensor) and it will always return the NO ECHO value (i.e. 0)?

No, as zoomx stated, if nothing is connected to a pin it’s in a floating state, and that could read as a distance measurement. Adding a pull-down to echo should help, but I’ve never tired doing this as I’ve always connected a sensor.

In any case, this would be outside the scope of software as it’s totally a hardware situation (missing sensor or floating echo pin). Nothing software can do in this situation, you need hardware to create the wanted pin state (keep echo pin low).

Tim

Hi! Can you please help me with my code?

I want combine motor code and newping. I use 1 stepper motor and 6 ultrasonic sensor. My intention is to program motor that rotate after take 200 cycles of newping reading. I have no idea how to program 200 sensorcycle reading of newping per rotation motor. When i try combine motor with 6 newping sensor, the reading only show at last sensor(refer photo attached).

I attach a copy below.

#include <NewPing.h>
#include <Stepper.h>

#define SONAR_NUM     6 // Number of sensors.
#define MAX_DISTANCE 1000 // 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.

const int stepsPerRevolution = 200;
int stepCount = 0;
Stepper myStepper(stepsPerRevolution, 32,33,34,35);

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

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

void loop() {
  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(); // 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.
{    if(stepCount < 10) 
  {
    RotateMotor();
    Serial.print("steps:");
    Serial.println(stepCount);
  }
  else {
    StopMotor();
  }
  stepCount++;}
}

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("US");
    Serial.print(i+1);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}

void RotateMotor() {
  myStepper.step(1);
  delay(500);
}

void StopMotor() {
  myStepper.step(0);
  delay(500);
}

Sadly, I get compile errors.

[SOLVED]

I gutted the timer2 bit. Actually the whole interupt segment as denoted by comments. Then it compiled fine and works much better than ultrasonic.h.

mattlogue:
Sadly, I get compile errors.

I and thousands of other people do not get compile errors. So you should really share what you’re getting and what you changed. My guess is that you’re not using Arduino hardware. But, who knows because you give no details.

Tim

Good day everyone, i want to know how if i can use “Timer Median Sketch” with 2 HC-SR04 Sensores.

I need to get a Median between both sensors, and aftes that get this median.

If someone can help, i will be very thanks.

I got 2 HCSR-04 getting a median between 30 measures.

So in the end, i need get 60 measures from both sensors, and get this median after that.

PLEASE HELP ME !

I try this way, but something dosnt work as expected.

// ---------------------------------------------------------------------------
// Calculate a ping median using the ping_timer() method.
// ---------------------------------------------------------------------------

#include <NewPing.h>

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

unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration.
unsigned int cm[ITERATIONS];         // Where the ping distances are stored.
uint8_t currentIteration = 0;        // Keeps track of iteration step.
uint8_t currentSensor = 0;

NewPing sonar[SONAR_NUM] = {  
  NewPing(3, 9, MAX_DISTANCE),
  NewPing(10, 11, MAX_DISTANCE)
  };

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 < ITERATIONS; i++) // Set the starting time for each iteration.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop() 
{
  medicoes();
}

void medicoes()
{
  for (uint8_t v = 0; v < SONAR_NUM; v++)                                     // SONAR_NUM[0] = cm[30] ITERATIONS
  {                                                                           // SONAR_NUM[1] = cm[30] ITERATIONS
    for (uint8_t i = 0; i < ITERATIONS; i++)                                  // Loop through all the iterations.
    { 
      if (millis() >= pingTimer[i])                                           // Is it this iteration's time to ping?
      {          
        pingTimer[i] += PING_INTERVAL * ITERATIONS;                           // Set next time this sensor will be pinged.
        if (i == 0 && currentIteration == ITERATIONS - 1) 
        {
          oneSensorCycle();                                                   // Sensor ping cycle complete, do something with the results.
        }
        sonar[v].timer_stop();                                                // Make sure previous timer is canceled before starting a new ping (insurance).
        currentIteration = i;                                                 // Sensor being accessed.
        cm[currentIteration] = 0;                                             // Make distance zero in case there's no ping echo for this iteration.
        sonar[v].ping_timer(echoCheck);                                       // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
      }
    }
    currentSensor = v;
  }
}

void echoCheck()                                                              // If ping received, set the sensor distance to array.
{ 
  if (sonar[currentSensor].check_timer())
  {
    cm[currentIteration] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
  }
}

void oneSensorCycle()                                                         // All iterations complete, calculate the median.
{ 
  unsigned int uS[ITERATIONS];
  uint8_t j, it = ITERATIONS;
  uS[0] = NO_ECHO;
  for (uint8_t i = 0; i < it; i++)                                            // Loop through iteration results.
  { 
    if (cm[i] != NO_ECHO)                                                     // Ping in range, include as part of median.
    { 
      if (i > 0)
      {          // Don't start sort till second ping.
        for (j = i; j > 0 && uS[j - 1] < cm[i]; j--) // Insertion sort loop.
          uS[j] = uS[j - 1];                         // Shift ping array to correct position for sort insertion.
      } 
      else j = 0;         // First ping is sort starting point.
      uS[j] = cm[i];        // Add last ping to array in sorted position.
    } 
    else it--;            // Ping out of range, skip and don't include as part of median.
  }
  Serial.println(uS[it >> 1]);
}

I Need to get 30 iterations from each sensor, and do a median between this 60 iterations.
And after that, print the result in Serial Port.

NariGODs:
Good day everyone, i want to know how if i can use “Timer Median Sketch” with 2 HC-SR04 Sensores.

I need to get a Median between both sensors, and aftes that get this median.

If someone can help, i will be very thanks.

I got 2 HCSR-04 getting a median between 30 measures.

So in the end, i need get 60 measures from both sensors, and get this median after that.

PLEASE HELP ME !

I try this way, but something dosnt work as expected.

// ---------------------------------------------------------------------------

// Calculate a ping median using the ping_timer() method.
// ---------------------------------------------------------------------------

#include <NewPing.h>

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

unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration.
unsigned int cm[ITERATIONS];        // Where the ping distances are stored.
uint8_t currentIteration = 0;        // Keeps track of iteration step.
uint8_t currentSensor = 0;

NewPing sonar[SONAR_NUM] = { 
  NewPing(3, 9, MAX_DISTANCE),
  NewPing(10, 11, MAX_DISTANCE)
  };

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 < ITERATIONS; i++) // Set the starting time for each iteration.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}

void loop()
{
  medicoes();
}

void medicoes()
{
  for (uint8_t v = 0; v < SONAR_NUM; v++)                                    // SONAR_NUM[0] = cm[30] ITERATIONS
  {                                                                          // SONAR_NUM[1] = cm[30] ITERATIONS
    for (uint8_t i = 0; i < ITERATIONS; i++)                                  // Loop through all the iterations.
    {
      if (millis() >= pingTimer[i])                                          // Is it this iteration’s time to ping?
      {         
        pingTimer[i] += PING_INTERVAL * ITERATIONS;                          // Set next time this sensor will be pinged.
        if (i == 0 && currentIteration == ITERATIONS - 1)
        {
          oneSensorCycle();                                                  // Sensor ping cycle complete, do something with the results.
        }
        sonar[v].timer_stop();                                                // Make sure previous timer is canceled before starting a new ping (insurance).
        currentIteration = i;                                                // Sensor being accessed.
        cm[currentIteration] = 0;                                            // Make distance zero in case there’s no ping echo for this iteration.
        sonar[v].ping_timer(echoCheck);                                      // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
      }
    }
    currentSensor = v;
  }
}

void echoCheck()                                                              // If ping received, set the sensor distance to array.
{
  if (sonar[currentSensor].check_timer())
  {
    cm[currentIteration] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
  }
}

void oneSensorCycle()                                                        // All iterations complete, calculate the median.
{
  unsigned int uS[ITERATIONS];
  uint8_t j, it = ITERATIONS;
  uS[0] = NO_ECHO;
  for (uint8_t i = 0; i < it; i++)                                            // Loop through iteration results.
  {
    if (cm[i] != NO_ECHO)                                                    // Ping in range, include as part of median.
    {
      if (i > 0)
      {          // Don’t start sort till second ping.
        for (j = i; j > 0 && uS[j - 1] < cm[i]; j–) // Insertion sort loop.
          uS[j] = uS[j - 1];                        // Shift ping array to correct position for sort insertion.
      }
      else j = 0;        // First ping is sort starting point.
      uS[j] = cm[i];        // Add last ping to array in sorted position.
    }
    else it–;            // Ping out of range, skip and don’t include as part of median.
  }
  Serial.println(uS[it >> 1]);
}




I Need to get 30 iterations from each sensor, and do a median between this 60 iterations.
And after that, print the result in Serial Port.

As I’ve described ad nauseam, don’t use the 15 sensor sketch as a base for your code unless you know what you’re doing. If you don’t, I can almost guarantee it won’t work. It’s for experts only and no one will want to spend the time to debug and rewrite your sketch. So you’ve been warned… again.

Instead, why not just use the built-in ping_median() method? Use the Ping 3 sensors sketch as a basis:

https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home#!ping-3-sensors-sketch

Change it to 2 sensors, and instead of doing a ping_cm(), do a ping_median(). Since you want to do 30 iterations from each sensor, you would be doing a ping_median(30). Then, take the two results from the 2 sensors and average them. Easy peasy. Don’t over-complicate it.

Tim