Yarana Iot Guru
Published © MIT

Building a Smart D Bistance Measuring System with ESP32

Measure distance with HC-SR04 + ESP32, show live readings on web serial, and send data to MQTT/Firebase for smart automation YaranaIoT Guru

BeginnerFull instructions provided8 hours29
Building a Smart D Bistance Measuring System with ESP32

Things used in this project

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

🔌 Schematics & Wiring (HC-SR04 ↔ ESP32)

C/C++
HC-SR04 pins: VCC, Trig, Echo, GND

Recommended wiring (use 5V VCC; Echo is 5V — use divider or a board that outputs 3.3V safe signal):
HC-SR04 VCC  -> 5V (ESP32 VIN or external 5V)
HC-SR04 GND  -> GND
HC-SR04 TRIG -> GPIO 26
HC-SR04 ECHO -> (voltage divider) -> GPIO 25
OLED SDA -> GPIO 21 (optional)
OLED SCL -> GPIO 22 (optional)

💻 Full Arduino/ESP32 Sketch (Web UI + Serial + optional MQTT)

C/C++
Reads HC-SR04

Serves small web page showing live distance (auto-refresh)

Optionally publishes to MQTT if you configure credentials
/* 
  Smart Distance Measuring System with ESP32
  - HC-SR04 ultrasonic sensor
  - Simple web UI: shows current distance and timestamp
  - Optional: MQTT publish
  Author: YaranaIoT Guru
*/

#include <WiFi.h>
#include <WebServer.h>
#include <Ticker.h>

// Optional MQTT
//#include <PubSubClient.h>

#define TRIG_PIN 26
#define ECHO_PIN 25    // Use voltage divider on Echo if sensor runs at 5V

// WiFi - EDIT THESE
const char* ssid = "YourWiFiSSID";
const char* password = "YourWiFiPassword";

// MQTT - optional (uncomment includes above and configure)
//const char* mqtt_server = "YOUR_MQTT_BROKER_IP";
//const char* mqtt_topic  = "home/sensor/distance";

WebServer server(80);
Ticker sensorTicker;

volatile unsigned long lastDuration = 0;
float lastDistance = 0.0;

// Read distance (blocking) - returns distance in cm, or -1 on timeout
float readDistanceCm() {
  // Ensure trigger low
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  // Send 10us HIGH pulse to trigger
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Read echo pulse duration (in microseconds)
  unsigned long duration = pulseIn(ECHO_PIN, HIGH, 30000UL); // timeout 30ms => ~5 meters
  if (duration == 0) {
    return -1.0; // timeout/no echo
  }
  float distance = duration / 58.0; // convert to cm
  // Alternative more exact: distance = (duration / 1e6) * 343.0 / 2.0 * 100.0;
  return distance;
}

// Periodic sensor read (called by Ticker)
void sensorReadTask() {
  float d = readDistanceCm();
  if (d >= 0) {
    lastDistance = d;
  } else {
    lastDistance = -1.0;
  }
  lastDuration = micros();
  // Optionally: publish to MQTT here
  // if (mqttClient.connected()) { ... }
}

String htmlPage() {
  String html = "<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'>";
  html += "<title>ESP32 Distance Monitor</title></head><body style='font-family:Arial,Helvetica,sans-serif;'>";
  html += "<h2>ESP32 Distance Monitor — YaranaIoT Guru</h2>";
  html += "<p>Distance: <strong>";
  if (lastDistance < 0) html += "No echo / out of range";
  else html += String(lastDistance,2) + " cm";
  html += "</strong></p>";
  html += "<p>Last update: " + String(millis()/1000) + " s since boot</p>";
  html += "<p><a href='/raw'>Raw JSON</a> | <a href='/calibrate'>Calibrate</a></p>";
  html += "<script>setTimeout(()=>location.reload(),3000);</script>";
  html += "</body></html>";
  return html;
}

void handleRoot() {
  server.send(200, "text/html", htmlPage());
}

void handleRaw() {
  String payload = "{";
  payload += "\"distance_cm\": ";
  if (lastDistance < 0) payload += "null";
  else payload += String(lastDistance,2);
  payload += ", \"timestamp_ms\": " + String(millis());
  payload += "}";
  server.send(200, "application/json", payload);
}

void handleCalibrate() {
  // Simple calibration page instructing how to measure offset if needed
  String p = "<h3>Calibration</h3><p>Place a known distance object and note reading. Use offset in code if required.</p><p><a href='/'>Back</a></p>";
  server.send(200, "text/html", p);
}

void setup() {
  Serial.begin(115200);
  delay(100);

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  digitalWrite(TRIG_PIN, LOW);

  // WiFi
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts++ < 30) {
    delay(500);
    Serial.print(".");
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nWiFi connected. IP: " + WiFi.localIP().toString());
  } else {
    Serial.println("\nWiFi connect failed. Starting AP mode...");
    WiFi.softAP("ESP32-Distance-AP");
    Serial.println("AP IP: " + WiFi.softAPIP().toString());
  }

  // Web server routes
  server.on("/", handleRoot);
  server.on("/raw", handleRaw);
  server.on("/calibrate", handleCalibrate);
  server.begin();

  // start periodic sensor reads every 2 seconds
  sensorTicker.attach(2.0, sensorReadTask);

  // Initial read
  sensorReadTask();
}

void loop() {
  server.handleClient();
  // add small yield
  delay(10);
}

Credits

Yarana Iot Guru
35 projects • 0 followers
Yarana Iot Guru Yarana IoT Guru: Arduino, ESP32, GSM, NodeMCU & more. Projects, Tutorials & App Development. Innovate with us!
Thanks to YaranaIoT Guru.

Comments