Appearance
手把手教你玩转测速模块(原理+驱动)
测速是现代化测控系统中不可或缺的一部分,它通过精确测量物体或现象的速度,为众多应用领域提供了关键的数据支持。无论是车辆行驶的速度监测,还是工业自动化中的生产线控制,甚至是科学实验中的粒子速度测量,测速模块都发挥着至关重要的作用。
测速模块的工作原理基于多种物理效应和先进技术,如多普勒效应、光电传感、光耦传感等,这些技术使得测速模块能够快速、准确地捕捉到速度信息。此外,测速模块还具有响应速度快、精度高等特点,使其在各种复杂环境下都能可靠工作。
本文将深入探讨测速模块之一的电机测速模块工作原理、技术实现和应用案例,帮助您更好地了解这一模块。
1. 源码下载及前置阅读
- STM32F103C8T6模板工程
链接:https://pan.baidu.com/s/1gJigWypYfwLo2cn2nP2DGg?pwd=yqya 提取码:yqya
- 本文的源码
链接:https://pan.baidu.com/s/1Hm47Z_UF6zwBj5fc3IT8DQ?pwd=v1su 提取码:v1su
如果你是嵌入式开发小白,那么建议你先读读下面几篇文章。
- 从零开始轻松掌握STM32开发的必备指南:零基础快速上手STM32开发(手把手保姆级教程)
- 通俗易懂的 GPIO 介绍与实践:如何快速成为点灯大师?
- 手把手让你掌握MDK的使用方式和技巧,助你更高效地进行开发:一文教你使用MDK开发工具
往期教程,有兴趣的小伙伴可以看看。
- 继电器模块的原理、功能和应用:继电器模块详解
- 如果想知道自己对嵌入式知识掌握程度:嵌入式自测题
- 蓝牙模块详解,轻松掌握一种无线通信技术:手把手教你玩转蓝牙模块(原理+驱动)
2. 测速模块介绍
2.1 测速模块型号介绍
测速模块常见用途:
- 电机转速检测
- 脉冲计数
- 位置限位
- 工件计数
常见的测速模块有以下三款,大同小异,都是接三个引脚(四引脚的那款 AO 引脚不起作用),除了正负极就是数字输出(OUT)。小差别已经写在图上啦。
大家在学习和工作中可以自行选择合适的型号,这里我使用的是宽槽,光耦传感器的这个型号。
2.2 测速模块参数及引脚介绍
测速模块参数:
- 使用进口槽型光耦传感器,槽宽度 10mm
- 有遮挡,输出高电平;无遮挡,输出低电平
- 有输出状态指示灯,输出高电平灯灭,输出低电平灯亮
- 使用宽电压 LM393 比较器
- 比较器输出,信号干净,波形好,驱动能力强,超过 15mA
- 工作电压:3.3V ~ 5V
- 输出形式:数字开关量输出(0 和 1)
- 设有固定螺栓孔,方便安装
- 小板 PCB 尺寸:2.3cm x 2cm
参考接线如下:
测速模块 | STM32 | 备注 |
---|---|---|
VCC | 3.3/5V | 电源正极 |
OUT | 任意 GPIO 口 | 数字输出 |
GND | GND | 电源负极 |
OUT 连接:
- 与单片机 IO 口直接相连,检测传感器是否有遮档,如用电机码盘则可检测电机的转速。
- 与继电器相连,组成限位开关等功能。
- 与有源蜂鸣器模块相连,组成报警器。
3. 使用逻辑
接下来让我介绍一下利用测速模块测距离和测速度的逻辑。
我们知道:
- 测速模块槽中无遮挡时,输出低电平;遮挡时,输出高电平
- 圆周长,C = 2×3.14×r = 3.14×d
拿我的 TT 马达和配套的轮胎(直径6.5cm)、码盘(20个格子)举例。
码盘每经过一个格子,会遮挡(高电平)和不遮挡(低电平)。
20格的码盘转一圈就会经历20个下降沿中断,一个下降沿中断就是走了 3.14×6.5/20 = 1.0205cm,约等于一个中断走1cm。
测距离:计算中断次数,即距离。
测速度:利用定时器,1 秒内接收多少个外部中断,即每秒速度。
其他轮胎或码盘可套用公式:
测距离 = 3.14×直径/码盘格子×中断次数。
测速度 = 定时器每秒输出 3.14×直径/码盘格子×中断次数,记得重置中断次数。
4. 编程实战
实战目标:串口输出电机旋转距离(cm)和速度(cm/s)。
4.1 硬件接线
本教程使用的硬件如下:
- 单片机:STM32F103C8T6
- 测速模块:宽槽,光耦传感器
- 电机:TT马达(和配套码盘)
- 串口:USB 转 TTL
- 烧录器:ST-LINK V2
测速模块 | STM32 | USB 转 TTL |
---|---|---|
VCC | 3.3/5V | |
OUT | A4 | |
GND | G | |
A10 | TX | |
A9 | RX | |
G | GND |
烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。
ST-Link V2 | STM32 |
---|---|
SWCLK | SWCLK |
SWDIO | SWDIO |
GND | GND |
3.3V | 3V3 |
接好如下图,大家可以不用接轮胎。
4.2 初始化引脚
初始化一下测速模块的 OUT 引脚。
我们采用中断的方式计数,需要初始化和使能一下 EXTI。
c
void GPIO_Init(void)
{
GPIO_InitTypeDef gpio_initstruct;
SP_CLK(); //IO口时钟使能
gpio_initstruct.Pin = SP_PIN; //OUT引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; //下降沿触发
gpio_initstruct.Pull = GPIO_NOPULL; //无电阻
HAL_GPIO_Init(SP_GPIO, &gpio_initstruct); //初始化OUT引脚
HAL_NVIC_SetPriority(EXTI4_IRQn,2,0); //抢占优先级2,响应优先级0
HAL_NVIC_EnableIRQ(EXTI4_IRQn); //使能EXTI4
}
4.3 设计中断
我们每次检测到测速模块的下降沿,速度和距离都加1。
因为 TT 马达的轮胎搭配上码盘,刚好每格大约1cm,所以我们直接加1,大家根据硬件不同自行调整。
c
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(SP_PIN); //调用中断处理公用函数 清除中断线 的中断标志位
__HAL_GPIO_EXTI_CLEAR_IT(SP_PIN); //HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == SP_PIN)
if (HAL_GPIO_ReadPin(SP_GPIO, SP_PIN) == GPIO_PIN_RESET){
speedCnt++;
distant++;
}
}
4.4 设计定时器
我们使用通用定时器2,设计初始化和中断。根据实战目标,我们希望定时器每秒溢出。
当定时器溢出,输出当前速度和行驶距离,并把当前速度归零。
定时器溢出时间计算方法:
公式:Tout = ((ARR + 1) * (PSC + 1)) / Ft (单位:us)。
已知 Tout = 1s;Ft,定时器工作频率,是 72Mhz。
那么公式里还剩下两个未知数,我们一般设定 PSC,求 ARR。
为了计算方便,Ft = 72M,所以我们 PSC 取7199(可取范围1~65535)。
于是,1 = ((ARR + 1) * (7199 + 1)) / 72000000。
计算可得,ARR = 9999。
c
void TIM2_Init(void)
{
htim2.Instance = TIM2; //通用定时器2
htim2.Init.Prescaler = 7199; //设置预分频系数(PSC)
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; //递增计数模式
htim2.Init.Period = 9999; //自动装载值(ARR)
HAL_TIM_Base_Init(&htim2); //初始化定时器2
HAL_TIM_Base_Start_IT(&htim2); //使能定时器2及其更新中断
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE(); //定时器2时钟使能
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); //抢占0,响应0
HAL_NVIC_EnableIRQ(TIM2_IRQn); //开启TIM2中断
}
}
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2); //定时器中断公共处理函数
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
printf("当前速度: %d cm/s \r\n", speedCnt);
printf("行驶距离: %d cm \r\n\r\n", distant);
speedCnt = 0;
}
4.5 主函数
主函数如下,用的是定时器溢出和中断,所以主函数里没写什么。
c
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
uart1_init(115200); /* 波特率设为115200 */
speed_init(); /* 定时器2初始化 */
printf("测速模块...\r\n");
TIM2_Init(); /* 定时器2初始化 */
while(1)
{
}
}
4.6 最终效果
串口输出如下,TT 马达的工作电压在 3~6V,这是我接单片机 3.3V 的速度,大概是 40 cm/s。
这是我接单片机 5V 的速度,大概是 55 cm/s。电压越大转速越大,测速模块工作正常。
5. 小结
测速模块作为现代科技中不可或缺的一部分,为我们提供了精确、实时的速度测量。随着技术的不断进步和创新,我们可以期待测速模块在未来的发展中发挥更重要的作用。它将继续为我们提供准确、可靠的速度测量解决方案,并为各行各业的发展做出贡献。
本文通过介绍测速模块的原理、工作方式以及应用场景,希望能够帮助大家对测速模块有更全面的了解,并激发对该技术的兴趣。感谢各位看官,peace and love!