NewPing: fast, filtered ultrasonic readings
NewPing by Tim Eckel was written because the usual pulseIn() approach to the HC-SR04 waits up to a second for an echo that is not coming. NewPing takes a maximum distance in its constructor and stops listening once sound could have gone that far and back, so a missed echo costs a few milliseconds instead of stalling the sketch.
Built in on Mokxi: #include <NewPing.h> and it builds, with nothing to install. Free, and no account needed.
What NewPing does
A ping that gets no echo inside that distance returns 0, not a large number. That is the most important thing to handle in a NewPing sketch: treat 0 as "nothing in range" rather than as an object touching the sensor.
ping_median() fires several pings, throws away the ones that failed and returns the middle value, which cleans up the odd wild reading from a soft or angled target. Upstream also offers ping_timer(), which runs the ping from a timer interrupt; in Mokxi it does the whole ping at once and then calls your function, so the result is the same but the sketch does not keep running meanwhile.
| Library Manager name | NewPing |
|---|---|
| Author | Tim Eckel |
| Include | #include <NewPing.h> |
| Boards | every board Mokxi compiles for |
| In the simulator | Runs, with a gap the note below names. |
| Parts it drives | Ultrasonic ranger |
Install it
It builds on every board Mokxi compiles for.
In Mokxi it is built in: #include <NewPing.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "NewPing" by Tim Eckel from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add NewPing to lib_deps in PlatformIO. Mokxi follows the calls of release 1.9.7, so a sketch written here builds there too.
What to know in the simulator: ping_timer() does the whole ping and then calls the sketch鈥檚 function once, rather than from a timer interrupt.
ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 ATtiny85 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE)
Creates the sensor with its pins and the farthest distance in centimeters worth waiting for (up to 500).
sonar.ping_cm()
One ping, returned in whole centimeters, or 0 when nothing came back within the maximum distance.
unsigned int cm = sonar.ping_cm();
if (cm == 0) Serial.println("out of range");
else Serial.println(cm);sonar.ping_in()
The same in inches.
sonar.ping_median(5)
Five pings, failures dropped, the middle one returned as an echo time in microseconds.
sonar.convert_cm(echoTime)
Turns an echo time from ping() or ping_median() into centimeters.
sonar.ping_timer(echoCheck)
Starts a ping that calls echoCheck() when done; inside it, check_timer() is true and ping_result holds the echo time.
Example: Distance with an HC-SR04
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include <NewPing.h>
#define TRIGGER_PIN 12
#define ECHO_PIN 11
#define MAX_DISTANCE 200
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
Serial.begin(9600);
}
void loop() {
delay(50);
Serial.print("Ping: ");
Serial.print(sonar.ping_cm());
Serial.println("cm");
}Wiring
- Arduino Uno R3 12 to Ultrasonic ranger TRIG
- Arduino Uno R3 11 to Ultrasonic ranger ECHO
- Arduino Uno R3 5V to Ultrasonic ranger VCC
- Arduino Uno R3 GND to Ultrasonic ranger GND
Common errors and how to fix them
ping_cm() returns 0
Zero means no echo inside MAX_DISTANCE. Raise the maximum in the constructor if the target is far, and check the echo wire. Filter zeros out before averaging, or use ping_median(), which ignores them.
multiple definition of '__vector_7' when the sketch also uses tone()
On an Uno, NewPing鈥檚 timer code and tone() both claim Timer 2. If you do not use ping_timer(), comment out the timer functions as the NewPing docs describe, or use a tone library on another timer.
Readings are a few centimeters short or long
Sound speed changes with temperature. NewPing assumes about 20 C; for better accuracy take ping() or ping_median() and convert the time yourself with the speed of sound at your temperature.
Try NewPing without installing anything
Open the example, change the sketch, and keep your version in a free account.