DIY 液体流量检测仪
1、项目概述
"Let's do活动"是DigiKey联合EEPW发起的为期一年的"跟着E课堂学技术,完成任务返现"活动。本次活动是2024年的第4期,也是2024年最后一期。
本项目通过小抽水泵和继电器实现流量控制,结合霍尔效应传感器,准确测量液体的流速,实现瞬时流量和累计流量的监测。另外还添加了USART1收发命令功能,实现了远程控制的定量抽水功能。
2、硬件设计
系统框图&电路原理图
后来担心干扰问题换成了电池供电,一直没有换回去,所以后来实际框图如下:
3、主要参数情况
STM32 开发板 - NUCLEO-F103RB
STM32F103RB芯片的开发板,STM32F103RB为主流增强型ARM Cortex-M3 MCU,具有128 KB Flash和20 KB的SRAM、72 MHz CPU、电机控制、USB和CAN
OLED 显示屏 - 104020208
模块中的屏是中景园的ZJY-2864KSWPG01,单白色OLED显示屏,尺寸为0.96"(24.38mm),像素为128 x 64,接口为I2C,控制器为SSD1315。
抽水泵 - COM3700
Digikey提供的链接不知道为什么打不开,在淘宝上找到类似的潜水泵参数如下:(实际似乎流量小不少)
l 直流电源3V电流:约190mA,扬程:约35-40厘米,流量:约1.4L/分钟
l 直流电源5V电流:约400mA,扬程:约65-70厘米,流量:约2.L分钟
l 使用介质:水,不能有颗粒杂质;水温:60度以下。
液体流量传感器 - 314150001
液体流量传感器由塑料阀体、水轮和霍尔效应传感器组成。当水流经转子,转子随之转动。其转速随流量的不同而变化。霍尔效应传感器输出相应的脉冲信号。这款传感器适用于饮水机或咖啡机的流量检测。
l 工作电压:DC 5V~24V
l 流量范围:0.3~6L/min
继电器模块 - DFR0017
l 额定电压:5V
l 最大切换电流:10A(常开)5A(常闭)
l 最大切换电压:150VAC 24VDC
l 控制信号:TTL 电平
l 时间动作:≤10ms
l 释放时间:≤5ms
l 额定负载:10A 277VAC(常开)10A 28VDC(常开),5A 250VAC(常闭)
l 最大切换功率:AC1200VA DC240W(常开)AC625VA DC120W(常闭)
l 接触动作时间:10 毫秒
电源模块 - DFR0140
内置LM1117-5.0和AMS1117-3.3两款LDO的电源模块,包含开关和电源状态指示灯。
l 输入电压:6-12V (DC2.1电源插孔) 、5V (USB)
l 输出电压:3.3V和5V
l 输出电流:500mA
4、实现步骤
4.1 单元模块调试
个人开发的顺序是GPIO输出(灯和继电器);OLED显示;USART1通讯;转子流量计采样;整合。
4.1.1 GPIO及继电器
直接用开发板的模版生成Cubemx工程,然后按照上图配置添加RELAY,生成的代码自动包含了驱动,用的时候使用下面函数即可开关继电器:
HAL_GPIO_WritePin(GPIOA, RELAY_Pin, GPIO_PIN_SET); //开继电器
HAL_GPIO_WritePin(GPIOA, RELAY_Pin, GPIO_PIN_RESET); //关闭继电器
4.1.2 OLED
找中景园淘宝客服要了个驱动,照下图配置SDA和SCL引脚:
再把oled.h里面的
#define OLED_SCL_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)//SCL
#define OLED_SCL_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)
#define OLED_SDA_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DIN
#define OLED_SDA_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)
改为:
#define OLED_SCL_Clr() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET) //SCL
#define OLED_SCL_Set() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET)
#define OLED_SDA_Clr() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET)//DIN
#define OLED_SDA_Set() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET)
即可,至于驱动里面的LED实际没有使用,RES也安排到不用的一个GPIO上了,并没有接。
这样接好线一次点亮成功。
4.1.3 USART1
参考了很多网上的帖子,最终采用DMA+IDLE的方式,主要是比较有实际意义,可以接收不定长的字节。配置CubeMX如下:
在main.c添加:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t Size)
{
if(huart == &huart1) //判断是否是串口一的中断
{
HAL_UART_DMAStop(huart); //暂停DMA接收
__HAL_UNLOCK(huart); //解锁串口状态
//这里添加处理代码
memset(USART1RxBuffer,0,16); //清除接收到的数据
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,USART1RxBuffer,15); //再次开启DMA空闲中断
}
}
就可以接收不定长的UART数据了。发送调用:
HAL_UART_Transmit(&huart1,USART1RxBuffer,strlen((const char *)USART1RxBuffer),10);//将接收到的数据发送出去
这里USART1只实现了发送一个数字给单片机,比如发送了1,单片机就会出水100ml;发送2,单片机就会出水200ml;以此类推。
4.1.4 转子流量计采样
使用Timer1的CH1输入端口,CubeMX配置如下:
在main.c添加:
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
iFreq++;
}
}
使Timer1CH1收到一个下降沿就将iFreq++;
4.1.5 整合
为了整合所有功能,添加了一个定时器TIM4,每0.5s触发一次中断。CubeMX配置如下:
在main.c添加回调函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //200ms
{
if(htim->Instance == TIM4)//判断进入定时1通道回调函数
{
HAL_GPIO_TogglePin(GPIOA, LD2_Pin);
if(iFreq > 0)
{
InstantaneousFlow = (float)iFreq/4.35; //30-32Hz //需要校准 更常见的是iFreq*x+y的校准方式
totalFlow += InstantaneousFlow; //ml
if(totalFlow > TargetFlow || TargetFlow-totalFlow < 0.5) //计算流量接近或超出目标遛量 //需要校准
{
HAL_GPIO_WritePin(GPIOA, RELAY_Pin, GPIO_PIN_RESET); //关闭继电器
TargetFlowU8 = 0;
}
iFreq = 0;
}
sprintf(DispBuf,"%4.2fmL",InstantaneousFlow); // 瞬时流量
OLED_ShowString(64+8,16,(uint8_t *)DispBuf,16,1);
sprintf(DispBuf,"%04dmL",(short)totalFlow); // 累计流量
OLED_ShowString(64+8,32,(uint8_t *)DispBuf,16,1);
OLED_Refresh();
if(TargetFlowU8)
{
HAL_GPIO_WritePin(GPIOA, RELAY_Pin, GPIO_PIN_SET);
}else{
HAL_GPIO_WritePin(GPIOA, RELAY_Pin, GPIO_PIN_RESET);
}
}
}
每次进入中断就会判断收到几个下降沿,通过计算即可获得瞬时流量和累计流量,并显示到OLED上。如果流量到达设定值就停止抽水。当然这里是中断回调函数,其实不应该做过多的处理,应该放到main函数的while(1)里面运行,这里就先实现个功能。
5、软件调试
借用新哥老师的方法,找来厨房秤加量杯进行校准,多次校准以后每次抽水100ml基本都在100g-101g。这里要注意的是刚开始抽水的一会其实是不出水的,刚关闭继电器的时候还会有一些水出来。这个都是物理决定的,所以我缩短了水泵与转子流量计之间管子的长度,并且将水位尽量提高,使转子流量计很快就能出水、断水,减小了误差。
当然实际使用的时候肯定要对各种流量数据进行精确标定,还要模拟不同的环境(一般常见的是温度、压力等),这样才能做出一个精确定量出水的机器。
6、项目代码
7、效果演示
最后实现了通过USART1发送定量取水几百ml,单片机收到指令后通过继电器控制水泵抽水,同时通过转子流量计监测出水量并显示,到达指定量后关闭水泵,等待下次命令。这个原型可以很容易地增加无线接口,比如蓝牙或者Wifi,实现远程控制,甚至可以实现出差在外,远程遥控给植物定量浇水。当然,添加温湿度传感器和AI边缘控制器,结合当地天气数据实现AI自动浇水也是顺理成章的事。
EETV成果视频链接:https://v.eepw.com.cn/video/play/id/16224