← SHEET 02 · ASSEMBLIES EL-005
Ultrasonic Sweep Radar
| PART NO | EL-005 |
|---|---|
| MATL / SYSTEM | ESP32 · HC-SR04 · SG90 SERVO |
| TOOLS | Arduino IDE · Wokwi · C++ |
A tabletop ultrasonic radar: an SG90 hobby servo sweeps an HC-SR04 ranger
back and forth through 180°, an ESP32 times each echo and keeps a
median-of-3 filtered reading per angle step, and a 128x64 I2C OLED redraws a
polar sweep display every step — arc, live sweep line, and a trail of
decaying “blips” at the last few detections, plus a serial CSV feed
(angle,distance_cm) for offline plotting. The whole sweep runs off a
non-blocking millis()/micros() state machine; nothing in loop() blocks
except the two microsecond-scale edges of the HC-SR04 trigger pulse.
OVERVIEW & MOTIVATION
The classic HC-SR04-on-a-servo “radar” build usually ends up blocking on
pulseIn() and delay() calls scattered through loop(), which makes the
servo motion jerky and throws away any chance of doing something else (like
redrawing a display) between pings. This build separates the three jobs —
moving the servo, timing an echo, and rendering — into an explicit state
machine driven off timers, and adds two filtering ideas that a bare
single-ping HC-SR04 read doesn’t have: taking three pings per angle step and
keeping the median (so one spurious short/long echo doesn’t put a false blip
on the display), and simulating “phosphor decay” on a display that has no
grayscale by keeping a small ring buffer of recent detections and shrinking
their drawn size each frame before dropping them.
COMPONENTS & BOM
| REF | COMPONENT | SPEC | ROLE |
|---|---|---|---|
| U1 | ESP32 DevKit-C V4 | dual-core, WiFi/BT, 3.3 V logic | controller, runs the sweep state machine |
| U2 | HC-SR04 | ultrasonic ranger, ~2-400 cm datasheet nominal | distance-to-target per angle step |
| U3 | SG90 micro servo | 180° hobby servo, ~4.8-6 V | pans the HC-SR04 through the sweep |
| U4 | SSD1306 OLED | 128×64, I2C, addr 0x3C | polar radar display |
WIRING
| ESP32 PIN | NET | PERIPHERAL PIN |
|---|---|---|
| GPIO5 | TRIG | HC-SR04 TRIG |
| GPIO18 | ECHO | HC-SR04 ECHO |
| GPIO13 | SERVO_PWM | SG90 PWM |
| GPIO21 | I2C_DATA | OLED DATA (SDA) |
| GPIO22 | I2C_CLK | OLED CLK (SCL) |
| 5V | 5V RAIL | HC-SR04 VCC, SG90 V+, OLED VIN |
| GND | GND RAIL | HC-SR04 GND, SG90 GND, OLED GND |
FIRMWARE
sketch.ino runs one sweep state machine — ST_MOVE, ST_SETTLE,
ST_TRIGGER, ST_ECHO_WAIT, ST_COOLDOWN — driven off millis(), plus an
interrupt that timestamps the HC-SR04 echo edge so the wait step never
blocks on pulseIn():
void IRAM_ATTR echoISR() {
if (digitalRead(PIN_ECHO)) {
echoRiseUs = micros();
} else {
echoFallUs = micros();
echoCaptured = true;
}
}
Three pings are taken per angle step before the sweep advances; the median of the three rejects a single bad echo (double-bounce, dropout, timeout) as long as two of three agree:
float median3(float a, float b, float c) {
if (a > b) { float t = a; a = b; b = t; }
if (b > c) { float t = b; b = c; c = t; }
if (a > b) { float t = a; a = b; b = t; }
return b;
}
renderRadar() converts angle/distance to (x, y) around a bottom-center
origin, redraws two dotted range rings, the live sweep line, and a
24-entry ring buffer of past detections — each blip is drawn as a filled
2x2 dot while fresh, shrinks to a single pixel, then flickers before it’s
dropped, which is the closest a 1-bit OLED gets to phosphor decay.
distance_cm = echo_us / 58.0 is the HC-SR04 datasheet-nominal conversion
(~343 m/s speed of sound); no bench calibration has been done against it.
SIMULATION
The full circuit runs in Wokwi against diagram.json
— confirmed end-to-end in this build: firmware compiled clean against
ESP32Servo, Adafruit SSD1306, and Adafruit GFX Library, the
servo sweeps continuously, and the OLED renders the polar arc with a live
angle/distance readout while the sweep runs. The HC-SR04 part is
interactive: open its part inspector and drag the distance slider while
the sim runs — the sweep line’s range and the blip trail on the OLED track
the slider live, and the same values stream out as angle,distance_cm CSV
over the serial monitor. All four Wokwi part types used
(board-esp32-devkit-c-v4, wokwi-hc-sr04, wokwi-servo, wokwi-ssd1306)
are real parts — no substitutions were needed. wokwi-ssd1306 is Wokwi’s
older, deprecated I2C-only OLED part (superseded in their part picker by
board-ssd1306, which uses different pin names); it’s still fully
functional, which this build’s own simulation run confirmed.
STATUS
Design, firmware, and simulation are complete and self-consistent — pinout
matches across sketch.ino, diagram.json, and this page, and the circuit
has been run end-to-end in the Wokwi simulator (servo sweeping, OLED
rendering, serial CSV streaming). No physical hardware has been assembled:
no bench measurements, no real HC-SR04 echo timing against a tape measure,
no photos. The 58 us/cm conversion, the 3-ping median window, and the
100 cm display scope are all design choices or datasheet-nominal values,
not measured results. Next step: build the bench circuit per the README’s
power/grounding notes and re-verify the same firmware unchanged.
USE CASES & APPLICATIONS
Sweep-based ultrasonic ranging is the working principle behind low-cost parking-assist sensors, small mobile-robot obstacle mapping (a cheap stand-in for a spinning LIDAR when only a coarse 2D scan is needed), tank/silo level or bin-occupancy sensing from a fixed sweep point, and it’s a standard teaching rig for time-of-flight ranging and echo-based sensing more generally — the median-filtering and non-blocking-state-machine patterns here generalize to any single-beam ranger (ultrasonic, ToF laser, IR) that needs to be panned and read without freezing the rest of the firmware.
FILES
sources/electronics/ultrasonic-radar/sketch.ino— full ESP32 Arduino firmware: non-blocking sweep state machine, interrupt-timed echo capture, median-of-3 filtering, polar OLED rendering, CSV serial output.sources/electronics/ultrasonic-radar/diagram.json— Wokwi wiring diagram, pinout matches the firmware exactly.sources/electronics/ultrasonic-radar/README.md— how to run the Wokwi sim, library list, and real-hardware power/grounding notes.