Breadboard with HC-SR04 ultrasonic sensor, buzzer and ESP32-C3 mounted near a doorway

Beginner

Build a Distance Warning System

SensorsAutomation

A real ultrasonic sensor and a buzzer -- point it at something and get an audible warning the closer it gets.

6 real parts included

Total for this kit: 1,575.00 ฿

Doesn't include any order discount you may get at checkout.

What you'll need

Project Goal

This project pairs an ultrasonic distance sensor with a buzzer to build a simple proximity alarm -- point it at something and get an audible warning that gets more urgent as the object gets closer. It's a good first sensor project because both the sensor and the output are digital and easy to reason about.

What the Controller Does

The controller repeatedly triggers a distance measurement, reads the result, compares it against a threshold, and decides whether to sound the buzzer -- the same read-decide-act loop that underlies most sensor-driven projects, just with a single sensor and a single output.

What the Ultrasonic Sensor Does

The HC-SR04 measures distance by sending a short ultrasonic pulse on its trigger pin and timing how long its echo pin stays high while the pulse travels out and reflects back. Combined with the known speed of sound, that timing converts directly into a distance -- the sensor itself doesn't report a distance value, the controller calculates it from the timing.

What the Buzzer Does

The active buzzer is the simplest possible output here: it makes noise for as long as the controller holds its control pin high, and stays silent otherwise. All the actual warning logic (should it be sounding right now?) lives entirely in the controller's code.

Sensor Voltage Compatibility

Before wiring anything, confirm the sensor's logic voltage against what your controller provides. This is a real, specific gotcha with HC-SR04 boards: some are designed for 5V logic, and using one directly with a 3.3V controller pin without a level shifter or voltage divider can produce unreliable readings or, in some cases, risk the controller's input pin. Check your specific board's documentation rather than assuming.

Software and Library Concepts

Most HC-SR04 libraries handle the trigger/echo timing for you and return a distance value directly, so you don't need to write the pulse-timing math yourself. Confirm you're getting sane, repeatable readings on their own -- before adding the buzzer threshold logic on top.

Testing and Troubleshooting

  • No distance readings at all -- check the trigger and echo wiring first, and confirm the sensor's logic voltage actually matches what your controller provides on that pin.
  • Distance always reads near-zero -- the sensor is likely facing something too close, or there's an obstruction right at the sensor face blocking the pulse.
  • Buzzer never triggers despite valid readings -- check the threshold value and comparison logic in your code before assuming it's a wiring problem; a threshold set below any distance you're actually testing will simply never fire.
  • Readings jump around unpredictably -- soft or angled surfaces can scatter the ultrasonic pulse and produce inconsistent echoes; test against a flat, hard surface first to confirm the sensor itself is working.

Optional Future Upgrade: Multi-Zone Distance Alarm

Once a single sensor and buzzer are working reliably, a natural extension is adding a second HC-SR04 pointed in a different direction and giving each zone its own alert tone or pattern, turning a single-direction alarm into basic spatial awareness.

Wiring

  • HC-SR04 VCC → ESP32-C3 SuperMini 5V — sensor needs 5V, not 3.3V, to drive its ultrasonic transducer
  • HC-SR04 GND → ESP32-C3 SuperMini GND
  • HC-SR04 TRIG → GPIO4 (`TRIG_PIN`) — digital output, direct connection is fine (3.3V trigger is well above the sensor's logic threshold)
  • HC-SR04 ECHO → 1kΩ resistor → GPIO5 (`ECHO_PIN`), with a 2kΩ resistor from that same junction to GND — ECHO is a 5V signal and ESP32 pins are only 3.3V-tolerant, so this divider is required to avoid damaging the pin
  • Active Buzzer signal/+ → GPIO6 (`BUZZER_PIN`)
  • Active Buzzer GND → ESP32-C3 SuperMini GND

Build the voltage divider on the breadboard before connecting ECHO to the ESP32 — never wire ECHO straight to a GPIO. Power the HC-SR04 from 5V (USB VBUS) while everything else can share the ESP32-C3's 3.3V rail and common GND. Test with `Serial.println` first to confirm sane distance readings before trusting the buzzer timing.

Wiring Diagram

VCC → 5V GND TRIG → GPIO4 ECHO GPIO5 signal/+ → GPIO6 GND ESP32-C3 SuperMini HC-SR04 1kΩ resistor Active Buzzer

Starter Code

#include <Arduino.h>

#define TRIG_PIN 4     // HC-SR04 TRIG - any digital output GPIO, adjust to match your wiring
#define ECHO_PIN 5     // HC-SR04 ECHO (via voltage divider) - any digital input GPIO
#define BUZZER_PIN 6   // Active buzzer signal - any digital output GPIO

const int MIN_DISTANCE_CM = 3;         // closer than this = fastest beep rate
const int MAX_DISTANCE_CM = 100;       // farther than this = no beeping
const int MIN_BEEP_INTERVAL_MS = 60;   // fastest beep rate (object very close)
const int MAX_BEEP_INTERVAL_MS = 800;  // slowest beep rate (object far away)

unsigned long lastToggle = 0;
bool buzzerOn = false;
int currentInterval = -1; // -1 = silent (nothing in range)

long readDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout, ~5m max range
  if (duration == 0) return -1; // no echo received (out of range / no object)

  return duration / 58; // speed-of-sound conversion: microseconds -> cm
}

void setup() {
  Serial.begin(115200);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
}

void loop() {
  long distance = readDistanceCm();

  if (distance > 0 && distance <= MAX_DISTANCE_CM) {
    long clamped = constrain(distance, MIN_DISTANCE_CM, MAX_DISTANCE_CM);
    currentInterval = map(clamped, MIN_DISTANCE_CM, MAX_DISTANCE_CM, MIN_BEEP_INTERVAL_MS, MAX_BEEP_INTERVAL_MS);
    Serial.printf("Distance: %ld cm | Beep interval: %d ms\n", distance, currentInterval);
  } else {
    currentInterval = -1; // no object in range, stay silent
  }

  unsigned long now = millis();
  if (currentInterval < 0) {
    digitalWrite(BUZZER_PIN, LOW);
    buzzerOn = false;
  } else if (now - lastToggle >= (unsigned long)currentInterval) {
    buzzerOn = !buzzerOn;
    digitalWrite(BUZZER_PIN, buzzerOn ? HIGH : LOW);
    lastToggle = now;
  }

  delay(20); // small pacing delay between HC-SR04 pings
}

Not sure about a step? Ask us