SRF05 Ultra-Sonic Ranger


I’ve just spend a couple of hours preparing this ultra-sonic ranger and the necessary code to integrate it into my autonomous tank project.

Here’s a quick post briefly explaining the theory and providing some Arduino code for it.

SRF05 in all its glory

Let’s start with a link to its specs and description.

As you can see, there are 2 modes of operation, the only difference being if the trigger / output pins are physically different or not.

I prefer mode 2, which uses the same pin for triggering the bursts and outputing the result. The benefit is simply saving 1 pin on the microcontroller.

SRF timing diagram - mode 2

There are 3 parts for doing 1 sampling:

  1. trigger the sampling by sending a 10uS high pulse on the trigger/output pin
  2. the ranger MCU sends 8 cycles of sonic bursts
  3. receive a high pulse with a duration proportional to the distance

Here’s the testing setup that I’ve used:

Test setup, connected to a Roboduino

And finally the Arduino code. It’s using interrupts to avoid blocking the program during the max 30mS when receiving the output pulse.

/*
The timing for an ultra sound signal can take as long as 30ms, so we need to use interrupts

The SRF05 can be triggered as fast as every 50mS, or 20 times each second.
You should wait 50ms before the next trigger, even if the SRF05 detects a close object and the echo pulse is shorter.
This is to ensure the ultrasonic "beep" has faded away and will not cause a false echo on the next ranging.
*/

#define PIN_US 3Β  // External Interrupt 1
// the beam of the US is quite wide, > 30degrees... this means that as the distance increases, so does the width
// at 120cm distance, the width is 1.4 meters ! so let's not go beyond that point...
#define MAX_RANGE VALID_PERC_MAX // in CM, has to fit into a byte

volatile unsigned int _usDistance;Β  // in cm
volatile unsigned long _startEchoPulse;


void us_triggerReading(){
detachInterrupt(1);

// 1. send a TRIGGER high 10microS pulse
pinMode(PIN_US, OUTPUT);
digitalWrite(PIN_US, LOW);
delayMicroseconds(2);
digitalWrite(PIN_US, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_US, LOW);
// now we have 700uS to turn the trigger pin around and make it an input

// 2. wait for the response
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the object we take half of the distance travelled.
pinMode(PIN_US, INPUT);

// now the ISR routine will handle whatever happens on this echo pin...
attachInterrupt(1, echoSignalISR, CHANGE);
}


void echoSignalISR(){
if (digitalRead(PIN_US) == HIGH ) {
_startEchoPulse = micros();
}else {
// calculate the distance while applying a filter to "smooth" transitions (and eventual error spikes)
if(_startEchoPulse > 0){
_usDistance = (_usDistance + (micros() - _startEchoPulse) / 58) / 2;
_startEchoPulse = 0;
}
}
}


unsigned int us_getDist() {
return _usDistance;
}

byte us_getByteDist() {
return constrain(_usDistance, 0, MAX_RANGE);
}

3 Responses to SRF05 Ultra-Sonic Ranger

  1. Mehras says:

    Hi,
    I have made an range finding solution for my quadcopter using HY-SRF05 SONAR & Arduino Leonardo
    so I get the PWM output from Arduino’s Pin 5, and I’m also using APM 2.6 (Arducopter) as flight controller
    so I need to converse PWM signal to Analog signals and connecting it to APM’s A0 analog input pin,
    I want to use an R/C low pass filter, I’m searching for proper Resistor & Capacitor values, but I can’t find exact answer,
    Can you help me?
    thanks πŸ™‚

  2. Pingback: Tiger 1 BB airsoft RC Tank – V3 « Robotics / Electronics / Physical Computing

Leave a comment