ESP32驱动墨水屏制作米家智能喂奶计时器:物联网项目实战

发布时间:2026/8/8 3:58:59
ESP32驱动墨水屏制作米家智能喂奶计时器:物联网项目实战 这次我们来看一个非常实用的物联网项目用 ESP32 做主控驱动一块墨水屏制作一个能接入米家智能家居的喂奶计时器。对于有新生儿的家庭来说记录喂奶时间是个高频且容易遗忘的任务这个项目直接把提醒和记录功能做成了一个物理设备并且能融入现有的智能家居生态实用性拉满。项目的核心思路很清晰ESP32 作为大脑负责联网、逻辑控制和驱动墨水屏显示墨水屏作为显示终端超低功耗且不伤眼适合长期显示Home Assistant 作为智能家居中枢负责与米家设备联动最终实现通过米家 App 或语音助手来控制或查看喂奶计时状态。它解决的不是一个复杂的算法问题而是一个典型的“硬件软件生态”的集成问题重点在于如何让这几个部分稳定、可靠地协同工作。如果你关心如何用低成本开发板ESP32实现一个实用的物联网设备如何将自定义设备接入主流智能家居平台米家或者对墨水屏的应用开发感兴趣这篇文章会带你走通从硬件选型、固件开发、Home Assistant 配置到米家联动的完整流程。我们会重点关注 ESP32 的编程、墨水屏的驱动、HTTP 服务器的搭建以及如何通过 Home Assistant 的“米家集成”实现间接接入。1. 核心能力速览在动手之前我们先快速了解这个项目的关键信息和技术栈判断它是否适合你。能力项说明核心功能基于 ESP32 和墨水屏的物理喂奶计时器可通过 Home Assistant 接入米家生态实现远程查看、定时提醒、状态同步。主控硬件ESP32 系列开发板如 ESP32-WROOM-32。成本低廉自带 Wi-Fi 和蓝牙资源足够。显示硬件电子墨水屏e-Paper。推荐 2.9 英寸或 4.2 英寸黑白即可功耗极低显示内容持久。联网与接入ESP32 连接本地 Wi-Fi运行一个简易 HTTP 服务器。Home Assistant 通过该 HTTP 接口获取/设置计时器状态并借助其“米家集成”将状态暴露给米家 App。开发环境Arduino IDE 或 PlatformIO (VS Code 插件)。使用 Arduino 框架开发 ESP32 固件库生态丰富。关键技术点ESP32 Wi-Fi 连接、墨水屏驱动 (GxEPD2 库)、HTTP Server 实现、JSON 数据解析、Home Assistant RESTful 传感器/开关配置。是否支持 API支持。ESP32 内置的 HTTP 服务器提供简单的 REST API用于状态查询和控制。是否支持“批量任务”不直接涉及。核心是单一设备的实时状态监控与控制。适合场景家庭智能家居 DIY、物联网学习项目、有新生儿家庭的实用工具制作、ESP32 及墨水屏应用开发练习。2. 适用场景与使用边界这个项目完美契合了特定场景下的需求但在开始前也需要明确它的能力边界和注意事项。它最适合谁新手父母/家庭成员需要一个放置在奶粉罐旁或尿布台上的、一目了然的物理计时器避免遗忘上一次喂奶时间并能通过手机远程查看。智能家居爱好者希望将自制的专用设备无缝融入现有的米家或 Home Assistant 生态实现自动化联动例如计时结束时让米家智能灯闪烁提醒。物联网/嵌入式学习者希望通过一个完整项目实践 ESP32 联网、外设驱动、服务器搭建以及与云端/本地中枢交互的全流程。它能解决什么问题可视化计时墨水屏实时显示距离上次喂奶过去了多久或显示下一次喂奶的倒计时。远程监控家人在其他房间可通过米家 App 查看宝宝上次进食时间。智能联动计时结束后可自动触发米家智能插座给温奶器断电、智能灯泡变色提醒或其他场景。数据记录通过 Home Assistant可以长期记录每次喂奶的时间点生成简单的统计。它的局限性是什么非直接米家接入项目通过 Home Assistant 中转并非直接以“米家蓝牙 Mesh 设备”或“Wi-Fi 设备”形式接入。这意味着你需要一个持续运行的 Home Assistant 服务器例如树莓派、旧电脑或 NAS。功能相对单一核心是计时和显示。如果需要复杂的多事件记录、图表分析可能需要扩展固件和 Home Assistant 的自定义组件。依赖本地网络ESP32 和 Home Assistant 需要在同一局域网内HTTP 通信才能正常进行。广域网访问需要配置 Home Assistant 的外部访问。硬件需要动手需要自行焊接或连接杜邦线对纯软件开发者有一定硬件门槛。安全与合规提醒本项目为家庭自用学习项目所有数据在本地网络传输。请注意 Wi-Fi 密码等敏感信息的安全不要在代码中硬编码建议使用 Arduino 的WiFiManager库实现网页配网。设备应放置在婴幼儿无法触及的地方避免误食小零件或拉扯线缆。3. 环境准备与前置条件要成功复现这个项目你需要准备好硬件、软件和网络环境。硬件清单ESP32 开发板x1如 ESP32 DevKitC、NodeMCU-32S 等。确保其 USB 口可用于供电和烧录。电子墨水屏e-Paperx1推荐使用 2.9 英寸或 4.2 英寸的黑白屏幕。务必确认其驱动芯片型号如 SSD1608、SSD1675、IL3820 等并购买对应的 SPI 接口屏。连接线杜邦线母对母若干用于连接 ESP32 与墨水屏。电源ESP32 可通过 USB 供电5V如需长期放置可使用 5V/1A 的 USB 电源适配器。其他可选配一个外壳用于保护和固定设备。软件与环境Arduino IDE或VS Code PlatformIO推荐后者对库管理和项目构建更友好。本文将以 PlatformIO 为例。ESP32 开发板支持在 Arduino IDE 或 PlatformIO 中安装 ESP32 开发框架。墨水屏驱动库在 PlatformIO 的库管理器中搜索并安装GxEPD2这是一个非常强大的、支持多种墨水屏的库。必要的 Arduino 库WiFi(内置)、WebServer(内置)、ArduinoJson(需安装用于处理 HTTP 请求和响应中的数据)。Home Assistant 服务器已安装并运行在本地网络中的 Home Assistant版本建议 2023.x 或更高。这是接入米家的关键桥梁。米家 App安装在手机上用于最终的控制和查看。网络条件一个 2.4GHz Wi-Fi 网络ESP32 通常不支持 5GHz。ESP32、运行 Home Assistant 的服务器如树莓派、你的手机需要处于同一局域网下。4. 硬件连接与引脚定义硬件连接是第一步务必仔细核对。不同的墨水屏引脚定义可能略有不同请以你购买的屏幕资料为准。以下以一款常见的 2.9 英寸 SSD1608 驱动芯片的墨水屏为例墨水屏引脚功能连接至 ESP32 引脚VCC电源 (3.3V)3.3VGND地GNDDIN (MOSI)SPI 数据输入GPIO 23CLK (SCK)SPI 时钟GPIO 18CS (SS)SPI 片选GPIO 5DC数据/命令选择GPIO 17RST复位GPIO 16BUSY忙状态指示GPIO 4连接注意事项电源务必确认墨水屏的工作电压是 3.3V。大部分 ESP32 开发板的 3.3V 引脚可以驱动小尺寸墨水屏如果屏幕较大或供电不稳可能需要外部 3.3V 稳压模块。SPI 引脚ESP32 的默认 SPI 引脚为MOSI-23, MISO-19, SCK-18, SS-5。我们这里只用了 MOSI, SCK 和 CS。MISO 引脚在本项目中不需要。GPIO 选择DC、RST、BUSY 引脚可以更改为其他空闲的 GPIO但需要在代码中做相应修改。连接完成后硬件部分就准备好了。接下来是固件开发。5. ESP32 固件开发详解固件是设备的大脑负责联网、提供 HTTP 接口和驱动屏幕。我们将分模块讲解核心代码。5.1 项目结构与库引入在 PlatformIO 中创建一个新项目选择板子为ESP32 Dev Module。在platformio.ini中确保包含必要的库[env:esp32dev] platform espressif32 board esp32dev framework arduino monitor_speed 115200 lib_deps olikraus/U8g2_for_Adafruit_GFX ^1.8.0 adafruit/Adafruit GFX Library ^1.11.9 adafruit/Adafruit BusIO ^1.14.5 zinggjm/GxEPD2 ^1.5.6 bblanchon/ArduinoJson ^6.21.3主程序文件src/main.cpp的开头引入必要的头文件#include WiFi.h #include WebServer.h #include ArduinoJson.h #include GxEPD2_BW.h // 根据你的屏幕选择这里是黑白屏 #include Fonts/FreeMonoBold9pt7b.h // 选择一种字体 // 定义墨水屏型号和引脚根据你的屏幕型号修改 // 例如GxEPD2_290_T94 代表 2.9 英寸T94 驱动器 #define EPD_CLASS GxEPD2_290_T94 #define EPD_CS 5 #define EPD_DC 17 #define EPD_RST 16 #define EPD_BUSY 4 // 初始化墨水屏对象 GxEPD2_BWEPD_CLASS, EPD_CLASS::HEIGHT display(EPD_CLASS(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY)); // 创建 Web 服务器对象监听端口 80 WebServer server(80); // 你的 Wi-Fi 凭证建议后期改用 WiFiManager 配网 const char* ssid 你的Wi-Fi名称; const char* password 你的Wi-Fi密码; // 喂奶计时器状态变量 unsigned long lastFeedTime 0; // 上次喂奶时间戳毫秒 bool timerActive false; // 计时器是否激活 int presetIntervalMinutes 180; // 预设提醒间隔默认3小时180分钟5.2 Wi-Fi 连接与 HTTP 服务器设置在setup()函数中初始化串口、连接 Wi-Fi、启动 HTTP 服务器并定义 API 路由void setup() { Serial.begin(115200); delay(1000); // 1. 初始化墨水屏 display.init(115200, true, 2, false); // 使用初始化参数 display.setRotation(1); // 根据需要设置旋转方向 display.setFont(FreeMonoBold9pt7b); display.setTextColor(GxEPD_BLACK); displayFullScreenMessage(Booting...); // 2. 连接 Wi-Fi WiFi.begin(ssid, password); Serial.print(Connecting to WiFi); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(\nConnected! IP address: ); Serial.println(WiFi.localIP()); displayFullScreenMessage(String(IP:) WiFi.localIP().toString()); // 3. 定义 HTTP API 路由 server.on(/, HTTP_GET, handleRoot); // 根路径返回简单状态页 server.on(/status, HTTP_GET, handleGetStatus); // 获取当前状态JSON server.on(/feed, HTTP_POST, handlePostFeed); // 记录一次喂奶 server.on(/timer, HTTP_POST, handlePostTimer); // 开启/关闭计时器 server.on(/interval, HTTP_POST, handlePostInterval); // 设置提醒间隔 server.onNotFound(handleNotFound); // 404 处理 // 4. 启动 HTTP 服务器 server.begin(); Serial.println(HTTP server started); // 5. 初始化计时器状态例如从EEPROM读取上次记录 // loadStateFromEEPROM(); updateDisplay(); // 首次更新显示 } void loop() { server.handleClient(); // 处理客户端请求 // 这里可以添加其他循环任务如检查定时提醒 checkTimerAlert(); }5.3 核心 API 处理函数API 设计应简洁使用 JSON 格式进行数据交换。1. 获取状态 (/status)void handleGetStatus() { DynamicJsonDocument doc(256); doc[last_feed_time] lastFeedTime; doc[timer_active] timerActive; doc[preset_interval] presetIntervalMinutes; doc[current_uptime] millis(); String response; serializeJson(doc, response); server.send(200, application/json, response); }2. 记录喂奶 (/feed)void handlePostFeed() { lastFeedTime millis(); // 记录当前时间为上次喂奶时间 timerActive true; // 自动启动计时器 // saveStateToEEPROM(); // 可选保存状态到EEPROM updateDisplay(); // 更新屏幕显示 DynamicJsonDocument doc(128); doc[success] true; doc[message] Feed recorded.; doc[new_last_feed_time] lastFeedTime; String response; serializeJson(doc, response); server.send(200, application/json, response); }3. 控制计时器 (/timer)void handlePostTimer() { // 解析请求体中的JSON例如 {active: true} DynamicJsonDocument doc(128); DeserializationError error deserializeJson(doc, server.arg(plain)); if (error) { server.send(400, text/plain, Invalid JSON); return; } bool requestedState doc[active]; timerActive requestedState; updateDisplay(); doc.clear(); doc[success] true; doc[timer_active] timerActive; String response; serializeJson(doc, response); server.send(200, application/json, response); }4. 设置间隔 (/interval)void handlePostInterval() { DynamicJsonDocument doc(128); DeserializationError error deserializeJson(doc, server.arg(plain)); if (error) { server.send(400, text/plain, Invalid JSON); return; } int newInterval doc[interval_minutes]; if (newInterval 0 newInterval 1440) { // 合理范围1分钟到24小时 presetIntervalMinutes newInterval; } doc.clear(); doc[success] true; doc[new_interval] presetIntervalMinutes; String response; serializeJson(doc, response); server.send(200, application/json, response); }5.4 墨水屏显示驱动墨水屏刷新较慢应尽量减少全屏刷新次数仅在内容变化时更新。void updateDisplay() { display.setFullWindow(); display.firstPage(); do { display.fillScreen(GxEPD_WHITE); display.setCursor(10, 20); // 显示标题 display.println(Feeding Timer); // 显示上次喂奶时间 display.print(Last: ); if (lastFeedTime 0) { display.println(Never); } else { unsigned long secondsPassed (millis() - lastFeedTime) / 1000; int hours secondsPassed / 3600; int minutes (secondsPassed % 3600) / 60; display.printf(%02d:%02d ago, hours, minutes); } // 显示计时器状态和预设间隔 display.print(Timer: ); display.println(timerActive ? ON : OFF); display.printf(Alert %d min, presetIntervalMinutes); // 显示网络IP可选 display.setCursor(10, display.height() - 10); display.print(WiFi.localIP().toString()); } while (display.nextPage()); // display.hibernate(); // 让屏幕进入深度休眠以省电 } void displayFullScreenMessage(String msg) { display.setFullWindow(); display.firstPage(); do { display.fillScreen(GxEPD_WHITE); display.setCursor(10, 30); display.println(msg); } while (display.nextPage()); }5.5 定时提醒检查在loop()中调用的检查函数用于判断是否到达提醒时间。void checkTimerAlert() { if (!timerActive || lastFeedTime 0) { return; } unsigned long currentTime millis(); unsigned long alertIntervalMs presetIntervalMinutes * 60 * 1000UL; // 注意millis() 大约50天会溢出对于喂奶计时器可忽略或加入溢出处理逻辑 if ((currentTime - lastFeedTime) alertIntervalMs) { // 触发提醒可以闪烁屏幕、控制GPIO连接蜂鸣器等 // 例如triggerVisualAlert(); // 同时可以通过HTTP请求通知Home Assistant进而触发米家设备 // notifyHomeAssistant(“feeding_alert”); Serial.println(ALERT: Time to feed!); // 为防止持续触发可以在这里重置 lastFeedTime 或设置一个提醒已发送标志 } }将以上代码模块整合编译并上传到 ESP32。上传成功后打开串口监视器你将看到 ESP32 获取到的 IP 地址。6. Home Assistant 配置与集成现在ESP32 已经是一个提供 REST API 的 Web 服务器了。下一步是让 Home Assistant 认识它并通过它间接接入米家。6.1 在 Home Assistant 中添加 RESTful 传感器和开关编辑 Home Assistant 的configuration.yaml文件添加以下配置。请将[ESP32_IP]替换为你的 ESP32 的实际 IP 地址。# 示例 configuration.yaml 片段 rest: - scan_interval: 30 # 每30秒更新一次状态 resource: http://[ESP32_IP]/status sensor: - name: Feeding Timer Last Feed unique_id: feeding_timer_last_feed value_template: {{ value_json.last_feed_time }} device_class: timestamp - name: Feeding Timer Uptime unique_id: feeding_timer_uptime value_template: {{ value_json.current_uptime }} unit_of_measurement: ms binary_sensor: - name: Feeding Timer Active unique_id: feeding_timer_active value_template: {{ value_json.timer_active }} device_class: running switch: - platform: rest name: Feeding Timer Toggle unique_id: feeding_timer_switch resource: http://[ESP32_IP]/timer body_on: {active: true} body_off: {active: false} is_on_template: {{ value_json.timer_active }} headers: Content-Type: application/json - platform: rest name: Record Feeding unique_id: record_feeding_button resource: http://[ESP32_IP]/feed body_on: {} # POST请求体可以为空或包含必要参数 headers: Content-Type: application/json配置说明rest传感器用于从/status端点获取只读数据如上次喂奶时间、设备运行时间、计时器开关状态。rest开关用于向/timer和/feed端点发送 POST 请求从而控制设备。record_feeding_button被配置为一个瞬间开关按钮按下即发送请求记录喂奶。保存configuration.yaml后重启 Home Assistant。在实体注册表里你应该能看到新添加的传感器和开关。6.2 创建 Lovelace 仪表板卡片为了让控制更直观可以在 Home Assistant 的前端创建一个 Lovelace 面板。进入 Home Assistant 前端点击右上角“...” - “编辑仪表板”。添加卡片选择“网格”或“垂直堆叠”布局。添加以下类型的卡片实体卡片显示sensor.feeding_timer_last_feed和binary_sensor.feeding_timer_active。按钮卡片调用switch.record_feeding_button服务。开关卡片控制switch.feeding_timer_toggle。历史图表卡片展示sensor.feeding_timer_last_feed的变化历史。现在你已经可以在 Home Assistant 的界面上查看喂奶计时器的状态并进行控制了。6.3 通过 Home Assistant 接入米家这是实现“接入米家”的关键一步。Home Assistant 强大的“Xiaomi Miot Auto”或“MIoT”集成可以将 Home Assistant 中的实体entity暴露给米家 App。安装集成在 Home Assistant 的“集成”页面搜索并安装Xiaomi Miot Auto集成。按照指引登录你的小米账号。添加设备在集成配置页面选择“添加设备”或“配置”集成会自动发现局域网内的米家设备。但我们的 ESP32 设备不在这个列表中。虚拟设备映射Xiaomi Miot Auto集成通常用于接入真实的米家设备。要将我们的虚拟设备接入米家需要用到Home Assistant Cloud如 Nabu Casa 云服务或第三方桥接工具如homebridge或homeassistant-miio的某些高级用法。这些服务/工具可以将 Home Assistant 的任意实体模拟成米家平台能识别的设备如开关、传感器。更直接的替代方案如果你只是想通过语音或米家 App 触发一个更简单的方法是在 Home Assistant 中创建一个自动化Automation或脚本Script其触发条件可以是“当sensor.feeding_timer_last_feed超过 X 小时”。然后在米家 App 中如果你有小米小爱音箱或支持米家场景的智能设备可以通过小爱同学的“语音技能”或米家场景的“手动执行”来调用这个 Home Assistant 的自动化这需要 Home Assistant 已正确配置外部访问并且与小爱技能或米家场景通过 IFTTT 或类似方式联动。这种方法略显迂回但避免了复杂的虚拟设备映射。简化建议对于大多数 DIY 项目在 Home Assistant 内完成所有控制和自动化已经足够强大。将状态“接入米家”更多是为了统一入口。如果米家接入不是硬性需求完全可以止步于 Home Assistant。如果你必须实现研究Xiaomi Miot Auto集成的“虚拟设备”功能或使用云桥接服务是方向。7. 功能测试与效果验证部署完成后我们需要系统地测试每个环节是否正常工作。7.1 ESP32 基础功能测试上电与联网给 ESP32 上电观察串口监视器。应能看到连接 Wi-Fi 成功并打印出 IP 地址。墨水屏应显示 “Booting…” 后变为 IP 地址和初始计时界面。HTTP API 测试在电脑浏览器或使用curl命令测试 API。获取状态curl http://[ESP32_IP]/status应返回 JSON 格式的状态信息。记录喂奶curl -X POST http://[ESP32_IP]/feed -H “Content-Type: application/json” -d “{}”执行后墨水屏显示的上次喂奶时间应立即更新并且 API 返回成功信息。控制计时器开关curl -X POST http://[ESP32_IP]/timer -H “Content-Type: application/json” -d “{\“active\”: false}”屏幕上的 “Timer: ON/OFF” 状态应随之改变。7.2 Home Assistant 集成测试实体状态同步重启 Home Assistant 后在“开发者工具” - “状态”页面搜索feeding应能看到相关的传感器和开关实体。它们的状态应与 ESP32 的实际状态一致。前端控制在 Lovelace 仪表板上点击“Record Feeding”按钮。观察 ESP32 的串口输出是否收到 POST 请求以及墨水屏是否更新。操作“Feeding Timer Toggle”开关观察计时器状态的同步情况。自动化测试在 Home Assistant 中创建一个简单的自动化进行测试。alias: “Test Feeding Alert” trigger: platform: state entity_id: sensor.feeding_timer_last_feed action: - service: notify.persistent_notification data: message: “Feeding timer state changed!”当你在 ESP32 上记录一次喂奶通过 API 或按钮这个自动化应该触发在 Home Assistant 中产生一条通知。7.3 系统联动与稳定性测试长时间运行让设备连续运行 24 小时观察 Wi-Fi 是否稳定连接HTTP 服务是否持续可用墨水屏显示是否正常无残影或异常。断电恢复拔掉 ESP32 电源再重新上电检查它是否能自动连接 Wi-Fi恢复之前的计时状态如果实现了 EEPROM 存储。网络压力测试同时从多个客户端如手机浏览器、curl脚本快速调用/status接口观察 ESP32 的响应是否正常有无崩溃或重启。8. 资源占用与性能观察作为一个物联网设备资源占用是需要关注的点。ESP32 内存与闪存本项目代码量不大使用 ArduinoJson 和 GxEPD2 库后编译后的固件通常仍在 ESP32 的 4MB 闪存容量内。运行时内存RAM也足够但需注意在 HTTP 请求处理中避免创建过大的 JSON 文档或字符串以免造成堆碎片或内存不足。网络负载HTTP 请求非常轻量/status的响应包通常小于 200 字节。即使 Home Assistant 每 30 秒轮询一次对路由器和 ESP32 造成的网络压力也微乎其微。墨水屏功耗这是本项目的最大优势。墨水屏仅在刷新时消耗电能约几十到一百毫安静态显示时功耗几乎为零。ESP32 在连接 Wi-Fi 并运行 HTTP 服务器时有持续的功耗约 70-100mA。如果对功耗有极致要求可以考虑让 ESP32 在空闲时进入轻睡眠模式并通过定时器或外部中断唤醒但这会使得 HTTP 服务器无法随时响应需要调整 Home Assistant 的轮询方式。Home Assistant 负载增加几个 RESTful 传感器和开关对 Home Assistant 服务器的 CPU 和内存占用影响极小。9. 常见问题与排查方法在制作和调试过程中你可能会遇到以下问题问题现象可能原因排查方式解决方案ESP32 无法连接 Wi-FiSSID/密码错误路由器仅支持 5GHz信号太弱。检查串口输出的连接状态用手机确认 2.4GHz 网络可用。确认代码中的 SSID/密码将路由器 2.4GHz 和 5GHz 网络分开调整 ESP32 位置或添加天线。串口显示 IP 但无法访问网页防火墙阻止IP 地址错误ESP32 的 HTTP 服务器未启动。在电脑上ping [ESP32_IP]检查串口是否有“HTTP server started”日志。关闭电脑防火墙临时测试确认代码中server.begin()已执行重启 ESP32。墨水屏白屏或乱码引脚连接错误驱动库型号不匹配供电不足。逐一检查 DIN, CLK, CS, DC, RST, BUSY 引脚连接确认GxEPD2_后的型号与屏幕一致。使用万用表检查 3.3V 和 GND 电压在GxEPD2_Example示例程序中测试你的屏幕为墨水屏单独供电。Home Assistant 无法添加 REST 传感器YAML 语法错误ESP32 IP 地址不可达rest:配置缩进错误。检查 Home Assistant 日志文件 (home-assistant.log)在 HA 服务器上用curl测试 ESP32 的/status接口。使用 YAML 语法检查器确保 HA 服务器和 ESP32 在同一子网检查configuration.yaml缩进必须是 2 个空格。Home Assistant 实体状态为unavailableESP32 断电或离线轮询间隔内请求失败。检查 ESP32 是否在线在“开发者工具”-“服务”中调用homeassistant.update_entity手动更新实体。检查 ESP32 电源和网络在rest:配置中增加timeout和retry参数。墨水屏刷新慢且有残影这是电子墨水屏的物理特性。正常现象。避免频繁全屏刷新使用display.hibernate()在空闲时让屏幕控制器断电考虑使用局部刷新功能如果驱动库和屏幕支持。millis()溢出导致计时错误millis()约 50 天后会归零。对于喂奶计时器最长间隔几天可忽略。若需长期运行需处理溢出。使用unsigned long差值计算时间间隔并正确处理currentTime - lastFeedTime在溢出情况下的计算使用(currentTime - lastFeedTime) 0xFFFFFFFF或使用elapsedMillis库。10. 优化与扩展思路基础功能跑通后你可以考虑以下优化和扩展让这个喂奶计时器更加强大和易用。WiFiManager 网页配网替代代码中硬编码的 Wi-Fi 密码首次启动时 ESP32 会创建一个 AP用手机连接后弹出网页即可配置网络更安全方便。EEPROM 存储状态将lastFeedTime、timerActive等状态保存到 ESP32 的 EEPROM 或 SPIFFS 文件系统中实现断电记忆。添加物理按钮在 ESP32 上连接一个实体按钮用于本地手动记录喂奶而不必依赖手机。蜂鸣器或 LED 提醒当计时器触发提醒时除了屏幕变化还可以让 ESP32 控制一个蜂鸣器发声或 LED 闪烁提供更强烈的本地提醒。多计时器管理扩展固件和 API支持记录左/右乳房喂奶时间、换尿布时间等多重事件。OTA 远程升级实现通过网页上传新固件进行升级无需再连接 USB 线。美化显示界面利用GxEPD2库的绘图功能设计更美观的图标、进度条或中文字体显示。深度睡眠与定时唤醒如果使用电池供电可以让 ESP32 大部分时间处于深度睡眠每隔几分钟唤醒一次连接 Wi-Fi 上报状态并更新屏幕以极大延长续航。这个项目麻雀虽小五脏俱全。它串联了嵌入式开发ESP32、外设驱动墨水屏、网络通信HTTP Server、家庭自动化Home Assistant和生态集成米家等多个物联网关键技术点。无论你是想做一个实用的家庭工具还是作为一个学习项目来深入理解物联网架构它都具有很高的实践价值。建议你将代码和配置分版本管理每完成一个功能点就进行测试稳扎稳打地构建属于你自己的智能喂奶计时器。