——基于 ESP32 和超声波传感器的低成本社区车库方案

💡 划重点

  • 利用 HC-SR04 超声波模块实时判断车位是否有车。
  • ESP32 通过 MQTT 上报占用状态,支持 Home Assistant、社区大屏等集成。
  • 深度睡眠 + 定时唤醒,降低功耗,适合 USB 供电或电池场景。
  • 硬件总成本控制在 35 元以内,单节点部署简单。
  • 提供完整 Arduino 骨架代码、接线指导和调测流程。

需求洞察

目标用户:社区物业、小型车队车库、共享办公停车场管理员,以及希望 DIY 智能车库的爱好者。

真实痛点

  1. 老旧社区或小车库没有车位引导系统,车主绕圈找位,浪费时间和燃油。
  2. 物业缺乏实时数据,无法统计车位使用率、合理分配资源。
  3. 市售地磁或视觉方案安装贵、施工复杂,不符合小预算改造需求。

为什么值得做

用一个 30 元出头的节点就能完成一个车位的数字化,数据可直接进云平台。该方案门槛极低,可快速复制到多个车位,形成低成本物联网停车网络,兼具实用性与教学价值。

方案设计

感知层

控制层

执行层

日志/联网层

物料清单

物料名称 数量 用途 估算单价(元)
ESP32 DEVKIT V1 开发板 1 主控及 Wi‑Fi 通信 15.0
HC‑SR04 超声波测距模块 1 距离采集 3.5
红色 LED 5mm 1 车位状态指示 0.05
220Ω 限流电阻 1 LED 保护 0.02
面包板 170孔 mini 1 电路搭建 3.5
母母、公公杜邦线若干 1 套 模块与开发板连接 2.0
Micro‑USB 供电线 1 供电及下载 2.0
合计 26.07
物料总成本约 26 元,满足 35 元预算要求。如需更稳定安装可增加扎带和亚克力支架,仍在预算内。

接线与结构

按照项目给定的 GPIO 进行接线(同时结合超声波模块典型工作模式):

微调说明:原接线指定 Trig=5, Echo=18, LED=2。此安排完全符合 ESP32 的 GPIO 功能,且 5 与 18 均非启动引脚,不会影响下载模式。GPIO2 内部有弱上拉,但此处输出高电平点亮 LED,亦无冲突。超声波模块的 Echo 引脚必须接输入捕获脚,GPIO18 为输入模式。若需要增加硬件中断可选用其他引脚,但 Echo 仅通过 pulseIn() 测量已足够,不强制使用中断编号,因此保持原方案不变。

结构思路:将超声波模块倒装于车位正上方或侧面高处,探测波束垂直向下或斜向照射。探测区域避开墙角等固定障碍物,保证无车时返回地面距离,有车时返回车顶或车底距离。开发板和面包板可封装在防水接线盒内固定于横梁。

核心代码


#include <WiFi.h>
#include <PubSubClient.h>
#include "esp_sleep.h"

// WiFi & MQTT 配置
const char* ssid = "Your_SSID";
const char* password = "Your_PASS";
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;
const char* topic = "parking/spot1";
const char* clientId = "ESP32_Parking1";

// 引脚定义
#define TRIG_PIN 5
#define ECHO_PIN 18
#define LED_PIN  2

// 距离阈值(厘米),小于此值认为有车
#define THRESHOLD_DIST 30.0

// 唤醒间隔(秒)
#define SLEEP_DURATION_SEC 30

WiFiClient espClient;

float readDistance() {
  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
  float dist = duration * 0.034 / 2;   // 声速换算为 cm
  return dist;
}

void setup_wifi() {
  WiFi.begin(ssid, password);
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    attempts++;
  }
}

void reconnect_mqtt() {
  while (!client.connected()) {
    if (client.connect(clientId)) {
      // 连接成功
    } else {
      delay(2000);
    }
  }
}

void go_to_sleep() {
  esp_sleep_enable_timer_wakeup(SLEEP_DURATION_SEC * 1000000ULL);
  esp_deep_sleep_start();
}

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

  // 首次上电执行一次测量与上报,之后进入睡眠
  float distance = readDistance();
  bool occupied = (distance < THRESHOLD_DIST);

  // LED 指示
  digitalWrite(LED_PIN, occupied ? HIGH : LOW);

  setup_wifi();
  if (WiFi.status() == WL_CONNECTED) {
    reconnect_mqtt();
    // 构建 JSON 字符串
    String payload = "{\"occupied\":" + String(occupied) + ",\"distance\":" + String(distance) + "}";
    delay(100);  // 保证数据发完
  }
  client.disconnect();
  WiFi.disconnect(true);

  go_to_sleep();
}

void loop() {
  // 永远不会执行到这里,因为 deep sleep 后复位进入 setup()
}

代码说明

  • 上电后先测距、判断是否有车,然后连接 Wi‑Fi 并通过 MQTT 上报 JSON 数据。
  • 使用深度睡眠,30 秒后 RTC 唤醒,ESP32 重新执行 setup()。如此循环,大幅降低平均功耗。
  • pulseIn 超时设为 30ms,防止传感器故障卡死。
  • 可根据需要调整 THRESHOLD_DIST,一般轿车底盘离地间隙约 15‑20cm,车顶距离若安装高度 2.5m,可设为 50cm 以下为有车。

调试步骤

  1. 硬件通电检查:通过 USB 给 ESP32 供电,测量 VCC 和 GND 是否正确。用万用表检查 HC‑SR04 的 VCC 电压是否为 5V。
  2. 串口监视:使用 Arduino IDE 串口监视器(115200 波特率)观察距离读数。可以用手遮挡模拟有车,看距离值是否突变。
  3. 阈值标定:在真实车位安装高度下,记录无车时的地面距离(例如 200cm)和有车时的底盘距离(例如 15cm)。将阈值设为两者中间值,如 30cm,同时预留 5‑10cm 的冗余避免误判。
  4. MQTT 连通性测试:在本机或服务器搭建 Mosquitto Broker,修改代码中的 IP 地址。通过 MQTT 客户端订阅 parking/spot1,观察上报内容是否与 LED 状态一致。
  5. 睡眠功耗验证:用 USB 电流表测量睡眠时电流,正常应在 100μA‑5mA 之间(取决于开发板)。若电流偏高,检查外围电路是否有漏电。
  6. 长时间运行:连续运行 24 小时,查看 MQTT 历史记录有无掉线和误报。可根据需要调整上报间隔(SLEEP_DURATION_SEC)。

设计图

停车位占用监测结构flow
1
感知输入(HC-SR04测距)
2
控制处理(ESP32判断有车/无车)
3
执行反馈(LED状态指示)
4
数据上报(MQTT发送JSON)
5
低功耗休眠(定时唤醒循环)