How to Interface Ultrasonic Sensors with an ESP8266
2021/04/30

Ultrasonic sensors are useful little helpers that have become very present in today’s everyday life. Most people will know them from parking sensors, commonly found in practically all modern cars and trucks. They can, however, also be useful in many other projects, and this article serves as an introduction to ultrasonic sensors. It also explains how you can get it up and running in no time using an ESP8266 powered development board!

BOM for this project

Product/Where to buy

  1. Adafruit Feather Huzzah!
  2. HC-SR04 Breakout Board
  3. Breadboard
  4. M/M Jumper Wires

Connecting the Sensor

The most troublesome part about this project is that the sensor board and the ESP8266 development board, which is an Adafruit Feather Huzzah in this case, use different voltage levels. The ultrasonic sensor requires a 5V power supply to function properly, and it also outputs a 5V signal. The ESP8266, on the other hand, only supplies 3.3V and the pins are, typically, also not 5V tolerant. On the Adafruit Feather Huzzah and many other ESP8266 development boards, there is, however, a 5V supply that comes directly from the USB plug. To solve the other problem, which is that the ultrasonic module outputs a 5V signal while the ESP8266 only tolerates up to 3.3V, the HC-SR04, linked above, includes two 10K resistors. You can connect them in series between the output pin of the module and GND to form a simple voltage divider. This reduces the output voltage to 2.5 Volts, which makes it safe to use with the ESP8266:

Making It Work With Software

Luckily, it is easy to understand how the HC-SR04 works. The ESP8266 (or any other microcontroller) sends a 10µs pulse to the HC-SR04 ultrasonic sensor module over the trigger input pin. The module then sends out several short ultrasonic bursts and pulls the output pin high. Once all the pulses, sent out earlier, make their way back to the module, the HC-SR04 pulls the output pin low again. The microcontroller can measure the time between the output pin going high and it getting pulled low again. Once it knows the duration of the pulse, it can calculate the distance to an object. I implemented this behavior in the readDistance function in the following sketch:

Copy Code
#define ECHO_PIN 2 #define TRIG_PIN 16 #define BUFF_LENGTH 5 #define TIME_BETWEEN_READS 100 // In milliseconds- float buff[BUFF_LENGTH]; int next = -1; void setup() {
  Serial.begin(9600);
 
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
} void loop() { float distance = readDistance();

  next = (next >= BUFF_LENGTH || next < 0) ? 0 : (next + 1);
  buff[next] = distance;

  Serial.println(getAverage(&buff[0], BUFF_LENGTH, 30.0f)); float current_millis = millis(); while(millis() - current_millis < TIME_BETWEEN_READS)
  { }
} float getAverage(float *buff, int len, float clamp) { float sum = 0; for(int i = 0; i < len; i++)
	sum += buff[i]; float ret = sum / len; return (ret > clamp) ? clamp : ret;
} float readDistance() { long duration; long current_micros = micros();

  digitalWrite(TRIG_PIN, HIGH); while(micros() - current_micros < 10)
  { }
 
  digitalWrite(TRIG_PIN, LOW);
 
  duration = pulseIn(ECHO_PIN, HIGH); return duration * 0.034f / 2.0f; // Speed of sound wave divided by 2 (go and back) }

As you can see, the setup method initializes the serial console and the necessary I/O pins. The loop method calls the readDistance function in a fixed interval and stores the result in a circular buffer. I did this to prevent inaccuracies in the sensor causing massive spikes in the output data. This way, extreme values don’t affect the overall output as dramatically. This, however, also means that the output reacts slower to changes. I also added a maximum distance that I want to measure with this code. In this example, I set it to 30 centimeters (which is approximately one foot). The output to the serial plotter looks like this:

As you can see, the values never go above 30 centimeters. In reality, this is a reasonable assumption, as you’re typically only interested in the distance in a certain interval, for example, when parking a car.

Summary

An ultrasonic distance sensor can be a useful addition in all kinds of projects. In practice, these sensors are best known as parking assistance systems in vehicles. The biggest problem when trying to connect an HC-SR04 ultrasonic sensor to an ESP8266 development board is the difference in voltages that the different devices use. The sensor works with a 5V supply and outputs a 5V signal, while the ESP8266 is only 3.3V tolerant. Besides that, ultrasonic sensors are very convenient to use and often deliver good results. Programmers, however, should take care of spikes in the output data, as they can commonly happen.