Fuelled by insatiable curiosity
One day a friend (who is also a Mechatronics engineer) and I decided to build an ultrasonic rangefinder. Sure, you can already buy modules such as the LV-EZ1 from Sparkfun, but where would the fun be in that? Moreover, things get expensive when you start wanting several of these sensors. Many people also disagree with the logo printed on the LV-EZ1 PCB. So we decided to build a sonic rangefinder (SRF) from parts. We managed to build 10 SRFs for around $12NZD each. At the time, this was a huge saving. Currently it still is, however, you can also buy SRF modules very cheaply off ebay (athough these do not have nice I2C or UART interfaces).
A key component of a SRF is its transducer. After scouring the internet, we came across the MB1100 from MaxBotix. This part is the transducer that is used on the LV-EZ1 and other SRFs from MaxBotix. Unfortunately, they seem to have stopped selling the transducer separately.
Interestingly, the LV-EZ1 datasheet provides the schematic of the SRF circuit. It uses a PIC16F676, and has UART and analog interfaces. We thought it would be more useful if we made it have an I2C interface. So we set out on creating the schematic and PCB layout for our SRF in EAGLE. The analog circuit provided in the datasheet was replicated, but the PIC was replaced with an ATmega8, and the interface to the module was changed to be I2C. A picture of the resulting schematic:
Once the PCB layout was complete, a stack of PCBs were made. The PCBs were DIY'd, using the toner transfer method. To prevent the PCBs from oxidising and looking horrible after a week, they were covered with a clear, solderable lacquer. The finished module:
There is limited information on the MB1100 datasheet to create a SRF module from. In order to find out how MaxBotix was driving the transducer, we got hold of a LV-EZ1 sensor and began probing it with an oscilloscope. The LV-EZ1 sends out 13 pulses of 40kHz. It is important to get this frequency right, as otherwise it will output a significantly weaker sonar pulse. In order to double the drive of the transducer, the microcontroller alternates between driving one terminal high and the other one low.
After sending out the pulses, the functionality of the transducer is changed to being a receiver. The high terminal is grounded, while the negative terminal is set to be an input. Since the transducer is a mechanical device, it will continue to resonate until the energy is dissipated through parasitic loses. To reduce the time it takes for the ringing to die down, before one of the leads is set as an input, the two terminals are shorted for 52us. A trace of the pulse generation and ringing (CH1 is +ive terminal, CH2 is -ive) is shown below:
The operating principle behind any sonar rangefinder is that distances to objects can be determined by finding the time between sending the pulse and receiving its echo. Sound waves travel at a known speed, i.e., ~340m/s. This of course assumes that the target does not totally absorb the sonar wave, and reflects a sufficient amount of it back towards the transceiver. I would show you a trace with the received echo, but this track is unaccessible on the LV-EZ1 (it is under the transducer that has been potted to the PCB).
Once the hardware had been built up, my friend and I started developing the software for the onboard microcontroller. The first step was to develop an I2C slave interface, followed by the sonar related functions. In hindsight, an LED would have been very useful to put on the PCB - particularly during the early phases of the software development. We made do by toggling a spare pin and looking at it with an oscilloscope.
After a bare-bones I2C interface had been implemented, we wrote the sonar related functions. The generation of the pulse was simple, but we had to increase the blanking time to 220us. If it was left at 52us, the transducer still had too much energy in it and the excessive amount of ring down got fed into the receive circuitry. After the blanking, the output from the receive circuitry was sampled for 450 intervals of 100us apart. These values were chosen as a balance between measuring resolution, maximum range capability, and the size of the array that could fit on the ATmega8's RAM.
A valuable lession I have learnt after doing many embedded projects is that you should do as much software development as possible on a computer. Developing and evaluating algorithms on an embedded system tends to waste time. In this project, I added an function to transmit the raw data (via I2C) to speed up the development. Another development board was programmed to act as an I2C to UART bridge, for which a computer could interface to. Another tip that I've learnt is that graphs are rather handy for analysing signals (who would have thought?). MATLAB is a fantastic program to use here, as would its free/open-source derivatives. Although MATLAB has built in methods for reading serial ports, I found it to be quite flakely. Instead, I used the ActiveX interface of RealTerm to collect the data and dump it to file. MATLAB then read this file.
With the data displayed visually in a MATLAB plot, it became a lot easier to devise signal processing routines. Firstly, some of the ring down pattern was still in the signal. If the blacking time was increased, this would adversely affect the minimum distance measuring ability of the rangefinder. Instead, the ring down pattern was found by recording the pattern in an obstacle-free environment. Thus each subsequent signal could be 'cleansed' by subtracting the ring down pattern from itself. The return signal with an object placed about 50cm from the sensor looked like:
Note that for convenience the calibration was done with the sensor facing towards the ceiling (hence the pulse at index 100). This is okay, but to get further ranges the calibration should be done with no objects within 6m.
It was reasoned that if there was an object reflected the sound wave back, its intensity would depend not only by the size of the object, but also its distance. The model we chose for the threshold was an expontial decay curve, which was tweaked until it looked right. The resulting signal processing routine would look for up to five segments above the threshold. The time of the echo was taken to be the to the peak in the first segment (provided the segment was greater than a minimum width). A smarter approach would be to rank the segments based on their likelihood of containing the time of the echo, using both the width and peak weighted against distance.
A bunch of tests were carried out, and once the algorithms had been adequately adjusted, they were implemented on the microcontroller. Most of the RAM was taken up in storing the ring down / calibration pattern and the sampling the return echo. Since the analysis can happen post-sampling, the threshold pattern was stored in and read out of program flash.
I've created a GitHub repository which contains all the relevant project files, including:
1. The schematic and PCB layout, in EAGLE.
2. The onboard SRF software.
3. The MATLAB analysis files.
If you're lucky enough to source some MB1100 files and decide to make up some of these rangefinder modules, I'd be interested to know how you get on. Improvements to the signal processing routines would also be appreciated.