STM32之水质浑浊度传感器模块
目录
一、模块概述
二、模块简介
2.1 模块特点
2.2 电气特性
2.3 模块接口说明
2.4 结构与工作原理
2.5 实际应用注意事项
三、硬件设计
3.1 硬件组成
3.2 硬件连接
四、软件设计
4.1 开发环境配置
4.2 关键代码实现
五、功能实现与优化
六、常见问题解决
七、总结
一、模块概述
浑浊度是衡量水体清澈程度的重要指标,广泛应用于水质监测、污水处理、饮用水生产等领域。浑浊度传感器是一种基于光学传感原理的模拟输出传感器,通过测量水中悬浮物对光的散射程度来间接反映水的浑浊度。本指南详细介绍了如何利用性价比较高的STM32F103C8T6最小系统板及其标准外设库,实现对浑浊度传感器数据的准确采集与处理。
二、模块简介
模块实物图:
2.1 模块特点
- 工作原理: 采用光学感应,内置红外LED光源和光电晶体管。
- 输出信号: 模拟电压信号输出,浑浊度越高,输出电压越高。
- 测量范围: 通常可测量0~1000 NTU ( Nephelometric Turbidity Unit ) 或更宽范围(具体需参考产品手册)。
- 易于集成: 接口简单,只需供电和读取模拟电压即可。
- 需注意点: 测量结果易受环境光、液体颜色、气泡等因素干扰。
2.2 电气特性
- 工作电压: 通常为5V DC(务必确认模块规格书,部分型号可能为3.3V-5V宽电压)。
- 输出信号: 0 ~ 4.5V 模拟电压(在5V供电下)。
- 工作电流: 约40mA。
2.3 模块接口说明
浑浊度传感器模块通常引出3个引脚(有的模块多一个DO数字信号输出引脚):
编号 | 名称 | 功能 |
1 | GND | 供电电压负极 |
2 | VCC | 供电电压正极 |
3 | AO | 模拟信号输出引脚 |
2.4 结构与工作原理
浑浊度传感器通过测量水中悬浮固体总量(TSS)的变化,来测量水中悬浮颗粒物的光透过率和散射率,利用光来检测悬浮颗粒物。随着 TTS 增加,液体浊度水平增加。
传感器头部包含一个红外LED和一个光电晶体管。LED向水中发射光线,水中的悬浮颗粒会导致光线发生散射。散射光的角度和强度与颗粒物的数量(浑浊度)相关。光电晶体管用于检测与入射光呈90°方向的散射光强度,并将其转换为电流信号,内部电路再将电流信号处理并放大为一个线性的电压信号输出。
传感器输出电压值大小受温度影响,输出电压与温度曲线关系如下图所示。进行浊度测量时需进行温度补偿以保证测量精度。
温度校正公式:∆U=- 0.0192×(T-25)
上式中∆ U 为温度变化引起的电压差; T 为当前测量温度值。
2.5 实际应用注意事项
1. 校准: 输出电压与浑浊度并非简单的线性关系,通常需要根据传感器手册提供的曲线或通过实验数据进行校准(例如使用标准浊度液),建立电压值与NTU值的对应公式。
2. 环境光屏蔽: 传感器头部应做好遮光处理,防止环境光进入干扰测量结果。
3. 气泡干扰: 水中的气泡会强烈散射光线,导致读数异常偏高,测量时应避免气泡。
4. 污染: 长期使用后,传感器光学窗口可能会被污染,需要定期清洁以保证精度。
5. 电源去耦: 在VCC附近并联一个100nF的电容到GND,以抑制电源噪声,提高ADC采样稳定性。
三、硬件设计
3.1 硬件组成
- 主控单元: STM32F103C8T6最小系统板
- 传感单元: 浑浊度传感器模块
- 供电电源: 5V USB电源(同时为开发板和传感器供电)
- 连接线: 杜邦线若干
3.2 硬件连接
STM32F103C8T6引脚 | 浑浊度传感器引脚 | 功能说明 |
---|---|---|
5V | VCC | 为传感器供电 |
GND | GND | 共同地 |
PA1 (或其他ADCx) | AOUT | 模拟信号输入 |
四、软件设计
4.1 开发环境配置
1. IDE: Keil uVision5 MDK
2. 固件库: 使用STM32F10x_StdPeriph_Lib_V3.5.0标准外设库。
4.2 关键代码实现
#include "stm32f10x.h"
#include "stdio.h" // 如果使用printf重定向// 简单的延时函数
void Delay_ms(uint32_t nCount) {for(; nCount != 0; nCount--) {for(uint32_t i = 0; i < 8000; i++);}
}// ADC初始化函数
void ADC1_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure;// 1. 开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);// 2. 配置PA1为模拟输入模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入GPIO_Init(GPIOA, &GPIO_InitStructure);// 3. 复位并配置ADC1参数ADC_DeInit(ADC1);ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道,非扫描模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;// 单次转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1; // 要转换的通道数量为1ADC_Init(ADC1, &ADC_InitStructure);// 4. 配置ADC通道规则组// 参数:ADCx, 通道号(PA1对应ADC1的通道1),采样顺序1,采样时间55.5个周期ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);// 5. 使能ADCADC_Cmd(ADC1, ENABLE);// 6. ADC校准(提高精度)ADC_ResetCalibration(ADC1); // 重置校准寄存器while(ADC_GetResetCalibrationStatus(ADC1)); // 等待重置完成ADC_StartCalibration(ADC1); // 开始校准while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成
}// 读取指定ADC通道的转换值
uint16_t Get_ADC_Value(uint8_t ch) {// 1. 配置规则组通道(这里固定为通道1,可根据参数ch修改使其更通用)// ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_55Cycles5);// 2. 启动软件转换ADC_SoftwareStartConvCmd(ADC1, ENABLE);// 3. 等待转换结束while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);// 4. 清除EOC标志位并返回转换结果ADC_ClearFlag(ADC1, ADC_FLAG_EOC);return ADC_GetConversionValue(ADC1);
}int main(void) {uint16_t adc_value = 0;float voltage = 0.0f;// float turbidity_ntu = 0.0f; // 用于存储计算后的NTU值// 初始化系统时钟等(默认使用内部8MHz RC振荡器,HCLK=72MHz)// 此处省略SystemInit(),因为最小系统板通常已配置好时钟ADC1_Init(); // 初始化ADCwhile(1) {// 1. 读取ADC原始值(12位精度,0-4095)adc_value = Get_ADC_Value(ADC_Channel_1);// 2. 将ADC值转换为电压值(单位:伏特)// 假设Vref+ = 3.3V (STM32F103C8T6的VDDA通常接3.3V)voltage = (float)adc_value * 3.3f / 4095.0f;// 3. (可选) 将电压值转换为浑浊度值(NTU)// 这一步需要根据传感器的校准曲线或公式进行。// 例如:turbidity_ntu = voltage * k + b; (k和b为校准系数)// 示例公式,请根据实际传感器校准修改!// turbidity_ntu = -1120.4 * voltage * voltage + 5742.3 * voltage - 4352.9;// 4. 打印结果(需实现printf重定向至串口,此处省略实现)// printf("ADC: %d, Voltage: %.2f V\r\n", adc_value, voltage);// 或者通过其他方式显示,如OLED// 5. 延时一段时间后进行下一次采集Delay_ms(1000); // 每秒采样一次}
}
1. 初始化 (ADC1_Init):
- 首先开启GPIOA和ADC1的时钟。
- 配置PA1引脚为模拟输入模式(GPIO_Mode_AIN),这是ADC输入的正确模式。
- 使用ADC_Init函数设置ADC的工作模式为独立、单次转换、软件触发、数据右对齐。
- 使用ADC_RegularChannelConfig指定要转换的通道(通道1)及其采样时间(55.5周期,提供足够的采样时间保证精度)。
- 使能ADC并进行校准,这是一个重要步骤,可以减少内部电容带来的误差。
2. 读取转换值 (Get_ADC_Value):
- 该函数启动一次软件转换,并等待转换结束标志(EOC)置位。
- 读取ADC1->DR寄存器中的转换结果并返回。由于是单通道,结果直接存放在这个寄存器中。
3. 主循环 (main):
- 循环调用Get_ADC_Value获取原始ADC值。
- 根据ADC的参考电压(假设为3.3V)将原始值(0-4095)转换为实际的电压值。
- 关键步骤: 根据校准数据将电压值转换为有物理意义的浑浊度值(NTU)。
- 最后延时1秒,控制采样频率。
五、功能实现与优化
1. 基本功能实现: 上述代码成功实现了对TSW-30传感器输出电压的周期性采样和电压值计算。
2. 软件滤波: 为了抑制随机噪声,可以在软件中实现滤波算法。例如:
- 多次采样求平均: 连续采样N次(如10次),然后取算术平均值作为最终结果。
- 中值滤波: 采样N次,排序后取中值,能有效滤除脉冲干扰。
六、常见问题解决
- Q1: 读取的ADC值始终为0或4095。
- A1: 检查硬件连接是否正确可靠,特别是GND是否共地。检查传感器供电电压是否正常。确认STM32的ADC引脚配置是否正确(必须为模拟输入`GPIO_Mode_AIN`)。
- Q2: 读数波动非常大,不稳定。
- A2:
1. 检查电源质量,在传感器VCC和GND之间并联一个100nF和一个10uF的电容。
2. 实施软件滤波(如平均值滤波)。
3. 确保传感器光学窗口清洁且无气泡,并处于遮光环境中。
4. 尝试增加ADC的采样时间(ADC_SampleTime),让采样电容充分充电。
- Q3: 转换得到的电压值/浑浊度值不准。
- A3:
1. 确认STM32的ADC参考电压是否准确。如果板载LDO质量差或负载重,3.3V可能不准,可以使用外部精密基准电压源。
2. 必须进行传感器校准。未经校准的读数只有相对参考意义,无法反映绝对物理值。
- Q4: 传感器对光线变化没反应。
- A4: 检查传感器供电。用万用表测量AOUT引脚对地电压,并尝试遮挡传感器探头,观察电压是否有变化。若无变化,可能是传感器已损坏或接线错误。
七、总结
本文详细阐述了如何使用STM32F103C8T6最小系统板和标准库驱动浑浊度传感器。核心在于正确配置ADC外设以读取传感器的模拟电压输出,并通过校准将电压值转换为有意义的浑浊度数值。硬件上需要注意电源质量和抗干扰,软件上则强调滤波和校准的重要性。
通过本项目,开发者可以掌握STM32 ADC的基本应用、传感器数据采集的基本流程以及数据处理的基本方法。此方案为基础框架,开发者可根据具体应用需求,进一步添加显示、通信、报警等功能,构建完整的水质监测系统。