Driver for QEI hardware

11 Dec 2010

If anyone would like to try using the Quadrature Encoder Interface hardware that is built into the mbed, feel free to take a look at the QEI_hw driver on my library page. ( http://mbed.org/users/hexley/libraries/QEI_hw/lj8o7d )

The driver supports interrupts on change of direction, on reaching one of 3 user-defined positions, and more. It provides for hardware filtering of the input signals to de-bounce mechanical switching transients. It can be set up to measure velocity at specified intervals. And, perhaps most importantly, it will track position even with interrupts disabled.

This driver is based on the CMSIS driver, with extensions supporting user-supplied interrupt service routines.

A guide to making the hardware mods is on my notebook page. ( http://mbed.org/users/hexley/notebook/qei_hw-interface-implementation-notes/ ).

13 Dec 2010

EXCELLENT WORK!!!   I was hoping to not have to write it myself.  I might get a chance to test it with my project this weekend.   I'm hoping it fixes an issue I was having with the interrupt based QEI setup where it lost counts at fast RPMs.

Thanks
matt

 

06 Oct 2011

I know, it's a quiet old thread, but I need some input.

I've posted here

http://mbed.org/users/hexley/notebook/qei_hw-interface-implementation-notes/

and pm'ed hexley but he seems to busy to look at mbed.

So I repeat my question here.

I managed to hook up also the index pin to the mbed

GetIndex() is counting each time the index hit's.

Now I tried to add an ISR using AppendISR.

mbed jumps into the ISR but stalls there.

Is there something to special care about or anything I'm missing?

here the code I use.

// Display changes in encoder position and direction
#include "mbed.h"
#include "qeihw.h"

DigitalOut led1(LED1);
DigitalOut led3(LED3);
QEIHW qei(QEI_DIRINV_NONE, QEI_SIGNALMODE_QUAD, QEI_CAPMODE_2X, QEI_INVINX_NONE );


void toggleIndexLed(void) {
  led3 = !led3;
}

int main() {
int32_t temp, position = 0;
qei.SetDigiFilter(480UL);
qei.SetMaxPosition(1024);
qei.AppendISR(QEI_INTFLAG_INX_Int, &toggleIndexLed);

qei.IntCmd(QEI_INTFLAG_INX_Int, ENABLE);

while (1) {
while (position == (temp = qei.GetPosition()) );
position = temp;
printf("New position = %d. idx : %d\r\n", temp, qei.GetIndex());
led1 = qei.Direction() == SET ? 1 : 0;
//         led3 = !led1;
wait(0.1);
}
}

I've added some printf's to hexley's QEIHW::Qeiisr(void) function. that function dispatches the ISR's

QEIHW::Qeiisr(void) function looks like that now

void QEIHW::Qeiisr(void)  
{
    int32_t i;

    //User defined interrupt handlers. Check all possible sources, dispatch to corresponding non-null service routines.
    for(i = 0; i < 13; i++) {
        if(LPC_QEI->QEIINTSTAT & ((uint32_t)(1<<i)) ) {
            if (_qei_isr[i] != NULL) {
            
            printf("call ISR at %d", _qei_isr[i] );
                _qei_isr[i]();
            
            } else {
                printf("No ISR defined for %d", _qei_isr[i] );
            }
        }
    }
    return;
}

and I get repeated

call ISR at 769

No ISR defined for 0

No ISR defined for 0

769 is the correct address of toggleIndexLed()

what else I have to do to make it run?

Thanks to all,

Ju

06 Oct 2011

OK, some further investigation after having launch made it clear.

I post solution here

http://mbed.org/users/hexley/notebook/qei_hw-interface-implementation-notes/

Ju