Pages: [1]   Go Down
Author Topic: arduino ultrasound sensor example  (Read 1264 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,

I just received my Arduino Dieimila last week, and I wanted to say thanks to the community for something that was so easy to set up with my Mac and get running.

As a first project, I worked through the Ultrasound example using the Parallax ultrasonic range finder. I modified the code to detect the returning pulse inside an external interrupt, rather than polling for it. I thought I'd post my code in case it proves useful for anyone else going in this direction. I haven't calibrated the sensor yet. The distances look approximately correct, with 0" starting a few inches from the sensor. That may be a timing issue on my part. Any comments or suggestions are welcome.

Thanks,

-Rob

 /* Ultrasound Sensor
 *------------------
 *
 * Reads values (00014-01199) from an ultrasound sensor (3m sensor)
 * and writes the values to the serialport.
 *
 * http://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);
}
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

hey

that is terrific... if you can, it's good to also make a page in the Playgorund, as the search function for the forum is terrible. At the bottom right corner of the Playground there is a link called "request contributor access". It issues you a password automatically.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the tip. I created a page called PingInterruptCode, and linked it from the Interrupts Example page. That page also links to the cool DCF77 receiver clock, which provided some inspiration to me on timer code.
Logged

Pages: [1]   Go Up
Jump to: