1. 项目概述:为什么选择STM32开发智能水杯?
去年冬天,我在办公室连续工作三小时没喝水,直到嘴唇干裂才意识到问题——这种场景相信很多程序员都经历过。为了解决这个痛点,我决定用STM32开发一款能定时提醒喝水、自动保温的智能水杯。相比市面动辄几百元的同类产品,自制成本不到100元,还能根据个人需求深度定制。
选择STM32F103C8T6作为主控主要基于三点考量:首先,它的72MHz主频足够处理温度采集、PID控制和用户交互;其次,内置RTC(实时时钟)模块完美支持定时提醒功能;最重要的是,其Stop Mode休眠模式下功耗仅20μA,搭配1000mAh锂电池可续航两周以上。这个芯片的性价比在智能硬件圈有口皆碑,堪称"国民MCU"。
2. 硬件设计:从元器件选型到防水处理
2.1 核心器件选型指南
温度传感器我对比了三种方案:DS18B20(数字输出)、NTC热敏电阻(模拟量)、红外测温模块。最终选择DS18B20是因为:
- 单总线协议仅需1个GPIO引脚
- ±0.5℃的精度完全满足饮水需求
- 自带防水不锈钢外壳(型号:DS18B20防水款)
显示模块选用0.96寸OLED而非LCD,原因很实际:
- 功耗对比:OLED全亮约20mA,LCD背光需60mA+
- 可视角度:OLED近乎180°,LCD存在视角限制
- 安装体积:OLED模组厚度仅1.3mm
震动马达推荐使用1020空心杯电机(直径10mm),比普通蜂鸣器更隐蔽。实测在办公场景下,震动提醒的感知度是声音提醒的3倍以上。
2.2 供电系统设计要点
采用18650锂电池(3.7V 2000mAh)配合TP4056充电模块的方案时,要注意:
- 必须加装DW01A保护芯片,防止过充/过放
- 升压到5V给STM32供电时,选用ETA1062这类同步整流芯片,效率可达92%
- 加热片供电需单独走线,线径不小于0.5mm²
警告:切勿将锂电池直接焊接到电路板!必须使用带保护板的电池或外接保护电路,我曾因这个失误烧毁过两块TP4056。
2.3 结构设计与防水处理
杯体结构需要分层设计:
- 上层:3D打印的杯盖(建议用PETG材料)
- 中层:防水电路仓(灌封胶处理)
- 下层:不锈钢杯体+加热片
防水关键点:
- 传感器探针处使用食品级硅胶密封圈
- 按键选用IP67等级薄膜开关
- 所有接缝处涂覆704硅橡胶
实测这个方案可以达到IPX5防水等级,即使水杯倾倒也不会损坏电路。
3. 软件实现:从温度采集到智能提醒
3.1 温度采集的实战技巧
DS18B20的驱动代码看似简单,但有三个易错点:
- 时序要求严格,必须禁用中断 during 复位脉冲
- 每次读取前要检查CRC校验
- 多设备挂载时需要ROM匹配
改进后的温度读取函数应包含错误处理:
c复制#define DS18B20_MAX_RETRY 3
float DS18B20_GetTemp() {
uint8_t retry = 0;
while(retry++ < DS18B20_MAX_RETRY) {
if(DS18B20_Start() == DS18B20_OK) {
DS18B20_WriteByte(0xCC); // Skip ROM
DS18B20_WriteByte(0xBE); // Read Scratchpad
uint8_t crc = 0;
uint8_t data[9];
for(int i=0; i<9; i++) {
data[i] = DS18B20_ReadByte();
crc = DS18B20_CRC8(crc, data[i]);
}
if(crc == 0) {
int16_t temp = (data[1]<<8) | data[0];
return temp * 0.0625f;
}
}
HAL_Delay(10);
}
return -999; // 错误值
}
3.2 PID温度控制算法调参
加热控制采用增量式PID算法,参数整定步骤:
- 先设Ki=Kd=0,增大Kp直到出现等幅振荡
- 记录振荡周期Tu,按Ziegler-Nichols公式:
- Kp = 0.6*Ku
- Ki = 2*Kp/Tu
- Kd = Kp*Tu/8
- 微调时重点关注积分项,防止"积分饱和"
实际代码实现:
c复制typedef struct {
float Kp, Ki, Kd;
float err, last_err, integral;
} PID_Controller;
float PID_Update(PID_Controller* pid, float setpoint, float measured) {
pid->err = setpoint - measured;
pid->integral += pid->err;
float derivative = pid->err - pid->last_err;
pid->last_err = pid->err;
float output = pid->Kp * pid->err
+ pid->Ki * pid->integral
+ pid->Kd * derivative;
// 抗积分饱和
if(output > PWM_MAX) {
pid->integral -= pid->err;
output = PWM_MAX;
}
return output;
}
3.3 低功耗设计实战
实现7天待机的关键技巧:
- 配置RTC唤醒中断(1Hz时钟)
- 外设电源分级管理:
c复制void Enter_StopMode() { HAL_GPIO_WritePin(PWR_OLED_GPIO_Port, PWR_OLED_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(PWR_Heater_GPIO_Port, PWR_Heater_Pin, GPIO_PIN_RESET); HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重新初始化时钟 } - 唤醒源配置:
- RTC闹钟(定时检测)
- 按键外部中断
- 加速度传感器中断(检测拿起动作)
实测电流:
- 运行模式:12mA(OLED关闭)
- Stop Mode:22μA
- 加热状态:800mA(5W加热片)
4. 进阶功能扩展与问题排查
4.1 蓝牙APP连接方案
使用HC-05模块时,推荐以下配置:
- 修改AT指令:
bash复制
AT+NAME=SmartCup AT+PSWD=1234 AT+UART=115200,1,0 - Android端开发要点:
- 使用BluetoothGATT API
- 数据协议建议用JSON格式:
json复制{ "temp": 45.2, "remind_interval": 30, "battery": 78 }
4.2 常见问题排查手册
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 温度读数跳动大 | 电源干扰 | 在DS18B20的VDD与GND间加0.1μF电容 |
| 加热片不工作 | MOSFET驱动不足 | 改用逻辑电平MOSFET(如IRLZ44N) |
| 蓝牙连接不稳定 | 天线被金属屏蔽 | 将模块天线部分伸出杯盖 |
| 按键失灵 | 防水处理导致 | 改用硅胶按键或电容感应 |
4.3 扩展功能建议
- 水质检测:加装TDS传感器,注意:
- 探头需定期校准
- 测量时需关闭加热功能
- 饮水统计:基于重量传感器(HX711模块)
- 智能联动:通过ESP8266接入物联网平台
5. 成品优化与使用心得
经过三个版本迭代,总结出以下经验:
- 杯盖开孔位置:显示屏应偏离中心2cm,避免喝水时遮挡视线
- 加热片功率选择:300ml以下杯子用5W,500ml以上建议8W
- 震动提醒时长:1.5秒最佳,过短易忽略,过长耗电
最让我惊喜的是加入"拿起检测"功能后,系统能智能判断用户是否准备喝水。这通过MPU6050加速度计实现,当检测到特定动作模式时,自动点亮OLED显示当前水温。