ESP32 with HC-SR04 Ultrasonic Sensor with Arduino IDE

This guide shows how to use the HC-SR04 Ultrasonic Sensor with the ESP32 board using the Arduino core. The ultrasonic sensor uses sonar to determine the distance to an object. We’ll show you how to wire the sensor to the ESP32 and provide several example sketches to determine the distance to an object using the HC-SR04.

ESP32 with HC-SR04 Ultrasonic Sensor Module with Arduino IDE

This tutorial covers the following topics:

Introducing the HC-SR04 Ultrasonic Sensor

The HC-SR04 ultrasonic sensor uses sonar to determine the distance to an object. This sensor reads from 2cm to 400cm (0.8inch to 157inch) with an accuracy of 0.3cm (0.1inches), which is good for most hobbyist projects. In addition, this particular module comes with ultrasonic transmitter and receiver modules.

The following picture shows the HC-SR04 ultrasonic sensor.

HC-SR04 Ultrasonic Sensor Module Distance Measurement Component Part Front

The next picture shows the other side of the sensor.

HC-SR04 Ultrasonic Sensor Module Distance Measurement Component Part Back

Where to buy HC-SR04 Ultrasonic Sensor?

You can check the Ultrasonic Sensor HC-SR04 sensor on Maker Advisor to find the best price:

HC-SR04 Ultrasonic Sensor Technical Data

The following table shows the key features and specs of the HC-SR04 ultrasonic sensor. For more information, you should consult the sensor’s datasheet.

Power Supply5V DC
Working Current15 mA
Working Frequency40 kHz
Maximum Range4 meters
Minimum Range2 cm
Measuring Angle15º
Resolution0.3 cm
Trigger Input Signal10uS TTL pulse
Echo Output SignalTTL pulse proportional to the distance range
Dimensions45mm x 20mm x 15mm

HC-SR04 Ultrasonic Sensor Pinout

Here’s the pinout of the HC-SR04 Ultrasonic Sensor.

VCCPowers the sensor (5V)
TrigTrigger Input Pin
EchoEcho Output Pin
GNDCommon GND

How Does the HC-SR04 Ultrasonic Sensor Work?

The ultrasonic sensor uses sonar to determine the distance to an object. Here’s how it works:

  1. The ultrasound transmitter (trig pin) emits a high-frequency sound (40 kHz).
  2. The sound travels through the air. If it finds an object, it bounces back to the module.
  3. The ultrasound receiver (echo pin) receives the reflected sound (echo).
How the  HC-SR04 Ultrasonic Sensor Module Works

Taking into account the sound’s velocity in the air and the travel time (time passed since the transmission and reception of the signal) we can calculate the distance to an object. Here’s the formula:

distance to an object = ((speed of sound in the air)*time)/2
  • speed of sound in the air at 20ºC (68ºF) = 343m/s

Parts Required

ESP32 Board HC-SR04 Ultrasonic Sensor Module Arduino Parts required

To complete this tutorial you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic – ESP32 with HC-SR04 Ultrasonic Sensor

Wire the HC-SR04 ultrasonic sensor to the ESP32 as shown in the following schematic diagram. We’re connecting the Trig pin to GPIO 5 and the Echo pin to GPIO 18, but you can use any other suitable pins.

ESP32 Wiring Circuit Ultrasonic Sensor Diagram
Ultrasonic SensorESP32
VCCVIN
TrigGPIO 5
EchoGPIO 18
GNDGND

Preparing Arduino IDE

We’ll program the ESP32 board using Arduino IDE. So, make sure you have the ESP32 add-on installed. Follow the next tutorial:

If you want to use VS Code with the PlatformIO extension, follow the next tutorial instead to learn how to program the ESP32:

Code – Getting Distance to an Object using the HC-SR04 Ultrasonic Sensor and ESP32

The following sketch is a simple example of how you can get the distance between the sensor and an object using the ESP32 board with the Arduino core.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-hc-sr04-ultrasonic-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

const int trigPin = 5;
const int echoPin = 18;

//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701

long duration;
float distanceCm;
float distanceInch;

void setup() {
  Serial.begin(115200); // Starts the serial communication
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
}

void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;
  
  // Convert to inches
  distanceInch = distanceCm * CM_TO_INCH;
  
  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  Serial.print("Distance (inch): ");
  Serial.println(distanceInch);
  
  delay(1000);
}

View raw code

Upload the code to your board and it will work straight away. Continue reading if you want to learn how the code works or skip to the demonstration section.

How the Code Works

First, define the trigger and the echo pins.

const int trigPin = 5;
const int echoPin = 18;

In this example, we’re using GPIO 5 and GPIO 18. But you can use any other suitable GPIOs—read ESP32 Pinout Reference: Which GPIO pins should you use?

The SOUND_SPEED variable saves the velocity of sound in the air at 20ºC. We’re using the value in cm/uS.

#define SOUND_SPEED 0.034

The CM_TO_INCH variable allows us to convert distance in centimeters to inches.

#define CM_TO_INCH 0.393701

Then, initialize the following variables.

long duration;
float distanceCm;
float distanceInch;

The duration variable saves the travel time of the ultrasonic waves (time elapsed since transmission and reception of the pulse wave). The distanceCm and distanceInch, as the names suggest, save the distance to an object in centimeters and inches.

setup()

In the setup(), initialize a serial communication at a baud rate of 115200 so that we can print the measurements on the Serial Monitor.

Serial.begin(115200); // Starts the serial communication

Define the trigger pin as an OUTPUT—the trigger pin emits the ultrasound. And define the echo pin as an INPUT—the echo pin receives the reflected wave and sends a signal to the ESP32 that is proportional to the travel time.

pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input

loop()

In the loop(), the following lines produce a 10uS HIGH pulse on the trigger pin—this means the pin will emit an ultrasound. Note that before sending the pulse, we give a short LOW pulse to ensure you’ll get a clean HIGH pulse.

// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

We use the pulseIn() function to get the sound wave travel time:

duration = pulseIn(echoPin, HIGH);

The pulseIn() function reads a HIGH or a LOW pulse on a pin. It accepts as arguments the pin and the state of the pulse (either HIGH or LOW). It returns the length of the pulse in microseconds. The pulse length corresponds to the time it took to travel to the object plus the time traveled on the way back.

Then, we simply calculate the distance to an object taking into account the sound speed.

distanceCm = duration * SOUND_SPEED/2;

Convert the distance to inches:

distanceInch = distanceCm * CM_TO_INCH;

And finally, print the results on the Serial Monitor.

Serial.print("Distance (cm): ");
Serial.println(distanceCm);
Serial.print("Distance (inch): ");
Serial.println(distanceInch);

Demonstration

Upload the code to your board. Don’t forget to select the board you’re using in Tools > Boards. Also, don’t forget to select the right COM port in Tools > Port.

ESP32 Board HC-SR04 Ultrasonic Sensor Module Arduino Demonstration

After uploading, open the Serial Monitor at a baud rate of 115200. Press the on-board RST button to restart the board and it will start printing the distance to the closest object on the Serial Monitor. Something as shown in the picture below.

Ultrasonic Sensor ESP32 ESP8266 Get Distance to an Object Arduino

ESP32 with HC-SR04 and OLED Display

ESP32 Board HC-SR04 Ultrasonic Sensor Module Arduino OLED Parts Required

In this section, we’ll show you a simple example with the ESP32 that displays the distance on an I2C OLED display.

To better understand how the project works, we recommend taking a look at our ESP32 tutorial with the I2C OLED display.

Parts Required

Here’s a list with the parts required to complete this example:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic Diagram – ESP32 with HC-SR04 and OLED Display

Wire all the parts as shown in the following schematic diagram.

ESP32 with HC-SR04 and OLED Display Wiring Circuit Diagram

Learn more about the OLED display with the ESP32: ESP32 OLED Display with Arduino IDE

Code – ESP32 Display Distance (HC-SR04) on OLED Display

To use this example, make sure you have the Adafruit SSD1306 and Adafruit GFX libraries installed. You can install these libraries through the Arduino Library Manager.

Go to Sketch > Library > Manage Libraries, search for “SSD1306,” and install the SSD1306 library from Adafruit.

Install Library I2C OLED Display SSD1306 Arduino IDE

After installing the SSD1306 library from Adafruit, type “GFX” in the search box and install the library.

Installing GFX Library ESP8266 ESP32 Arduino

After installing the libraries, restart your Arduino IDE.

Then, simply copy the following code to your Arduino IDE and upload the code to the board.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-hc-sr04-ultrasonic-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

const int trigPin = 5;
const int echoPin = 18;

//define sound speed in cm/uS
#define SOUND_SPEED 0.034
#define CM_TO_INCH 0.393701

long duration;
int distanceCm;
int distanceInch;

void setup() {
  Serial.begin(115200);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(500);
  display.clearDisplay();

  display.setTextSize(2);
  display.setTextColor(WHITE);
}

void loop() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate the distance
  distanceCm = duration * SOUND_SPEED/2;
  
  // Convert to inches
  distanceInch = distanceCm * CM_TO_INCH;
  
  // Prints the distance in the Serial Monitor
  Serial.print("Distance (cm): ");
  Serial.println(distanceCm);
  Serial.print("Distance (inch): ");
  Serial.println(distanceInch);

  display.clearDisplay();
  display.setCursor(0, 25);
  //Display distance in cm
  display.print(distanceCm);
  display.print(" cm");
  
  // Display distance in inches
  /* display.print(distanceInch);
  display.print(" in");*/
  display.display(); 

  delay(500);  
}

View raw code

How the Code Works

Start by including the required libraries for the OLED display:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Define the width and height of the OLED display. We’re using a 128×64 OLED display:

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Create an Adafruit_SSD1306 object called display to handle the OLED display.

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

Define the pins that the HC-SR04 sensor is connected to.

const int trigPin = 5;
const int echoPin = 18;

Create variables to save the distance and the duration between the transmission and reception of the sound waves.

long duration;
int distanceCm;
int distanceInch;

setup()

In the setup(), initialize a serial communication at a baud rate of 115200 so that we can print the results on the Serial Monitor.

Serial.begin(115200);

Define the trigger pin as an OUTPUT and the echo pin as an INPUT.

pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input

Initialize the OLED display:

if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
  Serial.println(F("SSD1306 allocation failed"));
  for(;;);
}

Set the font size and color for the display.

display.setTextSize(2);
display.setTextColor(WHITE);

loop()

In the loop() is where we’ll get the distance and display it on the OLED.

Get the distance (we’ve already explained in the previous section how to calculate the distance).

// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
  
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
  
// Calculate the distance
distanceCm = duration * SOUND_SPEED/2;
  
// Convert to inches
distanceInch = distanceCm * CM_TO_INCH;

Print the distance on the Serial Monitor.

// Prints the distance on the Serial Monitor
Serial.print("Distance (cm): ");
Serial.println(distanceCm);
Serial.print("Distance (inch): ");
Serial.println(distanceInch);

Clear the display in each loop() to write new readings.

display.clearDisplay();

Set the display cursor to (0, 25).

display.setCursor(0, 25);

The following lines print the distance in centimeters in the OLED display.

// Display static text
display.print(distanceCm);
display.print(" cm");

Comment the previous lines and uncomment the following lines if you want to display the readings in inches.

/* Display distance in inches
display.print(distanceInch);
display.print(" in");*/

Lastly, call display.display() to actually show the readings on the OLED.

display.display();

The distance is updated every 500 milliseconds.

delay(500);

Demonstration

Upload the code to your ESP32 board. Go to Tools > Board and select the ESP32 board you’re using. Go to Tools > Port and select the port your board is connected to. Then, click the upload button.

Open the Serial Monitor at a baud rate of 115200, press the on-board RST button. The sensor measurements will be displayed both on the Serial Monitor and the OLED display.

Approximate an object to the sensor and see the values changing.

ESP32 Board HC-SR04 Ultrasonic Sensor Module Arduino OLED Demonstration

You can watch a quick video demonstration:

Wrapping Up

The HC-SR04 Ultrasonic Sensor allows us to determine the distance to an object. In this tutorial you’ve learned how to use the HC-SR04 with the ESP32. We have tutorials for other popular sensors that you may like:

Learn more about the ESP32 with our resources:

Thanks for reading.



Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our newsletter!

17 thoughts on “ESP32 with HC-SR04 Ultrasonic Sensor with Arduino IDE”

  1. Excellent write-up; I hadn’t realized how simple it is to get one of these up and running! I do have a question: you’re using 5V to power the sensor, but the folks at Sparkfun say that the ESP32 uses 3.3V logic, and that there would be an overload danger with this setup.

    (source: https://learn.sparkfun.com/tutorials/esp32-thing-hookup-guide/hardware-overview)

    I saw a comment on a similar blog post that suggested a better choice of sensor would be the RCWL-1601, which is drop-in identical to the HC-SR04. A quick inquiry to Mr. Google suggests that the price and availability are about the same.

    Reply
    • I power the ultrasonic with 5v for more stable operation but connect the echo pin to the ESP via a level shifter as this is an output pin from the ultrasonic module and does output 5v which is too high for the 3v3 ESP module.
      A 1k0 and 2k2 resistor in series works for me.

      Reply
    • @Steve, lol yeah you are right. Sorry all.

      Except for the fact that the RCWL-0516 is a great little sensor, please ignore what I said 😉

      Reply
      • @Andre, it does indeed look like a great little sensor! And cheap too, I’m seeing them on Aliexpress for about $0.75 each, shipped (to the US). Maybe this would be a good topic for the next Random Nerd tutorial…??? 😀

        Reply
  2. A subject near and dear to me so I thought I’d share some findings I have made in my several months of trial, error and testing with ESP devices and the HC-SR04 (both the standard and the Waterproof versions.)

    #1 Your sketch for distance is a common method that was originally employed with AVR devices but I found that when used in conjunction with WiFi functionality the ESP device locks up after about 12 hours (I’m testing using a Blynk 2.0 setup). It was definitely the code for the HC-SR04 that caused it as when I changed to an Arduino library it no longer crashed. The library I’ve had most success with to date on any ESP device is https://github.com/gamegine/HCSR04-ultrasonic-sensor-lib/

    #2 You can in fact power the HC-SR04 with the 3.3v but you will need to increase the trigger time to 20us. I found anything less and you get too may false readings. My current test rig is an ESP12F on a BoB as it’s intended to be a battery powered project.

    #3 As distance increases you’ll find reflections causes havoc on your readings if your sensor is near other hard surfaces. I’ve improved the reliability greatly by surrounding the sensor with acoustic (sponge) foam.

    #4 To look at trying to improve the repeatability and accuracy for my project I have setup a sketch that has a smoothing array[10] and a single distance read and I have been comparing them for a month or two now. I round the values to MM and now at worst I get a variation of +/- 1mm between the two values.

    #5 The next step to improve accuracy is to make the speed of sound constant a variable as there will be situation of large temperature changes when using the HC-SR04 outdoors.

    #6 If intending to run the HC-SR04 as a battery project and employing deep sleep mode you need a minimum of 250ms between power on to the HC-SR04 and taking a reading. Any less and your reading will fail.
    Cheers
    Ralph

    Reply
    • Hi, nice tips, would you share your code? I think a sophisticated filter may also be good for reliable and stable readings. I also use the JSN SR-04T, but need to place a good filter. One thing important to keep in mind is the US sensor mounting, as there are 2 effects:
      1- is the blanking distance (where the sensor is no able to measure, due to pulse&echo measurement required delay) hence you may not be able to obtain very close to sensor readings.
      2.- Sensor ringing on tanks when you mount the sensor too tight to tank where the tank may be “resonating” with false readings.

      Reply
      • G’day Alvaro,
        The current code I’m working with is here https://pastebin.com/4BUHGjyF

        NB:
        #1 Current device is an ESP-12F on a BoB
        #2 To avoid having to change things I have a slide switch for PGM (always on) or Seep Sleep modes. Serial print of sensor reading only in PGM mode.
        #3 I use the onboard led to show activity but note its “Active LOW” on the ESP-12F
        #4 As stated above I have increased the pulse duration to 20us.

        Cheers
        Ralph

        Reply
    • Apologies, #1 in my original comment is wrong and it wasn’t the code locking up. Further tests have shown it to be the browser itself that has stopped refreshing and just refreshing solves the problem.

      Reply
  3. If somebody want to try real project for monitoring waterwell level using ESP32 with this HC-SR04 module or its waterproof fully compatible JSN-SR04T module with visualisation of datas to web interface, you can do it in my test DEMO project: arduino.clanweb.eu/studna_s_prekladom/?lang=en

    More technical informations about that project:
    martinius96.github.io/hladinomer-studna-scripty/en/index.html

    There are available source codes for ESP32 for StandBy / StandBy + OTA / Deep Sleep ULP in Arduino Core and also one experimental implementation for ESP-IDF that is using FreeRTOS with tasks.

    Reply
  4. In all schematics the sensor is powered by 5V (!) and the trig-pin and the echo-pin are connected directly (!) to GPIO-pins, even though the voltage of the IO-pins of ESP32 (WROOM) must not exceed 3.3V. How is that possible?

    Reply
  5. Once again: In all schematics the ultrasonic sensor is powered by 5V supply, but the GPIOs of ESP32 (WROOM) are NOT 5V tolerant, although they are connected directly (!) to the trigger and echo pins of the sensor. I’m a little bit confused: Did these schematics really work?

    Reply
    • Hi.
      Yes, they work and don’t do any harm to the board.
      You can try it yourself.
      However, you can add a level-shifter, if you prefer.
      You can also use 1k0 and 2k2 resistors in series as suggested in one of the comments.
      Regards,
      Sara

      Reply
  6. Many thanks Sara
    I trusted you and I copied your circuit as shown in your website (even without series resistors or level shifters). And I was very surprised that it actually worked without any damage to the ESP32. Also the measured values seem to be absolutely reliable. Still, I don’t understand it, but I’m very grateful because it simplifies my schematic after all.

    Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.