💡 划重点
- 用一块 ESP8266 做一个只读的车库门状态卡片:磁簧开关感知门体开合,LED 本地提示,MQTT 把“开/关”状态与在线状态推到家庭自动化平台。整机不改车库门控制线路,只做状态采集,目标成本 25 元内,依靠深度休眠降低长期在线功耗。
需求洞察
目标用户是已经使用车库门、但门体没有联网状态反馈的家庭。真实痛点不是“远程开门”,而是“我到底关没关门”:出门后怀疑门未关、夜间听到异响想确认、老人或租客使用后无法核对状态。成品智能门磁和摄像头方案要么价格高,要么涉及隐私和布线;直接改造门机控制又有安全风险。
这个项目值得做,原因有三点:第一,只读采集,不接入门机控制回路,误操作风险低;第二,磁簧开关成熟便宜,ESP8266 与 MQTT 生态完善,25 元内可落地;第三,状态以保留消息发布,手机或家庭自动化面板随时看到最新状态,低耗休眠适合车库长期通电场景。
方案设计
感知层采用常开磁簧开关,磁铁安装在门体,开关安装在门框,门关闭时磁簧闭合,GPIO 读到低电平;门打开时断开,读到高电平。软件做 50 毫秒去抖,避免门体振动误报。
控制层由 ESP8266 负责定时唤醒、采样、联网和发布。设备每 20 秒从深度休眠唤醒一次,连接 Wi-Fi 与 MQTT,读取门磁状态并发布,然后迅速休眠。这样门状态变化最长 20 秒内上报,平均功耗远低于常在线轮询。若需要更快响应,可缩短到 10 秒,但耗电会增加。
执行层包含板载 LED 和 MQTT 反馈。LED 在联网时快闪,门开时点亮,门关时熄灭;MQTT 使用保留消息,订阅端一上线就能收到最后状态。设备不驱动门机继电器,避免远程误开门。
日志与联网层使用 MQTT 主题:garage/door/state 发布 open 或 closed,garage/door/availability 发布 online/offline,并附带 RSSI 到 garage/door/rssi。家庭自动化平台可据此做通知、历史记录和离线告警。
物料清单
| 物料 | 数量 | 用途 | 估算单价 | 合计 |
|---|---|---|---|---|
| NodeMCU ESP8266 开发板 | 1 | 主控与 Wi-Fi | 12.5 元 | 12.5 元 |
| 常开磁簧开关 | 1 | 门体开合感知 | 2.0 元 | 2.0 元 |
| 3mm LED | 1 | 本地状态指示 | 0.2 元 | 0.2 元 |
| 1kΩ 电阻 | 1 | LED 限流 | 0.1 元 | 0.1 元 |
| 10kΩ 电阻 | 1 | 备用下拉/调试 | 0.1 元 | 0.1 元 |
| 洞洞板 | 1 | 焊接固定 | 1.5 元 | 1.5 元 |
| 杜邦线 | 若干 | 接线 | 1.0 元 | 1.0 元 |
| USB 电源线/旧充电器 | 1 | 5V 供电 | 3.0 元 | 3.0 元 |
| 塑料外壳 | 1 | 保护与固定 | 2.5 元 | 2.5 元 |
| 合计 | 21.9 元 |
接线与结构
给定建议为磁簧 GPIO2、LED GPIO0。实际方案把磁簧微调到 GPIO4(D2),原因是 GPIO2 属于 ESP8266 启动配置脚,门磁状态可能在复位瞬间被拉低,导致启动不稳定;GPIO4 没有该限制,更适合门磁输入。LED 仍使用 GPIO0,并采用低电平点亮接法,复位时 GPIO0 为高,LED 熄灭,不影响启动。
接线如下:磁簧开关一端接 GPIO4,另一端接 GND,GPIO4 使用内部上拉,门关闭合为低、门开为高;LED 正极经 1kΩ 电阻接 3.3V,负极接 GPIO0,低电平点亮;NodeMCU 的 D0(GPIO16)跳线到 RST,用于深度休眠定时唤醒;电源用 5V USB 供电。结构上,磁簧固定在门框侧面,磁铁固定在门体对应位置,间距控制在 10 至 15 毫米;主板和 LED 装入塑料外壳,LED 对准面板开孔。
核心代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "你的WiFi";
const char* WIFI_PASS = "你的密码";
const char* MQTT_HOST = "192.168.1.10";
const int MQTT_PORT = 1883;
#define DOOR_PIN 4
#define LED_PIN 0
WiFiClient espClient;
bool doorClosed() {
return digitalRead(DOOR_PIN) == LOW;
}
void ledWrite(bool on) {
digitalWrite(LED_PIN, on ? LOW : HIGH);
}
bool mqttConnect() {
if (client.connect("garage-door-card")) {
client.publish("garage/door/availability", "online", true);
return true;
}
return false;
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
delay(200);
}
if (WiFi.status() == WL_CONNECTED && mqttConnect()) {
bool closed = doorClosed();
client.publish("garage/door/state", closed ? "closed" : "open", true);
char rssiBuf[16];
snprintf(rssiBuf, sizeof(rssiBuf), "%d", WiFi.RSSI());
client.publish("garage/door/rssi", rssiBuf, true);
ledWrite(!closed);
delay(300);
client.disconnect();
}
ESP.deepSleep(20e6);
}
void loop() {
}
调试步骤
先不接磁簧,烧录后打开串口,确认 GPIO0 上电为高、LED 不常亮。接好磁簧后,用磁铁靠近和离开开关,观察串口与 MQTT 状态是否在 closed/open 间切换。用 MQTT 客户端订阅 garage/door/state,确认保留消息存在;断开电源再上电,确认平台能收到 online 和最新门状态。测量休眠电流,NodeMCU 板载稳压会有一定耗电,若后续改为电池供电可换 ESP-01S 方案。最后调整磁铁与磁簧间距,关门时确保可靠闭合,并连续观察 24 小时,检查误报和离线情况。