ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ESP32墨水屏喂奶计时器:本地接入米家智能家居全流程指南

2026/8/8 3:49:06 拓冰建站 浏览量
ESP32墨水屏喂奶计时器:本地接入米家智能家居全流程指南

这次我们来看一个非常实用的物联网DIY项目:用ESP32主控搭配墨水屏,制作一个能接入米家智能家居的喂奶计时器。对于有新生儿的家庭来说,记录喂奶时间是个高频且容易遗忘的任务,这个项目将硬件、固件和智能家居平台打通,提供了一个低成本、低功耗、信息常显的本地化解决方案。

项目的核心思路很清晰:利用ESP32的Wi-Fi和计算能力,运行一个简单的HTTP服务器,并通过Home Assistant(HA)这个开源家庭自动化平台作为桥梁,最终将计时器的状态和控制接入米家App。墨水屏的特性决定了它只在刷新时耗电,显示喂奶间隔时间等信息非常直观且省电。整个方案不依赖复杂的云服务,数据在本地流转,响应快且隐私性好。

本文将带你从零开始,完成这个喂奶计时器的硬件搭建、固件烧录、Home Assistant配置以及米家接入的全过程。无论你是ESP32的初学者,还是想深入了解如何将自制设备融入现有智能家居生态的开发者,这篇文章都能提供一套可落地的操作指南。我们会重点关注ESP32的HTTP服务器实现、Home Assistant的MQTT或RESTful传感器配置,以及通过Xiaomi Miot Auto插件实现米家控制的关键步骤。

1. 核心能力速览

在动手之前,我们先快速了解这个项目的关键特性和要求。

能力项说明
核心功能基于ESP32和墨水屏的本地喂奶计时器,状态通过Home Assistant接入米家App。
硬件门槛较低。需要ESP32开发板、墨水屏(如1.54英寸或2.9英寸)、杜邦线等。无需高性能GPU/CPU。
功耗表现极低。ESP32在深度睡眠模式下功耗极低;墨水屏仅在刷新时耗电,显示内容可长期保持。
通信方式ESP32作为HTTP服务器,通过Wi-Fi与家庭内网的Home Assistant通信。
接入生态通过Home Assistant及其插件,间接接入米家(Xiaomi)智能家居体系。
数据流本地化。计时数据在ESP32生成,通过HA处理,最终同步至米家App,无需经过第三方云。
开发环境Arduino IDE 或 PlatformIO (VS Code插件),使用Arduino框架进行ESP32开发。
适合场景家庭育儿智能硬件DIY、ESP32物联网入门项目、Home Assistant与米家生态桥接实践。

2. 适用场景与使用边界

这个喂奶计时器项目主要服务于特定场景,明确其边界能帮助你更好地判断是否适合自己。

适用场景:

  1. 新生儿家庭:父母需要频繁、准确地记录每次喂奶的起始时间,以掌握喂养规律。
  2. 物联网学习与实践:对于想学习ESP32联网、HTTP服务器、传感器数据上报以及Home Assistant集成的开发者,这是一个功能完整且贴近生活的练手项目。
  3. 智能家居深度用户:已经部署Home Assistant,并希望将更多自制、非标设备统一管理并接入常用App(如米家)的用户。
  4. 低功耗显示需求:需要长时间显示固定信息,且不希望频繁充电或更换电池的场景,墨水屏的优势明显。

使用边界与注意事项:

  1. 非商业产品:这是一个DIY项目,在稳定性、安全性和耐用性上无法与成熟商业产品相比,适合技术爱好者。
  2. 依赖家庭网络:ESP32和Home Assistant需要处于同一局域网(LAN)下。网络不稳定会导致计时器状态同步延迟或失败。
  3. 需要基础部署能力:你需要能够烧录ESP32固件、安装配置Home Assistant(通常以HASSOS、Docker等方式部署),并安装第三方插件。
  4. 功能相对单一:核心是计时和状态显示,不具备视频监控、奶量记录等复杂功能。扩展需要二次开发。
  5. 隐私与数据安全:项目设计为本地运行,数据不出家门。但需确保Home Assistant实例本身的安全配置(如设置强密码、不随意暴露到公网)。

3. 环境准备与前置条件

开始制作前,请确保你已准备好以下软硬件环境。

硬件清单:

  • ESP32开发板:如ESP32 DevKitC、NodeMCU-32S等,任何带有Wi-Fi功能的ESP32模块均可。
  • 墨水屏(E-Paper):建议选择与常用驱动库兼容的型号,例如:
    • GDEH0154D67 (1.54英寸)
    • GDEW029T5 (2.9英寸)
    • 购买时请确认其接口(通常是SPI)和电压(3.3V)与ESP32兼容。
  • 连接线:杜邦线(母对母或公对母),用于连接ESP32与墨水屏。
  • 电源:为ESP32供电,可使用USB线连接电脑或手机充电器,或使用3.7V锂电池配合充放电模块实现便携。
  • 可选:按键或触摸传感器,用于本地手动触发计时开始/结束。

软件与环境清单:

  • 开发环境
    • 方案一(推荐):Visual Studio Code + PlatformIO IDE插件。它提供了更好的库管理和项目结构。
    • 方案二:Arduino IDE。需要安装ESP32开发板支持包。
  • Home Assistant (HA):一个已安装并运行在你的家庭网络中的Home Assistant实例。这可以是运行在树莓派、旧电脑、NAS或虚拟机上的HASSOS、Docker容器等。
  • 网络:稳定的家庭Wi-Fi网络。你需要知道Wi-Fi的SSID(名称)和密码。
  • 米家App:在手机上安装米家App,并已登录账号。

4. 硬件连接与驱动库安装

首先,我们将ESP32与墨水屏连接起来,并配置好开发环境。

4.1 硬件连线(以SPI接口墨水屏为例)

大多数小尺寸墨水屏使用SPI接口。以下是典型的连接方式,请根据你的屏幕具体引脚定义进行调整:

墨水屏引脚ESP32 GPIO引脚功能说明
VCC3.3V电源正极(务必确认屏幕电压为3.3V
GNDGND电源地
DIN (MOSI)GPIO 23SPI数据输入(主出从入)
CLK (SCK)GPIO 18SPI时钟信号
CS (片选)GPIO 5片选信号,低电平有效
DC (数据/命令)GPIO 17用于区分发送的是数据还是命令
RST (复位)GPIO 16复位引脚,低电平复位
BUSYGPIO 4忙状态指示,高电平表示屏幕忙

注意:GPIO引脚编号可根据你的板子布局和代码定义进行修改,避免冲突。

4.2 安装开发环境与库

使用 PlatformIO (VS Code):

  1. 安装VS Code,然后在扩展商店搜索并安装“PlatformIO IDE”。
  2. 新建一个Project,选择Board为“Espressif ESP32 Dev Module”,Framework为“Arduino”。
  3. 打开项目根目录下的platformio.ini文件,在[env]部分添加依赖库。对于常用的GxEPD2墨水屏驱动库,添加如下内容:
    lib_deps = olikraus/U8g2_for_Adafruit_GFX @ ^1.8.0 zinggjm/GxEPD2 @ ^1.5.6
  4. PlatformIO会自动下载这些库。

使用 Arduino IDE:

  1. 安装Arduino IDE。
  2. 添加ESP32开发板支持:文件 -> 首选项 -> 附加开发板管理器网址,添加https://espressif.github.io/arduino-esp32/package_esp32_index.json
  3. 工具 -> 开发板 -> 开发板管理器,搜索“esp32”并安装。
  4. 项目 -> 加载库 -> 管理库,搜索并安装“GxEPD2”和“U8g2 for Adafruit GFX”库。

5. ESP32固件开发:HTTP服务器与计时逻辑

这是项目的核心代码部分。ESP32将同时扮演两个角色:一个简单的HTTP服务器,用于接收来自Home Assistant的命令;一个计时器,控制墨水屏的显示。

5.1 代码结构概述

我们将编写一个Arduino Sketch,主要包含以下功能模块:

  1. Wi-Fi连接:连接家庭Wi-Fi。
  2. 墨水屏驱动初始化与显示:使用GxEPD2库驱动屏幕,绘制计时界面。
  3. HTTP服务器:创建一个Web服务器,监听特定端口(如80),提供简单的API端点。
  4. 计时逻辑:记录“开始喂奶”的时间点,计算距离当前时间的间隔,并格式化显示。
  5. 与Home Assistant交互:通过HTTP端点,接收HA发来的“开始计时”指令,也可以将当前状态(如“已计时XX分钟”)通过HA暴露给米家。

5.2 核心代码示例

以下是一个高度简化的代码框架,展示了关键逻辑:

#include <WiFi.h> #include <WebServer.h> // 使用ESP32内置的WebServer库 #include <GxEPD2_BW.h> // 假设使用黑白墨水屏 #include <Fonts/FreeMonoBold9pt7b.h> // 1. 定义墨水屏对象(以2.9英寸为例) GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=*/5, /*DC=*/17, /*RST=*/16, /*BUSY=*/4)); // 2. 网络配置 const char* ssid = "你的Wi-Fi名称"; const char* password = "你的Wi-Fi密码"; WebServer server(80); // 在80端口创建服务器 // 3. 计时状态变量 unsigned long feedStartTime = 0; // 开始喂奶的时间戳(毫秒) bool isFeeding = false; // 是否正在喂奶 void setup() { Serial.begin(115200); // 初始化墨水屏 display.init(115200); display.setRotation(1); display.setFont(&FreeMonoBold9pt7b); display.setTextColor(GxEPD_BLACK); // 连接Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nConnected! IP address: "); Serial.println(WiFi.localIP()); // 定义HTTP API端点 server.on("/start", HTTP_GET, []() { // Home Assistant调用此端点开始计时 feedStartTime = millis(); isFeeding = true; updateDisplay(); server.send(200, "text/plain", "Timer started"); }); server.on("/stop", HTTP_GET, []() { // 停止计时 isFeeding = false; updateDisplay(); server.send(200, "text/plain", "Timer stopped"); }); server.on("/status", HTTP_GET, []() { // 提供当前状态,供HA读取 String status = isFeeding ? "feeding" : "idle"; String timeElapsed = String((millis() - feedStartTime) / 60000); // 转换为分钟 String jsonResponse = "{\"state\":\"" + status + "\", \"duration_minutes\":\"" + timeElapsed + "\"}"; server.send(200, "application/json", jsonResponse); }); server.begin(); Serial.println("HTTP server started"); // 首次显示 updateDisplay(); } void loop() { server.handleClient(); // 处理HTTP请求 // 可以添加定时刷新显示的逻辑,例如每分钟刷新一次时间 static unsigned long lastUpdate = 0; if (millis() - lastUpdate > 60000) { // 每分钟更新一次显示 lastUpdate = millis(); if (isFeeding) { updateDisplay(); } } } void updateDisplay() { display.setFullWindow(); display.firstPage(); do { display.fillScreen(GxEPD_WHITE); display.setCursor(10, 30); display.print("Feeding Timer"); display.setCursor(10, 60); if (isFeeding) { unsigned long minutes = (millis() - feedStartTime) / 60000; display.print("Time: "); display.print(minutes); display.print(" min"); } else { display.print("Ready"); } display.setCursor(10, 90); display.print("IP:"); display.print(WiFi.localIP()); } while (display.nextPage()); // 墨水屏进入休眠以省电 display.hibernate(); }

代码说明:

  • ESP32启动后连接Wi-Fi,并启动一个Web服务器。
  • 提供了三个简单的API端点:
    • /start:GET请求此地址,计时器开始。
    • /stop:停止计时。
    • /status:返回一个JSON,包含当前状态和持续时间。
  • updateDisplay函数负责在墨水屏上绘制内容,包括计时状态和ESP32的IP地址(便于调试)。
  • 计时逻辑基于millis()函数,避免了使用阻塞的delay()

5.3 烧录固件

  1. 将上述代码根据你的屏幕型号和引脚定义修改后,保存为.ino文件。
  2. 用USB线连接ESP32到电脑。
  3. 在开发环境(PlatformIO或Arduino IDE)中选择正确的端口和开发板型号。
  4. 点击上传按钮,编译并烧录固件。
  5. 打开串口监视器,查看输出日志,确认Wi-Fi连接成功并获取到IP地址(如192.168.1.100)。记下这个IP。

6. Home Assistant配置:创建传感器与自动化

现在,我们需要让Home Assistant认识这个ESP32计时器,并与之通信。

6.1 添加RESTful传感器

Home Assistant可以通过RESTful传感器(rest)来获取ESP32的状态。编辑HA的configuration.yaml文件,添加如下配置:

# configuration.yaml 示例 sensor: - platform: rest name: "Feeding Timer Status" resource: http://ESP32_IP_ADDRESS/status # 替换为你的ESP32 IP method: GET scan_interval: 30 # 每30秒查询一次状态 value_template: "{{ value_json.state }}" json_attributes: - duration_minutes

配置解释:

  • resource: 指向ESP32的/status端点。
  • value_template: 从返回的JSON中提取state字段的值(“feeding”或“idle”)作为传感器状态。
  • json_attributes: 将duration_minutes字段作为传感器的属性存储,可以在前端显示。

保存并重启Home Assistant。在HA的前端,你应该能看到一个名为“Feeding Timer Status”的传感器实体。

6.2 创建调用服务的开关或按钮

为了向ESP32发送“开始”/“停止”命令,我们可以在HA中创建一个脚本或直接使用“开关”实体。这里以创建一个“开关”为例,它实际上调用的是rest_command服务。

首先,在configuration.yaml中定义rest_command

rest_command: feeding_timer_start: url: "http://ESP32_IP_ADDRESS/start" method: GET feeding_timer_stop: url: "http://ESP32_IP_ADDRESS/stop" method: GET

然后,你可以通过HA的“开发者工具 -> 服务”手动调用rest_command.feeding_timer_start来测试。为了更方便,可以创建一个“虚拟开关”或“按钮”卡片来触发这些服务。

使用“帮助程序”创建开关:

  1. 进入HA侧边栏“设置” -> “设备与服务” -> “帮助程序”。
  2. 点击“创建辅助元素”,选择“开关”。
  3. 设置名称,如“开始喂奶计时”。
  4. 在开关配置中,为其添加一个自动化:当开关打开时,调用服务rest_command.feeding_timer_start;当开关关闭时,调用rest_command.feeding_timer_stop

现在,你在HA仪表盘上就有一个可以控制ESP32计时器的开关了。

7. 接入米家:通过Xiaomi Miot Auto插件

这是实现“通过米家控制”的关键一步。我们将利用Home Assistant强大的集成能力,通过第三方插件将HA中的实体暴露给米家App。

7.1 安装Xiaomi Miot Auto集成

Xiaomi Miot Auto是一个HA社区插件,可以将HA中的任意实体(如开关、传感器)同步到米家App中。

  1. 在HA中,确保已安装“File editor”或“Samba share”等插件,以便编辑配置文件。
  2. 通过HACS(Home Assistant Community Store)安装“Xiaomi Miot Auto”集成。如果未安装HACS,需先安装HACS。
  3. 安装完成后,重启HA。

7.2 配置Xiaomi Miot Auto

  1. 进入HA侧边栏“设置” -> “设备与服务” -> “集成”。
  2. 点击“添加集成”,搜索“Xiaomi Miot Auto”。
  3. 按照提示,选择“账号集成”模式,使用你的小米账号(即米家App账号)登录授权。
  4. 授权成功后,集成会自动同步你米家账号下的设备。但这还不够,我们需要将HA的实体添加进去。

7.3 将HA实体映射到米家

Xiaomi Miot Auto允许你通过YAML配置,将HA的实体映射为虚拟的米家设备。编辑HA的configuration.yaml文件,添加如下配置:

# configuration.yaml 示例 xiaomi_miot_raw: - host: 127.0.0.1 # 固定为本地 token: auto mapping: switch.feeding_timer_start: # 这是你在HA中创建的辅助开关实体ID siid: 2 # 自定义服务ID,通常2代表开关 piid: 1 # 属性ID aiid: 1 # 动作ID value: true value_off: false value_on: true sensor.feeding_timer_status: # 这是RESTful传感器的实体ID siid: 3 # 自定义服务ID,通常3代表传感器 piid: 1 value: '{{ value }}'

注意siid,piid,aiid的值需要根据米家设备模型的规范来定义,上述示例是一个简化版本。更可靠的做法是参考Xiaomi Miot Auto的官方文档,使用其“自定义模型”功能,或直接复制一个现有米家开关设备的模型进行修改。

配置完成后,重启Home Assistant。

7.4 在米家App中查看和控制

  1. 重启后,打开米家App。
  2. 在“我的设备”页面,下拉刷新。通常,稍等片刻后,一个名为“Home Assistant”或类似名称的设备会被自动添加进来。
  3. 点开这个设备,你应该能看到里面包含了我们在HA中映射的“开关”和“传感器”。
  4. 现在,你就可以直接在米家App里点击“开关”来远程启动/停止ESP32上的喂奶计时器,并查看计时状态了。

8. 功能测试与效果验证

完成所有配置后,需要进行系统化测试以确保各环节工作正常。

8.1 本地ESP32功能测试

  1. 基础显示:ESP32启动后,墨水屏应显示初始界面(如“Ready”和IP地址)。
  2. HTTP API测试:在电脑浏览器或使用curl命令测试ESP32的API。
    • 打开浏览器,访问http://[ESP32_IP]/status,应返回JSON数据。
    • 访问http://[ESP32_IP]/start,屏幕应立即更新,显示计时开始。
    • 访问http://[ESP32_IP]/stop,计时停止,屏幕显示“Ready”。
  3. 计时准确性:开始计时后,观察屏幕显示的时间增量是否与真实时间基本一致(允许秒级误差)。

8.2 Home Assistant集成测试

  1. 传感器状态:在HA的“概览”或“开发者工具 -> 状态”中,找到sensor.feeding_timer_status实体,检查其状态是否随ESP32计时状态变化而更新。
  2. 服务调用:在“开发者工具 -> 服务”中,调用rest_command.feeding_timer_startrest_command.feeding_timer_stop,观察ESP32屏幕和HA传感器状态是否同步变化。
  3. 辅助开关:操作在HA前端创建的“开始喂奶计时”开关,验证其能否正确控制ESP32。

8.3 米家App端到端测试

  1. 设备发现:确认米家App中出现了来自Home Assistant的虚拟设备。
  2. 控制测试:在米家App中,点击虚拟设备里的开关。观察:
    • HA中对应的辅助开关状态是否变化。
    • ESP32的墨水屏显示是否变化。
  3. 状态同步测试:在ESP32本地通过HTTP API开始计时,等待片刻(HA的扫描间隔),查看米家App中传感器显示的状态是否变为“feeding”,并看到持续时间更新。

9. 常见问题与排查方法

在部署过程中,你可能会遇到以下问题:

问题现象可能原因排查方式解决方案
ESP32无法连接Wi-FiSSID/密码错误、信号弱、路由器设置限制检查串口日志输出确认密码正确,将ESP32靠近路由器,检查路由器是否开启了MAC过滤或AP隔离。
浏览器无法访问ESP32 IP防火墙阻止、IP地址错误、ESP32服务器未启动在HA主机或同一网络下电脑ping ESP32的IP;检查串口日志确认服务器启动关闭电脑防火墙临时测试;确认ESP32与测试设备在同一子网;检查代码中server.begin()是否执行。
HA中REST传感器状态为“unavailable”HA无法访问ESP32的/status端点、网络问题、扫描间隔未到在HA主机上用curl命令测试http://ESP32_IP/status;检查HA日志确保IP正确,网络互通;暂时增大scan_interval;检查ESP32代码确保/status端点正确处理请求并返回有效JSON。
米家App中找不到HA设备Xiaomi Miot Auto配置错误、米家账号未同步、网络延迟检查HA中Xiaomi Miot Auto集成的日志;重启HA和米家App;等待更长时间仔细检查YAML配置中实体ID是否正确;尝试在Xiaomi Miot Auto集成设置中手动“同步设备”。
米家App能控制但状态不同步传感器映射配置错误、HA传感器本身状态未更新首先在HA前端确认传感器状态是否正确;检查米家映射配置中的value模板确保HA侧的传感器工作正常;检查Xiaomi Miot Auto配置中传感器映射的value字段是否正确引用了状态值。
墨水屏不显示或显示乱码引脚连接错误、驱动库不匹配、电源问题逐一检查杜邦线连接;确认使用的驱动库(GxEPD2)支持你的屏幕型号;测量VCC电压对照引脚定义表重新接线;在代码中尝试使用库自带的示例程序测试屏幕;确保使用3.3V供电。
计时不准使用delay()导致阻塞、millis()溢出(约50天后)检查代码中是否在loop()里使用了长延时delay()使用非阻塞的定时逻辑(如示例代码中millis()差值判断);对于超长运行,需考虑millis()溢出处理,但喂奶计时场景通常无需考虑。

10. 优化与扩展思路

基础功能实现后,可以考虑以下优化和扩展,让项目更完善:

  1. 低功耗优化

    • ESP32深度睡眠:如果使用电池供电,可以在计时结束后让ESP32进入深度睡眠模式,仅由外部按键(连接到EN或GPIO0)唤醒,极大延长续航。
    • 墨水屏局部刷新:如果屏幕支持,在更新计时数字时使用局部刷新(display.powerRefresh())而非全屏刷新,速度更快、更省电、减少残影。
  2. 本地交互

    • 物理按键:增加1-2个物理按键连接到ESP32,实现本地手动开始/停止/重置计时,不依赖网络。
    • 触摸感应:使用电容触摸传感器,实现更优雅的交互。
  3. 功能扩展

    • 多计时器:管理“左/右”喂奶或“喂奶/换尿布”等多个计时任务。
    • 历史记录:ESP32将每次喂奶的起止时间通过HTTP POST发送到HA,HA将其记录在数据库(如InfluxDB)中,并可通过Grafana等工具可视化喂养历史。
    • 声音/灯光提醒:增加蜂鸣器或LED,当计时达到一定时长(如30分钟)时发出提醒。
  4. 可靠性提升

    • Wi-Fi重连机制:在代码中添加健壮的Wi-Fi断开重连逻辑。
    • 看门狗定时器:启用硬件看门狗,防止程序跑飞导致设备死机。
    • OTA升级:实现通过网络远程更新ESP32固件,无需插线。

这个项目成功地将一个简单的ESP32设备,通过Home Assistant的桥梁,融入了成熟的米家智能生态。它不仅解决了喂奶计时这个具体问题,更提供了一个经典的物联网设备接入范例。你可以举一反三,将类似的思路应用于其他传感器(如温湿度计、门窗磁)或控制器(如继电器开关),打造完全自定义的智能家居设备。