1. 项目概述
作为一名嵌入式开发工程师,我最近完成了一个基于STM32的智能水壶项目。这个项目源于我自己的日常需求——经常因为工作太投入而忘记烧水,或者烧好水后又忘记倒出来。传统的智能水壶大多只能实现简单的定时和保温功能,而我希望打造一个真正"智能"的水壶系统,能够远程控制、实时监测水温,并且可以自动完成从烧水到倒水的全过程。
这个项目最核心的创新点在于:
- 实现了真正的端到端自动化控制,从加水、烧水到倒水全过程无需人工干预
- 采用FreeRTOS实时操作系统,确保多任务稳定运行
- 通过ESP32 WiFi模块实现了手机远程控制
- 加入了完善的安全机制,包括温度异常保护和干烧保护
2. 硬件系统设计
2.1 核心控制器选型
选择STM32F103ZET6作为主控芯片主要基于以下几点考虑:
- 72MHz主频足够处理多任务需求
- 512KB Flash和64KB RAM满足FreeRTOS运行需求
- 丰富的GPIO和外设接口(5个USART、3个SPI、2个I2C)
- 内置PWM控制器,方便电机控制
- 价格适中,开发资源丰富
提示:STM32F103系列虽然性能不是最强的,但其稳定性和性价比在消费级产品中表现优异。实际开发中,我建议优先考虑F1系列而非更新的F4/F7,除非有特殊性能需求。
2.2 关键外设模块
2.2.1 温度监测模块
采用DS18B20数字温度传感器,其优势在于:
- 单总线接口,节省GPIO资源
- ±0.5℃的测量精度
- 防水封装可直接接触水体
- 独特的64位序列号支持多点组网
实际使用中需要注意:
- 上拉电阻取值4.7kΩ最佳
- 每次温度转换需要约750ms
- 必须严格按照时序图操作
2.2.2 电机驱动模块
选用L298N驱动直流电机,主要参数:
- 驱动电压:5-35V
- 单路最大电流:2A
- 内置续流二极管
- 支持PWM调速
接线示意图:
code复制STM32 PWM引脚 -> L298N ENA
STM32 GPIO1 -> L298N IN1
STM32 GPIO2 -> L298N IN2
电机两端 -> L298N OUT1/OUT2
2.2.3 WiFi通信模块
ESP32-WROOM-32D模组特点:
- 双核240MHz主频
- 内置WiFi和蓝牙
- 丰富的外设接口
- 支持MicroPython开发
与STM32通过UART连接,波特率设置为115200bps。
3. 软件系统架构
3.1 FreeRTOS任务划分
系统共创建4个主要任务:
| 任务名称 | 优先级 | 功能描述 | 堆栈大小 |
|---|---|---|---|
| TempMonitor | 3 | 温度监测与控制 | 256字节 |
| MotorCtrl | 2 | 电机驱动控制 | 192字节 |
| WiFiComm | 4 | 网络通信处理 | 512字节 |
| IRRemote | 1 | 红外遥控处理 | 128字节 |
任务调度策略采用优先级抢占式,确保温度监控和网络通信等高优先级任务能及时响应。
3.2 关键算法实现
3.2.1 温度PID控制
采用增量式PID算法控制加热功率:
c复制typedef struct {
float Kp, Ki, Kd;
float last_error;
float integral;
} PID_Controller;
float PID_Update(PID_Controller* pid, float error) {
float derivative = error - pid->last_error;
pid->integral += error;
pid->last_error = error;
return pid->Kp * error +
pid->Ki * pid->integral +
pid->Kd * derivative;
}
参数整定经验:
- Kp初始值设为(100%功率)/(目标温度-室温)
- Ki=Kp/10,Kd=Kp*2
- 实际调试时先调P,再调I,最后调D
3.2.2 WiFi通信协议
设计简化的HTTP-like协议:
code复制请求格式:
GET /ctrl?cmd=start HTTP/1.1
Host: 192.168.4.1
响应格式:
HTTP/1.1 200 OK
Content-Type: text/json
{"status":"success","temp":65.2}
4. 系统实现细节
4.1 硬件电路设计
电源部分采用两级稳压:
- 第一级:220V AC转12V DC(成品电源模块)
- 第二级:12V转5V(LM7805)和12V转3.3V(AMS1117)
重要提示:电机驱动电源必须与MCU电源隔离,否则电机启停时会产生电压波动导致MCU复位。
4.2 关键外设驱动
4.2.1 DS18B20驱动代码
复位时序实现:
c复制void DS18B20_Reset(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 配置为推挽输出
GPIO_InitStruct.Pin = DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
// 拉低480us
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
delay_us(480);
// 释放总线
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
delay_us(60);
// 切换为输入模式检测应答信号
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
// 等待60-240us
delay_us(60);
uint8_t ret = HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN);
delay_us(180);
return ret == 0; // 0表示有器件应答
}
4.2.2 PWM电机控制
使用TIM3_CH1产生PWM波:
c复制void Motor_PWM_Init(uint16_t arr, uint16_t psc) {
TIM_HandleTypeDef htim3;
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = psc;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = arr;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim3);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比0%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}
5. 系统优化与问题解决
5.1 遇到的主要问题
-
电机干扰导致WiFi断连
- 现象:电机启动时ESP32经常断开连接
- 排查:用示波器发现电源线上有大幅电压波动
- 解决:增加1000μF电解电容和0.1μF陶瓷电容组合滤波
-
DS18B20读取失败
- 现象:温度读取时不时失败
- 排查:时序不够精确,特别是等待转换时间不足
- 解决:严格按照手册实现时序,增加重试机制
-
FreeRTOS任务堆栈溢出
- 现象:系统运行一段时间后死机
- 排查:使用uxTaskGetStackHighWaterMark()发现WiFi任务堆栈不足
- 解决:将堆栈从256增大到512字节
5.2 性能优化措施
-
低功耗优化
- 在无操作时进入Tickless模式
- 动态调整CPU频率
- 关闭未使用的外设时钟
-
响应速度优化
- 关键中断使用NVIC_SetPriority()提高优先级
- 高频访问的变量使用"volatile"修饰
- DMA传输替代CPU轮询
-
稳定性增强
- 增加看门狗定时器
- 关键操作加入互斥锁
- 实现异常重启机制
6. 实际使用体验
经过两个月的实际使用,这个智能水壶系统表现稳定,基本达到了设计目标。几个特别实用的功能:
- 远程预热:下班前用手机启动烧水,到家正好可以喝
- 温度保持:可以设置保持特定温度(如60℃适合冲奶粉)
- 安全保护:干烧时会自动断电并报警
- 用水统计:记录每日用水量,帮助养成饮水习惯
最让我满意的是系统的响应速度——从手机发送指令到水壶开始动作,延迟通常在300ms以内,基本感觉不到等待。
这个项目的全部源码和电路设计我已经开源,希望能给对嵌入式开发和物联网感兴趣的开发者一些参考。在实际开发过程中,我最大的体会是:硬件项目的成功=30%设计+50%调试+20%文档。特别是调试阶段,一个好的示波器和逻辑分析仪能节省大量时间。