This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Reading position from QEI



I have a problem reading encoder position using _position = QEIPositionGet(QEI0_BASE);               

Part if LM4F231

code:

 //////////////////////////////////

int _position; 
int _velocity; 
void QEI0IntHandler(void)
{     
 unsigned long status2, status1;
 status1 = QEIIntStatus(QEI0_BASE,false);     
 if ( (status1 & QEI_INTTIMER) == QEI_INTTIMER)
 {         
 QEIIntClear(QEI0_BASE, QEI_INTTIMER);         
 _position = QEIPositionGet(QEI0_BASE);         
 _velocity = QEIVelocityGet(QEI0_BASE);     
 }     
 if (  (status1 & QEI_INTDIR) == QEI_INTDIR)     
 {         
 QEIIntClear(QEI0_BASE, QEI_INTDIR);     
 }     
 if (  (status1 & QEI_INTDIR) == QEI_INTERROR)     
 {         
 QEIIntClear(QEI_BASE, QEI_INTERROR);     
 }
 
    volatile int ix = 0;     while(ix < 1000)     {         ix++;     } 
}
static void Qei0Init() {     
//     
// Enable the QEI peripheral.     
//     
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);     
SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);     
SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_QEI0);         
// wait to make syre periph. enabled     
volatile int ix = 0;     while(ix < 1000)     {         ix++;     }
    QEIDisable(QEI0_BASE);
    //     
 // Configure the QEI pins.     
 // 
 GPIOPinConfigure(GPIO_PF0_PHA0);     
 GPIOPinConfigure(GPIO_PF1_PHB0);     
 //GPIOPinConfigure(GPIO_PF4_IDX0);     
 GPIOPinTypeQEI(GPIO_PORTF_BASE, (GPIO_PIN_0 | GPIO_PIN_1));     
 //GPIOPinTypeQEI(GPIO_PORTF_BASE, GPIO_PIN_4);
    //     
 // Configure the operation     
 //     
 QEIConfigure(QEI0_BASE,(QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP), 20000);
    QEIEnable(QEI0_BASE);     
 QEIPositionSet(QEI0_BASE, 1000);
    //Timer Interval 1s/1000 = 1ms     
 QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, SysCtlClockGet()/1000);     
 //     
 //Enable the Velocity capture Module     
 //     
 QEIVelocityEnable(QEI0_BASE);
    QEIIntRegister(QEI0_BASE,*QEI0IntHandler);
    IntEnable(INT_QEI0);     
 QEIIntEnable(QEI0_BASE,QEI_INTDIR | QEI_INTTIMER);
    //
 // Loop forever
 //
 while(1)     
 {         
 ix = 0;         
 while(ix < 1000)         {             ix++;         }     
 } 
}

 /////////////////////////////////////////

When code is run _velocity changes.  _position doesn't change; or at least doesn't change much - it may drift from 1000 one or two counts there and there, but with no pattern.

Enabling Index pin doesn't have an effect.

Reading values outside of ISR doesn't have an effect.

Reading value from register directly using HWREG doesn't have an effect.

Monitoring register content using IAR debugger confirms observation: value of QEI0POS doesn't change.

Errata has couple entries on QEI operations, but doesn't seem to have that affect.

What am I missing here?

 

Thank you

 

 

  • Perhaps 2 posts removed from yours - poster had QEI issue.  And - like you - initially failed to recognize the default of PF0 into NMI.

    Pin must first be "unlocked" to re-purpose to any other function - and w/out this your QEI issue cannot meet your expectations.

    MCU manual details the unlock procedure - as well as adjoining post...

  • Hello, I'm having the same problem on a LM4F232H5QD (except its not, rather its a LX4F232H5QD and I imagine the production versions wouldn't be released until the problem was solved, that's right isn't it?) but I'm using Port D PD6-7 which doesn't involve locked pins. If the hardware can generate velocity values flawlessly (and it does) then it absolutely must be a hardware defect in the position counter. Any thoughts?

  • Correction, closer inspection reveals PD7 can also be an NMI pin. I'll try unlocking and report back...

  • Whew! and now, as promised:

    This works...

        // *************************************************************************************************** Lx4F232H5QD
        //    Initialize right side QEI (Quadrature Encoder Interface) for use by the right side drive.
        //    Uses GPIO Port D bits PD6 & PD7 (There is no Index wire from the encoder, perhaps we could install one on the axle).
        //    Note: Port D pin 7 defaults to a NMI input at reset. That functionality is protected by a mechanism
        //    which must be "unlocked" before it can be made available to another module (like QEI0).
        // ***************************************************************************************************

        // Enable Port D module so we can work with it
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

        // Make pin direction of bits 6 and 7 INPUTS (this may be unnecessary?)
        ROM_GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_7 | GPIO_PIN_6, GPIO_DIR_MODE_IN);

        // Write this 'key' 0x4C4F434B into Port D's Lock register to enable access to Port D's Commit register
        GPIO_PORTD_LOCK_R = 0x4C4F434B;

        // Flip only bit 7 ON to ALLOW Port D bit 7 to be switched from NMI use to QEI use
        GPIO_PORTD_CR_R |= 0x80;

        // Switch pin usage
        GPIO_PORTD_AFSEL_R |= 0x80;            // Selects alternative usage for the pin
        GPIO_PORTD_PCTL_R  |= 0x60000000;    // Selects QEI0 PHB0 in particular (pages 722 & 1405 in LM4F232H5QD manual)

        // Flip only bit 7 OFF to Re-lock
        GPIO_PORTD_CR_R &= !0x08;

        // Enable programming access to QEI Module 0
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);

        // Tell the mux which particular QEI function to connect to specified pin
        ROM_GPIOPinConfigure(GPIO_PD6_PHA0);
        ROM_GPIOPinConfigure(GPIO_PD7_PHB0);    // now redundant

        // Tell the GPIO module which pins will be QEI type pins
        ROM_GPIOPinTypeQEI(GPIO_PORTD_BASE, GPIO_PIN_7 | GPIO_PIN_6);

        // Zero the position counter
        ROM_QEIPositionSet(QEI0_BASE, 5900);
    etc.

  • david genge said:
    f the hardware can generate velocity values flawlessly (and it does) then it absolutely must be a hardware defect in the position counter. Any thoughts?

     You solved the problem by unlocking pin, issue to measure velocity not relative position when missing quadrature came from just pulse are needed for speed measurement, so no sign can be detected but hardware can generate speed from just a pulse. To detect direction and relative position a quadrature is necessary to decode phase of, relative position never increase or just oscillate by 1 around  if one of two QE signal miss. This can/must be detected as fault, I wait till samples arrive to inspect if failure detection flag/interrupt is implemented in on real hardware.