这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sdo第四期-DIY液体流量检测仪-过程帖

共1条 1/1 1 跳转至

Let'sdo第四期-DIY液体流量检测仪-过程帖

菜鸟
2025-01-25 22:08:09     打赏

在上一个开箱帖中简单介绍了本次活动的开发板和各个模块,在本贴中,将对各个模块进行简单的测试及驱动。

首先是开发板的驱动:当拿到一个开发板的时候,第一个烧录的程序通常是点灯操作。keil的操作相信大家都非常熟悉,本次使用的keil模板是单片机是STM32F103C8T6,我们只需在Device中将单片机型号换成STM32F103RB即可使用。

image.png

查阅原理图,发现开发板上共有3个灯,最上面的是st-link指示灯,LD3是电源指示灯,需要我们点亮的是LD2。

image.png

在原理图上LD2绿灯与PA5和PB13都进行了连接,那么如何判断它连接的是PA5还是PB13呢?开发板背面有我们需要的答案!

图片1.jpg

可以看到SB42焊接了0Ω的电阻,而SB29没有。由此可以判断,LD2绿灯与PA5相连。那么下面的操作就非常简单了。

首先是创建.h和.c文件

led.h

#ifndef __LED_H__
#define __LED_H__

#include "stm32f10x.h"

#define RCC_GPIO RCC_APB2Periph_GPIOA
#define RCC_GPIO_LED RCC_APB2Periph_GPIOA
#define LED_GPIO GPIOA
#define LED_GPIO_Pin GPIO_Pin_5

void led_init(void);
void led_on(void);
void led_off(void);

#endif

led.c

#include "LED.h"

void led_init(void)
{
    GPIO_InitTypeDef GPIOA_Initstruct;
    RCC_APB2PeriphClockCmd(RCC_GPIO, ENABLE);
    GPIOA_Initstruct.GPIO_Pin = LED_GPIO_Pin;
    GPIOA_Initstruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIOA_Initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_GPIO, &GPIOA_Initstruct);
}

void led_on(void)
{
    GPIO_SetBits(LED_GPIO, LED_GPIO_Pin);
}

void led_off(void)
{
    GPIO_ResetBits(LED_GPIO, LED_GPIO_Pin);
}

在main.c中添加头文件并初始化,即可点亮LD2。效果如下:

点灯图片.jpg

继电器的驱动与LED的驱动类型,都是通过给引脚高低电平开实现功能,只是最终实现的功能不同。继电器的实现效果如下:

0b93653c2a41128370de3089e5761fa.jpg

给下面的信号线高电平时,继电器模块上的红灯会亮,COM与NO连通。下面是LCD显示模块的驱动,因为LCD模块的显示驱动比较复杂,我们可以将别人写好的模块移植到我我们这块开发板上面。在本次实验中,使用的时软件模拟IIC,所以可以任意选择SDA和SCL,因此选择PC2位SDA,PC3为SCL。使用LCD取模软件获得”瞬间流量“和”累计流量“的数组,将其存入到oledfront.h中。

在main.c中初始化及驱动后,效果如下

1dc8efe5654f1bb4bfd460d6f78b1b6.jpg

最后是比较复杂的流量传感器,它是一种叶轮式水流量传感器,工作原理是当水通过传感器时,会推动叶轮旋转,叶轮上装有磁铁,每旋转一圈时,磁场的变化会被霍尔传感器检测到,霍尔传感器将磁场变化转换为电脉冲信号,脉冲的频率与水流速度成正比。由公式Q=kf即可计算出水流速。在本次实验中,使用中断来接收脉冲信号。

YF_S401.h

#ifndef __YF_S401_H__
#define __YF_S401_H__

#include "sys.h"
#include "stdlib.h"
#include "stm32f10x.h"

//定义流量相关参数
typedef struct
{
    float instant; // 瞬时流量
    float acculat; // 累计流量
    float cnt;     // 脉冲数
} GOLBAL_FLOW;

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

//引脚定义
#define YF_S401_RCC RCC_APB2Periph_GPIOA
#define YF_S401_GPIO GPIOA
#define YF_S401_GPIO_PIN GPIO_Pin_1
#define YF_S401_EXTI_Line EXTI_Line1

//函数定义
void bsp_YF_S401_Init(void);
void Flow_Read(void);

#endif // ! __YF_S401_H__

YF_S401.c

#include "YF_S401.h"

GOLBAL_FLOW golbal_flow;

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

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

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

void bsp_YF_S401_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	EXTI_InitTypeDef EXTI_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;

	RCC_APB2PeriphClockCmd(YF_S401_RCC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = YF_S401_GPIO_PIN;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(YF_S401_GPIO, &GPIO_InitStruct);

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
	EXTI_InitStruct.EXTI_Line = YF_S401_EXTI_Line;
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStruct);

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 

	NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

/**
 * @brief 读取YF-S40流量传感器流量
 *
 */
void Flow_Read(void)
{
	// 根据 Flow_Model 选择不同的流量参数
	float flowKValue = flowK[flowModel];
	float pulseCntValue = pulseCntPerLiter[flowModel];

	if (golbal_flow.cnt > 0)
	{
		golbal_flow.acculat += (golbal_flow.cnt * 1000 / pulseCntValue); // 单位mL
		pluse1L += golbal_flow.cnt;
		golbal_flow.instant = golbal_flow.cnt / flowKValue; // 单位(mL/min)

		if (golbal_flow.acculat >= 1000000) // 最大累计流量1000L
		{
			golbal_flow.acculat = 0;
		}
	}
	else
	{
		golbal_flow.instant = 0;
	}
	golbal_flow.cnt = 0;
}

void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(YF_S401_EXTI_Line) != RESET)
	{
		golbal_flow.cnt++;
		EXTI_ClearITPendingBit(YF_S401_EXTI_Line);
	}
}

在上述代码中,每接收到一个上升沿,程序将产生一次中断,将脉冲数加1,然后再计算瞬间流量和累计流量,并再LCD屏上进行显示实时显示。此外,需要根据水泵的实际情况,对流量参数中的参数进行修改。

7546d8996361efa914f3ce8221d47ea.jpg

本帖是液体流量检测仪活动的过程贴,针对开箱贴中的各个模块进行简单驱动,实际效果并没有达到活动要求,后面将对程序进行调试,以达到实验要求。




关键词: 液体     流量     检测仪     过程贴    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]