The HC-SR04 is cheap and accurate to about a centimetre, but it is a 5 V part. On the S3-DevKitC-1, power it from the 5V pin and protect GPIO7 with a two-resistor divider on ECHO.
The sketch fires five pings per reading and prints the middle value, a simple filter that makes the output steady enough for tank levels and parking sensors.
Wiring
| ESP32-S3-DevKitC-1 | HC-SR04 ultrasonic sensor | Wire | Notes |
|---|---|---|---|
| 5V | VCC | red | 5 V from USB. |
| 6 | Trig | purple | |
| 7 | Echo | green | Via 1 kΩ / 2 kΩ divider — 1 kΩ from ECHO to GPIO7, 2 kΩ from GPIO7 to GND → about 3.3 V. |
| GND | GND | black |
5 V (HC-SR04P / RCWL-1601: 3–5.5 V) part, 3.3 V board. The classic HC-SR04 needs 5 V and its ECHO pin outputs 5 V. On a 3.3 V board (ESP32, Pico) send ECHO through a 1 kΩ / 2 kΩ divider. A 3.3 V trigger signal is enough for TRIG.
Board quirks
- The S3’s GPIOs are 3.3 V only. ECHO is a 5 V pulse, so it goes through the divider; TRIG works fine at 3.3 V.
- GPIO6/7 are on the same header as 3V3 and 5V, so all four wires land close together. They have no boot role.
- The sketch takes the median of five pings, 60 ms apart — that removes the odd wild reading from a stray echo, which matters for a water-tank level sensor.
Code
// HC-SR04 ultrasonic sensor on an ESP32-S3-DevKitC-1.
// VCC → 5V, GND → GND, Trig → GPIO6, Echo → GPIO7 through a 1 kΩ / 2 kΩ divider
// (ECHO is 5 V; the S3's pins are 3.3 V only).
constexpr uint8_t TRIG_PIN = 6;
constexpr uint8_t ECHO_PIN = 7;
float readCm() {
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
return us ? us * 0.0343f / 2.0f : -1;
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
pinMode(ECHO_PIN, INPUT);
Serial.println("HC-SR04: Trig GPIO6, Echo GPIO7");
}
void loop() {
// Median of 5 pings rejects the odd stray echo.
float r[5];
for (int i = 0; i < 5; i++) {
r[i] = readCm();
delay(60);
}
for (int i = 1; i < 5; i++)
for (int j = i; j > 0 && r[j] < r[j - 1]; j--) std::swap(r[j], r[j - 1]);
if (r[2] < 0) Serial.println("Out of range (no echo)");
else Serial.printf("Distance: %.1f cm\n", r[2]);
}// HC-SR04 ultrasonic sensor on an ESP32-S3-DevKitC-1.
// VCC → 5V, GND → GND, Trig → GPIO6, Echo → GPIO7 through a 1 kΩ / 2 kΩ divider
// (ECHO is 5 V; the S3's pins are 3.3 V only).
constexpr uint8_t TRIG_PIN = 6;
constexpr uint8_t ECHO_PIN = 7;
float readCm() {
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
return us ? us * 0.0343f / 2.0f : -1;
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
pinMode(ECHO_PIN, INPUT);
Serial.println("HC-SR04: Trig GPIO6, Echo GPIO7");
}
void loop() {
// Median of 5 pings rejects the odd stray echo.
float r[5];
for (int i = 0; i < 5; i++) {
r[i] = readCm();
delay(60);
}
for (int i = 1; i < 5; i++)
for (int j = i; j > 0 && r[j] < r[j - 1]; j--) std::swap(r[j], r[j - 1]);
if (r[2] < 0) Serial.println("Out of range (no echo)");
else Serial.printf("Distance: %.1f cm\n", r[2]);
}Expected serial output
HC-SR04: Trig GPIO6, Echo GPIO7
Distance: 87.4 cm
Distance: 87.3 cm
Out of range (no echo)HC-SR04: Trig GPIO6, Echo GPIO7 Distance: 87.4 cm Distance: 87.3 cm Out of range (no echo)
Common errors
Always out of range
VCC on 3V3, or the divider reversed. Full fix.
Works on the bench, fails in a water tank
Condensation on the transducers. Use the sealed JSN-SR04T for tanks.