我做了一个智能水杯秤,试着让喝水记录真正无感
用 ESP32、称重传感器和稳定段算法,自动识别办公室里的喝水、加水与拿杯动作。
「每天多喝水」是一件所有人都知道,却很难长期坚持的事情。
很多饮水 App 的问题并不在提醒,而在记录:每喝一次水,都要拿起手机、打开 App、选择容量、再点确认。坚持几天后,这套流程很容易被放弃。
所以我想做一个不需要主动操作的喝水记录设备。它看起来只是工位上的一个杯垫,却能感知杯子重量变化,自动判断喝了多少、什么时候加了水,以及一天喝水的频率。
项目的基本想法
核心结构很简单:
水杯
│
承重面板
│
称重传感器
│
HX711
│
ESP32
│
Wi-Fi
│
云端 API / 数据库
ESP32 读取称重数据,通过 Wi-Fi 把有效事件上传到服务端。但真正设计时马上遇到一个问题:
重量下降,并不一定意味着喝水。
用户可能只是碰了一下杯子,也可能端起来又原样放回,甚至把手机、钥匙临时放到杯垫上。如果只看前后重量差,误报会非常多。
因此,这个项目真正的核心不是称重,而是 如何理解重量变化。
不记录每一次波动,只记录稳定状态
称重传感器的数据一直在变。桌面震动、杯中水晃动、传感器漂移,都会带来几克甚至十几克的波动。
所以我没有直接使用瞬时重量,而是先判断「稳定段」。一个稳定值需要满足:
- 连续约 3 秒重量变化处于允许范围
- 剔除明显异常值
- 多次采样后取平均或中位数
- 重量变化小于约 10 克时,不作为饮水事件上传
系统处理的不再是每一条原始数据,而是一串稳定状态:
稳定 520g
稳定 0g
稳定 460g
这三个状态,比一条不断抖动的重量曲线更有意义。
如何识别一次喝水
一次典型的喝水过程:
- 杯子原本放在底座上
- 用户拿起杯子
- 杯垫重量变成 0
- 用户喝水
- 杯子重新放回
- 新重量小于拿起前的重量
因此喝水事件可以表示为:
稳定 A → 稳定 0 → 稳定 B
当 A > B 时:
喝水量 = A - B
例如 520g → 0g → 455g,可判断本次约喝水 65g。水的密度接近 1g/ml,可近似记为 65ml。
更明确的历史条件是:
上一次稳定重量是 0,并且上上次稳定重量大于当前重量,则判断为喝水。
这正是项目中最关键的一条规则。
如何识别加水
加水与喝水相似,只是最终重量变大:
稳定 A → 稳定 0 → 稳定 C
当 C > A 时,加水量 = C - A。例如 180g → 0g → 610g,可理解为拿起后加入了约 430g 水。
系统不需要用户点击「加水」,也不需要知道杯子标称容量,只需要观察一次完整的拿起和放回。
为什么必须经过 0
如果重量从 520g 直接变成 460g,并不能确认发生了喝水——可能是杯子被推到边缘受力异常,也可能是其他物品被拿走。
而经过稳定 0,意味着杯子曾经完整离开承重面板。系统才能把事件理解为:
拿起杯子 → 发生某种行为 → 放回杯子
因此 A → 0 → B 比单纯的 A → B 稳定得多。
每天的统计方式
早期还考虑过更简单的逻辑:每天 0 点新开一轮、累积重量减少量、小于 10g 不上报。实现成本低,但换杯、移动和临时放置物品仍容易干扰。
更稳妥的方案是以事件为核心:
{
"event": "drink",
"before_weight": 520,
"after_weight": 455,
"amount": 65,
"timestamp": "2026-07-20T10:32:14+08:00"
}
服务端再按天聚合:当日总量、次数、平均单次量、最长未饮水时长、时间段分布、加水次数。
ESP32 的配网与运行
设备放在办公室工位上,不能依赖串口配网。希望首次启动时创建临时热点,用户连上后打开网页完成配置:
- ESP32 创建配置热点
- 手机连接热点
- 打开本地配置页
- 选择办公室 Wi-Fi 并输入密码
- 配置设备名称和服务端地址
- 保存并重启
- 页面提示如何开始运行
配网完成后进入普通模式,自动连 Wi-Fi 并向云端上传事件。用 ESP-IDF 开发学习成本更高,但对长期运行、网络管理和状态控制更合适。
云端不需要接收所有原始数据
常见错误是把所有重量采样都上传。称重频率可能每秒数十次,绝大多数没有业务价值。
更合理的方式:
- 原始采样在 ESP32 本地处理
- 本地完成滤波和稳定段识别
- 只有稳定值或饮水事件才上传
- 异常诊断时临时开启原始数据模式
这样既减少网络和存储成本,也能在短暂断网时继续工作——事件先入本地队列,网络恢复后再补传。
结构设计比想象中更重要
为了适合长期摆在工位上,我还计划做一个 3D 打印底座,大致四层:
1. 水杯与承重面板
2. 传感器受力结构
3. HX711、ESP32 与供电
4. 防滑底壳
设计重点包括:杯子放在不同位置仍准确;承重面板不碰底壳;泼洒后不易进水;外壳防滑;传感器不受侧向力;拆装和校准不能太复杂。
外观上,我不想做成普通电子秤,更喜欢类似《健身环大冒险》通关站立台那种轻微仪式感,同时保持简洁。它不是医疗设备,也不是强制管理工具,而是桌面上的轻量反馈装置。
产品真正的价值是什么
表面上在记录喝水量,更有价值的部分是「无感」。用户不必改变原有习惯:
- 仍然用自己的杯子
- 仍然像平时一样拿起放下
- 不需要点按钮
- 不需要每次打开 App
- 不需要买带特殊结构的智能水杯
设备只负责观察重量变化,并把行为转换成记录。这类产品的关键,不是增加更多提醒,而是尽量减少用户需要完成的步骤。
仍然存在的问题
还需要继续处理边界情况:
- 更换杯子
- 杯子没有完全放回中央
- 杯子和其他物品同时放在底座上
- 端起杯子但没有喝水
- 用吸管时杯子始终不离开底座
- 水温变化引起微小重量变化
- 长时间运行后零点漂移
- 桌面震动导致稳定段判断失败
其中吸管场景尤其特殊。如果杯子始终不离开底座,需要另一种模式:在足够长的稳定时间内,检测到持续、缓慢且超过阈值的重量下降。
但第一版我仍更倾向只支持「拿起杯子喝水」——清晰的行为边界,比覆盖所有场景更重要。
写在最后
我喜欢这个项目,是因为它没有试图发明一种新的喝水方式,只是让原本已经发生的行为可以被可靠地记录。
一块称重传感器、一个 HX711 和一块 ESP32 并不复杂。真正需要设计的,是设备如何从一串不稳定的重量数字中,理解用户刚刚做了什么。
当硬件不再要求用户配合,而是安静地适应用户原有习惯时,它才开始真正变得有用。