A Sensitive DIY Ultrasonic Range Sensor

I needed some ultrasonic range finders for my project. But most of the commercial sensors like Parallax’s PING sensor and other similar products are quite expensive, especially if multiple units are needed. So I thought why not building it myself?

The theory behind ultrasonic ranging is quite simple. Typically a short ultrasonic burst is transmitted from the transmitter. When there is an object in the path of the ultrasonic pulse, some portion of the transmitted ultrasonic wave is reflected and the ultrasonic receiver can detect such echo. By measuring the elapsed time between the sending and the receiving of the signal along with the knowledge of the speed of sound in the medium, the distance between the receiver and the object can be calculated. The picture below (source: Wikipedia) illustrates this basic principal:

Ultrasonic Ranging (Courtesy of Wikipedia)

Ultrasonic Ranging (Courtesy of Wikipedia)

In my design, I used separate transducers for transmitter and receiver. It is possible to multiplex the transmission and receiving with a single transducer (e.g. Maxbotix range finders), but the design would be significantly more complex.

Ultrasonic Transducer

There are quite a few ultrasonic transducers to choose from, and the main criteria are the resonant frequency, radiation pattern and sensitivity. Generally speaking, these parameters affect the measurement in the following ways: a higher resonant frequency can provide finer details of the surroundings due to the shorter wavelength. A more directional radiation pattern can also enhance the resolution of the measurement. Sensitivity affects the efficiency of the transducer and also attributes to the SNR (signal to noise ratio).

I bought these 24 kHz transducers on sale (see picture below). These transducers are very inexpensive (around a dollar each, and even cheaper when on sale) but effective. With properly designed circuits these sensors can easily achieve a range of more than 20 feet. Of course, using the higher priced 40 kHz sensors should achieve even better performance.

24 kHz Ultrasonic Transducers

24 kHz Ultrasonic Transducers

But for these DIY ultrasonic range finders, the choice of the transducers are really not that critical and this transducer really hits the performance to price sweet spot.

The Transmitter

The ultrasonic transmitter is powered from ATmega328′s counter 1 PWM output (chip pin 16 and Arduino digital pin 10). In order to achieve the maximum output power of the transducer for a given supply voltage, I used the bridged output design as shown in the following schematics:

Ultrasonic Transmitter

Ultrasonic Transmitter

This bridged circuit produces an output voltage roughly twice the Vcc. I used +5V for Vcc and the result is already quite good (more than 20 feet of range). For even longer range measurement, you can safely increase this driving voltage to around 12 Volts as most ultrasonic transducers can be driven with voltage as high as 20 to 30 volts. If you increase the voltage significantly above 5V however, you will have to change the transistors to allow more power dissipation. With 2N3904 and 2N3906 the transistors get warm during normal operation and would heat up drastically with voltage above 6V.

Here is the output of the ultrasonic burst measured at the output transducer’s terminals:

Output Waveform

Output Waveform

The small “ladders” at the half-way voltage point in the output waveform is due to the slight added delay of the inverted signal stage due to the use of an extra NPN transistor. To obtain purer rectangular wave form and reduce switching loss, a PNP transistor with similar timing parameters can be used on the side that is directly connected to the driving signal. For this application though, the waveform is more than adequate and the added switching loss is negligible.

The transmitter and receiver transducers can be mounted on a circuit board with approximately one inch of spacing (see below).

Ultrasonic Range Sensor

Ultrasonic Range Sensor

In order to reduce possible interference from the reflected ultrasonic waves, the components are mounted on the reverse side of the board (below is the H-bridge circuit that drives the ultrasonic transducer, a few decoupling capacitors are used to reduce noise and they are not shown in the schematics above):

H Bridge

H Bridge

The code to drive the transducer is similar to that I used previously, except that I changed the pre-scalar to 1 so that the output frequency can be controlled more precisely in the kHz range.

void startTransducer(float freq, float dutyCycle)
{
  if (dutyCycle > 0.5) dutyCycle = 0.5;
  else if (dutyCycle < 0) dutyCycle = 0;

  cli();
  TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(ICNC1);
  //f0 = fclk / (2 * N * Top)
  long topv = (long) ((float) F_CPU /(freq * 2.0 * 1.0));
  ICR1 = topv;

  OCR1A = (int) ((float) topv * dutyCycle);
  OCR1B = (int) ((float) topv * (1 - dutyCycle));
  DDRB |= _BV(PORTB1) | _BV(PORTB2);
  TCCR1A = _BV(COM1A1) | _BV(COM1B1);
  sei();
}

void stopTransducer()
{
  cli();
  TCCR1B = 0;
  sei();
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
}

The Receiver

The performance of the range sensor is largely determined by the sensitivity of the receiver for a given transmitter power level. Because the received signal is usually very weak (less than 1 mV), a high gain low noise amplifier is needed to ensure optimal performance.

I used a two stage inverted band-pass amplifier design (see below). Each stage has a gain of around 67 (36.5 dB) and the circuit has a combined voltage gain of 73 dB. The operational amplifier I used is National’s LPC662. In general, any operational amplifier with a sufficient gain bandwidth product should work just as well.

Each stage has a band-pass filter that is centered around the operation frequency (24 kHz). Because the amplifier has a very high gain, we must pay special attention to the circuit layout in order to prevent parasitic oscillation. The connection between the receiver transducer and the circuit input (6.8n capacitor) needs to be shielded to reduce noise and unwanted coupling.

Ultrasonic Receiver

Ultrasonic Receiver

Because we are using a single power supply the output voltage of the opamp is centered at around Vcc/2 (2.5V). In order to make it easier to process the echo, a diode (IN4148), capacitor (0.1uF) and resistor (10k) are used to demodulate the signal and a coupling capacitor (1uF) is used to rid the demodulated signal of the DC component.

You can see the demodulated envelope waveform from the following oscilloscope screenshots (you can ignore the frequency measurement as these signals are none-periodical the frequency readings are meaningless). The higher amplitude waveforms in both images are the results of the ultrasonic burst, the lower amplitude waveforms are from the echo. In the first screenshot on the left, two echoes can be seen.

Echo and the demodulated waveform 1

Echo and the demodulated waveform 1

Echo and the demodulated waveform 2

Echo and the demodulated waveform 2

The following screenshot shows the relationship between the ultrasonic pulses (measured from ATmega328 pin 16) from the transmitter and the demodulated echo output. One key observation is that the received signal takes much longer time to fade then the original pulse duration and thus we must add in some delay after the transmission of the ultrasonic pulses. A delay of 1 to 2 millisecond is typical. With a 1 millisecond delay, the shortest measurable distance is around 30 centimeters or one foot.

Demodulated Echo

Demodulated Echo

And here is a picture of the finished project.

Ultrasonic Range Finder

Ultrasonic Range Finder

Range Calculation

Since the measured distance is a function of the time interval between the time at which the pulse is transmitted and the time at which the echo is received, we need to reliability detect the echo.

Empirically, we can measure the peak of the received echo and use the time displacement to calculate the distance. We assume that the strongest echo comes from the closest object (this may not always be true as the reflectivity of different objects are different, but generally achieves very good results in real-world situations) and thus the peak measurement corresponds to the closest object’s position.

The code snippet below assumes that we are interested in measuring objects with a range of up to about 20 feet. After the pulses are transmitted from the transmitter, we wait for a millisecond for the initial receiver signal to fade. Then we search the peak value in the next 20 milliseconds or so (the loop limit 256 is set empirically, in the code below this setting corresponds to a 20 milliseconds interval between transmitted pulses which is suitable for distance measurement up to approximately 20 feet. To measure longer distance, the upper limit for the loop needs to be increased correspondingly) and assume that the peak comes from the first echo.

byte a = 0;
unsigned long t_start = 0;
unsigned long t_peak = 0;
unsigned long t = 0;
byte v_peak = 0;
const float SPEED_OF_SOUND_20C = 0.0003432; //meters per micro-second
float d = 0;

void loop()
{
  startTransducer(24000.0, 0.5);
  delayMicroseconds(300);
  stopTransducer();

  v_peak = 0;
  t_start =micros();
  t_peak = t_start;
  delayMilliseconds(1);

  for (int i = 0; i < 256; i++) {
    a = analogRead(0);
    t = micros();

    if (a > v_peak) {
      t_peak = t;
      v_peak = a;
    }
  }

  t = t_peak - t_start;
  d = (float) t * SPEED_OF_SOUND_20C / 2.0;
  Serial.println(d , 2);
}

Here’s the full code listing for this project:
UltraSonicRangeFinder.tar.gz

The bill of material for this ultrasonic range finder is less than 5 dollars (excluding the MCU since it can be incorporated into your projects).

Update

I would like to thank Thomas for pointing out the mistakes in my H-Bridge schematic. The PNP transistor’s collector and emitter are swapped by mistake (I should have double checked the schematics. Anyway, the photo shows the correct orientation) and I have updated the image.

Also on the receiver side, the first OP’s output was missing connection to the 0.1uF capacitor, I have updated it as well.

Be Sociable, Share!

127 Comments

  1. Gee says:

    Hi everyone,

    I have two ultrasonic sensor, and planned to use it for distance measuring. But I am new to this thing.
    May I ask which one is the Transmitter and the Receiver?

    Here’s the picture of my sensor:

    Bottom view : http://goo.gl/H772c
    Top view : http://goo.gl/Z4Pzp

    Will it work if I connect it directly to my PIC16F84a mcu IO pin?

    If you know the link to the documentation of this sensor, please let me know.

    thanks in advance and hope you can help me.

    gee

  2. Gonzalo says:

    On the transmitter, I’d probably replace all the transistors for one of those H-bridge ICs, used for DC motor drivers.
    You can also use some RS232 IC and pull out some +/-15V to drive the Xducer from a PIC pin
    At the receiver, I’d use a 3rd opamp as Schmitt trigger, to clean up the output a bit.

    Note that 24KHz falls within the hearing range of dogs and cats. At the 10Vpp you’re using, your circuit can easily output some 90-100dB -which dogs will love to hear. If you have pets at home, you can use 40KHz Xducers.

    The receiver circuit was great, thanks for posting! Been digging on Google for a while, trying to find some info about the voltage levels at the receiver side, before and after the amplifier.

    Thanks.

  3. @Q33! says:

    Hey this circuit of yours id pretty useful =)
    I wana know what changes will I have to make if my sonar pair works on 40khz?
    waiting for ur reply

  4. Lavan says:

    Kerry Wong, This is a great circuit. Can I use this to measure the water level in a tank? The distance I will be measuring will be about 10 Feet maximum. If I use 40KHZ transducers, can I drive the transducer without bridge circuit? Can I connect it directly to GND and PIN 10? And also can you please suggest the RC values 40KHZ transducers?

    Thanks in Advance

    • kwong says:

      Hi Lavan,

      I haven’t tried measuring water depth, but it seems that it should work since the water surface will reflect the sound wave. You cannot connect the transducer directly to PIN 10 as each pin does not have sufficient power to power the transducer. You could use a simple transistor to amplify the signal if you intend to use a single supply, but the range would be greatly affected.

      Regarding the RC values, the values shown in the circuit above are actually wider than necessary (with a bandwidth of 19 to 60kHz) so it should work with a 44kHz transducer as well (of course you will have to change the transducer frequency via the startTransducer() function.

  5. kuluvale says:

    hi kwong sir, your design is very nice. and i’m a beginner to this actually. but i know some basics of electronics. so i need a calculation mode for putting a resistor and capacitor in receiver side. i use 40khz transceiver.so for that you suggest 1n in place of 6.8n, 4k in place of 1.2k, like that… and can you please give some links to get information about, how to produce a desired gain from LPC662. and also for about H bridge design.

  6. [...] for range finder using at89c2051 and 40khz ultrasonic sensors…. i have given a sample circuit, http://www.kerrywong.com/2011/01/22/…-range-sensor/ which i found in google. they used atmega… can i use at89c2051 instead of atmega. [...]

  7. Ab says:

    ???

    The GBW of the LPC662 is 0.35 MHz. How can you possibly expect to get a gain of 67 out of it at 24 KHz? Don’t you need a GBW of at least 1.6 MHz?

  8. Bogdan Farcas says:

    Dear Mr. Wong
    Can you help me to translate your code for Mega 2560 board,
    I am pretty new guy in this area (software)…
    I have started to learn about Timers, Interrupts but I need time to understant these.
    Can I use Timer3 on Mega; because on Timer1 I have an 20×4 LCD? (I can use PWM8 and9)
    Please specify again: PWM8 goes to TX and PWM9 toRX?
    The RxTx ultrasound board is ready and seems to work but I need the signal from Mega!
    thanks!
    Bogdan

  9. john says:

    hi Sir,
    I am doing a project in Germany, and this project needs to have sensors to detect the presence of vehicles and any moving object inside at least 1 kilometer. Do you think using a high frequency ultrasonic sensor would help?
    Thanks anyway for your article, it was highly informative.

    • kwong says:

      Using a higher frequency transducer can increase the resolution due to the shorter wavelength, but I don’t know if there are any civilian ultrasound transducers that could handle such long distance (1 km) though. This type of long distance object detection is usually done via radar not ultrasonic sensors.

  10. Francesco says:

    do you know what’s the maximum range you were able to measure? I’m trying to build a cusotm tape measure, like the Stanley used to measure house rooms… so if it could work more than 20 feet would be great…

  11. deladriere says:

    Hello
    Beautiful piece of code
    I found out that you also use the pin 9 to generate the signal. Maybe this was designed to feed the H bridge to maximize the signal.
    Maybe you don’t use it because the left most transistor act as inverter ?
    I don’t have a bridge yet and I am trying to use you code to feed an audio piezo directly with pin 9 & 10
    I have an old single channel oscilloscope and when I use a duty cycle different than 0.5 and can see that the signal from pin 9 & 10 are “mirrored”
    If I use a duty cycle of 0.5 no sound are produced because the sum of the signal equals zero
    Is this a flaw ?
    can you update the code to have the two signal in opposition when the duty cycle is 0.5 ? (to complex for me to do)

    Thanks a lot

    Jean-Luc

  12. Deladriere says:

    Can you help me to do this
    http://softsolder.com/2009/05/21/arduino-push-pull-pwm/
    (running pwm 9 & 10 in opposition)
    but using your code ?
    (too complex for me)
    thanks

    • kwong says:

      Hi Deladriere,

      Sorry I didn’t get a chance to get back to you earlier. I wouldn’t be able to assist you with your particular request as I simply don’t have the time to do that, I got lots of similar requests from users directly. I would suggest that you post your questions on Arduino forum and you might get your answer there.

      Good luck!

  13. sumit says:

    hello, Mr Kwong
    i have searched a lot for designing an ultrasonic distance finder.
    m having a pair of sensor(40khz) planing to implement your design but unable to figure out dis things
    >do this sensor have polarities i mean which terminal should be connected to ground an all
    >where should i put d decoupling capacitor in d transmitter circuit(that too m not able to figure from your image)
    >you have updated a Power Supply Decoupling circuit do i need to build that also to make dis thing work
    >i m using atmega32 can i give a 2ms pulse from a pin directly to the transmitter and planing to receive the o/p of receiver in another pin (i hope i will be getting o/p as logic 1 or 0)

    i will posting more doubt as i progress looking forward for your guidance

    • kwong says:

      Hi Sumit,

      Ultrasonic sensors usually do not have polarity and can be driven either way (think of a speaker).
      The decoupling capacitor should be placed as close to your circuits (e.g. near the Vcc pin on Atmega). The power supply decoupling is not strictly necessary. It depends on how good your power source is. If you are not using the same power source to drive large motors, you probably don’t need it.

      You can’t use the MCU pin to drive the ultrasonic sensors directly as it does not provide enough power and may damage the MCU as a result.

      Hope it helps.

      • sumit says:

        Thanks MR Wong for d reply
        >2ms pulse from a pin directly to the transmitter……
        i mean making a pin 1 den providing 2ms delay ans again making it 0.(without using timer/pwm)
        and giving dis as a input to your transmitter circuit.
        >can i use diode IN4007 instead of IN4148
        >m using OP LM324 in receiver coz m nt getting LPC662 in my area
        the hardware part is done working on code rite nw

  14. Paul Ibrahim says:

    small question can i use the R/t 40K sensors directly with the microprocessor (pic16f877a) and is there a difference between the terminals of the sensors positive negative if there is how can i tell them apart , the terminals are the same height . Thank you :)

  15. umair ahmed says:

    hey. i am using 40khz transducer and you have said that you have used capacitors to reduce noise effect which are not shown in schematic kindly tell me their connections or if you can publish the schematic with capacitors connected as well. secondly tell me that for 40kh the h bridge’s transistors would remain same or not.

    thanks alot
    waiting for reply

    • kwong says:

      The bypassing capacitors added on the H-Bridge board are simply small capacitors (e.g. 100nF) between Vcc and Gnd. The same circuit can be used to drive 40KHz transducers without any issue.

      • Umair Ahmed says:

        sir I am using PIC18f877a microcontroller to generate 40khz pulse which I will use to drive my transducer. It means that I dont have to make any changes to H-Bridge circuit and receiver circit as well.

        thanks for your reply sir.

  16. norulshahlam says:

    HI Mr Kerry Wong,
    I am doing a project on ultrasonic flow meter, specifically measuring blood flow flowing through the hemodialysis tube. I was given a pic18f2520. For the transmitter part, I managed to write a simple code to transmit 40khz to the transmitter (pwm function). Then I measure the receiver part using the oscilloscope. Thankfully it reads 40khz on the oscilloscope.

    But now, the hard part is the receiver. I am aware that signal received is very weak hence need op-amp to amplify the weak signal. I am not sure how to patch up the op amp, and what value of the resistors. I did google on ultrasonic receiver schematic but what I got is receiver for different use (distance measurement, motion detector,etc) and didn’t use pic controller which I think might be no use for my purpose of this project.

    My question is:
    How do I patch up the circuit for the op amp? and maybe for the filter based on 40khz?
    If I manage to get the receiver working, I will test this on plain water first, then on blood so is 40khz is efficient for blood flow measurement?
    If I manage to get the receiver working, how do I write the program codes on how to capture the signal at one time, or within a fixed/given period, or even instantaneously?

    I will be greatly appreciate if I atleast manage to get the idea from your explanations.

    Thank you

    Norulshahlam
    Diploma in Biomedical Informatics Engineering
    Temasek Polytechnic
    Singapore

Leave a Reply