毕业设计|基于STM32的水质多参数智能监测与预警系统设计

📅 2026/7/15 16:58:31 👁️ 阅读次数 📝 编程学习
毕业设计|基于STM32的水质多参数智能监测与预警系统设计

1. 系统设计背景与意义

水质监测在环境保护、水产养殖和饮用水安全等领域扮演着关键角色。传统的水质检测方法往往需要人工采样和实验室分析,不仅耗时耗力,而且无法实现实时监测。随着物联网技术的发展,基于嵌入式系统的智能监测方案逐渐成为主流。STM32作为一款高性能、低功耗的微控制器,非常适合用于构建小型化、智能化的水质监测设备。

我在实际项目中发现,单纯的水位或浑浊度检测已经不能满足现代水质监测的需求。比如在水产养殖场,养殖户不仅需要知道水位高低,还需要掌握水温、pH值等多项指标。这就是为什么我们需要设计一个多参数的水质监测系统,能够同时监测多种水质参数,并通过智能算法进行预警。

2. 系统整体架构设计

2.1 硬件组成

系统以STM32F103C8T6为核心控制器,这是一款基于Cortex-M3内核的32位微控制器,具有丰富的外设资源和较低的功耗。实测下来,这款芯片在数据处理和功耗控制方面表现非常稳定。

系统硬件主要包括以下几个部分:

  • 主控模块:STM32F103C8T6最小系统
  • 传感器模块:
    • 水位传感器(超声波或压力式)
    • 浑浊度传感器(TSW-30或TS-300B)
    • 温度传感器(DS18B20)
    • pH值传感器(工业级模拟输出)
  • 显示模块:0.96寸OLED显示屏
  • 报警模块:蜂鸣器+LED指示灯
  • 通信模块:ESP8266 WiFi模块(用于数据上传)
  • 电源模块:锂电池供电+充电管理

2.2 软件架构

软件部分采用模块化设计,主要包括:

  1. 传感器驱动层:负责各类传感器的数据采集
  2. 数据处理层:对原始数据进行滤波和校准
  3. 业务逻辑层:实现预警算法和系统控制
  4. 人机交互层:处理按键输入和显示输出
  5. 通信层:负责数据上传和远程控制

我在实际开发中发现,采用这种分层架构可以大大提高代码的可维护性。比如当需要更换传感器型号时,只需要修改驱动层的代码,其他部分基本不用改动。

3. 关键硬件设计详解

3.1 STM32最小系统设计

STM32F103C8T6最小系统包括以下几个必要部分:

  1. 电源电路:3.3V稳压,建议使用AMS1117-3.3
  2. 复位电路:10k电阻+0.1uF电容
  3. 时钟电路:8MHz晶振+两个22pF负载电容
  4. 调试接口:SWD四线接口(VCC、GND、SWDIO、SWCLK)

这里有个小技巧:在设计PCB时,最好在电源引脚附近放置一个0.1uF的去耦电容,可以有效抑制电源噪声。我曾在项目中因为忽略这个细节,导致ADC采样结果波动很大。

3.2 传感器接口设计

不同传感器需要不同的接口方式:

  1. 水位传感器

    • 超声波模块(如HC-SR04):需要5V供电,使用GPIO触发和回波检测
    • 压力式传感器:通常输出模拟信号,需要接ADC引脚
  2. 浑浊度传感器

    • TSW-30:输出模拟信号,接ADC
    • TS-300B:支持数字和模拟输出,建议使用模拟输出以获得更高精度
  3. 温度传感器

    • DS18B20:单总线接口,需要接上拉电阻
    • 模拟温度传感器:如NTC热敏电阻,需要分压电路
  4. pH传感器

    • 工业级pH传感器:输出0-3V模拟信号,需要高精度ADC
    • 需要设计信号调理电路,通常包括运放和滤波电路

3.3 显示与报警电路

OLED显示采用I2C接口,只需要4根线(VCC、GND、SCL、SDA)。蜂鸣器电路设计时要注意:

  • 有源蜂鸣器:直接接GPIO,加限流电阻
  • 无源蜂鸣器:需要PWM驱动,建议使用NPN三极管驱动

4. 软件设计与实现

4.1 传感器数据采集

以浑浊度传感器为例,采集代码如下:

// 初始化ADC void ADC1_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // 配置ADC引脚为模拟输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // ADC配置 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; ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); // ADC校准 ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } // 获取ADC值 u16 Get_ADC_Value(u8 ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); return ADC_GetConversionValue(ADC1); }

4.2 多任务调度设计

由于系统需要同时处理多个传感器、显示和通信任务,建议使用简单的任务调度机制:

typedef struct { void (*task_func)(void); // 任务函数指针 uint32_t interval; // 执行间隔(ms) uint32_t last_run; // 上次执行时间 } Task_t; Task_t task_list[] = { {Sensor_Update, 100, 0}, {Display_Update, 500, 0}, {Comm_Update, 1000, 0}, {Alarm_Check, 200, 0} }; void Task_Scheduler(void) { uint32_t current_time = HAL_GetTick(); for(int i=0; i<sizeof(task_list)/sizeof(Task_t); i++) { if(current_time - task_list[i].last_run >= task_list[i].interval) { task_list[i].task_func(); task_list[i].last_run = current_time; } } }

4.3 智能预警算法

传统的固定阈值预警方式在实际应用中效果不佳。我设计了一种自适应预警算法,主要思路是:

  1. 学习阶段:系统运行初期记录正常范围值
  2. 动态调整:根据历史数据自动调整预警阈值
  3. 趋势预测:使用简单移动平均预测未来变化趋势

算法实现代码片段:

#define SAMPLE_SIZE 20 typedef struct { float values[SAMPLE_SIZE]; uint8_t index; float sum; } MovingAverage_t; void MA_Init(MovingAverage_t *ma) { memset(ma->values, 0, sizeof(ma->values)); ma->index = 0; ma->sum = 0; } float MA_Update(MovingAverage_t *ma, float new_value) { ma->sum -= ma->values[ma->index]; ma->values[ma->index] = new_value; ma->sum += new_value; ma->index = (ma->index + 1) % SAMPLE_SIZE; return ma->sum / SAMPLE_SIZE; } // 自适应阈值计算 float Calculate_Dynamic_Threshold(float current_value, float *history, int size) { float avg = 0, std_dev = 0; // 计算平均值 for(int i=0; i<size; i++) { avg += history[i]; } avg /= size; // 计算标准差 for(int i=0; i<size; i++) { std_dev += (history[i] - avg) * (history[i] - avg); } std_dev = sqrt(std_dev / size); // 动态阈值 = 平均值 ± 2倍标准差 return avg + 2 * std_dev; }

5. 系统优化与实测结果

5.1 低功耗优化

为了延长电池供电时间,我做了以下优化:

  1. 传感器间歇工作:非必要时不采集数据
  2. STM32睡眠模式:在空闲时进入Stop模式
  3. 显示控制:无操作时降低刷新率或关闭显示
  4. 无线通信:采用定时上报而非持续连接

实测下来,优化后的系统在锂电池供电下可以连续工作2周以上。

5.2 抗干扰设计

在水产养殖场实测时,发现以下干扰问题:

  1. 传感器信号受电磁干扰
  2. 无线通信距离受限
  3. 长期使用后传感器漂移

解决方案:

  1. 信号线使用屏蔽线
  2. 增加软件滤波算法
  3. 定期自动校准

5.3 实测数据对比

在三个不同场景下测试系统性能:

测试场景水位误差浑浊度误差温度误差pH误差
实验室标准溶液±0.5cm±2%±0.2℃±0.1
养殖池塘±1.2cm±5%±0.5℃±0.3
污水处理厂±2.0cm±8%±1.0℃±0.5

从测试结果看,系统在相对清洁的环境中表现更好,这也符合传感器的工作特性。

6. 扩展应用与改进方向

6.1 物联网集成

通过ESP8266模块,可以将数据上传到云平台,实现远程监控。我在项目中使用了MQTT协议,代码示例如下:

void MQTT_Publish_Data(float water_level, float turbidity, float temp, float ph) { char payload[128]; snprintf(payload, sizeof(payload), "{\"water_level\":%.1f,\"turbidity\":%.1f,\"temperature\":%.1f,\"ph\":%.1f}", water_level, turbidity, temp, ph); if(mqttClient.connected()) { mqttClient.publish("sensor/data", payload); } }

6.2 移动端应用

开发了配套的Android应用,主要功能包括:

  1. 实时数据显示
  2. 历史数据曲线
  3. 阈值设置
  4. 报警通知

6.3 未来改进方向

  1. 增加更多水质参数监测,如溶解氧、电导率等
  2. 采用机器学习算法进行水质评估
  3. 设计防水外壳,提高户外使用可靠性
  4. 开发太阳能供电版本

在实际部署过程中,我发现防水设计尤为重要。有一次设备因为外壳密封不严导致进水损坏,后来改用IP67等级的防水盒就再没出过问题。