When I think of Arduino and measuring distance the readily available and cheep ultrasonic sensors come to mind. Add while these senors are great for most projects there are a few project that need a little more accuracy.
So I ran a few experiments to see if the accuracy of the HC-SR04 could be improved. I will be honest and say that while I did increase the accuracy it was only by a small amount. If you want to see the exact experiments I did and the results, read on.
The Control
Before we can do any experiments, we need to know how accurate the sensor is normally, so I hooked up my sensor to pins 8 and 9, and ran the following code.
#define SEND_PIN 8
#define RECIEVE_PIN 9
void setup() {
Serial.begin(9600);
pinMode(8,OUTPUT);
pinMode(9,INPUT);
}
void send(int length_of_pulse){
digitalWrite(SEND_PIN,LOW);
delayMicroseconds(4);
digitalWrite(SEND_PIN,HIGH);
delayMicroseconds(length_of_pulse);
digitalWrite(SEND_PIN,LOW);
}
int recieve(int timeout_in_seconds){
return pulseIn(RECIEVE_PIN,HIGH,timeout_in_seconds*100000);
}
//generic speed of sound 0.0343
//custom speed of sound 0.03412
void loop() {
send(10);
unsigned long time = recieve(1);
float cm = ((time * 0.0343 / 2 ));
Serial.println(cm);
delay(1000);
}
With this code I took three types of measurements. The first was at 10cm way and at room temperature. The sensor gave readings that were with easily with in one centimeter of the actual distance. Here is the setup I use and a picture of the results in the Serial Monitor.
I even though I have tried my best, it is hard to position a piece of wood exactly 10 cm away and to account for that and any other errors that might be affecting the result, I will round up and say that the sensor can measure distances with one centimeter of potential error.
The next measurements I took were at long range from 100-300 cm and I got essentially the same result. I was afraid that the accuracy would go down as the distance increased but all in all nothing really changed. This is the basic setup I used.
The last test I took outside. This was the only test to give a different result. Unfortunately I forgot to take pictures, but The piece of wood was 100 cm away and the sensor was only able to get with 2cm of that value. What made outside different was that the temperature was 31F.
Temperature and Sound
These sensors work by using the speed of sound. If the air temperature changes the speed of sound also changes slightly.
Normally when we code up these sensor, we assume the speed of sound is 343 m/s but if you where to measure the temperature around you and calculate the speed of sound from that, you could get a more accurate number.
So that is what I did. The first few times, I measured the temperature with a thermometer then put it through an on line converter and then inserted the result into the code.
To make this process faster, I hooked up a temperature sensor to my board and made it do the calculations before each measurement. That temperature sensor also measured humidity which has a slight effect on sound so I factored that in as well.
If you look in the bottom corner you can see the temperature sensor underneath all the wires.
I calculated the speed of sound with the following equation.
331.4 + 0.6*temperature + 0.0124*humidity
One important thing to mention is that the equation above returns the speed of sound in meters per second, but the Arduino board needs centimeters per microsecond, so we divide the speed of sound by 10,000 which turns it into centimeters per microsecond which the Arduino can easily use.
Here is the full code I used.
#include <Wire.h>
#include "Adafruit_HTU21DF.h"
#define SEND_PIN 8
#define RECIEVE_PIN 9
Adafruit_HTU21DF sensor = Adafruit_HTU21DF();
void setup() {
Serial.begin(9600);
pinMode(8,OUTPUT);
pinMode(9,INPUT);
sensor.begin();
delay(100);
}
void send(int length_of_pulse){
digitalWrite(SEND_PIN,LOW);
delayMicroseconds(4);
digitalWrite(SEND_PIN,HIGH);
delayMicroseconds(length_of_pulse);
digitalWrite(SEND_PIN,LOW);
}
int recieve(int timeout_in_seconds){
return pulseIn(RECIEVE_PIN,HIGH,timeout_in_seconds*100000);
}
float get_speed_of_sound(){
float temp = sensor.readTemperature();
float humidity = sensor.readHumidity();
return (331.4 + 0.6*temp + 0.0124*humidity)/10000;
}
void loop() {
float speed = get_speed_of_sound();
send(10);
unsigned long time = recieve(1);
float cm = ((time * speed / 2 ));
Serial.println(cm);
delay(1000);
}
The result of this code is that the distance senor will all ways stays within 1cm of the correct value. If you take it outside or leave it in, it never decreases in accuracy.
What Improved?
The table below shows the values I got from the experiments. As you can see under normal conditions using a thermometer does nothing to increase the accuracy. If you take the sensor somewhere very cold the thermometer code will work better.
Noraml Code | Temp Code | |
---|---|---|
Inside 68F | 1 cm | 1 cm |
Outside 31F | 2 cm | 1 cm |
What I take away form this experiment is that only if you distance sensor is going to be exposed to extreme changes in temperature you should run the above code above but most of the time its not worth the work.
When I started this project I was thinking about building a Arduino sonar system. To make one you need to be able to accurately position your sonar sensor and if you are thinking about building one of your own you might be interested in Accurately Position a Stepper Motor In Degrees.