1. 项目概述
这款基于STM32的智能水质检测仪是我最近完成的一个嵌入式系统项目,它能够实时监测水温和浊度,并在水质超标时发出预警。作为一个经常需要检测水质的电子爱好者,市面上的商用设备要么太贵,要么功能单一,于是决定自己动手打造一款性价比高、功能实用的检测工具。
整套系统以STM32F103C8T6为主控,搭配DS18B20温度传感器和TSW-30浊度传感器,通过OLED显示屏实时显示数据。最核心的功能是当检测到水质浑浊度超过预设阈值时,会同时触发软件蜂鸣器和硬件LED报警,形成双重保障机制。实测表明,这套系统在25℃环境下的浊度检测误差小于±5%,完全满足日常水质监测需求。
2. 硬件设计详解
2.1 核心器件选型
选择STM32F103C8T6作为主控主要基于三点考虑:
- 72MHz主频足够处理传感器数据
- 内置12位ADC满足浊度检测精度要求
- 丰富的外设接口方便扩展功能
温度传感器选用DS18B20的原因:
- 数字输出,抗干扰能力强
- ±0.5℃的精度满足需求
- 单总线协议节省IO口资源
浊度传感器最终选定TSW-30模块:
- 0-1000NTU测量范围
- 模拟电压输出便于ADC采集
- 自带温度补偿功能
2.2 电路设计要点
电源部分采用AMS1117-3.3稳压芯片,为整个系统提供稳定供电。特别要注意的是:
- 每个传感器电源脚都加了100nF去耦电容
- ADC参考电压引脚接入1μF+100nF组合滤波
- 蜂鸣器驱动电路使用NPN三极管隔离
传感器接口设计:
c复制// DS18B20连接示意图
VCC ---- 3.3V
DQ ---- PA0 (加上拉电阻)
GND ---- GND
// TSW-30连接方式
VCC ---- 5V
OUT ---- PA5 (ADC通道5)
GND ---- GND
3. 软件实现关键
3.1 温度检测实现
DS18B20的驱动是项目第一个难点。单总线协议要求严格的时序控制,下面是经过优化的读取流程:
- 初始化时序:拉低总线480μs后释放
- 跳过ROM命令:发送0xCC
- 启动转换:发送0x44
- 等待转换完成(典型750ms)
- 再次初始化并发送读取命令0xBE
c复制float Read_Temperature(void) {
uint8_t tempL, tempH;
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // Skip ROM
DS18B20_WriteByte(0xBE); // Read Scratchpad
tempL = DS18B20_ReadByte();
tempH = DS18B20_ReadByte();
int16_t temp = (tempH << 8) | tempL;
return temp * 0.0625f; // 转换系数
}
注意事项:实际调试中发现,当环境温度低于0℃时,tempH的最高位会置1表示负数,需要特殊处理符号位。
3.2 浊度检测算法
浊度传感器输出的是0-5V模拟信号,经过电阻分压后接入STM32的ADC引脚。为提高精度,采用了以下措施:
- ADC过采样技术:将12位ADC提升到14位有效精度
- 滑动平均滤波:对连续10次采样取平均值
- 温度补偿:根据DS18B20读数修正浊度值
ADC配置代码:
c复制void ADC_Config(void) {
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 过采样配置
ADC_OverSamplingCmd(ADC1, ENABLE);
ADC_OverSamplingFactorSet(ADC1, 256);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
浊度值转换公式:
code复制NTU = (Vout - Vzero) × (400 / (Vfull - Vzero))
其中:
- Vzero:蒸馏水对应的输出电压(实测0.8V)
- Vfull:400NTU标准液对应的输出电压(实测3.2V)
4. 系统优化与调试
4.1 低功耗设计
为延长电池续航,采取了多项省电措施:
- 动态调整系统时钟:检测间隔期间降频到8MHz
- 传感器分时供电:非采样时段切断传感器电源
- OLED间歇刷新:每500ms更新一次显示
实测功耗对比:
| 工作模式 | 电流消耗 | 续航时间 |
|---|---|---|
| 全速运行 | 28mA | 约3天 |
| 优化模式 | 7mA | 约12天 |
4.2 抗干扰处理
现场测试时遇到的主要问题及解决方案:
-
问题:ADC读数跳变严重
原因:电源纹波过大
解决:增加LC滤波电路,改用低ESR电容 -
问题:温度读数偶尔异常
原因:总线受电磁干扰
解决:缩短导线长度,加磁珠滤波 -
问题:预警误触发
原因:阈值设置不合理
解决:改为滞后比较算法c复制#define THRESHOLD_HIGH 50.0f #define THRESHOLD_LOW 45.0f void Check_Warning(float ntu) { static uint8_t alarm_state = 0; if(!alarm_state && ntu > THRESHOLD_HIGH) { Alarm_On(); alarm_state = 1; } else if(alarm_state && ntu < THRESHOLD_LOW) { Alarm_Off(); alarm_state = 0; } }
5. 功能扩展方向
当前系统预留了以下扩展接口:
- UART接口:可接蓝牙模块实现无线传输
- 备用ADC通道:支持增加PH值检测
- GPIO扩展口:可连接更多报警装置
已验证的升级方案:
- 添加SIM800L模块实现短信报警
- 接入SD卡存储历史数据
- 移植FreeRTOS实现多任务管理
6. 项目总结与心得
通过这个项目,我深刻体会到几个关键点:
-
传感器校准至关重要:浊度检测前必须用标准液校准,且要定期重新校准
-
硬件滤波不可忽视:尽管软件滤波算法强大,但良好的硬件设计是基础
-
实时性需要权衡:过快的采样率会导致系统负担加重,500ms间隔是较优选择
-
预警机制要冗余:软硬件双重报警确实提高了系统可靠性
这套系统目前已在鱼缸水质监测、饮用水检测等场景实际应用超过3个月,运行稳定。后续计划增加PH值检测功能,并将所有数据通过WiFi上传到云平台,实现远程监控。
