💡 划重点
- 主控芯片:ESP32,支持 Wi-Fi 与深度睡眠,是低成本低功耗联网方案的理想选择。
- 核心传感:HC-SR04 超声波模块,通过回波时间计算车位占用状态,精度高、价格低。
- 联网协议:MQTT 轻量级发布/订阅,适合窄带宽、不稳定网络环境下的状态上报。
- 功耗策略:定时唤醒 + 单次测量 + 立即休眠,平均功耗可控制在毫瓦级。
- 目标成本:整机物料不超过 35 元,适合社区小车库批量部署。
- GPIO 分配:Trig=5、Echo=18、LED=2,仅需三根信号线,接线简单可靠。
需求洞察
目标用户是社区小车库的管理员、物业运维人员以及拥有固定车位的业主。真实痛点在于:车库车位数量少但车辆进出频繁,经常出现外来车辆占用私人车位、车主找不到空位而堵塞通道的情况。人工巡查效率低,安装地磁或摄像头方案成本高、布线麻烦。因此,一个成本极低、安装简单、能实时上报车位状态的设备,能有效减少纠纷、提升车位周转率。本项目核心价值在于用 35 元以内成本,实现可与现有智能家居或物业系统联动的车位占用感知节点,并且电池供电可长期运行,不需要频繁维护。
方案设计
感知层:HC-SR04 超声波传感器每隔 N 秒被唤醒一次,发射超声脉冲并测量回波时间,转换为距离值。当距离小于设定阈值(如 50cm)时,判定为有车占用;否则为空闲。
控制层:ESP32 作为主控,负责定时从深度睡眠中唤醒,驱动超声波测距、处理数据、控制 LED 指示、建立 Wi-Fi 连接并发布 MQTT 消息,完成后立即重新进入睡眠。
执行层:板载 LED 作为本地状态指示(亮起=占用,熄灭=空闲),同时可通过 MQTT 消息触发远程告警或联动道闸、指示灯牌。
日志/联网层:通过 MQTT 将车位状态发布到本地 Broker(如 Mosquitto),或云端 Broker(如 EMQX、阿里云 IoT)。消息主题可设置为 parking/spot/status,消息内容为 JSON 格式,包含车位 ID、状态、时间戳。Broker 端可订阅该主题进行数据存储、可视化或推送通知。
物料清单
| 物料名称 | 数量 | 用途 | 估算单价(元) | 小计(元) |
|---|---|---|---|---|
| ESP32 DevKit 开发板 | 1 | 主控与联网 | 15.00 | 15.00 |
| HC-SR04 超声波模块 | 1 | 距离检测 | 3.00 | 3.00 |
| 5mm LED(红色) | 1 | 状态指示 | 0.10 | 0.10 |
| 220Ω 电阻 | 1 | LED 限流 | 0.05 | 0.05 |
| 3.7V 18650 锂电池 | 1 | 供电(可充电) | 8.00 | 8.00 |
| 18650 电池座 | 1 | 电池固定 | 0.50 | 0.50 |
| AMS1117 3.3V 稳压模块 | 1 | 电压稳定 | 0.80 | 0.80 |
| 面包板 + 杜邦线 | 1套 | 电路连接 | 2.50 | 2.50 |
| 亚克力或塑料外壳(自制) | 1 | 保护结构 | 3.00 | 3.00 |
| 合计 | 32.95 |
物料总成本约 33 元,控制在 35 元以内,如需进一步降低成本可去掉外壳或使用更小的 ESP32 模组。
接线与结构
- HC-SR04 Trig → GPIO 5
- HC-SR04 Echo → GPIO 18
- LED 正极(串 220Ω 电阻)→ GPIO 2
- LED 负极 → GND
- HC-SR04 VCC → 3.3V(也可接 5V,需确认模块稳压能力,本方案使用 3.3V 以减少功耗)
- HC-SR04 GND → GND
- 电池正极 → 稳压模块输入,稳压输出 3.3V 接 ESP32 VIN
结构上建议将超声波模块朝向车位正上方或斜前方,距离地面高度约 1.2 至 1.5 米,避免误测到地面或其他障碍物。LED 可外露在外壳表面,便于远距离观察状态。整体采用垂直壁挂或天花吊装方式,减少人为触碰。接线说明:选用 GPIO 5 和 GPIO 18 是因为它们均为 ESP32 常规 IO,且不与 Flash 通信引脚冲突,方便程序烧录与调试。GPIO 2 板载 LED 也在同一引脚,但板载 LED 焊接在开发板上,若外接 LED 需要拔掉板载跳线或直接使用其他空闲 GPIO 以避免冲突,本方案中 GPIO 2 默认外接 LED 使用。
核心代码
#include <WiFi.h>
#include <PubSubClient.h>
#include <driver/rtc_io.h>
#define TRIG_PIN 5
#define ECHO_PIN 18
#define LED_PIN 2
#define DEEP_SLEEP_SEC 15
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
const char* mqttServer = "192.168.1.100";
const int mqttPort = 1883;
const char* mqttTopic = "parking/spot/status";
WiFiClient espClient;
float getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
return duration * 0.034 / 2;
}
void connectWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
}
void connectMQTT() {
while (!client.connected()) {
if (client.connect("ESP32_Parking")) {
}
delay(50);
}
}
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
float dist = getDistance();
bool occupied = (dist < 50);
digitalWrite(LED_PIN, occupied ? HIGH : LOW);
rtc_gpio_hold_enable(GPIO_NUM_2); // 保持 LED 状态在睡眠中不丢失
connectWiFi();
connectMQTT();
String payload = String("{\"occupied\":") + (occupied ? "true" : "false") + ",\"dist_cm\":" + String((int)dist) + "}";
delay(50);
client.disconnect();
WiFi.disconnect();
esp_sleep_enable_timer_wakeup(DEEP_SLEEP_SEC * 1000000ULL);
esp_deep_sleep_start();
}
void loop() {
// 程序不会运行到这里
}
代码说明:程序启动后立即进行超声波测距,根据距离设置 LED 状态,然后连接 Wi-Fi 和 MQTT 发布消息,最后进入深度睡眠。每次唤醒周期 15 秒,调整 DEEP_SLEEP_SEC 可改变功耗与实时性平衡。
调试步骤
- 基础通信验证:先用 Arduino 串口监视器打印距离值,确认 HC-SR04 正常,避免接线错误。用手遮挡传感器,距离应明显减小。
- LED 逻辑验证:设置临时阈值,遮挡时 LED 亮起,移除后熄灭。确认 GPIO 2 输出正常,若板载 LED 与外部 LED 同时亮,则说明状态逻辑正确。
- MQTT 连接测试:使用 MQTT.fx 或 mosquitto_sub 订阅主题
parking/spot/status,观察是否收到 JSON 消息。若连接失败,检查 SSID、密码、服务器 IP 是否可达。 - 功耗测量:在电池回路串联万用表,测量工作状态(约 80-120mA)和睡眠状态(约 10-20uA),确认深度睡眠生效。若电流偏高,检查是否有外设未断电。
- 部署实测:将设备安装在车位上方,模拟车辆进出,连续运行 24 小时记录 MQTT 消息准确率,调整阈值或测量角度。
- 稳定性优化:如果 Wi-Fi 连接时间过长导致单次唤醒功耗增大,可减少上报频率或将
DEEP_SLEEP_SEC增加到 30 秒。