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 }