【电机控制中编码器的使用】

简介

编码器:一种将直线位移、角位移数据转换为脉冲信号、二进制编码的设备。
常用于测量物体运动的位置、角度或者速度
编码器都至少有两个传感器,通过传感器接收时间差,产生ab两相脉冲,根据先后关系判断旋转方向(顺逆时针)。并且还可以根据单位时间收到的脉冲数确定旋转速度

分类

磁电+增量式:利用霍尔效应,将位移转换成计数脉冲,用脉冲个数计算位移和速度,ab两个传感器用于检测转向
在这里插入图片描述
在这里插入图片描述

光电+增量式:利用光电系统,将位移转换成计数脉冲,用脉冲个数计算位移和速度
在这里插入图片描述

参数

分辨率:编码器可以测量的最小距离。 对于增量式编码器,分辨率即转轴每旋转一圈所输出的脉冲数(PPR)
精度:编码器输出的信号数据与实际位置之间的误差,常用 角分 ′ 、角秒 ″
最大响应频率:编码器每秒能输出的最大脉冲数,单位Hz,也称为PPS
最大转速:指编码器机械系统所能承受的最高转速

编码器接口

STM32定时器编码器接口模式就相当于带有方向选择的外部时钟
编码器AB两相脉冲,A高电平在前,cnt递增计数,反之则反。同时脉冲频率越快,计数越快(来一个脉冲计数一次),每秒脉冲数越多,计数越快 。

编码器接口框图

在这里插入图片描述
A、B 两相脉冲信号从 TIMx_CH1 和 TIMx_CH2 这两个通道输入,经过滤
波器和边沿检测器(可以设置滤波和反相)的处理,ti1fp1和ti2fp2进入到编码器接口控制器中。需要注意,TIMx_CH3 和 TIMx_CH4 是不支持编码器接口模式的

编码器计数原理

分辨率(Resolution)是指编码器测量系统能够区分或识别输入信号变化的最小量。虽然不能改变转一圈的脉冲个数,但可以增加单个脉冲的计数次数来提升它的分辨率。
TIMx 从模式控制寄存器 (TIMx_SMCR),位 2:0 SMS:从模式选择
在这里插入图片描述
在这里插入图片描述
不想太多,直接读这个位了解转动方向。

编码器参数

在这里插入图片描述
按照这里11 ppr,我对它4分频,让转动一圈产生11个脉冲,计数值可以打印为44的数值

代码部分

HAL库函数

在这里插入图片描述

重要的结构体

typedef struct 
{
    
    uint32_t EncoderMode;		/* 编码器模式, 选择检测模式,这里选双相检测,也就是4倍频,即一个脉冲计数4次 */ 
    uint32_t IC1Polarity;       /* 输入极性(边沿检测器),是否反相输入*/ 
    uint32_t IC1Selection;		/* 输入通道选择,映射,这里设置TI1映射到IC1,TI2映射到IC2*/ 
    uint32_t IC1Prescaler;		/* 时钟分频因子 */ 
    uint32_t IC1Filter;     	/* 滤波器,设置上升沿后立即检测的次数 */ 
    uint32_t IC2Polarity; 		
    uint32_t IC2Selection; 		
    uint32_t IC2Prescaler; 		
    uint32_t IC2Filter; 
} TIM_Encoder_InitTypeDef;

代码实现步骤

在这里插入图片描述

电机速度计算

在这里插入图片描述

/**
 ****************************************************************************************************
 * @file        dcmotor_time.c
 * 说明:这是基于正点原子G474电机开发板的编码器代码
 ****************************************************************************************************
 */

#include "./BSP/LED/led.h"
#include "./BSP/TIMER/dcmotor_tim.h"
#include "./BSP/DC_MOTOR/dc_motor.h"


/******************************* 第一部分 电机基本驱动 互补输出带死区控制程序 **************************************/

TIM_HandleTypeDef g_atimx_cplm_pwm_handle;                              /* 定时器x句柄 */

/**
 * @brief       高级定时器TIM1 互补输出 初始化函数(使用PWM模式1)
 * @note
 *              配置高级定时器TIMX 互补输出, 一路OCy 一路OCyN, 并且可以设置死区时间
 *
 *              高级定时器的时钟来自APB2, 而PCLK2 = 170Mhz, 我们设置PPRE2不分频, 因此
 *              高级定时器时钟 = 170Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率, 单位 : Mhz
 *
 * @param       arr: 自动重装值
 * @param       psc: 时钟预分频数
 * @retval      无
 */

void atim_timx_cplm_pwm_init(uint16_t arr, uint16_t psc)
{
   
    TIM_OC_InitTypeDef tim_oc_cplm_pwm = {
   0};
    TIM_BreakDeadTimeConfigTypeDef sbreak_dead_time_config = {
   0};

    g_atimx_cplm_pwm_handle.Instance = TIM1;                                  			/* 定时器x */
    g_atimx_cplm_pwm_handle.Init.Prescaler = psc;                                       /* 定时器预分频系数 */
    g_atimx_cplm_pwm_handle.Init.CounterMode = TIM_COUNTERMODE_UP;                      /* 向上计数模式 */
    g_atimx_cplm_pwm_handle.Init.Period = arr;                                          /* 自动重装载值 */
    g_atimx_cplm_pwm_handle.Init.RepetitionCounter = 0;                                 /* 重复计数器寄存器为0 */
    g_atimx_cplm_pwm_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;     /* 使能影子寄存器TIMx_ARR,只要有就开它*/
    HAL_TIM_PWM_Init(&g_atimx_cplm_pwm_handle) ;

    /* 设置PWM输出 */
    tim_oc_cplm_pwm.OCMode = TIM_OCMODE_PWM1;                                           /* PWM模式1 */
    tim_oc_cplm_pwm.Pulse = 0;                                                          /* 比较值为0,PWM信号将始终输出低电平 */
    tim_oc_cplm_pwm.OCPolarity = TIM_OCPOLARITY_LOW;                                    /* OCy 低电平有效 */
    tim_oc_cplm_pwm.OCNPolarity = TIM_OCNPOLARITY_LOW;                                  /* OCyN 低电平有效 */
    tim_oc_cplm_pwm.OCFastMode = TIM_OCFAST_ENABLE;                                     /* 使用快速模式,在快速模式下,PWM的切换频率会更快,这有助于减少死区时间(如果有的话)和增加PWM的精度*/
    tim_oc_cplm_pwm.OCIdleState = TIM_OCIDLESTATE_RESET;                                /* 主通道的空闲状态 */
    tim_oc_cplm_pwm.OCNIdleState = TIM_OCNIDLESTATE_RESET;                              /* 互补通道的空闲状态 */
    HAL_TIM_PWM_ConfigChannel(&g_atimx_cplm_pwm_handle, &tim_oc_cplm_pwm, ATIM_TIMX_CPLM_CHY);    /* 配置后默认清CCER的互补输出位 */   
    
    /* 设置死区参数,开启死区中断 */
    sbreak_dead_time_config.OffStateRunMode = TIM_OSSR_ENABLE;                          /* OSSR设置为1,当定时器运行时,此设置启用了主输出(MOE)位被清除时的输出比较关断状态。这允许在软件控制下立即关闭PWM输出 */
    sbreak_dead_time_config.OffStateIDLEMode = TIM_OSSI_DISABLE;                        /* OSSI设置为0,当定时器处于空闲模式时,此设置禁用了主输出(MOE)位被清除时的输出比较关断状态。在大多数应用中,您可能希望禁用这个功能,以避免在空闲模式下不必要地关闭PWM输出 */
    sbreak_dead_time_config.LockLevel = TIM_LOCKLEVEL_OFF;                              /* 上电只能写一次,需要更新死区时间时只能用此值 */
    sbreak_dead_time_config.DeadTime = 0X0F;                                            /* 死区时间,死区时间用于避免在PWM信号的高电平和低电平之间立即切换,这有助于减少由于PWM驱动器中的MOSFET开关时间不匹配而产生的损害。这里的值0x0F代表具体的死区时间长度,但确切的时间长度取决于定时器的时钟频率和预分频器设置。 */
    sbreak_dead_time_config.BreakState = TIM_BREAK_DISABLE;                             /* BKE = 0, 关闭刹车检测 */
    sbreak_dead_time_config.BreakPolarity = TIM_BREAKPOLARITY_LOW;                      /* BKP = 1, 刹车低电平有效 */
    sbreak_dead_time_config.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;              /* 使能AOE位,允许刹车后自动恢复输出 */
    HAL_TIMEx_ConfigBreakDeadTime(&g_atimx_cplm_pwm_handle, &sbreak_dead_time_config);  /* 设置BDTR寄存器 */

}

/**
 * @brief       定时器底层驱动,时钟使能,引脚配置
                此函数会被HAL_TIM_PWM_Init()调用
 * @param       htim:定时器句柄
 * @retval      无
 */
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
   
    if (htim->Instance == ATIM_TIMX_CPLM)
    {
   
        GPIO_InitTypeDef gpio_init_struct;
        
        ATIM_TIMX_CPLM_CHY_GPIO_CLK_ENABLE();                                   /* 通道y对应IO口时钟使能 */
        ATIM_TIMX_CPLM_CHYN_GPIO_CLK_ENABLE();                                  /* 互补通道对应IO口时钟使能 */
        AT
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值