Ultrasonic Range Finder with Arduino
A typical healthy human is capable of distinguishing a range of frequencies between 20Hz and 20kHz. Frequencies above this range, called ultrasound, are inaudible to humans because of physical and neural limitations set by our auditory systems. Sound, much like light, is a great scientific tool because of its predictable behavior and manipulative properties. The primary applications of ultrasound are in civil and biomedical engineering. Ultrasound is remarkably tunable and is often used for non-destructive testing and surgical applications. Here, the application is time-of-flight calculation and the method is straightforward. Ultrasound can be treated as a disturbance traveling through a medium (air). As such, we can define the linear relationship between distance, velocity, and time as:
where c is the speed of sound, d is distance, and t is time. The trick to ultrasonic distance calculation comes in the geometry setup and the time delay between the transmitted and received pulses:
Focus will now shift from physics to instrumentation. The ultrasonic distance sensor, HC-SR04 (and its many variations), is common in maker electronics because of its simple and intuitive design. The sensor sends out a series of 40kHz pulses and listens for a return signal. The Arduino can be programmed to calculate the time difference between pulse transmission and reception to approximate the distance of an object. A typical wiring diagram for the HC-SR04 is shown below, with one caveat being that the SIG of the diagram below would be Trig and Echo on HC-SR04. The Trig should be connected to digital pin 2 on the Arduino Uno and the Echo should be connected to pin 3.
Below is the basic implementation of the ultrasonic time-of-flight calculation using the Arduino IDE.
At this point, your Arduino board should be spitting out reasonable estimates of an object some distance away from the sensor. If there are any issues, it is likely a programming error or wiring issue. Otherwise, if your values are reasonable and you are satisfied with your results, then you are finished with this tutorial. However, if you are seeing an error in your measurements, then please continue reading as I discuss calibration and how to correct the HC-SR04 for drift or factory inaccuracies.
The sensor used for my experiments was exhibiting consistent error when measured over several distances. The error was small, but noticeable and consistent enough that I decided to investigate its calibration. I used grids of engineering paper and a moving target to record several time-of-flight (TOF) distance calculations to determine how well the sensor was approximating the target's location. I recorded several TOF measurements using Python's serial read function. This made plotting and understanding the behavior conclusive. The raw data from the moving target experiment is shown below:
It is not clear from the plot above, however, after inspection and conversion to distance it is clear that the sensor had some drift to the true values. Consequently, I decided to use Python's polyfit tool (in numpy) and attempt to find a trend in imprecise data. The basic idea behind implementation of polynomial regression is that sensors often drift over time and under certain circumstances (temperature/humidity changes, component stress from usage over time, physical stress, etc.), so it is not uncommon for sensors to need calibration from time to time. I used a first order regression to model a linear drift and used the data gathered from the moving target readings against the real, measured distances and found the following constants:
The d in the above equation signifies the calculated distance using the traditional TOF physical model. After finding those constants for the linear model and using the linear model to adjust the original calculated values, the error was minimized and the produced the following results:
The improvement on the original estimates is huge. Upon substitution back into the original Arduino code, the errors are completely minimized. Now, the values printed on the Arduino serial monitor are completely accurate and within a reasonable margin of error. The HC-SR04 sensor is reliable and fully functional (I tested mine up to 7 ft), and the error was less than 1% (beyond 1ft) and less than 10% (less than 3 inches). It proves, once again, that the science is backed by nature, but instrumentation needs to be backed by humans.