【直流无刷电机 DBC】二 编码器测速

前言:

声明:学习笔记来自正点原子B站教程,仅供学习交流!!

1 编码器分类

1.1 按检测原理分类

  •         光电编码器

        光电编码器,是一种通过光电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。这是目前应用最多的传感器,光电编码器是由光源、光码盘和光敏元件组成。

        光栅盘是在一定直径的圆板上等分地开通若干个长方形孔。由于光电码盘与电动机同轴,电动机旋转时,光栅盘与电动机同速旋转,经发光二极管等电子元件组成的检测装置检测输出若干脉冲信号,通过计算每秒光电编码器输出脉冲的个数就能反映当前电动机的转速。

        此外,为判断旋转方向,码盘还可提供相位相差90°的两路脉冲信号

【直流无刷电机 DBC】二 编码器测速_第1张图片

  •         霍尔编码器

        霍尔编码器是一种通过磁电转换将输出轴上的机械几何位移量转换成脉冲或数字量的传感器。

        霍尔编码器是由霍尔码盘(磁环)和霍尔元件组成。

        霍尔码盘是在一定直径的圆板上等分地布置有不同的磁极。霍尔码盘与电动机同轴,电动机旋转时,霍尔元件检测输出若干脉冲信号,为判断转向,一般输出两组存在一定相位差的方波信号

【直流无刷电机 DBC】二 编码器测速_第2张图片

1.2 按输出信号分类 

  •         增量式编码器

增量式编码器是将设备运动时的位移信息变成连续的脉冲信号,脉冲个数表示位移量的大 小。其特点如下:

  • 只有当设备运动时才会输出信号。
  • 一般会输出通道A和通道B 两组信号,并且有90° 的相位差(1/4个周期),同时采集这两组信号就可以计算设备的运动速度和方向。

如下图,通道A和通道B的信号的周期相同,且相位相差1/4个周期,结合两相的信号值:

  • 当B相和A相先是都读到高电平(1 1),再B读到高电平,A读到低电平(1 0),则为顺时针
  • 当B相和A相先是都读到低电平(0 0),再B读到高电平,A读到低电平(1 0),则为逆时针
  • 除通道A、通道B 以外,还会设置一个额外的通道Z 信号,表示编码器特定的参考位置

如下图,传感器转一圈后Z 轴信号才会输出一个脉冲,在Z轴输出时,可以通过将AB通道的计数清零,实现对码盘绝对位置的计算。

  • 增量式编码器只输出设备的位置变化和运动方向,不会输出设备的绝对位置

【直流无刷电机 DBC】二 编码器测速_第3张图片

  •          绝对式编码器

绝对式编码器在总体结构上与增量式比较类似,都是由码盘、检测装置和放大整形电路构成,但是具体的码盘结构和输出信号含义不同。

它是将设备运动时的位移信息通过二进制编码的方式(特殊的码盘)变成数字量直接输出。其特点如下:

  • 其码盘利用若干透光和不透光的线槽组成一套二进制编码,这些二进制码与编码器转轴的每一个不同角度是唯一对应的。
  • 绝对式编码器的码盘上有很多圈线槽,被称为码道,每一条(圈)码道内部线槽数量和长度都不同。它们共同组成一套二进制编码,一条(圈)码道对应二进制数的其中一个位(通常是码盘最外侧的码道表示最低位,最内侧的码道表示最高位)。
  • 码道的数量决定了二进制编码的位数,一个绝对式编码器有N 条码道,则它输出二进制数的总个数是2的N次方个。
  • 读取这些二进制码就能知道设备的绝对位置,所以称之为绝对式编码器。
  • 编码方式一般采用自然二进制、格雷码或者BCD 码等。
  • 自然二进制的码盘易于理解,但当码盘的制造工艺有误差时,在两组信号的临界区域,所有码道的值可能不会同时变化,或因为所有传感器检测存在微小的时间差,导致读到错误的值。比如从000跨越到111,理论上应该读到111,但如果从内到外的3条码道没有完全对齐,可能会读到如001或其它异常值。
  • 格雷码(相邻的两个2进制数只有1个位不同)码盘可以避免二进制码盘的数据读取异常,因为格雷码码盘的相邻两个信号组只会有1位的变化,就算制造工艺有误差导致信号读取有偏差,最多也只会产生1个偏差(相邻信号的偏差)

【直流无刷电机 DBC】二 编码器测速_第4张图片

2. 编码器测数原理

2.1 编码器倍频

编码器倍频是什么意思呢,比如某光栅编码器一圈有N个栅格,理论上电机带动编码器转一圈,只能输出N个信号,通过倍频技术,可以实现转一圈,却能输出N*n个信号,这里的n为倍频数。

增量式编码器输出的脉冲波形一般为占空比50% 的方波,通道A 和B 相位差为90°。

  • 如果只使用通道A计数,并且只捕获通道A的上升沿,则一圈的计数值=码盘的栅格数,即为1倍频(没有倍频)
  • 如果只使用通道A计数,并且捕获了通道A的上升沿和下降沿,则编码器转一圈的计数值翻倍,实现2倍频
  • 如果既使用通道A计数,又使用通道B计数,且都捕获了上升沿和下降沿,则实现了4倍频

【直流无刷电机 DBC】二 编码器测速_第5张图片

2.2 M法测速

又叫做频率测量法。该方法是在一个固定的时间内(以秒为单位),统计这段时间的编码器脉冲数,计算速度值。M法适合测量高速

假设:

  • 编码器单圈总脉冲数为C(常数)
  • 统计时间为T0 (固定值,单位秒)
  • 该时间内统计到的编码器脉冲数为 M0 (测量值)

则:转速n (圈/秒)的计算公式为:

如何理解这个公式:
        M0 /C 即统计时间内有多少个编码器脉冲,再除以统计时间 T0 ,即1s(单位时间)内转了多少圈 ,​ 当M0很大,即转速快时,这个方法测得精度和平稳性都很好,但当M0很小,速度改变带来的M0变化很小,即转速慢时算出的误差就很大。所以M法测速适用于高转速场景

2.3 T法测速

又叫做周期测量法。这种方法是建立一个已知频率的高频脉冲并对其计数。T法适合测量低速

假设:

  • 编码器单圈总脉冲数为C(常数)
  • 高频脉冲的频率为 F0 (固定值,单位Hz)
  • 捕获到编码器相邻两个脉冲的间隔时间为 T_E,其间的计数值为 M1 (测量值)

则:转速n 的计算公式为:

如何理解这个公式:
        1/$T_E$ 即1s内有多少个编码器脉冲,再除以一圈的脉冲数C,即1s内转了多少圈
        $F_0$/$M_1$ 即1s内的高频脉冲数除以两编码器脉冲间的高频脉冲数,也即1s内有多少个编码器脉冲,再除以一圈的脉冲数C,即1s内转了多少圈 

2.4 M/T法测速

这种方法综合了M 法和T 法各自的优势,既测量编码器脉冲数又测量一定时间内的高频脉冲数

在一个相对固定的时间内,假设:

  • 编码器脉冲数产生 M0 个 (测量值)
  • 计数一个已知频率为 F0 (固定值,单位Hz)的高频脉冲,计数值为 M1 (测量值),计算速度值
  • 码器单圈总脉冲数为C(常数)

则转速n 的计算公式为:

        

3. M法测速

  • 定时器初始化(初始化IO,配置定时器、编码器接口,增加TIM6更新中断)
  • 更新中断回调函数(处理溢出中断,判断溢出方向,记录溢出次数,计算电机速度)
  • 编码器计数函数(总计数值=计数当前值+溢出次数*65536)
  • 电机速度滤波(根据计数值计算电机转速,并增加滤波功能)

3.1  编码器定时器 HAL库配置

        编码器定时器使用的是TIM3,此处开启了开启了两个计数通道,即Encoder Mode中设置为Encoder Mode TI1 and TI2。这里就是上文倍频技术的4倍频,将溢出次数设置为最大值,即计数达到65535之后会产生溢出中断

【直流无刷电机 DBC】二 编码器测速_第6张图片

3.2 基本定时器配置

        基本定时器使用的是TIM8,基本定时器我设置为168分频,此时钟频率为168MHz,将计数次数设置为1000,即1ms会产生一次溢出中断,在溢出中断里,我们将会进行速度的计算

【直流无刷电机 DBC】二 编码器测速_第7张图片

3.3  速度计算

  • 首先是定时器TIM3的中断回调函数,在此函数里,统计定时器计数的溢出次数
  • 在TIM8的中断回调函数里,获取当前的编码值,通过 以下公式计算出电机转速,单位RPM

电机转速 = 一分钟内计数变化量 / 倍频系数 / 编码器线数 / 减速比

  •  在滤波函数里,为了使曲线更加平缓,是通过平均滤波计算的,即将最近几次的速度采样值存放到数组中,每测得一个新的速度,就将新速度存入数组,将最早测得的速度值从数组中删除,我们使用的速度值是数组中所有速度的平均值(如果数组元素不足,即返回当前速度)
#define CALC_SPEED_TIMER			    50		//计算一次速度的周期,ms
#define FILTER_COUNT					5		//过滤次数
#define MOTOR_SPEED_RERATIO 	        30u     //电机减速比
#define ROTO_RATIO 						44 		//线数*倍频系数,即 11*4=44
#define RELOADVALUE 					__HAL_TIM_GetAutoreload(&htim3)    //获取自动装载值
#define COUNTERNUM 						__HAL_TIM_GetCounter(&htim3)        //获取编码器定时器中的计数值
float speed_calc_filter(float speed)
{
	static float speed_arry[FILTER_COUNT] = {0};
	static int speed_number = 0;
	float sum = 0.0f;
	
	if(speed_number < FILTER_COUNT) speed_number++;
	
	for(int i = 0; i < FILTER_COUNT - 1; i++)
	{
		speed_arry[i + 1] = speed_arry[i];
		sum += speed_arry[i];
	}
	
	sum += speed;
	speed_arry[0] = speed;
	
	if(sum < FILTER_COUNT) return speed;
	
	return sum/FILTER_COUNT;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM3)
	{
		if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim))	motor_encoder.totalCount --;
		else	motor_encoder.totalCount ++;
	}
	else if(htim->Instance == TIM8)
	{
		static int32_t timer = 0;
		float speed = 0.0f;
		timer ++;
		
		if(timer == CALC_SPEED_TIMER)
		{
			timer = 0;
			
			motor_encoder.totalCount = COUNTERNUM + motor_encoder.overflowNum*RELOADVALUE;

            /*防止溢出*/
			if((dc_motor.dir == CW) && (motor_encoder.totalCount < motor_encoder.lastCount))
			{
				motor_encoder.overflowNum ++;
				motor_encoder.totalCount = COUNTERNUM + motor_encoder.overflowNum*RELOADVALUE;
			}
			else if((dc_motor.dir == CCW) && (motor_encoder.totalCount > motor_encoder.lastCount))
			{
				motor_encoder.overflowNum --;
				motor_encoder.totalCount = COUNTERNUM + motor_encoder.overflowNum*RELOADVALUE;
			}

			speed = ((float)(motor_encoder.totalCount - motor_encoder.lastCount)*(1000/CALC_SPEED_TIMER)*60/MOTOR_SPEED_RERATIO/ROTO_RATIO);
			motor_encoder.lastCount = motor_encoder.totalCount;
			
			dc_motor.speed = speed_calc_filter(speed);
		}
	}
}

你可能感兴趣的:(电机专题,人工智能)