水流量传感器

YF-S401水流量传感器

简介

YF-S401水流传感器
​ 水流量传感器主要由塑料阀体、水流转子组件和霍尔传感器组成。装在热水器进水端,用于检测进水流量,当水通过水流转子组件时,磁性转子转动并且转速随着流量变化而变化,霍尔传感器输出相应脉冲信号,反馈给控制器,由控制器判断水流量的大小,进行调控。该模块以霍尔传感器为核心器件,每流经1L水就会产生固定的脉冲,有着三种型号:YF-S201(4分G1/2螺纹接口)、YF-S401(6mm软管接口),以及YF-S401(6mm软管)。型号不同的水流量传感器每升水流量产生的脉冲数不同,本文以YF-S401为例。

特性参数
额定工作电压DC3.5 5V-12V
最大工作电流15mA (DC5V)
允许耐压水压1.75Mpa以下
温度范围≤80°C

接线

YF-S401描述
VCC(红)正极,接5V
GND(黑)负极,接地
OUT(黄)信号输出

执行流程

​ 首先进行引脚配置及初始化、外部中断配置与初始化、以及定时器设置。随后,利用定时器设定1秒的时间间隔,计算在此时间段内触发的中断次数,通过中断次数推算水流量。

开始
初始化引脚
初始化定时器
初始化中断
计算脉冲数
定时1s
计算水流量
结束

工程介绍

​ 本次代码实现按键控制继电器实现12V直流水泵抽水并计算累计出水量和瞬时出水量,使用串口打印。在找到的水流传感器的参考代码中,只有4分管和6分管的流量系数而没有6mm水管的,所以自己测了一下YF-S401水流传感器在出水1L时大概会产生4800个脉冲(脉冲数有点离谱),以这个数据计算水流量并最后实现了功能。

外部中断计数

CubeMX配置

设备为STM32F407ZGT6

  1. 外部中断配置
  • 配置PA11为外部中断引脚
  • 下降沿触发,配置成上拉

在这里插入图片描述

  1. 定时器中断配置
  • 使用基本定时器TIM7,设置Prtscaler (定时器分频系数)为8400-1,Counter Period(自动重装载值)为10000-1

  • Counter Mode为向上计数模式,并自动重装使能

  • 定时器溢出时间 : T o u t = ( a r r + 1 ) × ( p s c + 1 ) T c l k 定时器溢出时间:T_{out} = \frac{{(arr + 1) \times (psc + 1)}}{T_{clk}} 定时器溢出时间:Tout=Tclk(arr+1)×(psc+1)

在这里插入图片描述

  1. NVIC配置

在这里插入图片描述

代码实现

  1. 定时器中断

在初始化后开启TIM7中断

  HAL_TIM_Base_Start_IT(&htim7);
  1. 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&htim7))
    {
        golbal_flow.receive_flag = 1;
    }
}
  1. 外部中断

外部中断回调函数中,实现按键对继电器的通断的控制和水流传感器的脉冲计数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY1_Pin)
	{
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 0)
		{
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,1);  //控制继电器通水
            golbal_flow.acculat = 0.0;              //清空累计流量
		}
	}
    if(GPIO_Pin == KEY2_Pin)
	{
        HAL_Delay(10);
        if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == 0)
		{
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,0);	//控制继电器停水
		}
    }
    if(GPIO_Pin == YFS401_Pin)
	{
        golbal_flow.pluse_1s++;           //下降沿采集脉冲数
    }
}
  1. 水流量计算
#include "YFS401.h"

GOLBAL_FLOW golbal_flow;

// 定义流量模型的枚举类型
typedef enum {
    MODE_4_PIPE = 0,   // 四分管
    MODE_6_PIPE = 1,   // 六分管
    MODE_6MM_PIPE = 2  // 6mm管
} FlowModel;

// 定义流量参数
float flowK[3] = {5.0f, 5.5f, 80.0f};                  // 流量系数 K
float pulseCntPerLiter[3] = {300.0f, 330.0f, 4800.0f}; // 每升水脉冲数

// 定义 Flow_Model
FlowModel flowModel = MODE_6MM_PIPE; // 默认使用6mm管


uint32_t pluse1L;           //测试1L水的脉冲数

//==============================================================================
// @函数: Flow_Read(void)
// @描述: 读取流量
// @参数: None
// @返回: None
// @时间: 2024.2.26
//==============================================================================
void Flow_Read(void)
{
    // 根据 Flow_Model 选择不同的流量参数
    float flowKValue = flowK[flowModel];
    float pulseCntValue = pulseCntPerLiter[flowModel];
    
	if(golbal_flow.pluse_1s > 0)
	{
		golbal_flow.acculat += (golbal_flow.pluse_1s * 1000 / pulseCntValue);   //单位mL
		pluse1L+=golbal_flow.pluse_1s;
		golbal_flow.instant = golbal_flow.pluse_1s / flowKValue;  //单位(L/min)

        if(golbal_flow.acculat >= 1000000)        //最大累计流量1000L
		{
			golbal_flow.acculat = 0;
		}
	}
	else
	{
		golbal_flow.instant  = 0;
	}
	
    printf("瞬间流量:%.2f(L/min) 累计流量:%.2f mL   脉冲数:%d \n",golbal_flow.instant,golbal_flow.acculat,golbal_flow.pluse_1s);
   
	golbal_flow.receive_flag = 0;   //接收完成标志位清零
    golbal_flow.pluse_1s = 0;       //脉冲数清零
}

根据多次测量水量并更改系数后,运行结果如下图所示:

在这里插入图片描述

外部时钟计数

CubeMX

  • 外部时钟配置

流程基本和上面一致,区别在于不配置外部中断,而是配置定时器外部时钟触发

在这里插入图片描述

代码实现

  1. 定时器中断

初始化TIM2和TIM7

	HAL_TIM_Base_Start(&htim2);

	HAL_TIM_Base_Start_IT(&htim7);
  1. 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&htim7))
    {
        golbal_flow.pluse_1s = __HAL_TIM_GET_COUNTER(&htim2);   //得到TIM2的脉冲计数
        __HAL_TIM_SET_COUNTER(&htim2,0);                        //TIM2计数清零
        
        golbal_flow.receive_flag = 1;
    }
}
  1. 水流量计算
#include "YFS401.h"

GOLBAL_FLOW golbal_flow;

// 定义流量模型的枚举类型
typedef enum {
    MODE_4_PIPE = 0,   // 四分管
    MODE_6_PIPE = 1,   // 六分管
    MODE_6MM_PIPE = 2  // 6mm管
} FlowModel;

// 定义流量参数
float flowK[3] = {5.0f, 5.5f, 80.0f};                  // 流量系数 K
float pulseCntPerLiter[3] = {300.0f, 330.0f, 4800.0f}; // 每升水脉冲数

// 定义 Flow_Model
FlowModel flowModel = MODE_6MM_PIPE; // 默认使用6mm管


uint32_t pluse1L;           //测试1L水的脉冲数

//==============================================================================
// @函数: Flow_Read(void)
// @描述: 读取流量
// @参数: None
// @返回: None
// @时间: 2024.2.26
//==============================================================================
void Flow_Read(void)
{
    // 根据 Flow_Model 选择不同的流量参数
    float flowKValue = flowK[flowModel];
    float pulseCntValue = pulseCntPerLiter[flowModel];
    
	if(golbal_flow.pluse_1s > 0)
	{
		golbal_flow.acculat += (golbal_flow.pluse_1s * 1000 / pulseCntValue);   //单位mL
		pluse1L+=golbal_flow.pluse_1s;
		golbal_flow.instant = golbal_flow.pluse_1s / flowKValue;  //单位(L/min)

        if(golbal_flow.acculat >= 1000000)        //最大累计流量1000L
		{
			golbal_flow.acculat = 0;
		}
	}
	else
	{
		golbal_flow.instant  = 0;
	}
	
    printf("瞬间流量:%.2f(L/min) 累计流量:%.2f mL   脉冲数:%d \n",golbal_flow.instant,golbal_flow.acculat,golbal_flow.pluse_1s);
   
	golbal_flow.receive_flag = 0;   //接收完成标志位清零
    golbal_flow.pluse_1s = 0;       //脉冲数清零
}

结果如下图所示:
在这里插入图片描述

STM32水流量传感器是一种利用STM32单片机核心板、水流量传感器、LCD1602液晶显示、按键、蜂鸣器及电源等组成的系统。其主要功能包括实时显示瞬时流量和累计流量、设置累计流量阈值、报警、继电器控制水阀开关等。具体特点如下: 1. 水流量传感器采用椭圆齿轮传感器,能够准确测量水流量。 2. 通过液晶LCD1602液晶实时显示瞬时流量和累计流量、设置的累计流量,方便用户了解水流量情况。 3. 通过按键设置累计流量阈值,如果累计流量超过设置阈值,蜂鸣器报警、继电器断开,否则不报警继电器闭合,保证水流量在安全范围内。 4. 继电器模拟水阀开关,如果当前累计流量低于设置流量,打开继电器打开水阀的意思,方便用户控制水流量。 5. 按键有设置按键、设置+、设置-,在设置情况下可以对设置值进行加减运算,方便用户设置累计流量阈值。 代码示例: ```c //定义引脚 #define FlowPin PA0 #define RelayPin PA1 #define BeepPin PA2 #define Key1Pin PA3 #define Key2Pin PA4 #define Key3Pin PA5 //定义变量 float flow = 0; //瞬时流量 float total = 0; //累计流量 float setTotal = 100; //设置的累计流量 int alarm = 0; //报警标志 int relay = 0; //继电器状态 int key1 = 0; //设置按键状态 int key2 = 0; //设置+按键状态 int key3 = 0; //设置-按键状态 void setup() { pinMode(FlowPin, INPUT); pinMode(RelayPin, OUTPUT); pinMode(BeepPin, OUTPUT); pinMode(Key1Pin, INPUT_PULLUP); pinMode(Key2Pin, INPUT_PULLUP); pinMode(Key3Pin, INPUT_PULLUP); Serial.begin(9600); } void loop() { flow = pulseIn(FlowPin, HIGH); //读取瞬时流量 flow = flow / 7.5; //转换为L/min total += flow * 0.05; //累计流量 if (total >= setTotal) { //如果累计流量超过设置阈值 alarm = 1; //报警 digitalWrite(RelayPin, LOW); //继电器断开 digitalWrite(BeepPin, HIGH); //蜂鸣器报警 } else { alarm = 0; //不报警 digitalWrite(RelayPin, HIGH); //继电器闭合 digitalWrite(BeepPin, LOW); //蜂鸣器不报警 } key1 = digitalRead(Key1Pin); //读取设置按键状态 key2 = digitalRead(Key2Pin); //读取设置+按键状态 key3 = digitalRead(Key3Pin); //读取设置-按键状态 if (key1 == LOW) { //如果按下设置按键 while (digitalRead(Key1Pin) == LOW); //等待按键释放 delay(10); if (key2 == LOW) { //如果同时按下设置+按键 while (digitalRead(Key2Pin) == LOW); //等待按键释放 delay(10); setTotal += 10; //设置值加10 } else if (key3 == LOW) { //如果同时按下设置-按键 while (digitalRead(Key3Pin) == LOW); //等待按键释放 delay(10); setTotal -= 10; //设置值减10 } } Serial.print("Flow: "); Serial.print(flow); Serial.print(" L/min, Total: "); Serial.print(total); Serial.print(" L, SetTotal: "); Serial.print(setTotal); Serial.print(" L, Alarm: "); Serial.print(alarm); Serial.print(", Relay: "); Serial.println(relay); delay(50); } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值