iotdata, by Data Frontieriot
data
Block coding

HC-SR04 ultrasonic sensor: measuring distance with the robot

How the HC-SR04 measures distance from the echo, the math that turns time into centimeters, why the Echo pin needs a divider on the ESP32, what throws the reading off and how to use the sensor on the robot arm.

Data Frontier Engineering· Published October 22, 2026

The HC-SR04 is the most common "eye" on benchtop robots. It doesn't actually see: it shouts and listens. It emits a sound above the range of human hearing, waits for the echo to come back and measures how long that took.

How a measurement works

The module has four pins: VCC (5 V), GND, Trig and Echo. A measurement happens in three steps:

  1. The board drives Trig high for at least 10 µs.
  2. The module sends a burst of eight 40 kHz pulses and drives Echo high.
  3. When the echo returns, Echo goes low. The time it stayed high is the sound's round-trip time.

From time to distance

Sound travels at about 343 meters per second in air at 20 °C, or 0.0343 cm per microsecond. Since the measured time covers the trip there and back, divide by two:

distance (cm) = time (µs) × 0.0343 ÷ 2

The datasheet sums up the same math as time in µs divided by 58. A 580 µs echo means an object 10 cm away.

The speed of sound changes with temperature, by about 0.6 m/s per degree. For a benchtop robot, the difference between a room at 20 °C and one at 30 °C is under 2%: not worth worrying about.

What the datasheet promises

  • Range from 2 cm to 400 cm.
  • Measuring angle of about 15 degrees: it sees a narrow cone straight ahead.
  • At least 60 ms between one measurement and the next, so the previous echo isn't mistaken for the new one.

What gets in the way

  • Angled surfaces: the sound bounces off to the side and the echo never comes back. The sensor reads "nothing" or a longer distance.
  • Soft materials: foam, fabric and plush absorb sound.
  • Thin or small objects: a pencil lying sideways may not return enough echo.
  • Closer than 2 cm: the echo returns before the module is ready to listen.

That's why, on a robot, you should never trust a single reading. Averaging three measurements, or discarding values that jump too much, makes the behavior much more stable.

On the Arduino Nano

The Nano runs at 5 V, like the module: the four wires connect directly. To measure the pulse, Arduino has the pulseIn function. It's worth passing it a timeout (for example, 30,000 µs, which corresponds to about 5 meters): without one, if the echo never comes back, the program just sits there waiting.

On the ESP32: the divider on Echo

The ESP32 works at 3.3 V, and the HC-SR04's Echo pin outputs 5 V. Wiring it directly puts the board's pin at risk. The fix is a voltage divider made with two resistors:

  • Module Echo → 1 kΩ resistor → ESP32 pin.
  • ESP32 pin → 2 kΩ resistor → GND.

The pin gets about 3.3 V. Trig can be wired directly: 3.3 V is enough for the module to recognize the command. Some versions of the module run at 3.3 V; check the markings before leaving out the divider.

In MicroPython, the machine.time_pulse_us function measures the Echo pulse and returns a negative number when the timeout expires.

On the robot arm

With the sensor mounted at the front of the gripper, two classic behaviors become possible: beeping when something gets close and closing the gripper when the object is within reach. In the block coding IDE, the "if the distance is less than" card asks for the Trig and Echo pins and the limit in centimeters. The generated code already uses the timeout and ignores readings with no echo.