1. 项目背景与核心功能
家里养鱼的朋友应该都有过这样的经历:明明按时换水喂食,鱼却莫名其妙生病甚至死亡。后来我发现,水质问题才是罪魁祸首。水温波动、PH值异常、水中杂质过多,这些肉眼看不见的变化都会影响水生生物健康。这就是为什么我决定用STM32开发一套智能水质监测系统。
这套系统的核心功能非常实用:
- 三合一检测:同时监测水体的TDS(总溶解固体)、PH值和水温三个关键指标
- 双屏显示:本地OLED屏幕实时刷新数据,手机APP或电脑上位机远程查看
- 智能预警:当水质参数超出设定范围时,系统会自动发出提醒
实测下来,这套方案成本不到200元,但效果堪比专业水质检测仪。我把它用在鱼缸、家庭饮用水和实验室培养液监测等多个场景,稳定性都很不错。
2. 硬件选型与电路设计
2.1 核心元器件清单
这是我反复测试后确定的最佳配置方案:
- 主控芯片:STM32F103C8T6(性价比之王,72MHz主频完全够用)
- 显示模块:0.96寸OLED(I2C接口,省IO口)
- 传感器组合:
- TDS检测:工业级TDS传感器模块(0-1000ppm量程)
- PH检测:E201-C PH电极+信号放大板
- 水温检测:DS18B20(防水封装版)
- 通信模块:ESP8266-01S(支持AT指令,便宜好用)
特别说一下传感器选择要点:
- TDS模块要选带温度补偿的,实测误差能控制在±10%以内
- PH电极一定要配专用放大电路,直接接单片机ADC会读不到有效数据
- DS18B20记得买不锈钢外壳的防水版本,我用普通版坏过两个
2.2 关键电路设计
PH检测电路最容易被忽视。这里分享一个实测可用的设计:
// PH值读取代码示例 float Read_PH() { int buf[10], temp; for(int i=0;i<10;i++) { buf[i] = analogRead(PH_PIN); delay(10); } // 中值滤波 for(int i=0;i<9;i++) { for(int j=i+1;j<10;j++) { if(buf[i]>buf[j]) { temp = buf[i]; buf[i] = buf[j]; buf[j] = temp; } } } float avgValue = 0; for(int i=2;i<8;i++) avgValue += buf[i]; float phValue = (float)avgValue*5.0/1024/6; // 转换为电压值 phValue = 3.5 * phValue; // 根据校准结果调整系数 return phValue; }TDS模块的供电要注意稳定性,建议单独用LDO稳压到3.3V。我在PCB上加了0.1uF去耦电容,数据波动明显减小。
3. 软件架构与关键代码
3.1 主程序逻辑设计
系统采用多任务调度架构:
- 传感器数据采集:每2秒轮询一次
- 本地显示刷新:OLED每1秒更新
- 无线数据传输:通过ESP8266定时上报
- 异常检测:实时判断阈值告警
void main() { HW_Init(); // 硬件初始化 WiFi_Connect(); // 连接路由器 while(1) { Read_Sensors(); // 读取所有传感器 OLED_Display(); if(++upload_cnt >= 30) { // 每60秒上传一次 WiFi_Upload(); upload_cnt = 0; } Check_Alarm(); // 异常检测 delay(1000); } }3.2 WiFi通信实现
ESP8266配置有几个坑要注意:
- 波特率建议用115200,太低会影响响应速度
- 每次AT指令后要加足够延时
- 最好做重连机制
这是我优化后的网络配置代码:
void WiFi_Init() { Serial2.begin(115200); // ESP8266通信串口 Send_AT("AT+RST", "ready", 3000); Send_AT("AT+CWMODE=1", "OK", 1000); Send_AT("AT+CWJAP=\"SSID\",\"PASSWORD\"", "OK", 5000); Send_AT("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80", "CONNECT", 3000); } void WiFi_Upload() { String cmd = "GET /update?api_key=XXX&field1="+String(tds)+"&field2="+String(ph)+"&field3="+String(temp); Send_AT("AT+CIPSEND="+String(cmd.length()+2), ">", 1000); Serial2.println(cmd); }4. 多终端显示方案
4.1 OLED本地界面设计
我用U8g2库实现了分级显示:
- 第一屏:实时数值(大字体)
- 第二屏:历史曲线(需要外扩Flash存储)
- 第三屏:参数设置(通过按键操作)
显示效果优化技巧:
- 使用反色显示当前选中项
- 重要参数添加闪烁效果
- 温度单位'°C'要特殊处理,需要自定义字模
4.2 手机APP开发
推荐三种方案:
- Thingspeak平台:最简单,无需编程
- Blynk应用:拖拽式开发,适合新手
- 自定义Android应用:用MIT App Inventor就能做
我用的Thingspeak配置流程:
- 注册免费账号
- 创建Channel并定义字段
- 复制API Key到STM32程序
- 即可生成实时数据看板
4.3 上位机软件
用Python+PyQt5写了个简易监控程序,核心代码如下:
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.serial = SerialThread() self.serial.data_received.connect(self.update_ui) def update_ui(self, data): self.lcd_temp.display(data['temp']) self.lcd_ph.display(data['ph']) self.plot.addData(data['tds'])5. 校准与优化经验
5.1 传感器校准方法
PH传感器校准:
- 准备PH4.0和PH9.18标准缓冲液
- 将电极浸入PH4.0溶液,读取ADC值
- 调整代码中的斜率参数
- 重复步骤2-3直到读数准确
TDS校准公式:
TDS = (133.42 * V^3 - 255.86 * V^2 + 857.39 * V) * 0.5其中V为传感器输出电压
5.2 抗干扰设计
踩过几个坑后总结的优化方案:
- 所有传感器信号线加磁珠滤波
- ADC采样时关闭WiFi模块
- 地线采用星型连接
- 外壳加导电漆屏蔽
电源管理也很关键,我后来改用TP4056充电模块+18650电池的方案,续航能达到72小时以上。