正交编码器接口(QEI)模块
dsPIC30F的正交编码器接口(QEI)模块提供了一个与增量光编码器的接口,允许从电机或机械系统中,获得速度和相对转子位置信息。QEI模块提供16位时基,接受从增量编码器连接的A、B和标志信号。电机速度和位置信息能用×2或×4分辨率进行测量。
QEI模块有两个速度通道:A相(QEA)和B相(QEB)。两个通道有对应关系,如果A相超前B相,则认为电机的方向是正转或正向的。如果A相滞后B相,则认为电机的方向是反转或反向的。第三个通道是INDX,称标志脉冲通道,电机转子每旋转一周产生一个脉冲,用于确立转子绝对位置的基准。图1是这三个信号的相对时间关系。
由解释A相、B相和标志信号的逻辑译码器和精确计数的上/下计数器组成正交编码器。数字滤波器在输入信号时对信号进行滤波。图2是QEI模块的方框图。这些功能包括:
两相信号和标志信号。
可编程译码器(提供计数器脉冲和计数方向)。
16位上/下位置计数器。
计数方向状态。
×2和×4分辨率计数。
位置计数器复位的两个模式。
普通用途16位定时器/计数器模式。
QEI或计数器事件产生中断。
应用实例
图3是典型的QEI应用实例,这里交流电机(ACIM)用正交编码器作为反馈信息控制。
应用实例要求:
在0°-360°范围内测量转子角位置。已知增量编码器光栅的数量,设置成相应的定标系数。用一个16位无符号变量表示。
测量角速度。已知的电机最高速度。用一个有符号16位变量表示,这里转子正转时符号是(+),反转时符号是(-)的。
在本例中使用下面的电机和编码器:
电机:Lesson Cat##102684,转子速度3450RPM
编码器:US数字模块E3-500-500-IHT,分辨率500线。
QEI模块初始化
使能数字滤波器
使能数字滤波器在增量编码器信号中滤波其他信号。对本例所用的结构,图4说明了输入信号的滤波作用。
滤波器计算时,编码器最小脉冲宽度为最高电机速度。在这个实例中,最小脉冲宽度由下式确定:
所配置的滤波器滤出任何小于15祍的脉冲,运行14.75MIPS,能够满足滤波器的要求,滤波器分频器由下式计算:
在QEI模块中有可选择参数,选择64分频,13祍以下的脉冲将被滤出。
增量脉冲计数器
在每个QEn引脚输入增量脉冲计数器信号。为了尽可能提高分辨率,QEI配置成×4。×4计数模式时,每个QEA和QEB信号沿到来时,POSCNT寄存器增量计数或减量计数,图5是×4配置的定时信号。
复位脉冲计数器
脉冲计数器由INDEX引脚复位。图6是INDEX脉冲复位脉冲计数器的定时图。
代码实例
下面是QEI模块初始化的代码实例:
实例1:QEI模块初始化
void InitQEI(viod)
{
ADPCFG|=0x0038;
//配置QEI引脚作为数字输入
QEICONbit.QEIM=0; //禁止QEI模块
QEICONbit.CNTERR=0; //清除计数错误
QEICONbit.QEISIDL=0; //睡眠期间连续工作
QEICONbit.SWPAB=0; //QEA和QEB交换
QEICONbit.PCDOUT=0; //标准I/O引脚工作
QEICONbit.POSRES=1;
//标志脉冲复位位置计数器
DELTCONbits.CEID=1; //禁止计数错误中断
DELTCONbits.QEOUT=1;
//允许QEn引脚数字滤波器输出
DELTCONbits.QECK=5;
//对QEn数字滤波器1:64时钟分频
DELTCONbits.INDOUT=1;
// 允许INDEX引脚数字滤波器输出
DELTCONbits.INDCK=5;
//对INDEX数字滤波器1:64时钟分频
POSCNT=0;
//复位位置计数器
QEICONbit.QEIM=6;
//用INDEX位置计数器复位×4模式
Return;
}
用QEI计算角度位置
控制算法采用小数运算,需要将位置计数器结果变换成一个符号小数。下式用于计算每转最大计数值。
MAX_COUNT_PER_REV=PULSES_PER_REV×COUNT_INC_PER_REV-1=500×4-1=1999
这里分辨率为0.18°。
用这个结果,位置计数变量需要将0到1999变换成有符号16位小数值0到32767。下面的公式是定标系数。
标志脉冲配置自动地复位POSCNT。
编码实例
实例2:用QEI计算角位置
int AngPos[2]={0,0};
//用于速度计算的两个变量
int POSCNTcopy=0;
{
POSCNTcopy=(int)POSCNT;
If (POSCNTcopy<0)
POSCNTcopy=- POSCNTcopy;
AngPos[1]= AngPos[0]
AngPos[0]=(unsigned int)(((unsigned long) POSCNTcopy*2048)/125;
//0<=POSCNT<=19991到0<=POSCNT<=32752
return;
}
用QEI计算角速度
在一个周期性中断中执行速度计算,因为角速度在一个固定时间周期中是增长的数字,这个中断间隔,必须小于最大转速的1/2转所需时间。电机的转速是3450RPM,所以在这个实例中选用4000RPM,以避免在任何速度计算时溢出。下式用于计算时间间隔:
实例3是定时器1的初始化,用于产生周期性中断,dsPIC DSC运行在14.75MIPS。
实例3:定时器1初始化,产生0.0075秒ISR周期
void InitTMR1(void)
{
TMR1=0; //复位定时器计数器
T1CONbit.TON=0; //关闭定时器1
T1CONbit.TSIDL=0; //睡眠期间连续工作
T1CONbit.TGATE=0; //禁止进入精确定时器
T1CONbit.TCS=0; //使用Tcy作为时钟源
T1CONbit.TCK=2; //Tcy/64作为输入时钟
PR1=1728 ;
//用64预分频器确定中断周期=0.0075秒
IFSobit.T1IF=0; //清定时器1中断标志
IECobits.T1IE=1; //允许定时器1中断
T1CONbits.TON=1; //打开定时器1
turn;
}
实例4是在周期性ISR中计算速度变量:
实例4:角速度计算实例
#define MAX_CNT_PER_REV(500*4-1)
#define MAXSPEED (unsigned int)(((unsigned long)MAX_CNT_PER_REV*2048)/125)
#define HALFMAXSPEED (MAXSPEED>>1)
int Speed;
void_attribute_((_interrupt_))_T1Interrupt(void)
{
IFSobits.T1IF=0;//清定时器1中断标志
PositionCalculation();
Speed=AngPos[0]- AngPos[1];
If(Speed>=0)
{
if (Speed>=(HALFMAXSPEED)
Speed=Speed-MAXSPEED;
}
else
{
if (Speed<-(HALFMAXSPEED)
Speed=Speed+MAXSPEED;
}
Speed*=2;
Return;
}
结语
从本文的编码实例,可以得到表1所示数据。
如果测量的速度和角位置需要比较高的分辨率,可以用下列方法:
用比较长地时间周期精确计数。必须避免脉冲计数器寄存器POSCN溢出,所以在这种情况下推荐使用POSCN寄存器的精度。
使用输入捕捉通道代替转换每转计数周期测量。
用每转产生更多脉冲地增量计数器。