前言
随着电动汽车在国内迅速发展,电机控制领域方面的技术的发展越来越受到人们的重视,本文就介绍了电机控制中位置的获取方式:如何通过TC275芯片对增量编码器的ABZ信号进行解码和处理。
一、ABZ是什么?
- ABZ又称ABI,叫法不同但都是指增量式编码器,ABZ编码器最初是光电式的,近几年随着磁编码器的兴起,磁编码器上也增加了ABZ信号的输出;
- A、B两相相差90度,可通过比较A相在前还是B相在前,以判断编码器的正转与反转,通过零位脉冲,可获得编码器的零位参考位,如下图所示。
- 本项目采用的是AMS公司的AS5147P旋转编码器,它既可以产生ABI信号,也可以获取绝对位置,本文注重介绍对该编码器芯片的ABI信号的解码;
二、ABZ信号解码的实现
1.TC275芯片GPT1模块
- TC275芯片的通用定时器单元 GPT1 和 GPT2 模块具有非常灵活的多功能定时器结构, 可用作定时、 事件计数、 脉宽测量、 脉冲生成、 倍频及其它用途。
- GPT1 模块有三个定时器/计数器: 内核定时器 T3 和两个辅助定时器 T2、 T4。 最大的分辨率为 fGPT/4。 GPT1 模块的辅助定时器可为内核定时器有选择的配置成重载或捕捉寄存器,如下图所示。
- 可以利用T2定时器的两个引脚:T2IN和T2EUD接受A,B相的信号输入,T4定时器的引脚来接受Z相的信号输入,再分别开启T2和T4的中断,在中断函数检测Z相电平的变化,以此达到重启T2定时器计数的功能,同时可以计算电机转的圈数,而在T2定时器中断函数检测电机的旋转方向。
- 具体关于TC275芯片GPT1模块的介绍可以跳转这个链接: 深入了解GPT1模块
2.代码实现
- 该处配置定时器的分辨率,这里我配置的是fGPT/4,默认的fGPT为100MHZ。
Ifx_GPT12 *gpt12=&MODULE_GPT120;
IfxGpt12_enableModule(gpt12);
IfxGpt12_setGpt1BlockPrescaler(gpt12, IfxGpt12_Gpt1BlockPrescaler_4);
IfxGpt12_setGpt2BlockPrescaler(gpt12, IfxGpt12_Gpt2BlockPrescaler_4);
- 该处配置AB相的引脚。
/* T2 Configuration */
IfxGpt12_initTxInPinWithPadLevel(&ENCODER_PINA, IfxPort_InputMode_noPullDevice, IfxPort_PadDriver_cmosAutomotiveSpeed1); //PINA
IfxGpt12_initTxEudInPinWithPadLevel(&ENCODER_PINB, IfxPort_InputMode_noPullDevice,IfxPort_PadDriver_cmosAutomotiveSpeed1); //PINB
- 该处配置T2定时器的模式,这里我只选择TxIN上边沿检测,根据外部信号确定计数方向,启动T2定时器。
IfxGpt12_T2_setMode(gpt12, IfxGpt12_Mode_counter);
IfxGpt12_T2_setCounterInputMode(gpt12, IfxGpt12_CounterInputMode_risingEdgeTxIN );
IfxGpt12_T2_setDirectionSource(gpt12, IfxGpt12_TimerDirectionSource_external);
IfxGpt12_T2_run(gpt12, IfxGpt12_TimerRun_start);
- 该处初始化并启用定时器T2的中断源。
{
IfxGpt12_T2_setInterruptEnable(gpt12, TRUE);
IfxGpt12_T2_setRemoteControl(gpt12, IfxGpt12_TimerRemoteControl_off);
/* setup interrupt */
volatile Ifx_SRC_SRCR *src = IfxGpt12_T2_getSrc(gpt12);
IfxSrc_init(src, IfxSrc_Tos_cpu0, INTERRUPT_ENCODER_GPT12_T2);
IfxSrc_enable(src);
}
- 该处定义了T2定时器的中断函数,这里我就没有添加功能了。
void ISR_Encoder_Gpt12_T2(void)
{
Ifx__NOP(1);
g_bldc.testcount++;
__enable();
}
- 该处配置T4定时器的一些基本参数。
/* T4 Configuration */
IfxGpt12_initTxEudInPinWithPadLevel(&ENCODER_PINZ, IfxPort_InputMode_noPullDevice, IfxPort_PadDriver_cmosAutomotiveSpeed1);//PINZ
IfxGpt12_T4_setMode(gpt12, IfxGpt12_Mode_incrementalInterfaceRotationDetection);
IfxGpt12_T4_setIncrementalInterfaceInputMode(gpt12,IfxGpt12_IncrementalInterfaceInputMode_bothEdgesTxINOrTxEUD);
IfxGpt12_T4_run(gpt12, IfxGpt12_TimerRun_start);
- 该处初始化并启用定时器T2的中断源。
/* T4 Interrupt*/
{
IfxGpt12_T4_setInterruptEnable(gpt12, TRUE);
IfxGpt12_T4_setRemoteControl(gpt12, IfxGpt12_TimerRemoteControl_off);
/* setup interrupt */
volatile Ifx_SRC_SRCR *src = IfxGpt12_T4_getSrc(gpt12);
IfxSrc_init(src, IfxSrc_Tos_cpu0, INTERRUPT_ENCODER_GPT12_T4);
IfxSrc_enable(src);
}
- 该处定义并声明了T4定时器的中断函数,并在中断函数对T4引脚高低电平进行检测,通过for循环添加电平检测防干扰功能,在检测到高电平后,立马对T2定时器进行Reset。
void ISR_Encoder_Gpt12_T4(void)
{
//IfxGpt12_IncrEnc_isrOnZeroPulse(&g_motor.sensors.encoder);
//IfxStdIf_Pos_onZeroIrq(&g_motor.sensors.encoder);
boolean b_PulseFilter = TRUE;
for(int i=0;i<3;i++)//3us ( 40 counts == 1us)
{
for(int j=0;j<40;j++)
{
Ifx__NOP(1);
}
if(IfxPort_getPinState(ENCODER_PINZ.pin.port, ENCODER_PINZ.pin.pinIndex)==TRUE)
{
}
else
{
b_PulseFilter=FALSE;
}
}
if((b_PulseFilter)&&(IfxPort_getPinState(ENCODER_PINZ.pin.port, ENCODER_PINZ.pin.pinIndex)==TRUE))
{
g_TotalCountAcircle = EncoderUpdatePosition();
if (b_ZeroDetected)//start validcheck when the second zero pulse detected
{
TotalCountsPerCycle_ValidCheck();
}
b_ZeroDetected=TRUE;
EncoderReset();
cycle_total++;
cycle_speed++;
// g_bldc.testcount = 0;
}
__enable();
}
三、实现效果
- 如上图所示,由于as5147p编码器属性和之前的配置中选择上边沿,同时在T4中断对T2定时器进行RESET,所以将脉冲数用CAN信号发送到上位机,可以发现每当计数到0和1024后就会重新计数,之后可以利用这种计数方式可以实现电机速度的计算。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了ABZ解码的实现方式,而ABZ解码是为了获得电机的位置,为后面对电机速度计算做的铺垫,有感兴趣的朋友可以关注我后续的电机控制专栏。