[活动专区] 【杰发科技AC7802x测评】4.基于AC7802正交编码实现电机测速

[复制链接]
 楼主| GrootBrain 发表于 2023-6-3 20:55 | 显示全部楼层 |阅读模式
<
本帖最后由 GrootBrain 于 2023-6-3 20:55 编辑

#有奖活动# #申请原创#
基于AC7802正交编码实现电机测速


正交编码器测速原理
正交编码器是一种通过旋转或移动测量运动位置和速度的传感器。它通常由两个光学传感器(A相和B相)组成,每个传感器的输出波形完全相同,但相位相位差90度(即正交)。当物体被旋转或移动时,两个波形将发生同步变化,使得编码器可以确定方向和速度。
具体而言,在实际应用中,编码器的A和B两条输出线和中心的接地线连接到计数器或控制器电路中。计数器对A和B两种输信进行脉冲计数,并根据两条线之间的相对时间差确定运动速度和方向。如果传感器被旋转,每旋转一次会产生一定数量的脉冲,可以通过这些脉冲来计算旋转角度。
b082c00d221b38da445e0890951d232e_720w.jpg

a6a9cb3e3ef438d34f45a9657473d6be_720w.jpg

从上来看,以通道A的下降沿作为起始位置:
顺时针是01->00->10->11,也就是10进制的1-0-2-3
逆时针是00->01->11->10,也就是10进制的0-1-3-2
因此,只要知道计数规律,就知道是往哪个方向在转,计算脉冲的频率,就是旋转速度。

AC7802的正交解码功能
AC7802的PWM带正交解码功能,模块的通道0接phase A, 模块的通道1接phase B。7802正对正交编码进行正确记数。
无标题.jpg

AC7802的正交编码测速方案
硬件接口:
PB0,使用PWM1_CH1功能,用作编码器的phase A输入;
PB1,使用PWM1_CH2功能,用作编码器的phase B输入;
PWM1模块用于正交编码计数。phase A或phase B边沿跳变时计时器加1。正转时计数器增加,反转时计数器减少。


速度计算:
本实验中使用编码器是11线编码器,也就是电机转一圈,A/B两相分别输出11个脉冲,每个脉冲都使解码数值增加的话,电机转一圈是44个脉冲。
本实验电机的输出轴减速比是4.4,也就是电机转4.4圈,电机输出轴才会转一圈。也就是说。输出轴转一圈,脉冲计数器变化11*4*4.4=193.6个脉冲。
本实验每20ms计算一次转速,计算前200ms内转速,假如脉冲数变化为N,则转速rpm(转/分钟)
rpm=[ (N/193.6)  /  (  200 / 1000 ) ] * 60

AC7802的正交编码测速编程
测速模块提供初始化接口,速度计算接口以及获取速度接口。
  1. void speed_check_init( void );
  2. void speed_check_task( void );
  3. float speed_check_get_Revolutions_Per_Minute( void );

速度初始化接口speed_check_init(), 用于调用下层正交编码器初始化
  1. void speed_check_init( void )
  2. {
  3.     PWM_quadrature_decode_init();
  4. }

速度计算接口speed_check_task(),用于计算转速,必须周期性调用,这里的调用周期是20ms
  1. static void SpeedMeter(int currentPulse)
  2. {
  3.     int deltaPulse = 0;
  4.     uint8_t i;

  5.     for ( i=0; i < (SPEED_METER_BUF_LEN-1) ; ++i ) {
  6.         g_pulseRecordTbl[i] = g_pulseRecordTbl[i+1];
  7.     }
  8.     g_pulseRecordTbl[SPEED_METER_BUF_LEN-1] = currentPulse;

  9.     deltaPulse = g_pulseRecordTbl[SPEED_METER_BUF_LEN-1] - g_pulseRecordTbl[0];

  10.     if ( -QUAD_CHANGE_NUMBER_MAX_IN_CALC_CYCLE > deltaPulse ) {
  11.         // inc pass 0
  12.         deltaPulse += (QUAD_ENCODER_NUM_MAX + 1);
  13.     } else if ( deltaPulse > QUAD_CHANGE_NUMBER_MAX_IN_CALC_CYCLE ) {
  14.         // dec pass 0
  15.         deltaPulse -= (QUAD_ENCODER_NUM_MAX + 1);
  16.     }

  17.     SPEED_TASK_ENTER_CRITICAL();
  18.     g_MoterSpeedRPM = deltaPulse / QUAD_ENCODER_NUMBER_IN_A_CYCLE / (SPEED_METER_CYCLE * (SPEED_METER_BUF_LEN-1)/1000.0f) * 60;
  19.     SPEED_TASK_EXIT_CRITICAL();
  20. }


  21. void speed_check_task(void)
  22. {
  23.     SpeedMeter( PWM_quadrature_decode_get_val() );
  24. }

获取速度接口speed_check_get_Revolutions_Per_Minute(),给外部提供计算后的转速获取接口,正负值表示方向
  1. float speed_check_get_Revolutions_Per_Minute( void )
  2. {
  3.     float speed = 0.0f;

  4.     SPEED_TASK_ENTER_CRITICAL();
  5.     speed = g_MoterSpeedRPM;
  6.     SPEED_TASK_EXIT_CRITICAL();

  7.     return speed;
  8. }



测速模块会调用下层模块,下层模块提供编码器的初始化和获取编码器数值接口
  1. void PWM_quadrature_decode_init( void );
  2. uint32_t PWM_quadrature_decode_get_val( void );

正交编码器初始化接口PWM_quadrature_decode_init(), 完成PWM底层寄存器配置,端口配置
  1. void PWM_quadrature_decode_init( void )
  2. {
  3.     PWM_ConfigType config;
  4.     PWM_QuadDecodeConfigType quadDecodeConfig;
  5.     PWM_QuadPhaseConfigType quadPhaseAConfig, quadPhaseBConfig;

  6.     memset(&config, 0U, sizeof(config));
  7.     memset(&quadDecodeConfig, 0U, sizeof(quadDecodeConfig));
  8.     memset(&quadPhaseAConfig, 0U, sizeof(quadPhaseAConfig));
  9.     memset(&quadPhaseBConfig, 0U, sizeof(quadPhaseBConfig));

  10.     GPIO_SetFunc(GPIOB, GPIO_PIN0, GPIO_FUN2);  /* PB0--PWM1_CH1.该引脚只在32pin封装上有 */
  11.     GPIO_SetFunc(GPIOB, GPIO_PIN1, GPIO_FUN2);  /* PB1--PWM1_CH0,该引脚只在32pin封装上有.*/

  12.     GPIO_SetPullup(GPIOB, GPIO_PIN0, ENABLE); /*使能上拉*/
  13.     GPIO_SetPullup(GPIOB, GPIO_PIN1, ENABLE); /*使能上拉*/


  14.     /*通道配置*/
  15.     quadPhaseAConfig.polarity = PWM_QUAD_PHASE_NORMAL;  /*A相输入极性为正常极性。*/
  16.     quadPhaseAConfig.filterEn = DISABLE;                /*A相滤波器去能*/
  17.     quadPhaseAConfig.filterVal = 0;                     /*滤波值*/
  18.     quadPhaseBConfig.polarity = PWM_QUAD_PHASE_NORMAL;  /*B相输入极性为正常极性。*/
  19.     quadPhaseBConfig.filterEn = DISABLE;                /*B相滤波器去能*/
  20.     quadPhaseBConfig.filterVal = 0;                     /*滤波值*/
  21.     quadDecodeConfig.mode = PWM_QUAD_PHASE_ENCODE;      /*A相和B相编码模式*/
  22.     quadDecodeConfig.phaseAConfig = quadPhaseAConfig;   /*A相配置赋值*/
  23.     quadDecodeConfig.phaseBConfig = quadPhaseBConfig;   /*B相配置赋值*/
  24.     quadDecodeConfig.quadEn = ENABLE;                   /*正交解码使能*/

  25.     /*PWM模块配置*/
  26.     config.mode = PWM_MODE_QUADRATURE_DECODER;          /*PWM模块配置为正交解码模式*/
  27.     config.initModeStruct = &quadDecodeConfig;          /*正交解码配置赋值*/
  28.     config.clkSource = PWM_CLK_SOURCE_APB;              /*PWM时钟源配置*/
  29.     config.clkPsc = 0;                                  /*PWM时钟源分频*/
  30.     config.initValue = 0;                               /*计数器初始寄存器值*/
  31.     config.maxValue = PULSE_PER_REVOLUTION - 1;         /*PWM计数器最大值*/
  32.     config.overflowInterrupEn = DISABLE;                /*计数器溢出中断使能*/
  33.     config.cntOverflowFreq = 0;                         /*CNTOF中断产生的频率与计数器频率的关系(0-127), 0表示每次计数器溢出都产生溢出中断,1表示间隔1次,2表示间隔2次,以此类推。*/
  34.     config.interruptEn = DISABLE;                       /*PWM中断使能*/
  35.     config.callBack = NULL;                             /*PWM中断回调*/
  36.     PWM_Init(QUAD_PWM_MODULE, &config);                 /*配置初始化生效*/
  37. }


正交编码器数值获取接口PWM_quadrature_decode_get_val(),给上层接口提供获取数值的方法
  1. uint32_t PWM_quadrature_decode_get_val( void )
  2. {
  3.     uint32_t counter = QUAD_PWM_MODULE->CNT & 0xFFFF;

  4.     return counter;
  5. }


将速度计算功能嵌入到电机任务中
  1. void motor_Task( void *pvParameters )
  2. {
  3.     pvParameters = pvParameters;

  4.     adc_motor_ctrl_input_init();
  5.     PWM_motor_ctrl_output_init();
  6.     speed_check_init();

  7.     while (1) {
  8.         PWM_motor_ctrl_ouput_duty_val( adc_motor_ctrl_get_adc_Val() );
  9.         
  10.         speed_check_task();

  11.         vTaskDelay( pdMS_TO_TICKS(20) );
  12.     }
  13. }


在printTask输出电机转速数值
  1. void printf_Task( void *pvParameters )
  2. {
  3.     pvParameters = pvParameters;

  4.     InitDebug();

  5.     while (1) {
  6.         //printf( "Hi,I'm a small chip, AC7802.\r\n");
  7.         printf("speed(rpm) = %d\r\n", (int)speed_check_get_Revolutions_Per_Minute() );
  8.         vTaskDelay( pdMS_TO_TICKS(1000) );
  9.     }
  10. }


测试
正转
20230603-193525.jpg
反转:
20230603-193535.jpg
结论:电机测速与电机标定值相符,且能计算出电机转动方向。

测试工程
测试工程在linux环境下编译,基于freeRTOS开发。
AC7802_FreeRTOS_motor_speed_meter.zip (1.56 MB, 下载次数: 11)




您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

93

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

17

主题

93

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部