1. 项目概述
这个基于STM32的水位检测PID控制系统是我去年为一个农业大棚项目设计的解决方案。当时客户需要一套能够自动维持水培蔬菜营养液水位的智能控制系统,经过多次迭代最终形成了这个稳定可靠的方案。系统核心采用STM32F103C8T6单片机,配合水位传感器和温度传感器实现闭环控制,特别加入了PID算法使水位调节更加精准平稳。
整套系统最让我自豪的是它的多功能性:不仅支持本地TFT彩屏显示和按键控制,还开发了配套的手机APP实现远程监控。在实际部署中,这种双模式操作特别实用——现场工作人员可以通过按键快速调整,管理人员则能随时随地通过手机查看系统状态。
2. 系统硬件设计
2.1 核心控制器选型
选择STM32F103C8T6作为主控芯片主要基于三点考虑:
- 充足的GPIO资源:需要驱动显示屏、多个传感器和继电器
- 内置Flash存储:保存水位阈值等参数
- 性价比优势:相比同级ARM芯片价格更低
实际使用中,这款芯片的72MHz主频完全能满足实时采集和控制需求。我特别利用了它的定时器中断功能来实现精确的PID计算周期,确保控制响应及时。
2.2 传感器模块
系统使用了两种关键传感器:
- 水位检测传感器:选用的是电容式液位传感器,测量范围0-10cm,精度±1mm
- DS18B20温度传感器:防水型,测量范围-55°C~+125°C,精度±0.5°C
注意:水位传感器安装时要避免气泡附着影响测量精度,我通常会在容器侧壁开孔安装,并用硅胶密封。
2.3 执行机构驱动
驱动电路设计有几个关键点:
- 水泵驱动:采用光耦隔离+MOSFET的方案
- 加水泵:S8050 MOSFET
- 排水泵:S8550 MOSFET
- 蜂鸣器驱动:PNP三极管驱动有源蜂鸣器
- 所有驱动电路都加入了续流二极管保护
3. 软件系统设计
3.1 主程序流程
系统上电后的初始化流程如下:
- 硬件初始化(GPIO、定时器、ADC、I2C等)
- 从Flash读取保存的参数
- 启动传感器数据采集任务
- 进入主循环处理用户输入和状态更新
c复制void main() {
Hardware_Init();
Load_Parameters_From_Flash();
Start_Data_Acquisition_Task();
while(1) {
Handle_User_Input();
Update_System_Status();
PID_Control_Process();
Display_Update();
}
}
3.2 PID控制算法实现
PID控制是这个系统的核心,算法实现要点:
- 采样周期:设置为100ms(通过定时器中断触发)
- 参数整定:
- Kp=2.5, Ki=0.1, Kd=1.2(针对典型水箱模型)
- 加入了积分抗饱和处理
- 输出限幅:0-100%对应水泵的PWM调节范围
实际调试中发现,对于不同容积的水箱,PID参数需要微调。我在程序中预留了通过手机APP调整PID参数的接口,方便现场调试。
3.3 无线通信模块
系统支持蓝牙和WiFi两种无线方案:
- 蓝牙:HC-05模块,适合短距离控制
- WiFi:ESP8266,可实现远程访问
通信协议采用自定义的简单帧结构:
code复制[头字节][长度][命令字][数据][校验][尾字节]
手机APP通过解析这些帧来获取系统状态和发送控制指令。
4. 关键功能实现细节
4.1 水位控制逻辑
自动模式下的控制逻辑流程图:
- 读取当前水位值
- 与设定阈值比较:
- 低于下限:启动加水泵
- 高于上限:启动排水泵
- 在范围内:停止所有水泵
- 异常状态触发蜂鸣器报警
c复制void Water_Level_Control() {
float current_level = Get_Water_Level();
if(current_level < lower_threshold) {
Start_Water_Pump();
Stop_Drain_Pump();
Alarm_On();
}
else if(current_level > upper_threshold) {
Stop_Water_Pump();
Start_Drain_Pump();
Alarm_On();
}
else {
Stop_Water_Pump();
Stop_Drain_Pump();
Alarm_Off();
}
}
4.2 数据存储设计
使用STM32内部Flash模拟EEPROM存储关键参数:
- 存储区域:选择最后一页Flash(避免被程序覆盖)
- 存储内容:
- 水位上下限阈值
- PID参数
- 系统工作模式
- 写入策略:只有参数变更时才写入,避免频繁擦写
重要提示:Flash写入前必须先擦除整个页,单个字节无法单独修改。我采用了"先读后写"的策略,只有数据确实变化时才执行擦写操作。
4.3 人机交互设计
TFT显示屏的UI布局经过多次优化:
- 顶部状态栏:显示当前模式和时间
- 主区域:
- 实时水位(图形化进度条+数字显示)
- 温度显示
- 水泵状态图标
- 底部:参数设置入口提示
按键功能分配:
- K1:模式切换(自动/手动)
- K2:菜单/确认
- K3:数值增加
- K4:数值减少
5. 手机APP开发
5.1 APP功能架构
安卓APP采用Android Studio开发,主要功能模块:
- 连接管理:蓝牙/WiFi连接配置
- 数据监控:实时显示水位、温度等参数
- 设备控制:模拟硬件按键的所有功能
- 参数设置:可调整PID参数和阈值
- 历史记录:存储关键数据变化曲线
5.2 通信协议实现
APP与硬件的数据交换采用JSON格式,例如:
json复制{
"cmd": "set_param",
"data": {
"upper_threshold": 80,
"lower_threshold": 30,
"kp": 2.5,
"ki": 0.1,
"kd": 1.2
}
}
这种结构易于扩展,后续新增参数只需增加字段即可。
5.3 界面设计要点
APP界面设计遵循几个原则:
- 关键参数突出显示
- 控制按钮大而明显
- 状态变化有颜色反馈
- 保持与硬件显示屏一致的视觉风格
我特别加入了手势操作——在数据曲线页面可以通过双指缩放查看细节,这个功能在现场调试时非常实用。
6. 系统调试与优化
6.1 PID参数整定方法
经过多次实践,我总结出适合这类水位系统的PID整定步骤:
- 先将Ki和Kd设为0,逐步增大Kp直到系统出现等幅振荡
- 记录此时的Kp值和振荡周期Tu
- 按照Ziegler-Nichols法则设置初始参数:
- Kp = 0.6 × Ku
- Ki = 2 × Kp / Tu
- Kd = Kp × Tu / 8
- 微调至最佳效果
6.2 常见问题解决方案
在实际部署中遇到的典型问题及解决方法:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 水位波动大 | PID参数不合适 | 重新整定PID参数 |
| 传感器读数不稳 | 电源干扰 | 增加滤波电容,使用屏蔽线 |
| 水泵不动作 | 驱动电路故障 | 检查MOSFET和续流二极管 |
| 通信中断 | 模块供电不足 | 确保无线模块有独立稳压供电 |
6.3 性能优化技巧
几个显著提升系统稳定性的技巧:
- 传感器数据采用滑动平均滤波
- 关键操作加入软件看门狗
- 无线通信增加重传机制
- 显示屏刷新使用局部更新策略
- 空闲时进入低功耗模式
7. 项目扩展与改进
这个基础框架可以扩展多种实用功能:
- 多水箱联动控制
- 水质监测(PH值、EC值等)
- 太阳能供电系统
- 云端数据存储与分析
- 定时任务功能
最近我正在为该系统增加LoRa无线组网功能,适用于大面积农业园区的分布式水位监控。测试表明,在开阔场地LoRa的传输距离能达到2km以上,非常适合农业应用场景。
这个项目从最初的概念到最终产品历时3个月,期间经历了多次设计修改和现场测试。最大的收获是认识到嵌入式系统开发中硬件可靠性的重要性——再好的软件算法也需要稳定的硬件基础支持。建议开发类似系统的同行一定要重视电源设计和信号隔离,这些基础工作往往决定了项目的成败。
