编码器测速原理与实现

一、测速原理

通常情况下编码器旋转一周会输出固定的脉冲数,即编码器的分辨率,通过测量固定时间T内编码器输出的脉冲数即可求得电机的转速。
假设编码器的分辨率为P,T时间内测得脉冲数m个,则单倍频(编码器转动一圈输出的脉冲数与分辨率相同)情况下电机转速为:
在这里插入图片描述
(其中m/p为编码器转过的圈数,再除以时间即为转速)
编码器AB相输出两列相位差为90°的方波,当A相超前于B相90°时为正转,相反,B相超前于A相90°时为反转
在这里插入图片描述

为了提高采样精度,利用软件实现四倍频,即将编码器的分辨率提高4倍。原理图如上,一个小周期内AB两相分别各有一个上升沿和下降沿,只需要在AB两相的每个上升沿、下降沿进行采集,这样就实现了四倍频技术,即如果编码器分辨率为p,则现在编码器转动一圈就可以采集到4p个脉冲

二、CubeMX配置编码器模式

stm32的部分定时器有编码器模式,可以直接利用该功能采集编码器脉冲数
在这里插入图片描述
先配置串口,方便后期打印采集的数据

在这里插入图片描述
我这里采用定时器4做测速,选择编码器模式,Encoder Mode选择Encoder Mode T1 and T2,这个模式下将在AB相的上升沿和下降沿进行脉冲技术,即四倍频

在这里插入图片描述
配置一定时器用于定时读取和清空脉冲数,此处设置每500ms读取一次

在这里插入图片描述打开定时器全局中断

在这里插入图片描述
配置时钟

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

打开创建好的工程,在主函数中启动编码器脉冲采集和定时器中断
在这里插入图片描述
在这里插入图片描述
重定向
在这里插入图片描述
定时器中断服务函数中读取采集到的脉冲数,TIM2的计数值为0-65535,采用short int类型对其强制类型转换,若TIM2计数器值为0 ~ 32767,则强制转化后的值仍为0 ~ 32767,电机正转;
若TIM2计数器值为32768 ~ 65535,则强制转化后的值仍为-32768 ~ -1,电机反转;使用一阶滤波减小误差,每次采集的脉冲数保存至new_capturenumber,编码器转动一圈输出4096个脉冲,则new_capturenumber/4096为编码器转动的圈数,最后除以采集时间500ms就得到了电机转速(r/s)

三、利用外部中断采集脉冲

有些单片机没有编码器功能,如esp32,我们可以利用外部中断对编码器输出脉冲进行计数
在这里插入图片描述在这里插入图片描述
设置PE11 PE14的外部中断,上升沿、下降沿均触发

在这里插入图片描述
打开全局中断

在这里插入图片描述
配置一定时器每500ms读取一次脉冲值

在这里插入图片描述
打开定时器全局中断

在这里插入图片描述
编码器正反转时,脉冲波形如上图所示,我们可以先定义pulse_num来对脉冲进行计数
当A相下降沿时,若B相为低电平则为反转,pulse_num减一,若B相为高电平则为正转,pulse_num加一
当A相上升沿时,若B相为低电平则为正转,pulse_num加一,若B相为高电平则为反转,pulse_num减一
当B相下降沿时,若A相为低电平则为正转,pulse_num加一,若A相为高电平则为反转,pulse_num减一
当B相上升沿时,若A相为低电平则为反转,pulse_num减一,若A相为高电平则为正转,pulse_num加一
即:

/* USER CODE BEGIN 2 */
int pulse_num=0;
/* USER CODE BEGIN 2 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
//PE11 - A相发生中断
 if(GPIO_Pin==GPIO_PIN_11){
  //A相下降沿
  if(HAL_GPIO_ReadPin(GPIOE,A_phase_Pin)==0)
  {
    if(HAL_GPIO_ReadPin(GPIOE,B_phase_Pin)==0)
      pulse_num--;
    else
      pulse_num++;
  }
  //A相上升沿
  else
  {
    if(HAL_GPIO_ReadPin(GPIOE,B_phase_Pin)==0)
      pulse_num++;
    else
      pulse_num--;
  }
}


//PE14 - B相发生中断
else if(GPIO_Pin==GPIO_PIN_14){
  //B相下降沿
  if(HAL_GPIO_ReadPin(GPIOE,B_phase_Pin)==0)
  {
    if(HAL_GPIO_ReadPin(GPIOE,A_phase_Pin)==0)
      pulse_num++;
    else
      pulse_num--;
  }
  //B相上升沿
  else
  {
    if(HAL_GPIO_ReadPin(GPIOE,A_phase_Pin)==0)
      pulse_num--;
    else
      pulse_num++;
  }
		
}
}

在这里插入图片描述
最后在定时器中断函数中对采集到的脉冲个数处理,注意需要手动清空pulse_num

### 实现 STM32F4 外部中断用于编码器计数 为了实现 STM32F4 使用外部中断来处理旋转编码器的计数功能,需要配置 GPIO 和 EXTI (External Interrupt Line) 来响应编码器产生的信号变化。下面详细介绍具体方法。 #### 配置 GPIO 及中断线 首先,在初始化阶段设置好编码器连接的两个引脚作为输入模式,并启用上拉电阻以防止浮空状态[^2]: ```c GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); // 假设使用 PA口 // 编码器通道 A GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 编码器通道 B GPIO_InitStruct.Pin = GPIO_PIN_1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` 接着注册回调函数以便在发生边沿触发事件时调用特定逻辑处理程序[^3]: ```c void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ static int8_t lastStateChannelB = 0; if(GPIO_Pin == GPIO_PIN_0 || GPIO_Pin == GPIO_PIN_1){ uint8_t currentChannelA = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); uint8_t currentChannelB = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1); if(currentChannelA && !lastStateChannelB){ // CW direction encoderCount++; }else if(!currentChannelA && lastStateChannelB){ // CCW direction encoderCount--; } lastStateChannelB = currentChannelB; } } ``` 上述代码片段展示了如何读取当前两路的状态并据此更新全局变量 `encoderCount` 的值,以此达到记录转动方向的目的。注意这里假设了编码器采用的是四倍频方式工作;对于不同类型的编码器可能需要调整具体的判断条件。 #### 初始化 NVIC 并启动中断服务例程 最后一步是在主循环之前完成对NVIC控制器的相关设定以及使能对应线路的IRQ请求: ```c /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_NVIC_Init(); /* Add this function */ while(1){ // 主循环体... } static void MX_NVIC_Init(void){ __HAL_RCC_SYSCFG_CLK_ENABLE(); HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI1_IRQn); } ``` 以上就是利用STM32F4外部中断实现简单版旋转编码器计数的主要步骤。实际应用中还需考虑更多细节如防抖动措施等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sense_long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值