The following article was originally published at my blog.
For some years now, I have been on a never-ending quest to discover the cheapest way for a miniature vehicle to position itself. One that performs decently that is. My latest idea involved the, less-than-a-dollar, HC-SR04 ultrasonic sensors to acquire a holistic view of the surroundings. But let's take it from the beginning...
During my summer holidays (and to the dismay of my girlfriend) I was trying to come up with cool projects for the autumn and winter. Then, one day, an idea struck me while eating lunch: A disc-shaped board with many ultrasonic sensors mounted, that would provide a circular view of the surroundings. I googled around for similar projects and did not find something similar, so I decided to move it forward.
In the beginning, I thought the concept was flawed. The way I used the HC-SR04 ultrasonic sensors thus far was by triggering each to transmit an ultrasonic pulse, wait for it to reflect on an object and then determine how far away the object stood by the time it took for the "echo" to return. The problem with this lies in sequentially waiting for each measurement. When there are merely a couple of sensors, it is usually acceptable to wait for every one to finish. Empirically, I know it takes more or less 10 milliseconds for each measurement to complete for ranges under 1.5 meters, common for miniature car applications. Therefore, up to around 80 milliseconds could be wasted for the eight sensors I wanted to have on the board. To make matters worse, the results would be slightly inconsistent as the measurements would not have been initiated at the same moment.
A SonicDisc mounted on an Arduino
The solution was to execute the measurements in parallel. I checked out an article about using the HC-SR04 sensors with interrupts which verified the feasibility of the concept. I found the code there slightly complicated and as I needed to use eight sensors, there was no point trying to reuse it. However, I do suggest it as a nice reading if you want to understand the concept. Long story short, instead of waiting for each sensor to finish measuring, we initially trigger all sensors at once and then utilize the pin change interrupts to log down the echo arrival times. Finally, at a predefined interval we calculate the distance for each sensor. If an echo has not arrived yet, we consider the measurement as erroneous. The said interval is 10 milliseconds at the moment. This means we are able to conduct eight measurements in the time it took for a single one to be completed!
SonicDisc is designed to transmit the calculated distances to another unit, e.g. a microcontroller or a Raspberry Pi. It "talks" over the widely-adopted I2C bus. The communication protocol is outlined in the project's README and in code comments. Briefly, SonicDisc, which joins the I2C bus as a slave, can receive the operational mode it should be in. Moreover, it will transmit, upon request, a 9 byte "packet" containing an error code and the measurements from each sensor. Furthermore, it will send a very short pulse (~3μsec long) over the "INT" pin to indicate a new set of data being ready for transmission. This saves the master device the trouble of continuously polling SonicDisc for new data.
A SonicDisc on a SmartCar
Utilizing pin change interrupts to receive the echoes and port manipulation to trigger all sensors at once allow us to paralellize measurements and keep them consistent time-wise. This has the downside of making the code hardware-specific. That being said, the microcontroller of choice is the readily available Atmega328P. Not only it offers just enough pins, but also enables SonicDisc's firmware to work out of the box on any Arduino UNO. In other words, you will not face difficulties running the firmware on an UNO you already own.
To make things easier, aside of the code snippets in the README which describe how to fetch data from the SonicDisc, there is the SonicDiscReader example. This Arduino sketch, which I trust is fairly well-commented, exhibits not only how to fetch data from the module but also how to apply a simple filter onto the incoming data sets. Due to the nature of the HC-SR04 sensors, you can expect the measurements you will be getting to be fairly noisy, especially if the reflecting surfaces are not vertical towards the sensors. Subsequently, it is typically required to determine whether a series of measurements are reliable. The cool thing is that new data is arriving at such a high rate (every ~10ms) that you should not have a problem determining their quality fast enough. In the provided example, data is filtered based on the variance of five measurements for every sensor.
The SmartCar shield below the SonicDisc
On the hardware side of things, SonicDisc can act either as an Arduino shield or a standalone module. In the former case, the user can mount it on top of an Arduino Uno and then optionally (but suggested) connect "INT" to an interrupt enabled pin of the Arduino. The I2C and the power connections are already taken care of. Due to four of the sensors extruding downwards, you will not be able to mount it on a larger board, i.e. Arduino Mega, unless you find a way to raise it high enough. I personally use SonicDisc in conjuction with the Smartcar shield and yet it is not possible to fit it on top of a Mega. By all means you can always use SonicDisc as a standalone module. You will need to connect the power (5V & GND), the I2C lines (SDA & SCL) and last, but surely not least, the "INT" signal.
There are plenty of M3 mount holes that allow you to screw the module in place if deemed necessary and some sweet cutouts that let you to pass cables through them. They also somewhat compensate for the large size factor of the board, don't you think? Moreover, since it was the first time I was including cutouts to a board, I was insecure whether they would be fabricated correctly. Luckily, the helpful folks over at PCBway.com provided feedback and guidance on the matter and made sure the board would turn out exactly as I wanted it before ordering.
Cool looking boards by PCBway.com
SonicDisc will help you build cool autonomous driving applications by giving you a 360° view of the environment, and is very easy on your pocket! In fact if you buy all the necessary materials from China, it should not cost you much more than 10$ per board. For example, if you order 10 SonicDisc boards (the minimum quantity) from PCBway.com, the cost per board including standard shipping is just 1.5$. The ultrasonic sensors, cost 0.80$ per piece so that brings the total cost up to roughly 8$. The Atmega328P-PU goes for 1.5$ also and the remaining components should be around 0.5$. You can find a list of everything that is needed here.
Naturally, a module would not be complete without some example applications and cool videos. I inserted some business logic into the SonicDiscReader example and realized two cases which demonstrate the capabilities and potential of the SonicDisc. Utilizing the SmartCar platform, I developed an obstacle follower and an autonomous parker for my miniature vehicle. The former tries to rotate until it faces the detected obstacle like a crab defending itself. The latter allows the car to park between obstacles placed at different distances. As a matter of fact, autonomous parking worked exceptionally well. Check out the videos, they speak for themselves!
Finally, as it is accustomed the whole project is open source software and hardware, under an Apache license. I am really looking forward to see what others will create with SonicDisc. If you have a cool application for it in mind, contact me and I just might send you a SonicDisc PCB for free as long as I have one to spare!