00001 // --------------------------------------------------------------------------- 00002 // NewPing Library - v1.5 - 08/15/2012 00003 // 00004 // AUTHOR/LICENSE: 00005 // Created by Tim Eckel - teckel@leethost.com 00006 // Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html 00007 // 00008 // LINKS: 00009 // Project home: http://code.google.com/p/arduino-new-ping/ 00010 // Blog: http://arduino.cc/forum/index.php/topic,106043.0.html 00011 // 00012 // DISCLAIMER: 00013 // This software is furnished "as is", without technical support, and with no 00014 // warranty, express or implied, as to its usefulness for any purpose. 00015 // 00016 // BACKGROUND: 00017 // When I first received an ultrasonic sensor I was not happy with how poorly 00018 // it worked. Quickly I realized the problem wasn't the sensor, it was the 00019 // available ping and ultrasonic libraries causing the problem. The NewPing 00020 // library totally fixes these problems, adds many new features, and breaths 00021 // new life into these very affordable distance sensors. 00022 // 00023 // FEATURES: 00024 // * Works with many different ultrasonic sensor models: SR04, SRF05, SRF06, DYP-ME007 & Parallax PING)))™. 00025 // * Interface with all but the SRF06 sensor using only one Arduino pin. 00026 // * Doesn't lag for a full second if no ping/echo is received. 00027 // * Ping sensors consistently and reliably at up to 30 times per second. 00028 // * Timer interrupt method for event-driven sketches. 00029 // * Built-in digital filter method ping_median() for easy error correction. 00030 // * Uses port registers for a faster pin interface and smaller code size. 00031 // * Allows you to set a maximum distance where pings beyond that distance are read as no ping "clear". 00032 // * Ease of using multiple sensors (example sketch with 15 sensors). 00033 // * More accurate distance calculation (cm, inches & uS). 00034 // * Doesn't use pulseIn, which is slow and gives incorrect results with some ultrasonic sensor models. 00035 // * Actively developed with features being added and bugs/issues addressed. 00036 // 00037 // CONSTRUCTOR: 00038 // NewPing sonar(trigger_pin, echo_pin [, max_cm_distance]) 00039 // trigger_pin & echo_pin - Arduino pins connected to sensor trigger and echo. 00040 // NOTE: To use the same Arduino pin for trigger and echo, specify the same pin for both values. 00041 // max_cm_distance - [Optional] Maximum distance you wish to sense. Default=500cm. 00042 // 00043 // SYNTAX: 00044 // sonar.ping() - Send a ping and get the echo time (in microseconds) as a result. 00045 // sonar.ping_in() - Send a ping and get the distance in whole inches. 00046 // sonar.ping_cm() - Send a ping and get the distance in whole centimeters. 00047 // sonar.ping_median(iterations) - Do multiple pings (default=5), discard out of range pings and return median in microseconds. 00048 // sonar.convert_in(echoTime) - Convert echoTime from microseconds to inches (rounds to nearest inch). 00049 // sonar.convert_cm(echoTime) - Convert echoTime from microseconds to centimeters (rounds to nearest cm). 00050 // sonar.ping_timer(function) - Send a ping and call function to test if ping is complete. 00051 // sonar.check_timer() - Check if ping has returned within the set distance limit. 00052 // NewPing::timer_us(frequency, function) - Call function every frequency microseconds. 00053 // NewPing::timer_ms(frequency, function) - Call function every frequency milliseconds. 00054 // NewPing::timer_stop() - Stop the timer. 00055 // 00056 // HISTORY: 00057 // 08/15/2012 v1.5 - Added ping_median() method which does a user specified 00058 // number of pings (default=5) and returns the median ping in microseconds 00059 // (out of range pings ignored). This is a very effective digital filter. 00060 // Optimized for smaller compiled size (even smaller than skteches that 00061 // don't use a library). 00062 // 00063 // 07/14/2012 v1.4 - Added support for the Parallax PING)))™ sensor. Interface 00064 // with all but the SRF06 sensor using only one Arduino pin. You can also 00065 // interface with the SRF06 using one pin if you install a 0.1uf capacitor 00066 // on the trigger and echo pins of the sensor then tie the trigger pin to 00067 // the Arduino pin (doesn't work with Teensy). To use the same Arduino pin 00068 // for trigger and echo, specify the same pin for both values. Various bug 00069 // fixes. 00070 // 00071 // 06/08/2012 v1.3 - Big feature addition, event-driven ping! Uses Timer2 00072 // interrupt, so be mindful of PWM or timing conflicts messing with Timer2 00073 // may cause (namely PWM on pins 3 & 11 on Arduino, PWM on pins 9 and 10 on 00074 // Mega, and Tone library). Simple to use timer interrupt functions you can 00075 // use in your sketches totaly unrelated to ultrasonic sensors (don't use if 00076 // you're also using NewPing's ping_timer because both use Timer2 interrupts). 00077 // Loop counting ping method deleted in favor of timing ping method after 00078 // inconsistant results kept surfacing with the loop timing ping method. 00079 // Conversion to cm and inches now rounds to the nearest cm or inch. Code 00080 // optimized to save program space and fixed a couple minor bugs here and 00081 // there. Many new comments added as well as line spacing to group code 00082 // sections for better source readability. 00083 // 00084 // 05/25/2012 v1.2 - Lots of code clean-up thanks to Adruino Forum members. 00085 // Rebuilt the ping timing code from scratch, ditched the pulseIn code as it 00086 // doesn't give correct results (at least with ping sensors). The NewPing 00087 // library is now VERY accurate and the code was simplified as a bonus. 00088 // Smaller and faster code as well. Fixed some issues with very close ping 00089 // results when converting to inches. All functions now return 0 only when 00090 // there's no ping echo (out of range) and a positive value for a successful 00091 // ping. This can effectively be used to detect if something is out of range 00092 // or in-range and at what distance. Now compatible with Arduino 0023. 00093 // 00094 // 05/16/2012 v1.1 - Changed all I/O functions to use low-level port registers 00095 // for ultra-fast and lean code (saves from 174 to 394 bytes). Tested on both 00096 // the Arduino Uno and Teensy 2.0 but should work on all Arduino-based 00097 // platforms because it calls standard functions to retrieve port registers 00098 // and bit masks. Also made a couple minor fixes to defines. 00099 // 00100 // 05/15/2012 v1.0 - Initial release. 00101 // --------------------------------------------------------------------------- 00102 00103 #ifndef NewPing_h 00104 #define NewPing_h 00105 00106 #if defined(ARDUINO) && ARDUINO >= 100 00107 #include <Arduino.h> 00108 #else 00109 #include <WProgram.h> 00110 #include <pins_arduino.h> 00111 #endif 00112 00113 #include <avr/io.h> 00114 #include <avr/interrupt.h> 00115 00116 // Shoudln't need to changed these values unless you have a specific need to do so. 00117 #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. 00118 #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. 00119 #define US_ROUNDTRIP_CM 57 // Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total), uses integer to save compiled code space. 00120 #define DISABLE_ONE_PIN false // Set to "true" to save up to 26 bytes of compiled code space if you're not using one pin sensor connections. 00121 00122 // Probably shoudln't change these values unless you really know what you're doing. 00123 #define NO_ECHO 0 // Value returned if there's no ping echo within the specified MAX_SENSOR_DISTANCE or max_cm_distance. 00124 #define MAX_SENSOR_DELAY 18000 // Maximum uS it takes for sensor to start the ping (SRF06 is the highest measured, just under 18ms). 00125 #define ECHO_TIMER_FREQ 24 // Frequency to check for a ping echo (every 24uS is about 0.4cm accuracy). 00126 #define PING_MEDIAN_DELAY 29 // Millisecond delay between pings in the ping_median method. 00127 00128 // Conversion from uS to distance (round result to nearest cm or inch). 00129 #define NewPingConvert(echoTime, conversionFactor) (max((echoTime + conversionFactor / 2) / conversionFactor, (echoTime ? 1 : 0))) 00130 00131 00132 class NewPing { 00133 public: 00134 NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance = MAX_SENSOR_DISTANCE); 00135 unsigned int ping(); 00136 unsigned int ping_in(); 00137 unsigned int ping_cm(); 00138 unsigned int ping_median(uint8_t it = 5); 00139 unsigned int convert_in(unsigned int echoTime); 00140 unsigned int convert_cm(unsigned int echoTime); 00141 void ping_timer(void (*userFunc)(void)); 00142 boolean check_timer(); 00143 unsigned long ping_result; 00144 static void timer_us(unsigned int frequency, void (*userFunc)(void)); 00145 static void timer_ms(unsigned long frequency, void (*userFunc)(void)); 00146 static void timer_stop(); 00147 private: 00148 boolean ping_trigger(); 00149 boolean ping_wait_timer(); 00150 uint8_t _triggerBit; 00151 uint8_t _echoBit; 00152 volatile uint8_t *_triggerOutput; 00153 volatile uint8_t *_triggerMode; 00154 volatile uint8_t *_echoInput; 00155 unsigned int _maxEchoTime; 00156 unsigned long _max_time; 00157 static void timer_setup(); 00158 static void timer_ms_cntdwn(); 00159 }; 00160 00161 00162 #endif