Skip to content

Commit ccb453e

Browse files
committed
initial commit for port
0 parents  commit ccb453e

11 files changed

+822
-0
lines changed

NewPingESP8266.cpp

+362
Large diffs are not rendered by default.

NewPingESP8266.h

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// ---------------------------------------------------------------------------
2+
// NewPingESP8266 Library - v1.8 - 07/30/2016
3+
//
4+
// AUTHOR/LICENSE:
5+
// Created by Tim Eckel - [email protected]
6+
// Copyright 2016 License: GNU GPL v3 http://www.gnu.org/licenses/gpl.html
7+
//
8+
// LINKS:
9+
// Project home: https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home
10+
// Blog: http://arduino.cc/forum/index.php/topic,106043.0.html
11+
//
12+
// DISCLAIMER:
13+
// This software is furnished "as is", without technical support, and with no
14+
// warranty, express or implied, as to its usefulness for any purpose.
15+
//
16+
// BACKGROUND:
17+
// When I first received an ultrasonic sensor I was not happy with how poorly
18+
// it worked. Quickly I realized the problem wasn't the sensor, it was the
19+
// available ping and ultrasonic libraries causing the problem. The NewPingESP8266
20+
// library totally fixes these problems, adds many new features, and breaths
21+
// new life into these very affordable distance sensors.
22+
//
23+
// FEATURES:
24+
// * Works with many different ultrasonic sensors: SR04, SRF05, SRF06, DYP-ME007, URM37 & Parallax PING))).
25+
// * Compatible with the entire Arduino line-up (and clones), Teensy family (including $19 96Mhz 32 bit Teensy 3.2) and non-AVR microcontrollers.
26+
// * Interface with all but the SRF06 sensor using only one Arduino pin.
27+
// * Doesn't lag for a full second if no ping/echo is received.
28+
// * Ping sensors consistently and reliably at up to 30 times per second.
29+
// * Timer interrupt method for event-driven sketches.
30+
// * Built-in digital filter method ping_median() for easy error correction.
31+
// * Uses port registers for a faster pin interface and smaller code size.
32+
// * Allows you to set a maximum distance where pings beyond that distance are read as no ping "clear".
33+
// * Ease of using multiple sensors (example sketch with 15 sensors).
34+
// * More accurate distance calculation (cm, inches & uS).
35+
// * Doesn't use pulseIn, which is slow and gives incorrect results with some ultrasonic sensor models.
36+
// * Actively developed with features being added and bugs/issues addressed.
37+
//
38+
// CONSTRUCTOR:
39+
// NewPingESP8266 sonar(trigger_pin, echo_pin [, max_cm_distance])
40+
// trigger_pin & echo_pin - Arduino pins connected to sensor trigger and echo.
41+
// NOTE: To use the same Arduino pin for trigger and echo, specify the same pin for both values.
42+
// max_cm_distance - [Optional] Maximum distance you wish to sense. Default=500cm.
43+
//
44+
// METHODS:
45+
// sonar.ping([max_cm_distance]) - Send a ping and get the echo time (in microseconds) as a result. [max_cm_distance] allows you to optionally set a new max distance.
46+
// sonar.ping_in([max_cm_distance]) - Send a ping and get the distance in whole inches. [max_cm_distance] allows you to optionally set a new max distance.
47+
// sonar.ping_cm([max_cm_distance]) - Send a ping and get the distance in whole centimeters. [max_cm_distance] allows you to optionally set a new max distance.
48+
// sonar.ping_median(iterations [, max_cm_distance]) - Do multiple pings (default=5), discard out of range pings and return median in microseconds. [max_cm_distance] allows you to optionally set a new max distance.
49+
// NewPingESP8266::convert_in(echoTime) - Convert echoTime from microseconds to inches (rounds to nearest inch).
50+
// NewPingESP8266::convert_cm(echoTime) - Convert echoTime from microseconds to centimeters (rounds to nearest cm).
51+
// sonar.ping_timer(function [, max_cm_distance]) - Send a ping and call function to test if ping is complete. [max_cm_distance] allows you to optionally set a new max distance.
52+
// sonar.check_timer() - Check if ping has returned within the set distance limit.
53+
// NewPingESP8266::timer_us(frequency, function) - Call function every frequency microseconds.
54+
// NewPingESP8266::timer_ms(frequency, function) - Call function every frequency milliseconds.
55+
// NewPingESP8266::timer_stop() - Stop the timer.
56+
//
57+
// HISTORY:
58+
// 07/30/2016 v1.8 - Added support for non-AVR microcontrollers. For non-AVR
59+
// microcontrollers, advanced ping_timer() timer methods are disabled due to
60+
// inconsistencies or no support at all between platforms. However, standard
61+
// ping methods are all supported. Added new optional variable to ping(),
62+
// ping_in(), ping_cm(), ping_median(), and ping_timer() methods which allows
63+
// you to set a new maximum distance for each ping. Added support for the
64+
// ATmega16, ATmega32 and ATmega8535 microcontrollers. Changed convert_cm()
65+
// and convert_in() methods to static members. You can now call them without
66+
// an object. For example: cm = NewPingESP8266::convert_cm(distance);
67+
//
68+
// 09/29/2015 v1.7 - Removed support for the Arduino Due and Zero because
69+
// they're both 3.3 volt boards and are not 5 volt tolerant while the HC-SR04
70+
// is a 5 volt sensor. Also, the Due and Zero don't support pin manipulation
71+
// compatibility via port registers which can be done (see the Teensy 3.2).
72+
//
73+
// 06/17/2014 v1.6 - Corrected delay between pings when using ping_median()
74+
// method. Added support for the URM37 sensor (must change URM37_ENABLED from
75+
// false to true). Added support for Arduino microcontrollers like the $20
76+
// 32 bit ARM Cortex-M4 based Teensy 3.2. Added automatic support for the
77+
// Atmel ATtiny family of microcontrollers. Added timer support for the
78+
// ATmega8 microcontroller. Rounding disabled by default, reduces compiled
79+
// code size (can be turned on with ROUNDING_ENABLED switch). Added
80+
// TIMER_ENABLED switch to get around compile-time "__vector_7" errors when
81+
// using the Tone library, or you can use the toneAC, NewTone or
82+
// TimerFreeTone libraries: https://bitbucket.org/teckel12/arduino-toneac/
83+
// Other speed and compiled size optimizations.
84+
//
85+
// 08/15/2012 v1.5 - Added ping_median() method which does a user specified
86+
// number of pings (default=5) and returns the median ping in microseconds
87+
// (out of range pings ignored). This is a very effective digital filter.
88+
// Optimized for smaller compiled size (even smaller than sketches that
89+
// don't use a library).
90+
//
91+
// 07/14/2012 v1.4 - Added support for the Parallax PING)))� sensor. Interface
92+
// with all but the SRF06 sensor using only one Arduino pin. You can also
93+
// interface with the SRF06 using one pin if you install a 0.1uf capacitor
94+
// on the trigger and echo pins of the sensor then tie the trigger pin to
95+
// the Arduino pin (doesn't work with Teensy). To use the same Arduino pin
96+
// for trigger and echo, specify the same pin for both values. Various bug
97+
// fixes.
98+
//
99+
// 06/08/2012 v1.3 - Big feature addition, event-driven ping! Uses Timer2
100+
// interrupt, so be mindful of PWM or timing conflicts messing with Timer2
101+
// may cause (namely PWM on pins 3 & 11 on Arduino, PWM on pins 9 and 10 on
102+
// Mega, and Tone library). Simple to use timer interrupt functions you can
103+
// use in your sketches totally unrelated to ultrasonic sensors (don't use if
104+
// you're also using NewPingESP8266's ping_timer because both use Timer2 interrupts).
105+
// Loop counting ping method deleted in favor of timing ping method after
106+
// inconsistent results kept surfacing with the loop timing ping method.
107+
// Conversion to cm and inches now rounds to the nearest cm or inch. Code
108+
// optimized to save program space and fixed a couple minor bugs here and
109+
// there. Many new comments added as well as line spacing to group code
110+
// sections for better source readability.
111+
//
112+
// 05/25/2012 v1.2 - Lots of code clean-up thanks to Arduino Forum members.
113+
// Rebuilt the ping timing code from scratch, ditched the pulseIn code as it
114+
// doesn't give correct results (at least with ping sensors). The NewPingESP8266
115+
// library is now VERY accurate and the code was simplified as a bonus.
116+
// Smaller and faster code as well. Fixed some issues with very close ping
117+
// results when converting to inches. All functions now return 0 only when
118+
// there's no ping echo (out of range) and a positive value for a successful
119+
// ping. This can effectively be used to detect if something is out of range
120+
// or in-range and at what distance. Now compatible with Arduino 0023.
121+
//
122+
// 05/16/2012 v1.1 - Changed all I/O functions to use low-level port registers
123+
// for ultra-fast and lean code (saves from 174 to 394 bytes). Tested on both
124+
// the Arduino Uno and Teensy 2.0 but should work on all Arduino-based
125+
// platforms because it calls standard functions to retrieve port registers
126+
// and bit masks. Also made a couple minor fixes to defines.
127+
//
128+
// 05/15/2012 v1.0 - Initial release.
129+
// ---------------------------------------------------------------------------
130+
131+
#ifndef NewPingESP8266_h
132+
#define NewPingESP8266_h
133+
134+
#if defined (ARDUINO) && ARDUINO >= 100
135+
#include <Arduino.h>
136+
#else
137+
#include <WProgram.h>
138+
#include <pins_arduino.h>
139+
#endif
140+
141+
#if defined (__AVR__)
142+
#include <avr/io.h>
143+
#include <avr/interrupt.h>
144+
#endif
145+
146+
// Shouldn't need to change these values unless you have a specific need to do so.
147+
#define MAX_SENSOR_DISTANCE 500 // Maximum sensor distance can be as high as 500cm, no reason to wait for ping longer than sound takes to travel this distance and back. Default=500
148+
#define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. Default=57
149+
#define US_ROUNDTRIP_IN 146 // Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total), uses integer to save compiled code space. Defalult=146
150+
#define ONE_PIN_ENABLED true // Set to "false" to disable one pin mode which saves around 14-26 bytes of binary size. Default=true
151+
#define ROUNDING_ENABLED false // Set to "true" to enable distance rounding which also adds 64 bytes to binary size. Default=false
152+
#define URM37_ENABLED false // Set to "true" to enable support for the URM37 sensor in PWM mode. Default=false
153+
#define TIMER_ENABLED true // Set to "false" to disable the timer ISR (if getting "__vector_7" compile errors set this to false). Default=true
154+
155+
// Probably shouldn't change these values unless you really know what you're doing.
156+
#define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. Default=0
157+
#define MAX_SENSOR_DELAY 5800 // Maximum uS it takes for sensor to start the ping. Default=5800
158+
#define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). Default=24
159+
#define PING_MEDIAN_DELAY 29000 // Microsecond delay between pings in the ping_median method. Default=29000
160+
#define PING_OVERHEAD 5 // Ping overhead in microseconds (uS). Default=5
161+
#define PING_TIMER_OVERHEAD 13 // Ping timer overhead in microseconds (uS). Default=13
162+
#if URM37_ENABLED == true
163+
#undef US_ROUNDTRIP_CM
164+
#undef US_ROUNDTRIP_IN
165+
#define US_ROUNDTRIP_CM 50 // Every 50uS PWM signal is low indicates 1cm distance. Default=50
166+
#define US_ROUNDTRIP_IN 127 // If 50uS is 1cm, 1 inch would be 127uS (50 x 2.54 = 127). Default=127
167+
#endif
168+
169+
// Conversion from uS to distance (round result to nearest cm or inch).
170+
#define NewPingESP8266Convert(echoTime, conversionFactor) (max(((unsigned int)echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0)))
171+
172+
// Detect non-AVR microcontrollers (Teensy 3.x, Arduino DUE, etc.) and don't use port registers or timer interrupts as required.
173+
#if (defined (__arm__) && defined (TEENSYDUINO))
174+
#undef PING_OVERHEAD
175+
#define PING_OVERHEAD 1
176+
#undef PING_TIMER_OVERHEAD
177+
#define PING_TIMER_OVERHEAD 1
178+
#define DO_BITWISE true
179+
#elif !defined (__AVR__)
180+
#undef PING_OVERHEAD
181+
#define PING_OVERHEAD 1
182+
#undef PING_TIMER_OVERHEAD
183+
#define PING_TIMER_OVERHEAD 1
184+
#undef TIMER_ENABLED
185+
#define TIMER_ENABLED false
186+
#define DO_BITWISE false
187+
#else
188+
#define DO_BITWISE true
189+
#endif
190+
191+
// Disable the timer interrupts when using ATmega128 and all ATtiny microcontrollers.
192+
#if defined (__AVR_ATmega128__) || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny261__) || defined (__AVR_ATtiny461__) || defined (__AVR_ATtiny861__) || defined (__AVR_ATtiny43U__)
193+
#undef TIMER_ENABLED
194+
#define TIMER_ENABLED false
195+
#endif
196+
197+
// Define timers when using ATmega8, ATmega16, ATmega32 and ATmega8535 microcontrollers.
198+
#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega8535__)
199+
#define OCR2A OCR2
200+
#define TIMSK2 TIMSK
201+
#define OCIE2A OCIE2
202+
#endif
203+
204+
class NewPingESP8266 {
205+
public:
206+
NewPingESP8266(uint32_t trigger_pin, uint32_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE);
207+
unsigned int ping(unsigned int max_cm_distance = 0);
208+
unsigned long ping_cm(unsigned int max_cm_distance = 0);
209+
unsigned long ping_in(unsigned int max_cm_distance = 0);
210+
unsigned long ping_median(uint32_t it = 5, unsigned int max_cm_distance = 0);
211+
static unsigned int convert_cm(unsigned int echoTime);
212+
static unsigned int convert_in(unsigned int echoTime);
213+
#if TIMER_ENABLED == true
214+
void ping_timer(void (*userFunc)(void), unsigned int max_cm_distance = 0);
215+
boolean check_timer();
216+
unsigned long ping_result;
217+
static void timer_us(unsigned int frequency, void (*userFunc)(void));
218+
static void timer_ms(unsigned long frequency, void (*userFunc)(void));
219+
static void timer_stop();
220+
#endif
221+
private:
222+
boolean ping_trigger();
223+
void set_max_distance(unsigned int max_cm_distance);
224+
#if TIMER_ENABLED == true
225+
boolean ping_trigger_timer(unsigned int trigger_delay);
226+
boolean ping_wait_timer();
227+
static void timer_setup();
228+
static void timer_ms_cntdwn();
229+
#endif
230+
#if DO_BITWISE == true
231+
uint32_t _triggerBit;
232+
uint32_t _echoBit;
233+
volatile uint32_t *_triggerOutput;
234+
volatile uint32_t *_echoInput;
235+
volatile uint32_t *_triggerMode;
236+
#else
237+
uint32_t _triggerPin;
238+
uint32_t _echoPin;
239+
#endif
240+
unsigned int _maxEchoTime;
241+
unsigned long _max_time;
242+
};
243+
244+
245+
#endif

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
NewPing Library (Ultrasonic Sensors)
2+
3+
Written by Tim Eckel
4+
5+
https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home
6+
7+
Modified for Teensy 3.0 & 3.1
8+
9+
https://github.com/PaulStoffregen/NewPing
10+
11+
http://forum.pjrc.com/threads/25907-Multiple-HCSR-04-Ultrasonic-sensors-on-teensy-3
12+
13+
![Photo](https://raw.githubusercontent.com/PaulStoffregen/NewPing/master/extras/NewPing_photo.jpg)
14+
15+
![Screenshot](https://raw.githubusercontent.com/PaulStoffregen/NewPing/master/extras/NewPing_screenshot.png)
16+
17+

examples/.DS_Store

6 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// ---------------------------------------------------------------------------
2+
// This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust
3+
// the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the
4+
// "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor
5+
// is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results
6+
// are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project
7+
// would normally process the sensor results in this function (for example, decide if a robot needs to
8+
// turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs
9+
// to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other
10+
// processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind.
11+
// ---------------------------------------------------------------------------
12+
#include <NewPing.h>
13+
14+
#define SONAR_NUM 15 // Number of sensors.
15+
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
16+
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).
17+
18+
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
19+
unsigned int cm[SONAR_NUM]; // Where the ping distances are stored.
20+
uint8_t currentSensor = 0; // Keeps track of which sensor is active.
21+
22+
NewPing sonar[SONAR_NUM] = { // Sensor object array.
23+
NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
24+
NewPing(43, 44, MAX_DISTANCE),
25+
NewPing(45, 20, MAX_DISTANCE),
26+
NewPing(21, 22, MAX_DISTANCE),
27+
NewPing(23, 24, MAX_DISTANCE),
28+
NewPing(25, 26, MAX_DISTANCE),
29+
NewPing(27, 28, MAX_DISTANCE),
30+
NewPing(29, 30, MAX_DISTANCE),
31+
NewPing(31, 32, MAX_DISTANCE),
32+
NewPing(34, 33, MAX_DISTANCE),
33+
NewPing(35, 36, MAX_DISTANCE),
34+
NewPing(37, 38, MAX_DISTANCE),
35+
NewPing(39, 40, MAX_DISTANCE),
36+
NewPing(50, 51, MAX_DISTANCE),
37+
NewPing(52, 53, MAX_DISTANCE)
38+
};
39+
40+
void setup() {
41+
Serial.begin(115200);
42+
pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting.
43+
for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
44+
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
45+
}
46+
47+
void loop() {
48+
for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
49+
if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping?
50+
pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged.
51+
if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
52+
sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance).
53+
currentSensor = i; // Sensor being accessed.
54+
cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor.
55+
sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
56+
}
57+
}
58+
// Other code that *DOESN'T* analyze ping results can go here.
59+
}
60+
61+
void echoCheck() { // If ping received, set the sensor distance to array.
62+
if (sonar[currentSensor].check_timer())
63+
cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
64+
}
65+
66+
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
67+
// The following code would be replaced with your code that does something with the ping results.
68+
for (uint8_t i = 0; i < SONAR_NUM; i++) {
69+
Serial.print(i);
70+
Serial.print("=");
71+
Serial.print(cm[i]);
72+
Serial.print("cm ");
73+
}
74+
Serial.println();
75+
}

0 commit comments

Comments
 (0)