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!

237 Comments

  1. victor says:

    kerry so far so good. my progress has been minimal
    i effected the change in the source code for developing a 40KHZ frequency to run the transmitter. but unfortunately sir. my measurement on a frequency metter is 1.86KHZ. . pls what can be done sir

    sir i was likewise getting 0.19 on my serial board without any variation in the value. weather the object goes further or closer. the value on d serial board remains constant. i also reduced the transducer decay value. which was immediately after the statement T-peak〓 T-start. but any change made there would increase or reduce d serrial value to another constant value without any variation.

    sir my changes to ur circuit was dat am using an LM324 op amp.
    ® i also edited the resonant circuit and filter capacitor used at the negative input of each op amp stage.
    ® finally i dnt use the capacitor that ran through vcc and ground in th H-bridge circuit. what effect can dis have sir.

    am really sorry for bothering. i am running out of time to the completion of the project sir. i would appreciate a personal contact to u sir. u can email me personnaly sir on engrtor151@gmail.com.

  2. Randy says:

    The bridge transmitter doesn’t look right. The waveform should be +(5v – 1.2v) to -(5v – 1.2v) peak-to-peak. The 1.2v drops would be due to 0.6v base-emitter drops on the PNP and NPN transistor on either side of the transducer.

    With nothing connected to “Pin 10″ driver, there is a sneak circuit through the PNP Base-Emitter junction, through first 1.5K, through second 1.5K, through both NPN transistors. The Arduino Pin 10 driver source would have to source a lot of current to overcome the sneak circuit and it only seems to be sinking current.

    Anyway, you are not getting +3.8v to -3.8v peak-to-peak across the transducer and would be better off with a single P-Channel MOSFET highside switch or a single N-channel lowside switch. If you want a higher signal output, use a 1:10 transformer to raise the transducer voltage and match the higher transducer impedance. The transformer would put about 50v peak-to-peak across the transducer when using +5v Vcc.

    Very interesting and thanks for posting.

  3. Randy says:

    Yes, the Transmitter bridge circuit is upside down. NPN should be on top (+) and PNP on bottom (-), emitters connected to transducer, with perhaps a 2K resistor across the transducer for base current to flow in the transistors.

    http://www.electroschematics.com/1026/dog-repellent-circuit/

    • Jon says:

      Brilliant, Randy! I spent a day struggling with this trying to figure out where my stray current was going. With the original setup, during the 1-2 second Arduino startup when pin 10 is still an INPUT (default), there was about 100mA of current flowing to the circuit. Then when pin 10 was set to an output, there was still stray current: 13mA when pin 10 was HIGH and 35mA when pin 10 was LOW. If I didn’t configure pin 10 to be an OUTPUT at all, the 100mA would remain and start to cook my transistors, literally.

      Anyway, I did as you said and it worked perfectly. When pin 10 is set to LOW or as an input, it consumes < 2mA including during startup. Presumably this is solely due to the resistor.

      And regarding the resistor… it reduces ringing quite a bit it seems.

      Kudos!

  4. Alex says:

    love your write up on this, very well done indeed. i remember doing similar work on this when i was younger for a micromouse competition, where i was told it was impossible to use ultrasonics in such small places, and that was by the so called head of robotics for the UK. anyhow it worked, lol.
    just wondering if you mind if we used a couple of your photos and a bit of text for a review blog on our site of this, with your name and site mentioned and linked to?
    Regards
    Al

  5. [...] result measurements, circuits and code is all avaliable on Kerry’s website at: http://www.kerrywong.com/2011/01/22/a-sensitive-diy-ultrasonic-range-sensor/comment-page-3/#comment-… [...]

  6. mikel says:

    helo mr. Kwong, im using PIC18F.. as what i’ve read, you are using arduino, how would i connect the circuit to the PIC18F?

  7. Cheryl says:

    Hi Randy,

    Am i able to use other chip instead of lpc662? in addition, do u mind if i have a clearer picture of the circuit you have done? Thanks!

  8. kshitij says:

    Respected sir. Which op amp can i use instead of lpc662. Expecting ur reply at the earliest. THANKS 1 in advance.

  9. GarfFun says:

    Hi Kerry,
    First of all, great tutorial, it has been a great help in my project. I have a small question regarding the receiving of the signal. I understand you are using the single-ended ADC conversion of the microcontroler. What is the threshold voltage you are accepting as an echo? Should it be anything higher than 2.5V- the “ground” of the receiver output or something more precise?
    Thanks for any help!

    • kwong says:

      Thanks!

      For this simple example, I used the “peak” in the returned signal. But to make it more robust, you could use the peak along with a threshold (so when the object is too far away and there is no echo, the reading does not jump around). The threshold should be referenced to ground instead of 2.5V (Vcc/2) though since the cap at the ADC pin removed the DC offset already.

      • GarfFun says:

        Well, I forgot about the capacitor at the end. Anyway, I have another question. The amplification of each stage is 67. That makes 67*67=4489. Assuming we have echo peak at around 20mV, that would give us almost 90V output. How come the output signal doesn’t exceed 2.5V? Sorry for the stupid question, but I’m a begginer if it comes to electronics.

        • kwong says:

          In practice, the actual gain will be much smaller (as some pointed out, the first stage was probably not quite ideal as it was configured as none-inverting, which means the input impedance is quite low, never the less, the circuit does work quite well over all), the best way to determine whether the gain is adequate is to use a scope to measure the output.

  10. mashr says:

    hi. i have two Ultrasonic Transducer RC40K5 and OC40K5. Can someone please tell me which one is Transmitter & Receiver. how to get to know about it. and at what frequency it operates…thanks

  11. Rajeev says:

    Hi,
    I have an ultrasonic transducer of frequency 1 MHz. what part of the circuits(both Tx and Rx ) should I edit for getting an echo in digital oscilloscope.
    Now, I am trying to give signal using agilent waveform generator, pulse of 1 MHz,15 Vpp etc. but i am not getting proper distance measurement. Please help me.

    • Kenny says:

      Hi Rajeev, I am trying to do something similar. Could you share if you found an amplification solution? Maybe we can work together to determine a solution.

      Kind regards,
      Kenny

  12. amine says:

    hello sir , well i work on project that’s much similar to yours and i was very impressed when i saw your project and i wanted to associated to my robot but i am working w uth pic 18f6620 can you help me with some directions please

  13. sachin poreyana says:

    sir,
    I am a new bee into this. I have chosen my final year project regarding acceleration measurement using ultrasound. i have a 40 kHz transceiver. i would like to have range of 20 meters. I am using a pic16f877 controller, but my sensor is detecting just 1 meter, i am using 5v supply. what could be done to solve this please help me guys. what would be the maximum range measurable using 40 kHz sensor.

  14. Jitesh Verma says:

    Hi Kerry,
    First of all, I higly appreciate your valuable article. I am attempting to build a proximity sensor device for the first time.
    Can you suggest me an appropriate ultrasonic transducer part number for a higher range (25-30 meters)?
    Also, can you tell me whether the same ultrasonic tranducer part number can be used as both transmitter as well as receiver? Or, is it that the transmitter and receiver is given different part numbers by the manufacturers?
    Thanks,
    Jitesh

Leave a Reply