赞
踩
本文旨在记录和说明STM32CubeIde中ABZ编码器的配置。本人作为STM32新手,在使用STM32时,太多的意义不明的配置项让我摸不着头脑,查阅资料并在这里记录,如果有不对的,欢迎各位大佬指正。
本文硬件使用ST官方提供的NUCLEO-G474RE+X-NUCLEO-IHM16M1,记录ABZ的配置过程。
本文使用的是磁电增量式编码器
原理:利用霍尔效应,将位移转换成计数脉冲,用脉冲个数计算位移和速度。具体原理如下图所示
图中,磁电增量式编码器的结构包含:磁盘、霍尔传感器以及信号转换电路 3 个部分,其中,磁盘是由一个个交替排布的 S 极和 N 极磁极组成;霍尔传感器可以把磁场的变化转换成电信号的变化,它通常有 A、 B 两相(有的还有 Z 相),这两相的安装位置形成一定的夹角,这使得输出的 A、 B 两相信号有 90°的相位差;信号转换电路可以把电信号转换成脉冲信号。
在实际应用中,磁盘会装在电机的转轴上,它会随着电机的转轴旋转,而磁盘上面的 S 极和 N 极就会交替地经过霍尔传感器的 A、 B 两相,霍尔传感器就可以把磁盘上的磁场变化转换为电信号的变化,输入到信号转换电路中,经过信号的转换之后,我们就可以得到 A、B 两相脉冲信号了。从上图中可以看到, A、 B 两相脉冲信号存在 90°的相位差,而磁盘的正反转方向就决定了是 A 相信号在前还是 B 相在前。
我们选择定时器1,配置Combined Channels为Encoder Mode +Index。
编码器模式简单来说就是一个带方向的外部时钟,根据方向从0增加到ARR寄存器的值或者从ARR寄存器的值减少到0。
具有index的编码器有三个输出:A和B,用于控制计数器和索引的递增/递减;index,也就是Z信号,在每转一圈触发一次。在时序图中,当轴到达特定位置时产生零脉冲。
Encoder Mode + Index:就是有AB两相进行计算的变化,将Z相接入tim_etr_in,发出信号时会自动将计数重置,不需要我们手动增添计数重置的代码。同时,Index检测事件根据计数方向的不同而不同,以确保在速度反转期间对称操作:
在计数增加时,重置为0;
在计数减小时,重置为ARR寄存值;
简单来说,该模式通过PWM mode、CCR、ARR的值生成一个脉冲后停止定时器计数。
具体参考:
STM32 - 定时器的设定 -高级- 08 - One-pulse mode - 触发波的实现 - 可变长度和相位_one pulse mode-CSDN博客
之前我们提到,编码器模式就像外部时钟一样,所有捕捉,比较,分频,重复计数,触发都和定时器一样。具体可以参考我写的另一篇PWM配置文章
这个选择是指出现Index信号时,检测到AB两相处于什么状态时,进行计数重置,如下图为检测到AB都为高电平,才对编码器计数进行重置。
该值修改IDIR[1:0]的值,表示index信号被激活仅在指定的方向。电机有正反转,所以我们这里选择无论方向都重置。具体的图例如下。
该模式选择编码器时钟的计数方式,计数模式分为3种,分别为正交编码器模式、时钟加方向模式、定向时钟模式。
Encoder Mode TI1:只通过TI1计数,计数2分频
Encoder Mode TI2:只通过TI2计数,计数2分频
Encoder Mode TI1 and TI2:通过TI1和TI2计数,计数4分频
Encoder Mode x1_TI1:只通过TI1计数,计数1分频
Encoder Mode x1_TI2:只通过TI2计数,计数1分频
示例如图所示
接下来我们讲解一下正交编码器计数原理
编码器接口可以利用输入脉冲的边沿进行计数,我们通过计数值的变化量,就可以算出输入脉冲信号的变化量,也就可以进一步计算出电机的转速了。接下来我们看一下编码器接口是如何根据脉冲边沿计数的,它的计数方向与输入脉冲信号的关系如表所示:
表来自于《STM32G4xx 参考手册_V7(英文版) .pdf》中的表 75(第 415 页),上表中的有效边沿我们可以通过代码去配置,一共有 3 种边沿检测方式,其中仅在 TI1 处计数表示只检测 TI1 上的脉冲边沿变化,这时候的计数方向需要结合 TI2FP2 上的电平情况来确定,其他的两种边沿检测方式原理也是一样的,下面我们以一个实例来理解这个表格的内容:
假设我们把 A 相接在 CH1(TI1), B 相接在 CH2(TI2),选择仅在 TI1 处计数(仅检测A 相边沿)。此时编码器接口计数方向和输入脉冲信号的关系如下表:
编码器输出的 A、 B 两相脉冲信号如图所示:
图 中, A、 B 两相输出的脉冲信号有两种情况:当编码器正转, A 相在前;当编码器反转, B 相在前,我们选择仅在 TI1 处计数,也就是只检测 A 相的边沿。接下来我们分别介绍这两种情况下的计数方向:
正转:当 A 相上升沿到来时(图中①处),我们需要关注 B 相的电平高低,从图中可看到 B 相此时是低电平,结合表,可以得知此时计数方向为递增计数;当 A 相下降沿到来时(图中②处),从图中可以看到 B 相此时是高电平,结合表,可以得知此时计数方向为递增计数;当 A 相上升沿再次到来时(图中③处),同理可得此时计数方向为递增计数。综上所得,我们可以知道此时编码器正转对应的计数方向就是递增计数。
反转:当 A 相上升沿到来时(图中④处),我们需要关注 B 相的电平高低,从图 中可看到 B 相此时是高电平,结合表,可以得知此时计数方向为递减计数;当 A 相下降沿到来时(图中⑤处),从图中可以看到 B 相此时是低电平,结合表 ,可以得知此时计数方向为递减计数;当 A 相上升沿再次到来时(图中⑥处),同理可得此时计数方向为递减计数。综上所得,我们可以知道此时编码器反转对应的计数方向就是递减计数。
上述的就是仅在 TI1 处计数的实例分析,其他两种边沿计数方式的原理是一样的,大家可以举一反三,我们这里就不再展开分析。
除了正交编码器模式,定时器提供支持其他两种类型的编码器。在顶部时序图所示的“时钟加方向”模式中,时钟提供在TI2上的单线上,而方向是使用TI1输入强制的。在下面时序图所示的“定向时钟”模式下,时钟在两条线上,根据方向,同时有一条单时钟线,这样就有一条上行时钟线和一条下行时钟线。
下图为编码器更新的函数,通过__HAL_TIM_GET_COUNTER()获取ABZ计数值
- int UpdataEncoderCnt(void)
- {
- //获取电机读数
- encoderDef.preCnt = encoderDef.cnt;
- encoderDef.cnt = (int32_t)__HAL_TIM_GET_COUNTER(&htim4);
- //计算电机偏移量
- encoderDef.incCnt = ModifyIncCnt(encoderDef.cnt - encoderDef.preCnt);
- // 获取真实的编码器计数值
- int realCnt = encoderDef.cnt - encoderDef.offsetCnt;
- // 当计数值为负数时,加上一圈的计数数
- while(realCnt<0)
- {
- realCnt += ABZ_PULSE * 4;
- }
- // 计算真实的角度值
- encoderDef.angle=realCnt*2*3.1415926f / ABZ_PULSE / 4;
- // 计算电角度
- encoderDef.elecAngle = encoderDef.angle * MOTOR_POLE;
- // 返回编码器读数
- return encoderDef.cnt;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。