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
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 ;
}