Using the QEI with an optical rotary encoder

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using the QEI with an optical rotary encoder

1,327 Views
leo838
Contributor II

Hello all,

Has anyone had any luck using the quadrature encoder interface (QEI ) with a optical rotary encoder (similar to the Grayhill 62P series) ?

I've been trying without much luck, it seems its designed for motor control but I'm hoping to get it working with the above encoder.

Thanks,

Leo

Labels (1)
Tags (1)
0 Kudos
1 Reply

875 Views
leo838
Contributor II

Actually I got it working with a straightforward implementation below:

/*
===============================================================================
 Name        : LPC1769Template.c
 Author      : OH
 Version     :
 Copyright   : $(copyright)
 Description : Implementation of an optical decoder on using the QEI on a LPC1769
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>

// TODO: insert other include files here
#define RESET_VALUE 0x7FFFFFFF

volatile int new_pos = 0;    // Use to increment/ decrement position on interrupt
volatile int old_pos = 0;


void qei_setup(void){
    // setup for Grayhill series 62P optical encoder

    LPC_SC->PCONP    |= 1<<18;         // Power up QEI
    LPC_SC->PCLKSEL1 |= 3;             // Select clock for QEI = cclk/8
    LPC_PINCON->PINSEL3 |= (1<<8);     // configure as MCI0-QEA  - P1.20 -> Pad 7 on LPCXpresso 1769
    LPC_PINCON->PINSEL3 |= (1<<14);    // configure as MCI1-QEB  - P1.23 -> Pad 6 on LPCXpresso 1769
    //LPC_PINCON->PINSEL3 |= (1<<16);    // configure as MCI2-INDX - P1.24

    LPC_QEI->QEICONF |= (1<<2);        // Set quadrature mode - 4x mode
    LPC_QEI->QEIMAXPOS = RESET_VALUE;  // Maximum pulse count limit after which counter resets
    LPC_QEI->FILTER     = 0;          // Number of clk delays to delay before accepting input

    //Enable interrupts on postions
    //LPC_QEI-> QEIIES |= (1 << 6) | (1 << 7) | (1 << 8); // Enable interrupts on position captures

    //NVIC_EnableIRQ(QEI_IRQn);    // Enable interrupt

}

void led_setup(void){
    LPC_GPIO0->FIODIR |= (1 << 22); //Configure P0.22 as output, position 0, Red
    LPC_GPIO3->FIODIR |= (1 << 26); //Configure P3.26 as output, position 1, Blue
    LPC_GPIO3->FIODIR |= (1 << 25); //Configure P3.25 as output, position 2, Green
}

void QEI_IRQHander(){
    // Not used!!
    if ((LPC_QEI-> QEIINTSTAT >> 6) & 1){
        // Position 0
        new_pos = 0;
        LPC_QEI-> QEICLR |= (1<<6);
    }
    else if ((LPC_QEI-> QEIINTSTAT >> 7) & 1){
        // Position 1
        new_pos = 1;
        LPC_QEI-> QEICLR |= (1<<7);
    }
    else if ((LPC_QEI-> QEIINTSTAT >> 8) & 1){
        // Position 2
        new_pos = 2;
        LPC_QEI-> QEICLR |= (1<<8);
    }else {
        LPC_QEI-> QEICLR |= (1<<3) | (1 <<5);    // TODO: Clear dir & clock pulse
    }
}


int main(void) {

    qei_setup();
    led_setup();
    old_pos = LPC_QEI->QEIPOS;

    while(1) {

        new_pos = (LPC_QEI->QEIPOS - old_pos);

        if (new_pos > 0){
            // clockwise rotation?
            //LPC_GPIO0->FIOPIN = (1 << 22); // On
            LPC_GPIO3->FIOCLR = (1 << 25); // Off
            LPC_GPIO3->FIOPIN = (1 << 26); // Blue On

            old_pos = LPC_QEI->QEIPOS;
        }
        else if (new_pos < 0){
            //LPC_GPIO0->FIOCLR = (1 << 22);
            LPC_GPIO3->FIOPIN = (1 << 25); // Green On
            LPC_GPIO3->FIOCLR = (1 << 26); // blue off
            old_pos = LPC_QEI->QEIPOS;
        }
        else{
            //LPC_GPIO0->FIOCLR = (1 << 22);
            //LPC_GPIO3->FIOCLR = (1 << 25);
            //LPC_GPIO3->FIOCLR = (1 << 26);
        }

    }
    return 0 ;
}

0 Kudos