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:
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.
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:
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:
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).
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):
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.
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.
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.
And here is a picture of the finished project.
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.












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
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.
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
You can change the RC filters to a higher resonant frequency (> 40kHz) and also change the following line
startTransducer(24000.0, 0.5);
to
startTransducer(40000.0, 0.5);
so the circuit will generate signals at 40kHz instead of 24kHz.
Thanx alot for responding quite quick =)
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
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.
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.
Thanks for your comment. Regarding the op-amp inverting/non-inverting amp gain settings, you can learn more here (http://www.radio-electronics.com/info/circuits/opamp_basics/operational-amplifier-gain.php).
thanks kwong sir.. surely i’ll go through over this. i hope i can learn more from this.
sir, can i use at89c2051 instead of atmega328 for this application? how it will work when i use at89c2051? i need a range of minimum 15feet.
Sorry… I am not familiar with at89c2051. But I am sure you can use similar principle to build one with pretty much any MCU.
[...] 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. [...]
???
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?
You are correct. That was the only opamp I had at the time of the build. LPC662′s GBP isn’t quite sufficient in this scenario and the realistic gain is probably around 15 per stage.
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
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.
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.
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…
For my particular build, the range was right around 20 feet. The actual range depends on the particular transducers you use and also depends on the driving voltage.
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
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
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!
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
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.
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
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 :)
Ultrasonic sensors typically can be driven either way, and there is no polarity.
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
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.
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.
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
You may want to look at op-amp based amplifier and filters in general. Here’s is a good place to get you started: http://www.physics.unlv.edu/~bill/PHYS483/op_amp_filt.pdf