💡 划重点

  • 零接触感知:利用磁簧开关检测车库门的开闭,无需触碰门体,避免机械磨损。
  • 极低功耗:ESP8266 通过深度睡眠 + 定时唤醒上报,单颗 18650 电池预计可运行半年。
  • 即时通知:门状态变化时立即唤醒并通过 MQTT 推送到手机,延迟低于 2 秒。
  • 极致成本:总物料成本控制在 25 元以内,让每个家庭都能低成本实现车库安防升级。
  • 隐私安全:数据不经过第三方云端,全部走自建 MQTT Broker,家庭内网闭环。

需求洞察

目标用户

真实痛点

为什么值得做

方案设计

感知层

控制层

执行层

日志 / 联网层

物料清单

物料名称 数量 用途 估算单价(元) 小计(元)
ESP8266 开发板 (ESP-12F 最小系统) 1 主控及 WiFi 通信 9.5 9.5
磁簧开关 (常开型干簧管模块) 1 检测门状态 1.8 1.8
18650 锂电池 (2600mAh) 1 系统供电 6.0 6.0
TP4056 充电保护模块 1 电池充放电管理 1.5 1.5
红色 LED (5mm) 1 状态指示 0.2 0.2
220Ω 电阻 1 LED 限流 0.1 0.1
洞洞板 (3x7cm) 1 电路焊接载体 0.5 0.5
热缩管、排针、导线 若干 连接与绝缘 1.0 1.0
3D 打印外壳 / 亚克力片 1 保护电路 3.0 3.0
合计 23.6
总物料成本 23.6 元,未包含焊锡、工具折旧,符合 25 元内预算要求。

接线与结构

硬件接线

接线微调理由:方案中 LED 使用 GPIO0,该引脚启动时为高电平,恰好让 LED 在非控制状态保持熄灭。同时利用其内部已存在的上拉,外部无需额外电阻,简化 BOM。

安装结构

  1. 将 ESP8266、TP4056、LED、电阻焊接在洞洞板上,电池座与磁簧开关端子引出排针。
  2. 用热缩管包裹 TP4056 裸露焊点,整板装入 3D 打印外壳,侧壁预留 LED 导光柱和 Micro-USB 充电口。
  3. 磁簧开关本体用双面胶固定在门框非移动侧,永磁铁粘在门边缘对应位置,间距不超过 5mm。
  4. 连接磁簧开关与主机的导线沿门框内侧走暗线,末端用排插对接,方便拆卸维护。

核心代码

以下为 Arduino 骨架代码,基于 ESP8266 平台,实现中断唤醒、消抖、MQTT 上报。


#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASS";
const char* mqtt_server = "192.168.1.100";

const int DOOR_PIN = 2;   // GPIO2,磁簧开关
const int LED_PIN = 0;    // GPIO0,LED 指示
bool lastDoorState;
bool currentDoorState;
volatile bool doorChanged = false;

WiFiClient espClient;

void IRAM_ATTR doorISR() {
  doorChanged = true;
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  lastDoorState = digitalRead(DOOR_PIN);
  
  // 根据唤醒原因选择行为
  if (doorChanged) {
    blinkLED(3, 100); // 快闪三次表示事件唤醒
    currentDoorState = digitalRead(DOOR_PIN);
    delay(50);        // 消抖
    if (digitalRead(DOOR_PIN) != currentDoorState) return; // 抖动则放弃
    if (currentDoorState != lastDoorState) {
      connectAndReport();
      lastDoorState = currentDoorState;
    }
  } else {
    // 定时器唤醒,发送心跳
    connectAndReportBattery();
  }
  
  // 进入深度睡眠,GPIO2 中断唤醒 + 定时器 60 分钟
  ESP.deepSleep(3600e6, WAKE_RF_DEFAULT | WAKE_RFCAL);
  // 注意:如果由 GPIO 中断唤醒,sleep 立即返回,不影响
}

void connectAndReport() {
  digitalWrite(LED_PIN, LOW); // 点亮 LED 表示工作中
  WiFi.begin(ssid, password);
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 30) {
    delay(500);
    attempts++;
  }
  if (WiFi.status() == WL_CONNECTED) {
    if (client.connect("garage_sensor")) {
      String state = (currentDoorState == LOW) ? "CLOSED" : "OPEN";
      client.publish("garage/door/state", state.c_str(), true);
      client.publish("garage/device/heartbeat", String(analogRead(A0) * 4.2 / 1024).c_str());
      delay(100);
      client.disconnect();
      digitalWrite(LED_PIN, HIGH); // 成功,灭灯
    }
  } else {
    blinkLED(5, 500); // 慢闪表示失败
  }
}

void connectAndReportBattery() {
  WiFi.begin(ssid, password);
  // ... 省略重复 Wi-Fi 连接逻辑
  if (WiFi.status() == WL_CONNECTED) {
    if (client.connect("garage_sensor")) {
      float vcc = analogRead(A0) * 4.2 / 1024.0;
      client.publish("garage/device/heartbeat", String(vcc).c_str());
      delay(100);
      client.disconnect();
    }
  }
}

void blinkLED(int times, int interval) {
  for (int i = 0; i < times; i++) {
    digitalWrite(LED_PIN, LOW);
    delay(interval);
    digitalWrite(LED_PIN, HIGH);
    delay(interval);
  }
}
void loop() {} // 实际不会执行,全部在 setup 内完成

调试步骤

  1. 独立测试磁簧开关:用万用表蜂鸣档连接干簧管两端,磁铁靠近应导通,远离断开。确认磁体极性正确,最大感应距离不低于 5mm。
  2. 烧录基础固件:先在 Arduino IDE 中上传一个简单 Blink 测试,确认 ESP8266 工作正常,GPIO0 可控制 LED。
  3. 中断验证:烧录含串口打印的测试代码,手动触发磁簧开关,观察串口监视器是否实时输出 “CHANGE DETECTED”,并记录电平。
  4. 休眠功耗测量:将万用表调至电流微安档,串联在电池正极,深度睡眠时电流应小于 30μA。
  5. MQTT 连接测试:在局域网内用 MQTT 调试工具(如 MQTTX)订阅 garage/door/state,模拟门开关动作,查看主题是否收到 “OPEN”/“CLOSED”。
  6. 整体安装联调:固定磁体和主板,实际开关车库门,手机端确认状态变化延迟与准确率,必要时微调磁体位置。
  7. 续航验证:充满电后置于正常安装位置,统计一周耗电量,推算实际使用时间。

设计图

车库门远程状态卡片结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报