Alternate eMotor Speed Calcuation Scheme

Adjustment to the QEI routines

The initialization routine stays pretty much the same, except that now we don’t want the index pulse to reset POSCNT. So the only change is

typedef union 
    int half[2];
    long full;
} enc_cnt;

Now, how could we detect when overflow/underflow occurs? No big deal, since QEI module provides interrupt service for such event. The procedure is the same as other interrupt routines in dsPIC. We only have to enable it, and reset the interrupt flag. Add these two lines at the end of QEI initialization routine.

enc_cnt EncCnt;

The last task for the QEI section is to implement the update of upper 16-bit encoder count. Simply check the QEICONbits.UPDN bit for the rotation direction, and increase/decrese the value accordingly. Then reset the interrupt flag before leaving the ISR.

void __attribute__((interrupt, auto_psv)) _QEIInterrupt(void)
    if (QEICONbits.UPDN) EncCnt.half[1]++;
    else EncCnt.half[1]--;
    _QEIIF = 0;

Update of the lower 16-bit count EncCnt.half[0] by a copy of POSCNT must be done elsewhere before it is used, to avoid the slim chance of inconsistent data. Indeed, for best result the lower 16-bit should be updated very frequently by a timer routine.

Velocity computation

With the above mechanism to achive a 32-bit accumulated position, the velocity computation is now much easier. Here we use timer 2 with sampling period 50 millisecond (defined by DELTAT2.) ENCPPRx4 refers to 4 times the actual encoder lines minus one. Our eMotor has 100 encoder lines, so ENCPPRx4 = 100*4 – 1.

#define DELTAT2 50
#define ENCPPRx4 399 //
long EncCnt_old;   // global variable to keep previous position
void __attribute__((__interrupt__)) _T2Interrupt (void)
    IFS0bits.T2IF = 0; // Clear timer 2 interrupt flag
    dEnc = EncCnt.full - EncCnt_old;
    Velf = (double)dEnc*1000/(ENCPPRx4*DELTAT2);
    EncCnt_old = EncCnt.full;



Comments are closed.