单片机|stm32+HAL库制作转速仪

stm32+HAL库制作转速仪 前言 电机在运行过程中,需要实时检测其转速的稳定性,有效反映电机的运行情况。
本文介绍了基于stm32的转速仪的设计,可以用光电门传感器和红外对管传感器测量,可以设置选择传感器、计数方式,可以显示测量结果。描述总体设计方案、器件选型,各模块原理分析、软件设计思路与过程。制作测试仪并从精度、稳定性等角度对其进行测试。测试得转速仪可以正常稳定工作,有结构简单、便携、易于操作等优点,适用于小型直流电机的转速测量。
本文展示用cubeMX+MDK制作一个红外测温枪的过程。
下载工程
关注公众号小电动车,回复"转速仪"获取工程文件及其他资料,建议结合keil工程阅读本文。
单片机|stm32+HAL库制作转速仪
文章图片

效果 单片机|stm32+HAL库制作转速仪
文章图片
{#fig:转速仪}
总体方案设计 方案 红外循迹模块与光耦测速模块分别实现远距测速与近程测速功能,测量小风扇时,每当有扇叶通过,模块输出一个脉冲,用stm32的计数器接收脉冲并计数,同时开启定时器进行一秒定时,则KaTeX parse error: Undefined control sequence: \mbox at position 1: \?m?b?o?x?{转速}=\frac{\mbo…
用stm32的adc与终端输入检测摇杆XYZ的输入,摇杆的Y向为切换扇叶数,范围为1 9,摇杆的X方向为切换红外测速(远距测速)和光电门测速(近程测速)。
stm32通过SPI与OLED通讯,显示屏显示转速、扇叶数和测速模式,按下摇杆的Z方向为切换OLED显示方向,同时用数码管辅助显示转速。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:总体方案框图}
供电模块 采用两节18650电池供电,经过降压稳压模块得到系统工作电压3.3V。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:供电模块}
主控 使用stm32f103c8t6最小系统板,处理速度数据、执行摇杆指令和控制显示模块。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:最小系统板}
测速模块 使用红外循迹模块实现远程测速。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:红外循迹模块}
使用光电门模块实现近程测速。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:槽型光耦传感器}
控制模块 使用双轴按键摇杆传感器模块,实现控制计数方式、切换传感器与显示屏翻转。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:双轴按键摇杆传感器}
显示模块 【单片机|stm32+HAL库制作转速仪】使用0.96寸OLED显示转速、计数方式和当前传感器。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:0.96寸OLED显示屏模块}
控制模块 使用四位数码管显示转速,由于测试设备转速有限,只启用两位,剩余两位备用。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:数码管}
组装 使用面包板作为载体,结合杜邦线、铜柱等固定所有模块,完成一个手持仪器。
单片机|stm32+HAL库制作转速仪
文章图片

测试设备 使用两节18650电池供电,经过电源模块得到8V、5V、3.3V。
使用三个开关分别接三个电压,另一边接直流减速电机,模拟三个档位。
使用直流减速电机驱动三扇叶小风扇,作为直接被测目标。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:手持测试仪}
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:手持测试仪}
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:手持测试仪}
硬件设计 电源模块 AMS1117芯片
AMS1117是一个正向低压降稳压器,它的稳压调整管是由一个PNP驱动的NPN管组成的,在1A电流下压降为1.2V。有AMS1117固定输出版本和可调版本,固定输出电压1.5V,1.8V,2.5V,2.85V,3.0V,3.3V,5.0V,具有1%的精度,固定输出电压为1.2V的精度为2%,典型电路如图3.1。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:AMS1117典型电路}
AMS1117典型电路
选用AMS1117-33芯片,将18650电池的8V电压转化为系统工作电压3V3
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:电源模块原理图}
PCB绘制
根据原理图3.2,使用Altium Designer 2019绘制PCB板
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:PCB板三维模型}
测速模块 红外循迹模块
红外对射计数传感器TCRT5000可用于电度表脉冲数据检测、传真机碎纸机纸张检测、障碍检测、黑白线检测。
其特性为:检测反射距离在1mm~25mm之间,输出形式为数字开关量输出(0和1)。TCRT5000型传感器的红外线发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于熄灭状态;被检测物体出现在检测范围内时,红外线被反射回来其强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:红外循迹模块电路图}
对射光电传感器
对射光电传感器广泛应用于电机转速检测,脉冲记数,位置限位等。
其特点是模块槽中无遮挡时,接收管道通,模块DO输出低电平;遮挡时,DO输出高电平;DO输出接口可以与单片机IO口直接相连,检测传感器是否有遮挡,如用电机码盘则可以检测电机的转速;模块DO可以与继电器相连,组成限位开关等功能。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:光电门模块电路图}
控制模块 双轴按键传感器
两路模拟量输出,一路数字量输出
Y轴输出为两个电位器,可以通过AD转换读出扭动角度向下按摇杆,可以出动一路轻触开关,为数字输出,已上拉适用于两自由度舵机云台控制或者其他遥控比例控制。
使用双轴按键摇杆传感器模块,实现控制计数方式、切换传感器与显示屏翻转。
软件设计 总体方案 单片机选用stm32f103c8t6,开发平台为STM32CubeMX和Keil
MDK,使用HAL库开发。系统主频为72MHz。
开启stm32的定时器提供标准时间,计数器接收传感器脉冲,ADC接收摇杆XY控制信号,外部中断接收摇杆Z信号,硬件SPI与OLED通信,使用12个GPIO驱动数码管,USART留作调试接口。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:stm32资源使用情况}
红外循迹模块与光耦测速模块分别实现远距测速与近程测速功能,测量小风扇时,每当有扇叶通过,模块输出一个脉冲,用stm32的计数器接收脉冲并计数,同时开启定时器进行一秒定时,则。KaTeX parse error: Undefined control sequence: \mbox at position 1: \?m?b?o?x?{转速}=\frac{\mbo…
用stm32的adc与终端输入检测摇杆XYZ的输入,摇杆的Y向为切换扇叶数,范围为1 9,摇杆的X方向为切换红外测速(远距测速)和光电门测速(近程测速)。
stm32通过SPI与OLED通讯,显示屏显示转速、扇叶数和测速模式,按下摇杆的Z方向为切换OLED显示方向,同时用数码管辅助显示转速。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:程序流程图}
定时器/计数器 开启stm32的定时器TIM3作为秒表,内部时钟输入。
stm32主频设置为72MHz。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:stm32时钟树}
设置TIM3分频数为7199,计数周期为9999,则计数频率
f = 72 , 000 , 000 H z ( 7199 + 1 ) ( 9999 + 1 ) = 1 H z f=\frac{72,000,000Hz}{(7199+1)(9999+1)}=1Hz f=(7199+1)(9999+1)72,000,000Hz?=1Hz
即每秒定时一次,同时开启中断,则每秒钟单片机会进入一次中断。
单片机|stm32+HAL库制作转速仪
文章图片

单片机|stm32+HAL库制作转速仪
文章图片

开启stm32计数器TIM1、TIM2接收测速传感器的脉冲,输入方式为外部脉冲,同时开启最大滤波以排除干扰。
单片机|stm32+HAL库制作转速仪
文章图片

单片机|stm32+HAL库制作转速仪
文章图片

则每当进入秒表中断时,读取计数器寄存器的值,并将该值与上一秒计数器的值作差(第一次时上一秒为0),得到的差即为计数值,该值除以叶片数(由摇杆Y方向控制,初始值为3)得到秒转速,该值可以提供给OLED显示。最后将当前计数器值保存为上一秒计数器值,以便下次调用。
定时器的中断回调函数放在文件counter.c中,程序如下

uint16_t CountThis, CountLast, CountDis; //定义计数器的值、上一秒计数器的值、转速 extern uint8_t Leaves, ModuleFlag; //定义叶片数、传感器标志 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器中断回调函数 { if(ModuleFlag == 0){//采集红外传感器脉冲 CountThis = htim2.Instance->CNT; } else{//采集光电门传感器脉冲 CountThis = htim1.Instance->CNT; } CountDis = (CountThis - CountLast)/Leaves; //计算转速 //printf("\t%d r/s\r\n",CountDis); OLED_ShowNum(48,0,CountDis,3,16); //OLED显示刷新 OLED_Refresh(); CountLast = CountThis; //将此次计数器值保存为上一秒计数值 }

ADC 开启stm32的两个ADC采集摇杆模块的XY控制信号。由于当前ADC采集范围为0 3.3V,采集精度为12位。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:stm32ADC参数配置}
故摇杆模块供电VCC=3.3V,则当当X或Y轴不偏时,VRX/VRY管脚电压为1.65V;X/Y轴正方向偏到最大时,VRX/VRY管脚电压为3.3V;X/Y轴负方向偏到最大时,VRX/VRY管脚电压为0V。此时用ADC管脚接收,读取ADC寄存器可分别得数值2000、4096、0即代表不偏、正偏最大、反偏。
由三个值可判断摇杆的控制信号,设定当Y轴正偏一次,叶片数+1,反偏一次,叶片数-1;当X轴正偏或反偏则切换两个传感器。
ADC的采集放在main函数的while中,以5ms/次的频率扫描,程序如下:
while (1) { Dis_2Num(CountDis); //数码管显示 HAL_Delay(5); //每5ms进行一次采集 HAL_ADC_Start(&hadc1); //开启adc1 VRX = HAL_ADC_GetValue(&hadc1); //采集adc1的值 HAL_ADC_Start(&hadc2); //开启adc2 VRY = HAL_ADC_GetValue(&hadc2); //采集adc2的值 if(VRY > 3500){//当VRY>3500,认为Y轴正偏一次 adc_Flag ++; HAL_Delay(10); if(adc_Flag == 2){ if(Leaves<9)Leaves ++; //叶片数+1 OLED_ShowNum(56,16,Leaves,1,16); //叶片数显示刷新 OLED_Refresh(); adc_Flag = 0; HAL_Delay(400); //增加延时避免一次识别为多次 } } else if(VRY < 500){//当VRY<500,认为Y轴正偏一次 adc_Flag ++; HAL_Delay(10); if(adc_Flag == 2){ if(Leaves>1)Leaves --; //叶片数-1 OLED_ShowNum(56,16,Leaves,1,16); //叶片数显示刷新 OLED_Refresh(); adc_Flag = 0; HAL_Delay(400); //增加延时避免一次识别为多次 } } if((VRX > 3500)||(VRX < 500)){//当VRX<500||VRX>3500,认为X轴偏一次 mol_Flag ++; HAL_Delay(10); if(mol_Flag == 2){ if(ModuleFlag == 0){//当前传感器为红外传感器时 ModuleFlag = 1; //切换为光电门传感器 OLED_ShowChinese(32, 48, 8, 16); //显示刷新 OLED_ShowChinese(48, 48, 9, 16); } else{//当前传感器为光电门传感器时 ModuleFlag = 0; //切换为红外传感器 OLED_ShowChinese(32, 48, 4, 16); //显示刷新 OLED_ShowChinese(48, 48, 5, 16); } mol_Flag = 0; HAL_Delay(400); //增加延时避免一次识别为多次 } } }

外部中断 在遥感模块VCC=3.3V,SW管脚接上拉电阻前提下,当Z不按下时SW管脚为3.3V,当Z按下时SW管脚为0V。
故开启管脚PA3的外部中断输入模式,接上拉电阻,检测上升沿,即可判断Z是否按下。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:TIM3配置}
extern uint8_t TurnFlag; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数 { if(GPIO_Pin == KEY_Z_Pin)//判断PA3接收到中断 { if(TurnFlag == 1)TurnFlag = 0; else TurnFlag = 1; OLED_DisplayTurn(TurnFlag); //反转屏幕指令 HAL_Delay(100); } }

SPI 开启stm32的spi控制OLED屏幕,调用HAL库SPI函数和现成OLED库函数可以控制OLED显示中文、数字、字幕。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:0.96寸OLED显示内容}
直接调用的上层函数有:
OLED_Init(); //OLED初始化 OLED_Clear(); //清除显示内容 OLED_DisplayTurn(TurnFlag); //显示方向设置 OLED_ShowChinese(0, 0, 0, 16); //显示中文 OLED_Printf(80, 0, "r/s", 16); //显示字母 OLED_ShowNum(56,16,Leaves,1,16); //显示数字 OLED_Refresh(); //显示刷新

数码管 由数码管的原理,由于本次显示内容少,显示要求低,stm32主频较高,故采用循环显示的方式。
由于stm32GPIO口的推挽输出模式可以提供足够大的电流,使LED有较高亮度,故本次不需要放大,直接在LED的阳极接推挽输出高电平,在LED的阴极接推挽输出低电平,配合控制代码可以显示数字。
开启stm32的十二个GPIO的推挽输出模式,其中八个作为阳极显示数字,四个作为阴极选择显示位置。
单片机|stm32+HAL库制作转速仪
文章图片
{#fig:数码管相关GPIO配置情况}
显示单个数字函数如下:(显示位置1,数字1,其余同理省略)
void Dis_Num(uint8_t DIG, uint8_t NUM) { switch(DIG) { case 1: HAL_GPIO_WritePin(DIG1_GPIO_Port,DIG1_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(DIG2_GPIO_Port,DIG2_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(DIG3_GPIO_Port,DIG3_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(DIG4_GPIO_Port,DIG4_Pin,GPIO_PIN_SET); break; …… } switch(NUM) { case 1: HAL_GPIO_WritePin(A_GPIO_Port,A_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(B_GPIO_Port,B_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(C_GPIO_Port,C_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(D_GPIO_Port,D_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(E_GPIO_Port,E_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(F_GPIO_Port,F_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(G_GPIO_Port,G_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(DP_GPIO_Port,DP_Pin,GPIO_PIN_RESET); break; …… } }

显示两个数字可通过除和取余提取个位与十位实现,函数如下:
uint8_t NumFlag = 0; //个位与十位显示顺序标志,交换顺序使两位显示时长对称 void Dis_2Num(uint8_t Number) { uint8_t Decade,Uint; Decade = Number/10; //除法取十位 Uint = Number%10; //取余取个位 if(NumFlag == 0){ Dis_Num(2,Decade); //显示十位 Dis_Num(3,Uint); //显示个位 NumFlag = 1; } else{ Dis_Num(3,Uint); Dis_Num(2,Decade); NumFlag = 0; } }

单片机|stm32+HAL库制作转速仪
文章图片
{#fig:显示效果}
到此转速仪已经完成。
单片机|stm32+HAL库制作转速仪
文章图片

下载 关注公众号小电动车,回复"转速仪"获取工程文件及其他资料,建议结合工程阅读本文。
单片机|stm32+HAL库制作转速仪
文章图片


    推荐阅读