粉丝提问,NPN型脉冲风速变送器怎么求得风速
,平时很支持小哈哥工作的小伙伴有需求,小哈哥必须安排,这次发文总结一下,希望可以帮助大家。
NPN型脉冲风速变送器的使用方法,详见如下视频教程:
本文测试工程源码的获取方式,在上面展示视频结尾处获取。
欢迎关注小哈哥的视频号,更多精彩敬请期待。
产品型号命名规则如下:
由上面风速变送器上的标签可知,该风速仪的型号为:VMS-3000-FSJT-NPN,对比命名规则,我们可知这是一个不带内部上拉电阻的NPN输出的风速变送器。
脉冲输出型风速变送器风速和脉冲个数的换算关系如下:
由上我们可以得出,我们只要计算出来,一秒钟之内脉冲的个数N就好了,通过脉冲个数N和上面截图中的已知信息,我们可以得到风速的换算关系如下:
风速=(1.75 / 20) * N
所以本模块应用的难点就是如何精准的计算单位时间内的脉冲个数。
由于本模块是NPN型,所以我们只需要使用棕色(+5V)、黑色(GND)、蓝色(与一个GPIO相连)三根线即可。
在编写代码之前,我们首先要确定风速变送器有脉冲输出,并确定输出的脉冲波形有什么特点,所以我们需要使用示波器先看一下输出的脉冲信号。
将棕色线与+5V电源相连,黑色线接地,蓝色线接入示波器。
查询手册,NPN型输出的等效电路如下所示:
注意: 经测试,必须在图中RL位置添加一个上拉电阻才能输出正常的方波!!!
当风速仪转动时,蓝线输出的方波信号如下:
我们由上可以看出,风速变送器输出的脉冲为0~5V的脉冲信号,所以为了系统的稳定性,我们需要选择一个具有FT标识的引脚。
FT:five volt tolerant 意思是兼容5V信号电压,后面带有FT标识的,说明可以容忍5V。
本实例,我们选择PB12为例。
风速仪 | STM32 | 说明 |
---|---|---|
棕色线 | +5V | 电源正 |
黑色线 | GND | 电源负 |
蓝色线 | PB12 | NPN-OUT |
为了计数脉冲的个数,我们使用外部中断来对脉冲进行计数,每来一个脉冲,外部中断执行一次。
void NPNInit()
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//使用外部中断需要开启RCC_APB2Periph_AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
//初始化IO口为输入
GPIO_InitStructure.GPIO_Pin = NPN_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(NPN_PORT, &GPIO_InitStructure);
//GPIOB.12中断线
EXTI_ClearITPendingBit(EXTI_Line12);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line12;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising; //上升沿中断
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
//中断初始化配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
在外部中断函数中,自定义全局变量msNPNCount加1,该值即记录了收到的脉冲个数。
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line12)==SET)
{
msNPNCount++;
EXTI_ClearITPendingBit(EXTI_Line12); // 清除中断标志
}
}
因为要记录单位时间内收到的脉冲个数,所以我们要占用一个定时器用来计时,我们随便选择一个定时器皆可,这里我们选择TIM4,下面代码对TIM4进行初始化:
//通用定时器中断初始化
//arr:自动重装值。
//psc:时钟预分频数
void TIM4_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能//TIM4时钟使能
//定时器TIM4初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置TIMx时钟频率的预分频值,16位
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
TIM_Cmd(TIM4,DISABLE);
}
main函数中调用定时器4的初始化函数如下:
TIM4_Init(1000-1,7200-1); //7200分频,10KHz,计数1K耗时100ms
TIM4_Set(1); //开启定时器
TIM4每100ms执行一次中断。
我们定义了两个全局变量,一个数组用于记录每100ms内收到的脉冲数,一个用于记录当前数组的索引:
u32 CounterArr[10];
u8 CounterIndex = 0;
在TIM4的定时器中断函数中,每次中断发生时,将脉冲计数保存在数组CounterArr中,然后脉冲计数清零,进入下一个定时周期进行计数。
//定时器4中断
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update );
//保存NPN脉冲计数
CounterArr[CounterIndex] = msNPNCount;
msNPNCount = 0;
CounterIndex++;
if(CounterIndex>=10)
CounterIndex=0;
}
}
在main函数中,周期计算风速值,CounterArr数组中存的十个脉冲数之和,即1秒内的脉冲总数,然后将脉冲总数*0.0875,所得的结果即为风速值。
if(times%200==0)
{
//计算风速值
nTotalNPNCounter = 0;
for(i=0;i<9;i++)
{
nTotalNPNCounter += CounterArr[i];
}
printf("风速为 %.2f m/s\r\n",nTotalNPNCounter*0.0875);
}
HC-SR04超声波测距原理及实现
红外遥控功能的实现
485型风速和风向变送器数据包解析
程序员小哈带你玩转嵌入式,微信搜索:嵌入式从0到1,更多干货等着你。
原创不易 点个在看支持下~