欢迎光临
我们一直在努力

每天喝不够八杯水?30元DIY一个智能水杯垫,再也不忘喝水

💡 阅读提示:本文记录我用压力传感器和ESP8266,给普通水杯加装“智能饮水提醒”功能的完整过程。成本不到30元,一周后每天喝水量从800ml提升到2000ml,真实体验,不吹不黑。

🚨 开篇:那个因为喝水太少进急诊的下午

去年夏天,我在公司连续开了四个小时的会,一口水没喝。散会后站起来,眼前一黑,差点摔倒。同事扶我去医院,医生说:“轻度脱水,血压偏低,回去多喝水。”

“多喝水”三个字听起来像废话,但我是真的记不住。

忙起来的时候,水杯就在手边,但就是想不起来端起来喝一口。一天下来,早上倒的一杯水,下班时还是满的。

我也试过各种办法:手机设闹钟(响了就关,关了就忘)、买了个带时间刻度的水杯(前两格喝完了,后面就没动静了)、甚至贴了便利贴在显示器上(贴了三天就视而不见了)。

一个周末,我看着桌上一块落灰的压力传感器(HX711+称重传感器) ,冒出一个念头:能不能让水杯自己提醒我喝水?

于是有了这个小项目——一个放在水杯底下的“智能杯垫”,实时监测杯子重量变化,算出你已经喝了多少水,定时提醒“该喝水了”,如果杯子空了还会喊你“去接水”。

成本多少?不到30块。

一、我要解决什么?

先把需求想清楚,不做大而全,只解决核心问题。

痛点功能需求怎么实现
忘了喝水 每隔40分钟提醒一次 蜂鸣器/微信推送
不知道自己喝了多少 显示今日累计饮水量 OLED屏幕实时显示
杯子空了不知道 提示“该接水了” 重量低于阈值(空杯)时提醒
想回顾今天的喝水情况 数据记录 本地存储(可选)

一句话目标:把水杯变成一个“会说话的私人饮水教练”。

二、硬件准备(全用库存,成本为0)

我尽量用手里现有的东西。重新买的话也很便宜:

组件来源价格
ESP8266 NodeMCU 吃灰库存 0元
HX711 + 称重传感器(5kg量程) 之前做厨房秤剩下的 0元
0.96寸OLED(I2C) 吃灰 0元
蜂鸣器 库存 0元
杜邦线若干 库存 0元
薄木板/硬纸板(做杯垫外壳) 废料 0元
Micro USB线+充电头 旧手机充电器 0元

如果你什么都没:ESP8266约15元,HX711+传感器套装约12元,OLED屏约10元,蜂鸣器约1元,总计约38元。如果用ESP-01S(更便宜的模块)替代NodeMCU,还能再省几块钱。

三、工作原理

压力传感器放在杯垫下方,水杯放在压力传感器上。

  • 空杯时:传感器输出一个“基准值”

  • 倒水后:重量增加,传感器数值上升

  • 喝水后:重量减少,传感器数值下降

累计饮水量的计算逻辑:

  • 程序每秒读取一次重量

  • 记录每次“重量突然下降”的差值(差值就是喝掉的量)

  • 累加所有差值 = 今日总饮水量

  • 如果某次差值超过500g,判定为“倒水/换杯”,不计入饮水量

  • 提醒逻辑:

    • 距离上次喝水超过40分钟 → 蜂鸣器短响,OLED显示“该喝水了!”

    • 杯子重量低于“空杯基准值+50g”持续5分钟 → 显示“杯子空了,去接水!”

    四、制作过程

    4.1 传感器安装

    压力传感器很薄,像一片不锈钢片,有四根线(红黑绿白)。接在HX711模块上,HX711再通过I2C接ESP8266。

    接线:

    称重传感器HX711
    E+
    E-
    绿 A+
    A-
    HX711ESP8266
    VCC 3.3V
    GND GND
    DT D1 (GPIO5)
    SCK D2 (GPIO4)
    OLEDESP8266
    VCC 3.3V
    GND GND
    SDA D3 (GPIO0)
    SCL D4 (GPIO2)
    蜂鸣器ESP8266
    正极 D5 (GPIO14)
    负极 GND

    4.2 外壳制作(最丑但最实用)

    我用一块薄木板(装修剩下的地板边角料)做底座,上面垫了一块鼠标垫防滑。称重传感器夹在木板和鼠标垫中间。

    如果你没有木板:硬纸板叠三层也行,只要能承受水杯重量不变形。

    4.3 固件开发

    #include <ESP8266WiFi.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include <HX711.h>

    // 引脚定义
    #define DOUT_PIN 5 // D1
    #define SCK_PIN 4 // D2
    #define BUZZER_PIN 14 // D5

    HX711 scale;
    Adafruit_SSD1306 display(128, 64, &Wire, -1);

    // 参数配置
    float EMPTY_WEIGHT = 0.0; // 空杯基准重量(需校准)
    float TOTAL_DRUNK = 0.0; // 今日累计饮水量(ml)
    float LAST_WEIGHT = 0.0; // 上一次称重值
    unsigned long LAST_DRINK_TIME = 0;
    unsigned long LAST_EMPTY_TIME = 0;

    void setup() {
    Serial.begin(115200);

    // 初始化HX711
    scale.begin(DOUT_PIN, SCK_PIN);
    scale.set_scale(420.0); // 校准系数,需实际标定
    scale.tare(); // 去皮

    // 初始化OLED
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);

    // 蜂鸣器
    pinMode(BUZZER_PIN, OUTPUT);

    // 校准空杯重量
    delay(2000);
    EMPTY_WEIGHT = scale.get_units(10);
    LAST_WEIGHT = EMPTY_WEIGHT;
    LAST_DRINK_TIME = millis();

    displayMessage("Smart Cup", "Ready");
    }

    void loop() {
    float currentWeight = scale.get_units(5);

    // 1. 检测是否喝了水(重量突然下降)
    if (currentWeight > 50 && LAST_WEIGHT – currentWeight > 30) {
    float drinkAmount = LAST_WEIGHT – currentWeight;
    // 过滤掉“倒水”(一次性变化大于500ml不算喝水)
    if (drinkAmount < 500) {
    TOTAL_DRUNK += drinkAmount;
    LAST_DRINK_TIME = millis();
    Serial.printf("Drank: %.1f ml, Total: %.1f ml\\n", drinkAmount, TOTAL_DRUNK);
    beep(200, 1); // 喝一口响一声
    }
    }

    // 2. 检测杯子是否空了(低于基准值+50g持续超过5分钟)
    if (currentWeight < EMPTY_WEIGHT + 50) {
    if (millis() – LAST_EMPTY_TIME > 300000) { // 5分钟
    displayMessage("杯子空了", "去接水吧!");
    beep(500, 3); // 急促响三声
    LAST_EMPTY_TIME = millis();
    }
    } else {
    LAST_EMPTY_TIME = millis(); // 重置计时器
    }

    // 3. 喝水提醒(超过40分钟没喝)
    if (millis() – LAST_DRINK_TIME > 2400000) { // 40分钟
    displayMessage("该喝水了!", "已喝 " + String(TOTAL_DRUNK, 0) + "ml");
    beep(300, 2);
    LAST_DRINK_TIME = millis(); // 重置,避免一直响
    }

    // 4. 更新OLED显示
    updateDisplay(currentWeight);

    LAST_WEIGHT = currentWeight;
    delay(500);
    }

    void updateDisplay(float weight) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("今日饮水");
    display.setCursor(0, 20);
    display.setTextSize(2);
    display.print(TOTAL_DRUNK, 0);
    display.println(" ml");
    display.setTextSize(1);
    display.setCursor(0, 50);
    display.print("杯重: ");
    display.print(weight – EMPTY_WEIGHT, 0);
    display.println("g");
    display.display();
    }

    void beep(int duration, int times) {
    for (int i = 0; i < times; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(duration);
    digitalWrite(BUZZER_PIN, LOW);
    delay(100);
    }
    }

    void displayMessage(String line1, String line2) {
    display.clearDisplay();
    display.setCursor(0, 10);
    display.setTextSize(2);
    display.println(line1);
    display.setCursor(0, 40);
    display.setTextSize(1);
    display.println(line2);
    display.display();
    }

    4.4 校准

    第一次使用时,先放上空杯,系统自动校准基准重量。然后用厨房秤称出水的重量,对比系统显示的“喝水量”是否一致。如果偏差大,调整代码中的scale.set_scale(420.0)这个系数(不同传感器的系数不同,用已知重量去标定)。

    五、真实使用效果

    5.1 一周数据

    天数传统方式(估算)智能杯垫实测
    第1天 ~800ml 720ml
    第2天 ~800ml 1050ml
    第3天 ~800ml 1200ml
    第4天 ~800ml 1500ml
    第5天 ~800ml 1350ml
    第6天 ~800ml 1650ml
    第7天 ~800ml 1400ml

    一周后平均每天1500ml,比以前多了近一倍。

    5.2 最有用的功能

    说实话,最管用的不是蜂鸣器(我经常把它当成手机通知忽略了),而是OLED屏幕上那个不断增加的毫升数。

    看到“1050ml”的时候,会想“怎么才喝这么点,再喝一杯”;看到“1650ml”的时候,会想“今天表现不错,再接再厉”。

    数字让人上瘾。 这是这个项目成功的核心——它把“喝水”这个模糊的目标,变成了一个可量化的游戏。

    5.3 同事的反应

    放在工位上第一天,三个同事来问:“这什么玩意儿?”我解释完后,一个同事说:“帮我做一个,我愿意付材料费。”

    三天后,他又来了:“做了吗?我每天喝水量比我体重的含水量还少。”

    后来我帮他也做了一个,收了30块材料费。

    六、可以怎么升级

    升级方向方案成本
    微信推送提醒 接入巴法云/Server酱 免费
    远程查看 接入Blynk/HomeAssistant 免费
    数据持久化 加一个ESP8266本地Web服务器 免费
    更准的称重 换更高精度的HX711 约5元
    不用线(无线) 换ESP-01S + 锂电池+充电模块 约20元
    多杯位监测 扩展多个HX711(需分时复用) 每个约10元

    如果要把数据存下来分析趋势,可以在ESP8266上跑一个简单Web服务器,或者用ESP-NOW把数据发到家里的树莓派/NAS。

    七、问题与解决

    ❌ 问题1:传感器读数跳变

    现象:什么也没动,重量数值上蹿下跳,波动±30g。

    原因:压力传感器本身有噪声,加上桌面的轻微振动。

    解决:代码里已经做了5次平均(scale.get_units(5)),可以增加到10次。另外把杯垫放在桌角等震动小的地方,远离机械硬盘电脑。

    ❌ 问题2:每次放杯位置不同,重量不一样

    现象:杯子放偏一点,读数差几十克。

    原因:传感器只在中心区域最灵敏,放偏了力臂不同。

    解决:在杯垫表面画一个“杯子定位圈”,或者用双面胶粘一个杯垫环,强迫每次放在同一位置。

    ❌ 问题3:提醒被忽略

    现象:蜂鸣器响了几次后,我习惯了,继续不喝。

    解决:把蜂鸣器提醒改成微信推送(用巴法云,免费),或者设定“连续提醒三次后,LED闪烁不停”,直到你喝一口才重置。

    ❌ 问题4:换杯子/倒水被误判为喝水

    现象:换了一个杯子,或者倒掉剩水,系统显示“喝了500ml”。

    解决:已经在代码里设置了“单次变化超过500g判定为倒水/换杯”。如果你的杯子比较重,可以调到800g。

    八、写在最后

    一个30块钱的小装置,解决了我好几年都没改掉的“喝水少”问题。

    说到底,物联网的价值不一定非得是“智能家居”“工业4.0”这种宏大叙事。它也可以是——提醒你该喝水了。

    健康这件事,最大的敌人不是懒惰,是健忘。而技术,刚好可以帮我们对抗健忘。

    现在,放下手机,喝一口水。

    赞(0)
    未经允许不得转载:171主机测评 » 每天喝不够八杯水?30元DIY一个智能水杯垫,再也不忘喝水
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址