【电机控制】BLDC有感FOC控制——基于AS5047p芯片的电机速度获取和计算


前言

在机器人、AGV、数控机床、以及高精度运动控制中,伺服控制器扮演着重要角色。它是运动控制的关键组成部分,目前常采用基于FOC的电流、速度以及位置三闭环控制策略,而速度检测的准确与否直接影响系统的控制精度。本文主要介绍了磁编码器的工作原理,三种测速方法,最后再根据介绍的一种测速方法用代码实现展示。


一、磁编码器的工作原理

  • 当电流通过一个位于磁场中的导体的时候,磁场会对导体中的电子产生一个垂直于电子运动方向上的的作用力,从而在垂直于导体与磁感线的方向上产生电势差。
    在这里插入图片描述

  • 如果让施加在这个导体上的磁场以电流流经路径为轴线,按照上图箭头所示的方向旋转,那么这个霍尔电势差就会因为磁场与导体之间角度的改变而发生变化,而这个电势差的变化趋势,与之前一文中次级线圈旋转时的输出电压一样,是一条正弦曲线。因此,基于这个通电导体两侧的电压,就可以反推计算出磁场旋转的角度了。

  • 磁性编码器上用的霍尔传感器(芯片),一般都有着极高的集成度,不仅将霍尔半导体元件和相关的信号处理和调节电路整合在一起,同时还可以集成各种不同类型的信号输出模块,例如:正余弦模拟量信号、方波数字电平信号或者总线通讯输出单元。

  • 而编码器主要分为:增量式编码器和绝对式编码器

  • 增量式磁编码器:磁编码器的分辨率取决于磁盘周围的磁极数和传感器的数量。输出相对位置。

  • 绝对值式磁编码器:绝对值式磁编码器为每个测量位置分配了唯一的二进制代码或字。即使断电,这也使他们能够跟踪编码器的确切位置。

  • 磁编码器可以应用于电机的旋转位置反馈,将编码器的永磁体直接安装在电机轴的末端,从而省去了用传统反馈编码器时所需的过渡联接轴承(或联轴器),做到无接触式的位置测量,这样就降低了电机运行过程中因机械轴振动而造成编码器失效(甚至损坏)的风险,有助于提升电机运行的稳定性,如下图所示。
    在这里插入图片描述
    -项目中的PCB板:
    在这里插入图片描述

-项目中的电机轴:

在这里插入图片描述

  • 上述就是磁编码器工作原理,想要更深入的了解磁编码器工作原理可以参考这篇文章的链接: link

二、电机测速方法

1.M法测速

  • 在一定的周期Tc内,通过测量编码器输出的脉冲数M1来计算转速,如下图所示。用脉冲数除以时间就可以得到编码器输出脉冲的频率。
  • 假设电机转一圈可以产生Z个脉冲,Z=倍频x编码器线数。这里的倍频是指定时器采集A相和B相的上升沿和下降沿的选项,如果同时采集A相和B相的上升沿和下降沿,则表示4倍频,即Z=4。

在这里插入图片描述

  • 假设电机转一圈可以产生Z个脉冲,Z=倍频x编码器线数。这里的倍频是指定时器采集A相和B相的上升沿和下降沿的选项,如果同时采集A相和B相的上升沿和下降沿,则表示4倍频,即Z=4。
  • 用频率f1除以一圈的脉冲数Z再乘以60,就可以得到以r/min为单位的电机转速,如下图所示:
    在这里插入图片描述
  • 测速误差率与脉冲数成反比关系,转速越高,M值越大,误差越小;转速越低,M值越小,误差越大。因此,M法不适合低速测量,它适合高速测量。

2.T法测速

  • 通过测量编码器两个脉冲之间的时间间隔来计算转速。实际使用中通过高频时钟脉冲数M2来计算编码器两个脉冲之间的时间间隔,如下图:
    在这里插入图片描述
  • 假设高频脉冲的频率为f0,那么两个脉冲之间的时间间隔Tt = M2/f0,电机的转速可以表示如下图:
    在这里插入图片描述
  • T法测速最多能产生一个脉冲的误差,因此T法测速的最大误差率可以这样计算:
    在这里插入图片描述
  • 低速下编码器两个脉冲之间的时间间隔长,高频时钟脉冲数多,误差率低,因此T法测速更适合低速

三、M法测速的代码实现

代码如下(示例):

#define K_PULSES_TO_RPM_FACTOR  (5.86)
void EncoderUpdateSpeed(void)   /* 10ms task*/
{
    static sint16 DeltaPositons = 0;

    if(K_ROT_DIR_CW == g_bldc.rot_dir)   /*CW,Position is positive value*/
    {
        if(Encoder_RawPosition < 0)
        {
           Encoder_RawPosition +=K_TOTAL_COUNTS_PER_MECH_ROTATION;
        }

        if(Encoder_RawPosition >=Encoder_RawPositionOld)
        {
            DeltaPositons = Encoder_RawPosition - Encoder_RawPositionOld;
        }
        else
        {
            DeltaPositons = K_TOTAL_COUNTS_PER_MECH_ROTATION - (Encoder_RawPositionOld - Encoder_RawPosition);
        }
    }
    else if(K_ROT_DIR_CCW == g_bldc.rot_dir) /** CCW, Position is negative value**/
    {
        if(Encoder_RawPosition > 0)
        {
            Encoder_RawPosition -=K_TOTAL_COUNTS_PER_MECH_ROTATION;
        }

        if(Encoder_RawPosition <= Encoder_RawPositionOld)
        {
            DeltaPositons = Encoder_RawPosition - Encoder_RawPositionOld;
        }
        else
        {
            DeltaPositons =-(K_TOTAL_COUNTS_PER_MECH_ROTATION + (Encoder_RawPositionOld - Encoder_RawPosition));
        }

    }
    else
    {
        /* Do nothing because of unknown rotation direction */
    }

    g_bldc.RPM_s16MechSpeed = (sint16)((float)DeltaPositons* K_PULSES_TO_RPM_FACTOR);

    Encoder_RawPositionOld = Encoder_RawPosition;

    if(g_bldc.RPM_s16MechSpeed > 0)   /* calculate the absolute speed*/
    {
        absMotSpeed_raw = g_bldc.RPM_s16MechSpeed;
    }
    else
    {
        absMotSpeed_raw =0x00 - (g_bldc.RPM_s16MechSpeed);
    }

    {
        static uint16 speed_filter_array[10]={0};

        uint32 speed_sum = 0;

        speed_filter_array[0]=speed_filter_array[1];
        speed_filter_array[1]=speed_filter_array[2];
        speed_filter_array[2]=speed_filter_array[3];
        speed_filter_array[3]=speed_filter_array[4];
        speed_filter_array[4]=speed_filter_array[5];
        speed_filter_array[5]=speed_filter_array[6];
        speed_filter_array[6]=speed_filter_array[7];
        speed_filter_array[7]=speed_filter_array[8];
        speed_filter_array[8]=speed_filter_array[9];

        speed_filter_array[9]=absMotSpeed_raw;

        for(uint8 i=0;i<10;i++)
        {
            speed_sum+=speed_filter_array[i];
        }

//        g_absMotSpeed =((uint16)((uint16)(speed_sum/10)/10))*10;
        g_absMotSpeed =(uint16)(speed_sum/10);
        if(g_bldc.state == MOTOR_STATE_STOP)
        {
            g_absMotSpeed = g_bldc.second_speed;
        }
    }
}
  • 这段代码放在10ms的任务中,通过定时器计数得到10ms内的脉冲数变量DeltaPositons,由于定时器只对A相上升沿进行计数可得Z=1024,根据公式60/ZTc计算得到K_PULSES_TO_RPM_FACTOR5.86,所以速度g_bldc.RPM_s16MechSpeed = (sint16)((float)DeltaPositons* K_PULSES_TO_RPM_FACTOR)

  • 上位机1300r/min速度显示:
    在这里插入图片描述

  • 实际速度1300r/min在测量仪上显示:
    在这里插入图片描述

  • 从上面两图可知,根据软件公式计算得到1300r/min,与速度测量仪得到1302r/min相差不大。


总结

本文介绍了磁编码器的工作原理,介绍了M法和T法测速的原理,并用代码实现了M法测速,并成功对速度数值进行了验证。

  • 27
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值