This is a modification of the Ultrasound tutorial example using the Parallax ultrasonic "PING" range finder. I modified the code to detect the returning pulse inside an external interrupt, rather than polling for it. I haven't calibrated the sensor yet. The distances look approximately correct, with the "0" position starting a few inches from the sensor. That may be a timing issue on my part. Any suggestions or improvements are welcome.
The hardware setup requires connecting the PING data line to the Arduino digital pin 3. I used an Arduino Diecimila with the Arduino 9 software for OS X.
/* Ultrasound Sensor *------------------ * * Reads values (00014-01199) from an ultrasound sensor (3m sensor) * and writes the values to the serialport. * * https://www.xlab.se | http://www.0j0.org * copyleft 2005 Mackie for XLAB | DojoDave for DojoCorp * * 2007-09: Modified by RJL (robertlucier@yahoo.com) * to detect the ultrasound return pulse via INT1 * */ #define TIMER_US_PER_TICK 4 // 16MHz / 64 cycles per tick #define TIMER_OVERFLOW_US TIMER_US_PER_TICK * 65536 // timer1 is 16bit #define INCH_PER_SEC 13526 // speed of sound // use pin 3 because it is connected to external interrupt 1 (INT1) int ultraSoundSignal = 3; // Ultrasound signal pinint val = 0; int ledPin = 13; // LED connected to digital pin 13 int count = 0; // these are volatile because they are changed in interrupt handlers // otherwise the compiler will assume they are unchanged and replace with constants. volatile long ofStart = 0; volatile long timerStart = 0; volatile long ultrasoundValue = 0; volatile int timer1_overflow = 0; ISR(SIG_OVERFLOW1) { // keep track of timer1 overflows. // these should happen every TIMER_OVERFLOW_US microseconds (approx 4 per second at 16MHz clockspeed) timer1_overflow += 1; }; void ultrasound_response() { /* Listening for echo pulse * ------------------------------------------------------------------- * response should come withing ~.5ms (6") and 10ms(20") * handles falling pin interrupt signal */ if (ofStart != -1) { // check ofStart and return if a new ping has started. ultrasoundValue = diffTime(); } } void markTime() { // !!! even though interrupts are disabled, this calculation is still error prone // if the TCNT1 rolls over, but timer1_overflow isn't incremented. cli(); // disable global interrupts timerStart = TCNT1; ofStart = timer1_overflow; sei(); // enable global interrupts } long diffTime() { // return diff in microsec between now and the last mark long us; us = (timer1_overflow - ofStart) * 65536; us += (TCNT1 - timerStart); us *= TIMER_US_PER_TICK; return us; } long microsecs() { // for debugging long us; us = timer1_overflow * 65536; us += TCNT1; us *= TIMER_US_PER_TICK; return us; } void setup() { beginSerial(9600); // Sets the baud rate to 9600 pinMode(ledPin, OUTPUT); // Sets the digital pin as output attachInterrupt(1, ultrasound_response, FALLING); TCNT1 = 0; // reset timer 1 TCCR1A = 0x00; // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0, // PWM10=0 => PWM Operation disabled TCCR1B = 0x03; // clock/64 = increments every 3.2us - overflows in 209.7mS TIMSK1 |= _BV(0); // timer1 overflow interrupt enable TOIE1=1. atmel_doc2545 p. 135 } void triggerPulse() { /* Send low-high-low pulse to activate the trigger pulse of the sensor * ------------------------------------------------------------------- */ int val; ultrasoundValue = -1; // reset any previous value ofStart = -1; // indicator to INT1 interrupt to ignore this LOW pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output digitalWrite(ultraSoundSignal, LOW); // Send low pulse delayMicroseconds(2); // Wait for 2 microseconds digitalWrite(ultraSoundSignal, HIGH); // Send high pulse delayMicroseconds(5); // Wait for 5 microseconds digitalWrite(ultraSoundSignal, LOW); // Holdoff Serial.print("!"); // this could also be handled in an interrupt pinMode(ultraSoundSignal, INPUT); // Switch signalpin to output // poll until ultrasound sensor goes low val = digitalRead(ultraSoundSignal); // Append signal value to val while(val == LOW) { // Loop until pin reads a high value val = digitalRead(ultraSoundSignal); } markTime(); Serial.print("_"); } void printValue() { long in; long ft; // divide by 1000000 here in three steps of 100 in = ((ultrasoundValue/100) * (INCH_PER_SEC/100))/100; in /= 2; // total elapsed time is there and back - divide by two for one way ft = in / 12; in = in % 12; Serial.print("\n"); Serial.print('A'); // Example identifier for the sensor Serial.print(ultrasoundValue); Serial.print("\t"); Serial.print(ft); Serial.print("'\t"); Serial.print(in); Serial.print("\""); Serial.print("\n"); serialFlush(); } void loop() { printValue(); triggerPulse(); Serial.print("."); delay(100); }