基于STM32设计的水质检测装置

举报
DS小龙哥 发表于 2024/02/29 22:35:37 2024/02/29
【摘要】 一、前言随着健康意识的提升和环境保护的日益关注,水质安全已成为人们日常生活中不可忽视的重要问题。自来水作为日常生活中主要的饮用水源,其质量直接关系到我们的健康。因此,能够实时、方便地监测自来水水质显得尤为重要。本文介绍的是一款基于STM32F103ZET6微控制器的家用水质监测装置。该装置结合了先进的水质传感器和ADC(模数转换器)模块,通过STM32F103ZET6的强大处理能力和丰富的外...

一、前言

随着健康意识的提升和环境保护的日益关注,水质安全已成为人们日常生活中不可忽视的重要问题。自来水作为日常生活中主要的饮用水源,其质量直接关系到我们的健康。因此,能够实时、方便地监测自来水水质显得尤为重要。

本文介绍的是一款基于STM32F103ZET6微控制器的家用水质监测装置。该装置结合了先进的水质传感器和ADC(模数转换器)模块,通过STM32F103ZET6的强大处理能力和丰富的外设接口,实现了对自来水水质的实时检测与监测。

该装置的工作原理是:通过水质传感器实时采集自来水中的各种水质参数,如pH值、浊度、电导率等。随后,ADC模块将这些模拟信号转换为数字信号,便于STM32F103ZET6进行处理和分析。经过算法处理后,装置能够得出准确的水质参数值。

为了方便用户查看和理解,该装置还配备了一块0.96寸的OLED显示屏。用户只需将传感器浸入自来水中,即可在显示屏上直观地看到各项水质参数,从而轻松了解自来水的水质状况。

这款家用水质监测装置具有携带方便、操作简单、实时性强、精度高等特点。它不仅为家庭提供了一个简单方便的水质监测解决方案,也为人们关注水质安全、保护健康提供了有力的工具。


二、硬件选型

【1】主控芯片:STM32F103ZET6,这是一款基于ARM Cortex-M3内核的高性能微控制器。具有丰富的外设接口和较大的存储容量,适合用于处理水质传感器的数据采集和处理。

【2】水质传感器:自来水水质监测的传感器。

【3】显示屏:选择0.96寸OLED显示屏,可以在小尺寸的装置上显示采集到的水质数据。OLED显示屏具有高对比度、低功耗和快速刷新的特点,适合嵌入式应用。



三、常见的水质传感器

以下是一些常见的水质传感器类型,可用于家用自来水水质监测装置:

【1】pH传感器:用于测量水的酸碱度,即pH值。pH传感器通常基于玻璃电极原理,可以提供准确的pH值。

【2】溶解氧传感器:用于测量水中的溶解氧含量。溶解氧传感器可以采用膜式传感器或电极式传感器,根据测量原理的不同,提供溶解氧浓度的准确值。

【3】浊度传感器:用于测量水中的悬浮颗粒物的浓度或水的浊度。浊度传感器可以采用光散射原理或光吸收原理进行测量。

【4】电导率传感器:用于测量水中的电导率,即水的导电性。电导率传感器可以提供水中的总溶解固体(TDS)值或盐度值。


四、家用自来水的水质标准

以下是常见水质指标和标准参考:

【1】pH值:pH值表示水的酸碱度,一般应在6.5-8.5之间。

【2】浑浊度:浑浊度表示水中悬浮颗粒物的浓度,常用浊度单位为NTU(涡轮比色法浊度单位)。根据国际标准,家用自来水的浑浊度应小于1 NTU。

【4】溶解氧:溶解氧表示水中溶解的氧气含量,通常以毫克/升(mg/L)为单位。对于家用自来水,溶解氧的标准范围可以在5-8 mg/L之间。

【5】铁和锰:铁和锰是常见的金属元素,高浓度的铁和锰会给水带来颜色和异味。根据标准,家用自来水中的铁含量应小于0.3 mg/L,锰含量应小于0.1 mg/L。

【6】氟化物:氟化物是一种有益的微量元素,但高浓度的氟化物对人体有害。一般而言,家用自来水中的氟化物含量应小于1.5 mg/L。

【7】各种有害物质:家用自来水应符合国家或地区的相关法规和标准,以确保其不含有害物质,如重金属、有机污染物、农药残留等。


五、硬件代码

5.1 采集数据显示

#include "stm32f10x.h"
#include "oled.h"
​
// 定义ADC采集通道和引脚
#define ADC_CHANNEL   0   // 假设使用ADC1的通道0
#define ADC_PIN       GPIO_Pin_0
#define ADC_PORT      GPIOA
​
// 定义OLED屏幕相关参数
#define OLED_WIDTH    128
#define OLED_HEIGHT   64
​
// 全局变量
uint16_t adc_value = 0;   // ADC采集到的数值
​
// 函数声明
void ADC_Configuration(void);
void OLED_Init(void);
​
int main(void)
{
    // 初始化ADC和OLED
    ADC_Configuration();
    OLED_Init();
​
    while (1)
    {
        // 启动ADC转换
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
​
        // 等待ADC转换完成
        while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
​
        // 读取ADC转换结果
        adc_value = ADC_GetConversionValue(ADC1);
​
        // 在OLED上显示ADC采集的数值
        char str[10];
        sprintf(str, "%4d", adc_value);
        OLED_ShowString(0, 0, str);  // 在坐标(0, 0)位置显示字符串
​
        // 延时一段时间
        for (uint32_t i = 0; i < 100000; i++);
    }
}
​
// ADC配置函数
void ADC_Configuration(void)
{
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 使能ADC1和GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置ADC引脚为模拟输入
    GPIO_InitStructure.GPIO_Pin = ADC_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(ADC_PORT, &GPIO_InitStructure);
    
    // ADC配置
    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;
    ADC_Init(ADC1, &ADC_InitStructure);
​
    // 配置ADC通道
    ADC_RegularChannelConfig(ADC1, ADC_CHANNEL, 1, ADC_SampleTime_13Cycles5);
​
    // 使能ADC
    ADC_Cmd(ADC1, ENABLE);
​
    // 开启ADC校准
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1))
        ;
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1))
        ;
​
    // 设置ADC转换序列
    ADC_RegularChannelConfig(ADC1, ADC_CHANNEL, 1, ADC_SampleTime_13Cycles5);
}
​
// OLED屏幕初始化函数
void OLED_Init(void)
{
    // 初始化OLED屏幕
    OLED_Init();
    OLED_Clear();
}
​


5.2 oled.h

#ifndef __OLED_H__
#define __OLED_H__
​
#include "stm32f10x.h"
​
#define OLED_WIDTH      128
#define OLED_HEIGHT     64
​
void OLED_Init(void);
void OLED_Clear(void);
void OLED_WriteByte(uint8_t data, uint8_t cmd);
void OLED_SetPos(uint8_t x, uint8_t y);
void OLED_ShowChar(uint8_t x, uint8_t y, char ch);
void OLED_ShowString(uint8_t x, uint8_t y, const char* str);
​
#endif /* __OLED_H__ */
​


5.3 oled.c

#include "OLED.h"
​
const uint8_t OLED_GRAM[128][8] = {0};  // OLED显示缓存
​
void OLED_Init(void)
{
    // ... 初始化OLED屏幕的相关操作 ...
}
​
void OLED_Clear(void)
{
    // 清空OLED显示缓存(全黑)
    memset((void*)OLED_GRAM, 0x00, sizeof(OLED_GRAM));
​
    // 更新OLED屏幕显示
    OLED_SetPos(0, 0);
    for (uint8_t i = 0; i < 8; i++)
    {
        OLED_WriteByte(0xb0 + i, 0x00);  // 设置页地址(0-7)
        OLED_WriteByte(0x00, 0x00);  // 设置列地址低4位(0-3)
        OLED_WriteByte(0x10, 0x00);  // 设置列地址高4位(4-7)
​
        for (uint8_t j = 0; j < 128; j++)
        {
            OLED_WriteByte(0x00, 0x40);  // 写入数据,全黑
        }
    }
}
​
void OLED_WriteByte(uint8_t data, uint8_t cmd)
{
    // ... 将数据写入OLED屏幕的具体操作 ...
}
​
void OLED_SetPos(uint8_t x, uint8_t y)
{
    // ... 设置OLED屏幕显示位置的具体操作 ...
}
​
void OLED_ShowChar(uint8_t x, uint8_t y, char ch)
{
    uint8_t c = ch - ' ';  // 获取字库中的字模
​
    if (x >= OLED_WIDTH || y >= OLED_HEIGHT) return;
​
    for (uint8_t i = 0; i < 6; i++)
    {
        uint8_t line = cFont6x8[c][i];
​
        for (uint8_t j = 0; j < 8; j++)
        {
            if (line & 0x01)
            {
                OLED_GRAM[y + j][x + i] = 1;
            }
            else
            {
                OLED_GRAM[y + j][x + i] = 0;
            }
​
            line >>= 1;
        }
    }
​
    // 更新OLED屏幕显示
    OLED_SetPos(x, y / 8);
    for (uint8_t i = 0; i < 8; i++)
    {
        OLED_WriteByte(0xb0 + (y / 8) + i, 0x00);  // 设置页地址
        OLED_WriteByte((x & 0x0f), 0x00);  // 设置列地址低4位
        OLED_WriteByte((x >> 4) | 0x10, 0x00);  // 设置列地址高4位
​
        for (uint8_t j = 0; j < 128; j++)
        {
            OLED_WriteByte(OLED_GRAM[y + i][j], 0x40);  // 写入数据
        }
    }
}
​
void OLED_ShowString(uint8_t x, uint8_t y, const char* str)
{
    while (*str != '\0')
    {
        OLED_ShowChar(x, y, *str++);
        x += 6;
​
        if (x >= OLED_WIDTH)
        {
            x = 0;
            y += 8;
        }
    }
}
​
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。