TTB #22: The I2C Mode of the HC-SR04 Ultrasonic Sensor

The I2C Mode of the HC-SR04 Ultrasonic Sensor

Overview

The HC-SR04 (2021 version) is an enhanced ultrasonic distance sensor based on the classic HC-SR04 design. It integrates a dedicated RCWL-9200 ultrasonic signal processor that adds multiple digital communication modes to the original hardware platform.

Unlike the traditional two-pin TRIG/ECHO interface, this version supports four selectable communication modes:

  1. GPIO (TRIG/ECHO pins, classic HC-SR04 default mode)
  2. I²C (IIC)
  3. 1-Wire
  4. UART

This allows flexible integration into a wide variety of embedded systems.

In this tutorial, we will investigate the I2C mode.

 

Compatibility

Given the voltage input range for the HC-SR04 (2021 version) is between 2.8V and 5.5V, this module will work with a range of microcontroller development boards. Most notably the common 3.3V and 5V development boards such as: 

 

Technical Features

  • Main controller IC: RCWL-9200 ultrasonic signal processor
  • Integrated support for four communication modes
    • GPIO (TRIG/ECHO, default mode)
    • I²C (fixed address 0x57)
    • 1-Wire
    • UART
  • Operating voltage range: 2.8 V to 5.5 V
  • Operating current: ≈ 2 mA (very low power)
  • Measurement period: 200 ms (typical)
  • Measurement range
    • Minimum: ≈ 2 cm
    • Typical: 5 cm to 300–400 cm
    • Maximum: ≈ 450–500 cm (ideal conditions)
  • Beam angle: approximately 15°
  • Frequency: 40 kHz
  • Form factor: same physical dimensions as the classic HC-SR04 module. 4.2 cm X 1.7 cm
  • Logic-level compatibility: works directly with 5 V or 3.3 V microcontrollers

Range Explanation

The range specifications of the HC-SR04 ultrasonic sensor are:

  • Minimum distance: about 2 cm. This is the acoustic dead zone (the sensor cannot detect anything closer because the echo overlaps with the transmitted pulse).
  • Typical usable distance: about 5 cm to 300–400 cm. Within this range, readings are stable and accurate on flat, perpendicular targets.
  • Maximum distance: up to about 450–500 cm under ideal conditions:
    • Large, hard, flat target surface
    • Perpendicular to the sensor
    • Good power supply and stable I²C timing
    • Quiet environment (low acoustic noise)

Assumptions behind these figures:

  • Target surface is flat and hard (like a wall or book)
  • Target is directly facing the sensor (normal incidence)
  • Ambient temperature is near 20 °C, which gives a sound speed of about 343 m/s
  • Supply voltage is stable
  • Proper delay (~120–200 ms) is given between measurements

If any of these conditions are not met (soft or angled target, small object, background noise, short delay), the effective range becomes shorter and readings may fluctuate.

 

Mode Selection

The module uses two solder jumpers, M1 and M2, to select the communication mode.

For I²C mode:

  • M1: bridged (soldered closed)
  • M2: open

Ensure this configuration before uploading the sketch below. See the image below to verify the proper mode selection.

The I2C Mode selection of the HC-SR04 ultrasonic sensor.


Communication Protocol

The RCWL-9200 controller uses a simple I²C sequence:

  1. Send command: Write a single byte 0x01 to the device at address 0x57 to start a measurement
  2. Wait: Delay approximately 100 – 150 ms for the measurement to complete
  3. Read result: Read 3 bytes from register 0xAF
  4. Convert: Combine the three bytes into a 24-bit integer (micrometers), then divide by 10 000 to get distance in centimeters

 

Example Sketch

For this Mode 2: I2C Method simply connect Ground GND and VCC to the power pins of the Dev Board (Uno R3, Nano Flip, ESP32 microWatt, Nano Flip 3V3, etc). If using an ATmega328P based microcontroller, for example, connect the SCL pin to A5, and SDA pin to A4.


// Example: Mode 2) I2C (M1=1, M2=0)
// Last Update: Sept 16, 2025
//
// CONNECTIONS 
// In this example we are using the 5V ATmega328P based Uno R3+ microcontroller development board.
// But all other common dev boards should work
// HC-SR04 -> Uno R3+
// VCC -> 5V
// GND -> GND
// SDA -> A4
// SCL -> A5

// OPERATIONAL NOTES
/*
This ultrasonic module is designed for general distance measurement and typically provide a measurable range of about:
Minimum range: ≈ 2 cm (limited by transmit/receive dead zone)
Maximum range: ≈ 450 to 500 cm (4.5 to 5 meters) under ideal conditions

Key points
- Accuracy is best from 5 cm to 300 cm
- Beyond ~3 m, readings become more sensitive to target size, angle, and ambient noise
- Objects must be flat, hard, and perpendicular to the sensor to reflect the ultrasonic pulse effectively
*/

/*
The ultrasonic module integrates a dedicated controller (RCWL-9191/9300C/9200 series) that implements a proprietary I²C communication protocol, distinct from the commonly referenced SRF02 protocol.
In this protocol, the device operates at the fixed I²C address 0x57. 
To initiate a ranging operation, the host transmits a single command byte 0x01 to this address. 
After a measurement delay of approximately 100–150 ms, the host reads three consecutive bytes from register 0xAF. 
These bytes represent the measured distance in micrometers. 
The combined 24-bit value must be divided by 1000 to obtain the result in millimeters, and can be further divided by 10 to express the result in centimeters.
*/

#include 

const uint8_t I2C_ADDR = 0x57;          // Device address
const uint8_t CMD_START = 0x01;         // start ranging
const uint8_t REG_READ  = 0xAF;         // returns H M L
const uint16_t MEASURE_DELAY_MS = 120;
const uint16_t PERIOD_MS = 300;

void setup() {
  Serial.begin(9600);
  Wire.begin();
}

void loop() {
  Wire.beginTransmission(I2C_ADDR);
  Wire.write(CMD_START);
  uint8_t err = Wire.endTransmission();
  if (err) {
    Serial.print("I2C err "); Serial.println(err);
    delay(PERIOD_MS);
    return;
  }

  delay(MEASURE_DELAY_MS);

  Wire.beginTransmission(I2C_ADDR);
  Wire.write(REG_READ);
  Wire.endTransmission(false);
  Wire.requestFrom((int)I2C_ADDR, 3);

if (Wire.available() == 3) {
  uint32_t H = Wire.read();
  uint32_t M = Wire.read();
  uint32_t L = Wire.read();
  uint32_t micrometers = (H << 16) | (M << 8) | L;
  float cm = micrometers / 10000.0f;  // convert µm → cm
  Serial.print(cm, 2);
  Serial.println(" cm");
} else {
  Serial.println("no data");
}
  delay(PERIOD_MS);
}

 

How It Works

This sketch works because it follows the RCWL-9200’s I²C protocol. Sending 0x01 tells the controller to initiate a ranging cycle. After the measurement completes, the controller places a 24-bit distance value in micrometers into register 0xAF. The sketch reads this 3-byte value, converts it to centimeters, and prints it.

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.