NewPing.cpp
Go to the documentation of this file.
00001 // ---------------------------------------------------------------------------
00002 // Created by Tim Eckel - teckel@leethost.com
00003 // Copyright 2012 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
00004 //
00005 // See "NewPing.h" for purpose, syntax, version history, links, and more.
00006 // ---------------------------------------------------------------------------
00007 
00008 #include "NewPing.h"
00009 
00010 
00011 // ---------------------------------------------------------------------------
00012 // NewPing constructor
00013 // ---------------------------------------------------------------------------
00014 
00015 NewPing::NewPing(uint8_t trigger_pin, uint8_t echo_pin, int max_cm_distance) {
00016         _triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin.
00017         _echoBit = digitalPinToBitMask(echo_pin);       // Get the port register bitmask for the echo pin.
00018 
00019         _triggerOutput = portOutputRegister(digitalPinToPort(trigger_pin)); // Get the output port register for the trigger pin.
00020         _echoInput = portInputRegister(digitalPinToPort(echo_pin));         // Get the input port register for the echo pin.
00021 
00022         _triggerMode = (uint8_t *) portModeRegister(digitalPinToPort(trigger_pin)); // Get the port mode register for the trigger pin.
00023 
00024         _maxEchoTime = min(max_cm_distance, MAX_SENSOR_DISTANCE) * US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2); // Calculate the maximum distance in uS.
00025 
00026 #if DISABLE_ONE_PIN == true
00027         *_triggerMode |= _triggerBit; // Set trigger pin to output.
00028 #endif
00029 }
00030 
00031 
00032 // ---------------------------------------------------------------------------
00033 // Standard ping methods
00034 // ---------------------------------------------------------------------------
00035 
00036 unsigned int NewPing::ping() {
00037         if (!ping_trigger()) return NO_ECHO;                // Trigger a ping, if it returns false, return NO_ECHO to the calling function.
00038         while (*_echoInput & _echoBit)                      // Wait for the ping echo.
00039                 if (micros() > _max_time) return NO_ECHO;       // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
00040         return (micros() - (_max_time - _maxEchoTime) - 5); // Calculate ping time, 5uS of overhead.
00041 }
00042 
00043 
00044 unsigned int NewPing::ping_in() {
00045         unsigned int echoTime = NewPing::ping();          // Calls the ping method and returns with the ping echo distance in uS.
00046         return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
00047 }
00048 
00049 
00050 unsigned int NewPing::ping_cm() {
00051         unsigned int echoTime = NewPing::ping();          // Calls the ping method and returns with the ping echo distance in uS.
00052         return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters.
00053 }
00054 
00055 
00056 unsigned int NewPing::ping_median(uint8_t it) {
00057         unsigned int uS[it], last;
00058         uint8_t j, i = 0;
00059         uS[0] = NO_ECHO;
00060         while (i < it) {
00061                 last = ping();           // Send ping.
00062                 if (last == NO_ECHO) {   // Ping out of range.
00063                         it--;                // Skip, don't include as part of median.
00064                         last = _maxEchoTime; // Adjust "last" variable so delay is correct length.
00065                 } else {                       // Ping in range, include as part of median.
00066                         if (i > 0) {               // Don't start sort till second ping.
00067                                 for (j = i; j > 0 && uS[j - 1] < last; j--) // Insertion sort loop.
00068                                         uS[j] = uS[j - 1]; // Shift ping array to correct position for sort insertion.
00069                         } else j = 0;              // First ping is starting point for sort.
00070                         uS[j] = last;              // Add last ping to array in sorted position.
00071                         i++;                       // Move to next ping.
00072                 }
00073                 if (i < it) delay(PING_MEDIAN_DELAY - (last >> 10)); // Millisecond delay between pings.
00074         }
00075         return (uS[it >> 1]); // Return the ping distance median.
00076 }
00077 
00078 
00079 // ---------------------------------------------------------------------------
00080 // Standard ping method support functions (not called directly)
00081 // ---------------------------------------------------------------------------
00082 
00083 boolean NewPing::ping_trigger() {
00084 #if DISABLE_ONE_PIN != true
00085         *_triggerMode |= _triggerBit;    // Set trigger pin to output.
00086 #endif
00087         *_triggerOutput &= ~_triggerBit; // Set the trigger pin low, should already be low, but this will make sure it is.
00088         delayMicroseconds(4);            // Wait for pin to go low, testing shows it needs 4uS to work every time.
00089         *_triggerOutput |= _triggerBit;  // Set trigger pin high, this tells the sensor to send out a ping.
00090         delayMicroseconds(10);           // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10uS.
00091         *_triggerOutput &= ~_triggerBit; // Set trigger pin back to low.
00092 #if DISABLE_ONE_PIN != true
00093         *_triggerMode &= ~_triggerBit;   // 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).
00094 #endif
00095 
00096         _max_time =  micros() + MAX_SENSOR_DELAY;                  // Set a timeout for the ping to trigger.
00097         while (*_echoInput & _echoBit && micros() <= _max_time) {} // Wait for echo pin to clear.
00098         while (!(*_echoInput & _echoBit))                          // Wait for ping to start.
00099                 if (micros() > _max_time) return false;                // Something went wrong, abort.
00100 
00101         _max_time = micros() + _maxEchoTime; // Ping started, set the timeout.
00102         return true;                         // Ping started successfully.
00103 }
00104 
00105 
00106 // ---------------------------------------------------------------------------
00107 // Timer interrupt ping methods (won't work with ATmega8 and ATmega128)
00108 // ---------------------------------------------------------------------------
00109 
00110 void NewPing::ping_timer(void (*userFunc)(void)) {
00111         if (!ping_trigger()) return;         // Trigger a ping, if it returns false, return without starting the echo timer.
00112         timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS.
00113 }
00114 
00115  
00116 boolean NewPing::check_timer() {
00117         if (micros() > _max_time) { // Outside the timeout limit.
00118                 timer_stop();           // Disable timer interrupt
00119                 return false;           // Cancel ping timer.
00120         }
00121 
00122         if (!(*_echoInput & _echoBit)) { // Ping echo received.
00123                 timer_stop();                // Disable timer interrupt
00124                 ping_result = (micros() - (_max_time - _maxEchoTime) - 13); // Calculate ping time, 13uS of overhead.
00125                 return true;                 // Return ping echo true.
00126         }
00127 
00128         return false; // Return false because there's no ping echo yet.
00129 }
00130 
00131 
00132 // ---------------------------------------------------------------------------
00133 // Timer2/Timer4 interrupt methods (can be used for non-ultrasonic needs)
00134 // ---------------------------------------------------------------------------
00135 
00136 // Variables used for timer functions
00137 void (*intFunc)();
00138 void (*intFunc2)();
00139 unsigned long _ms_cnt_reset;
00140 volatile unsigned long _ms_cnt;
00141 
00142 
00143 void NewPing::timer_us(unsigned int frequency, void (*userFunc)(void)) {
00144         timer_setup();      // Configure the timer interrupt.
00145         intFunc = userFunc; // User's function to call when there's a timer event.
00146 
00147 #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
00148         OCR4C = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit.
00149         TIMSK4 = (1<<TOIE4);                  // Enable Timer4 interrupt.
00150 #else
00151         OCR2A = min((frequency>>2) - 1, 255); // Every count is 4uS, so divide by 4 (bitwise shift right 2) subtract one, then make sure we don't go over 255 limit.
00152         TIMSK2 |= (1<<OCIE2A);                // Enable Timer2 interrupt.
00153 #endif
00154 }
00155 
00156 
00157 void NewPing::timer_ms(unsigned long frequency, void (*userFunc)(void)) {
00158         timer_setup();                       // Configure the timer interrupt.
00159         intFunc = NewPing::timer_ms_cntdwn;  // Timer events are sent here once every ms till user's frequency is reached.
00160         intFunc2 = userFunc;                 // User's function to call when user's frequency is reached.
00161         _ms_cnt = _ms_cnt_reset = frequency; // Current ms counter and reset value.
00162 
00163 #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
00164         OCR4C = 249;         // Every count is 4uS, so 1ms = 250 counts - 1.
00165         TIMSK4 = (1<<TOIE4); // Enable Timer4 interrupt.
00166 #else
00167         OCR2A = 249;           // Every count is 4uS, so 1ms = 250 counts - 1.
00168         TIMSK2 |= (1<<OCIE2A); // Enable Timer2 interrupt.
00169 #endif
00170 }
00171 
00172 
00173 void NewPing::timer_stop() { // Disable timer interrupt.
00174 #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
00175         TIMSK4 = 0;
00176 #else
00177         TIMSK2 &= ~(1<<OCIE2A);
00178 #endif
00179 }
00180 
00181 
00182 // ---------------------------------------------------------------------------
00183 // Timer2/Timer4 interrupt method support functions (not called directly)
00184 // ---------------------------------------------------------------------------
00185 
00186 void NewPing::timer_setup() {
00187 #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
00188         timer_stop(); // Disable Timer4 interrupt.
00189         TCCR4A = TCCR4C = TCCR4D = TCCR4E = 0;
00190         TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4); // Set Timer4 prescaler to 64 (4uS/count, 4uS-1020uS range).
00191         TIFR4 = (1<<TOV4);
00192         TCNT4 = 0;    // Reset Timer4 counter.
00193 #else
00194         timer_stop();           // Disable Timer2 interrupt.
00195         ASSR &= ~(1<<AS2);      // Set clock, not pin.
00196         TCCR2A = (1<<WGM21);    // Set Timer2 to CTC mode.
00197         TCCR2B = (1<<CS22);     // Set Timer2 prescaler to 64 (4uS/count, 4uS-1020uS range).
00198         TCNT2 = 0;              // Reset Timer2 counter.
00199 #endif
00200 }
00201 
00202 
00203 void NewPing::timer_ms_cntdwn() {
00204         if (!_ms_cnt--) {            // Count down till we reach zero.
00205                 intFunc2();              // Scheduled time reached, run the main timer event function.
00206                 _ms_cnt = _ms_cnt_reset; // Reset the ms timer.
00207         }
00208 }
00209 
00210 
00211 #if defined (__AVR_ATmega32U4__) // Use Timer4 for ATmega32U4 (Teensy/Leonardo).
00212 ISR(TIMER4_OVF_vect) {
00213 #else
00214 ISR(TIMER2_COMPA_vect) {
00215 #endif
00216         if(intFunc) intFunc(); // If wrapped function is set, call it.
00217 }
00218 
00219 
00220 // ---------------------------------------------------------------------------
00221 // Conversion methods (rounds result to nearest inch or cm).
00222 // ---------------------------------------------------------------------------
00223 
00224 unsigned int NewPing::convert_in(unsigned int echoTime) {
00225         return NewPingConvert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
00226 }
00227 
00228 
00229 unsigned int NewPing::convert_cm(unsigned int echoTime) {
00230         return NewPingConvert(echoTime, US_ROUNDTRIP_CM); // Convert uS to centimeters.
00231 }


segbot_firmware
Author(s): Jose Bigio, Jack O'Quin, Tim Eckel (NewPing library)
autogenerated on Thu Jun 6 2019 21:37:01