Hotdry.
embedded-systems

ESP32低功耗IoT设备设计:从HTTP轮询到BLE推送的架构演进

基于ESP32的智能办公室干扰检测设备,探讨从HTTP轮询到BLE推送的架构演进,涵盖低功耗设计、自定义二进制协议与3D打印公差控制。

在远程办公成为常态的今天,如何在共享空间中保护会议隐私成为一个实际需求。传统的解决方案如共享日历或简单的门牌存在诸多局限:日历无法覆盖突发会议,门牌需要手动操作,而手机通知又可能被忽略。一个名为 "Over-Engineering a 'Do Not Disturb' Device" 的开源项目提供了一个硬件解决方案,其技术演进路径值得深入分析。

问题背景与技术选型

项目最初的需求很简单:当 MacBook 摄像头开启时,门外设备显示红色 "请勿打扰" 状态;摄像头关闭时显示绿色 "可进入" 状态。作者尝试了多种方案后,最终选择了 ESP32 作为核心控制器,原因在于其内置 Wi-Fi 和蓝牙双模通信能力,以及丰富的 GPIO 接口。

最初的架构采用 HTTP 轮询方式:ESP32 每隔 500ms 向 MacBook 上的 Bun 服务器发送请求,查询摄像头状态。这种方式虽然实现简单,但存在两个核心问题:一是动态 IP 地址导致设备需要频繁重新配置,二是轮询机制带来不必要的功耗浪费。

从 HTTP 轮询到 BLE 推送的架构演进

HTTP 轮询的局限性

在初始设计中,ESP32 通过 Wi-Fi 连接,定期向http://192.168.0.5:1337发送 GET 请求。这种方式的功耗相当可观:ESP32 在 Wi-Fi 活动模式下功耗可达 240mA,即使采用轻睡眠模式,每 500ms 唤醒一次的功耗也超过 50mA。对于 USB 供电的设备来说,这或许可以接受,但对于电池供电的场景则不可持续。

BLE 推送的优势

项目演进到第二阶段时,作者将通信协议从 HTTP 切换到了 BLE(蓝牙低功耗)。BLE 的核心优势在于其极低的功耗特性:在连接间隔为 100ms 的情况下,平均功耗仅为 1-2mA,相比 Wi-Fi 节省了 90% 以上的功耗。

更重要的是,BLE 支持服务器主动推送(Server Push)模式。当摄像头状态发生变化时,MacBook 作为 BLE 服务器可以立即向 ESP32 客户端发送通知,无需等待轮询。这不仅降低了延迟,还进一步减少了不必要的通信开销。

mDNS 解决动态 IP 问题

在局域网内,作者采用了 mDNS(多播 DNS)技术来解决动态 IP 地址问题。通过将 MacBook 注册为Apoorvs-MacBook-Pro.local,ESP32 可以通过域名而非 IP 地址进行连接,避免了因路由器 DHCP 重新分配 IP 而导致的连接中断。

自定义二进制协议设计

协议设计动机

作者在设计过程中发现,标准的 JSON 或 Protocol Buffers 格式对于这个简单场景来说过于重量级。一个简单的状态更新{"status": "on", "timestamp": 1736294400}需要数十字节,而实际上只需要传达几个比特的信息。

DoorFrame Protocol v1

为此,作者设计了名为 "DoorFrame Protocol" 的自定义二进制协议。协议的核心思想是用最少的字节传达最多的信息

握手协议(2 字节)

  • 0xDF:协议魔数(DoorFrame)
  • 0x01:版本号

状态命令(1 字节)

  • 0xC0:摄像头关闭(C 代表 Camera)
  • 0xC1:摄像头开启

时间编码(2 字节)

  • 小时字节:0x7H(H 为小时数,24 小时制)
  • 分钟字节:0x8M(M 为 5 分钟间隔,如0x86表示 30 分钟)

这种设计将原本需要 20-30 字节的 JSON 数据压缩到 1-3 字节,不仅减少了传输开销,还降低了 ESP32 的解析复杂度。

协议扩展性考虑

虽然当前协议非常简单,但作者在设计时考虑了扩展性。协议头部预留了版本字段,未来可以向后兼容。同时,命令字节的高 4 位用于标识命令类型,低 4 位用于具体参数,这种设计允许最多 16 种命令类型,每种命令最多 16 个参数值。

低功耗设计策略

ESP32 功耗模式选择

ESP32 提供了多种功耗模式,根据项目需求选择合适的模式至关重要:

  1. 活动模式(Active Mode):240mA,全功能运行
  2. 调制解调器睡眠模式(Modem-sleep):20-30mA,CPU 运行,Wi-Fi / 蓝牙关闭
  3. 轻睡眠模式(Light-sleep):0.8mA,CPU 暂停,内存保持
  4. 深度睡眠模式(Deep-sleep):10μA,仅 RTC 运行
  5. 休眠模式(Hibernation):2.5μA,最低功耗

对于这个项目,作者采用了轻睡眠模式结合 BLE 事件唤醒的策略。当没有 BLE 通信时,ESP32 进入轻睡眠状态,功耗降至 0.8mA;当 MacBook 发送状态更新时,BLE 中断唤醒 ESP32,更新显示后立即返回睡眠。

功耗优化参数清单

基于实际测试,以下是推荐的功耗优化参数:

  1. BLE 连接参数

    • 连接间隔:100-200ms(平衡响应速度与功耗)
    • 从机延迟:0(每次连接事件都唤醒)
    • 监控超时:2s(连接丢失检测)
  2. 睡眠策略

    • 无通信超时:5s 后进入轻睡眠
    • 显示更新后:立即返回睡眠
    • RTC 内存使用:保存连接状态和显示内容
  3. 显示功耗控制

    • OLED 屏幕亮度:30%(足够室内可见)
    • 屏幕刷新率:1Hz(状态稳定时)
    • 背光控制:根据环境光自动调节

预期电池寿命计算

假设使用 1000mAh 的锂电池:

  • 活动模式(持续):1000mAh ÷ 240mA ≈ 4.2 小时
  • BLE 连接模式(平均 2mA):1000mAh ÷ 2mA ≈ 500 小时(约 21 天)
  • 轻睡眠模式(0.8mA):1000mAh ÷ 0.8mA ≈ 1250 小时(约 52 天)

实际使用中,设备大部分时间处于轻睡眠状态,偶尔被 BLE 事件唤醒,预计电池寿命可达 30-40 天。

硬件工程与 3D 打印优化

外壳设计挑战

作者从软件工程师转型硬件设计,面临的最大挑战是公差控制。在软件世界中,1 + 1总是等于2;但在 3D 打印中,材料收缩、喷嘴尺寸、层高都会影响最终尺寸。

公差设计参数

经过多次迭代,作者总结出以下公差设计原则:

  1. 干涉配合:对于需要紧密配合的部件,设计负公差(-0.1mm)
  2. 滑动配合:对于需要相对运动的部件,设计正公差(+0.2mm)
  3. 卡扣设计:悬臂梁厚度为 1.2mm,挠度控制在 0.5mm 以内
  4. 材料收缩补偿:PLA 材料收缩率约 0.2%,设计时按 1.002 倍放大

装配优化清单

  1. 分件设计:将外壳分为前盖、后盖和内部支架,便于打印和装配
  2. 定位特征:添加定位柱和定位孔,确保组件对齐
  3. 螺丝孔设计:M2 螺丝孔设计为 2.4mm,预留 0.4mm 装配间隙
  4. 线缆管理:设计线槽和固定点,避免内部线缆松动

热管理考虑

虽然 ESP32 功耗不高,但在密闭外壳中仍需考虑散热:

  • 外壳顶部设计通风孔
  • ESP32 与外壳间预留 1mm 空气间隙
  • 避免将电源模块与主控芯片堆叠

软件架构与监控系统

分层架构设计

项目采用清晰的分层架构:

  1. 硬件抽象层:封装 ESP32 的 GPIO、BLE、显示驱动
  2. 协议层:实现 DoorFrame Protocol 的编码解码
  3. 业务逻辑层:处理状态机、功耗管理、错误恢复
  4. 监控层:记录设备状态、连接质量、电池电压

错误处理策略

  1. 连接丢失检测:BLE 连接超时 2s 后尝试重连
  2. 状态同步:重连后立即请求当前状态
  3. 降级策略:BLE 失败时回退到 HTTP 轮询(如果配置了 Wi-Fi)
  4. 电池保护:电压低于 3.3V 时进入深度睡眠,防止过放电

监控指标

设备通过 BLE 定期上报以下监控数据:

  • 电池电压(12 位 ADC 精度)
  • 内部温度(ESP32 内置传感器)
  • 连接质量(RSSI 值)
  • 运行时间(从启动开始的毫秒数)

部署与维护考虑

生产部署清单

  1. 固件烧录:使用 PlatformIO 或 Arduino IDE 批量烧录
  2. 设备配对:首次启动进入配对模式,通过手机 App 配置 Wi-Fi
  3. 质量控制:每台设备进行功能测试和功耗测试
  4. 包装设计:防静电包装,包含快速入门指南

OTA 更新策略

虽然当前版本未实现 OTA,但架构预留了扩展空间:

  1. 双分区设计:ESP32 支持 A/B 分区,实现无缝更新
  2. 差分更新:仅传输变更部分,减少带宽需求
  3. 回滚机制:更新失败自动回退到上一版本
  4. 版本验证:数字签名确保固件完整性

总结与展望

这个 "过度工程" 的项目实际上展示了 IoT 设备开发的完整生命周期:从需求分析、技术选型、架构设计,到功耗优化、硬件工程、生产部署。虽然项目规模不大,但涉及的技术栈相当全面。

关键收获

  1. 协议设计:自定义二进制协议在资源受限场景下的优势明显
  2. 功耗优化:从毫安级到微安级的优化需要系统级思考
  3. 硬件软件协同:公差控制、热管理等硬件问题直接影响软件设计
  4. 渐进式演进:从简单的 HTTP 轮询到复杂的 BLE 推送,架构需要支持平滑迁移

未来扩展方向

  1. 多设备同步:支持多个状态指示器同步显示
  2. 环境感知:集成光线传感器、运动传感器,实现更智能的状态判断
  3. 云集成:将设备状态同步到云端,实现远程监控
  4. 能源收集:集成太阳能电池板,实现完全无线供电

这个项目最值得借鉴的不是其具体实现,而是其工程思维:在满足核心需求的前提下,不断优化各个技术环节,平衡性能、功耗、成本和可维护性。对于嵌入式开发者来说,这种端到端的思考方式比掌握某个具体技术更为重要。

资料来源

  1. Over-Engineering a "Do Not Disturb" Device - 原始项目博客
  2. ESP32 Sleep Modes & Power Consumption - ESP32 功耗分析
  3. Custom Network Protocol Development - 自定义协议设计指南
查看归档