💡 划重点

  • 基于 ESP32‑C3 的低成本硬件方案,整体物料成本控制在 50 元以内。
  • 四个物理按键对应四种药品/服药时段,按下即打卡。
  • 0.96 寸 OLED 屏即时显示本次打卡状态与最近记录。
  • 通过 Wi‑Fi 自动将打卡时间与药品信息发送至飞书群通知家人。
  • 结构简单、操作友好,专为独居长辈设计,零学习成本。

需求洞察

独居老人和慢性病患者每天需要按时服用多种药品,漏服、错服是常见问题。子女或监护人不可能 24 小时在身边,电话提醒往往被打断或忘记,而普通药盒仅能物理分装,无法记录实际服用情况。一旦发生漏服,家人只能事后被动知晓,往往等到身体出现不适才被发现,延误干预。

本方案将“打卡”这一日常概念引入服药管理:老人在正确时间按下对应药品的按钮,设备立刻给予屏显和灯光反馈,同时将打卡记录作为一条消息推送到子女手机上的飞书群。这样既不需要老人学习智能手机,也不依赖复杂的健康 App,只需按一下按钮就能让家人安心。相比市面上动辄几百元的智能药盒,这套自制的方案成本可以控制在 50 元以内,非常适合动手能力较强的子女为父母亲手制作,兼顾情感陪伴与实际效用。

方案设计

系统按照感知层、控制层、执行层、日志与联网层四层结构设计。

感知层

使用 4 个独立微动按键,每个按键对应一种药品或一个服药时段(早、中、晚、睡),按键一端接 GPIO,一端接地,利用芯片内部上拉电阻,平时读为高电平,按下为低电平。

控制层

ESP32‑C3 作为主控,负责周期性扫描按键状态、进行 20 ms 软件消抖,记录每个按键的按下事件和系统时间。同时驱动 OLED 和 LED,并通过 Wi‑Fi 发送打卡数据。

执行层

一块 0.96 寸 I2C OLED(128×64)显示最近 4 次打卡记录(药品编号+时间),采用大字体,方便老年人辨认。一颗高亮 LED 在按键按下时短暂点亮,作为即时视觉反馈,确认打卡成功。

日志与联网层

ESP32‑C3 通过家庭 Wi‑Fi 连接互联网,每次有效打卡后,将药品编号、时间戳封装成 JSON,通过 HTTP POST 发送至预设的飞书机器人 Webhook 地址。飞书群内立即显示如“妈妈已服用降压药,时间 08:05”。同时主控内部保留一份打卡计数,连接 OLED 显示,方便老人查看当天已服次数。

物料清单

序号 物料名称 数量 用途 估算单价(元) 小计(元)
1 ESP32‑C3 开发板(合宙或安信可) 1 主控与 Wi‑Fi 19.00 19.00
2 0.96 寸 OLED 模块(I2C,SSD1306) 1 状态显示 12.00 12.00
3 6×6mm 微动按键 4 药品打卡输入 0.50 2.00
4 5 mm LED(红色) 1 打卡反馈指示 0.20 0.20
5 220 Ω 电阻 1 LED 限流 0.10 0.10
6 杜邦线 + 焊接排针 若干 连接导线 3.00 3.00
7 定制亚克力外壳或 3D 打印壳 1 成品外壳 10.00 10.00
8 热缩管、双面胶、螺丝 1 批 固定与绝缘 2.00 2.00
合计 48.30

总成本约 48 元,满足 50 元预算要求。按键、LED 和 OLED 均可使用开发板自带的 3.3 V 供电,无需额外电源模块。

接线与结构

为避免影响 ESP32‑C3 的正常启动和串口输出,对接线做了微调:

结构上,所有元件安装在一个长方形小盒中,顶部开 4 个按键孔并标注药品名称或时间,正面留出 OLED 窗口,侧面开孔露出 LED。内部使用杜邦线连接,再用热熔胶固定,避免松动。盒子底部贴防滑垫,放置在床头或餐桌等固定位置。

核心代码

以下给出基于 Arduino 框架(PlatformIO/Arduino IDE)的可运行骨架,使用 U8g2 库驱动 OLED,HTTPClient 发送飞书通知。


#include <WiFi.h>
#include <HTTPClient.h>
#include <U8g2lib.h>

// 用户配置
const char* ssid = "your_SSID";
const char* password = "your_PWD";
const char* feishu_webhook = "https://open.feishu.cn/..."; // 替换为实际链接

// 引脚定义
const uint8_t btn_pins[4] = {2, 3, 4, 5};
const uint8_t led_pin = 10;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* SCL=*/ 9, /* SDA=*/ 8);

unsigned long last_debounce_time[4] = {0};
bool last_btn_state[4] = {HIGH};
const unsigned long debounce_delay = 50;
int dose_count[4] = {0};

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
  }
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
  
  u8g2.begin();
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { delay(500); }
  show_status("已连接");
}

void loop() {
  for (int i = 0; i < 4; i++) {
    bool reading = digitalRead(btn_pins[i]);
    if (reading != last_btn_state[i]) {
      last_debounce_time[i] = millis();
    }
    if ((millis() - last_debounce_time[i]) > debounce_delay) {
      if (reading == LOW) {  // 按下有效
        dose_count[i]++;
        digitalWrite(led_pin, HIGH);
        delay(200);
        digitalWrite(led_pin, LOW);
        
        String msg = "药品" + String(i+1) + "已服用 " + getTimeStr();
        show_status(msg.c_str());
        send_feishu(msg);
        
        while(digitalRead(btn_pins[i]) == LOW) delay(10); // 等待释放
      }
    }
    last_btn_state[i] = reading;
  }
  delay(10);
}

void show_status(const char* text) {
  u8g2.clearBuffer();
  u8g2.setCursor(0, 15);
  u8g2.print(text);
  u8g2.sendBuffer();
}

void send_feishu(String message) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(feishu_webhook);
    http.addHeader("Content-Type", "application/json");
    String payload = "{\"msg_type\":\"text\",\"content\":{\"text\":\"" + message + "\"}}";
    int httpCode = http.POST(payload);
    http.end();
  }
}

String getTimeStr() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo;)) return "时间获取失败";
  char buf[20];
  strftime(buf, sizeof(buf), "%H:%M", &timeinfo;);
  return String(buf);
}

代码要点:按键使用内部上拉,下降沿消抖;每次按键触发 LED 闪烁、OLED 更新并调用飞书 Webhook;时间通过 NTP 自动同步(需在 setup 中添加 configTime,本骨架省略,实际需补全)。

调试步骤

  1. 硬件连接检查:用万用表确认所有按键在未按下时 GPIO 电压为 3.3 V,按下后为 0 V;LED 极性正确。
  2. 单独点亮 LED:编写简单脚本让 GPIO10 输出高电平,确认 LED 能亮。
  3. 扫描按键:在串口监视器打印每个按键的状态,确认按下时读到 0,松开为 1,且消抖后无重复触发。
  4. OLED 测试:运行 U8g2 示例程序,确保地址 0x3C 可识别,显示正常。
  5. Wi‑Fi 与飞书联调:先通过串口查看 Wi‑Fi 连接状态,成功后再测试飞书 Webhook 发送固定文本,确认群内收到消息。
  6. 联机测试:将以上功能整合,按下任一按钮,观察 OLED 刷新、LED 闪烁、飞书消息是否同步到达。
  7. 装入外壳后再次测试按键手感与位置,确保老人也能轻松按下。

设计图

药品服用打卡按钮盒结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报