Hello, I am working on calculating the Motor Revolutions. As part of that, I found that in the register in Quadrature Encoder Interface, there is a register "INXCNT" in QEI, which will provide me with the revolution counting.
1. "When I tried to read the INXCNT register value in QEI after performing a few revolutions, I see the value as "0xFFFFFFFF". Using the "CON" register I cleared the index counter by setting the bit 3 of the ‘CON’ register to 1. Even after that, for the first revolution itself, "INXCNT" is set to "0xFFFFFFFF". For the second time, I tried to rotate the motor manually in the opposite direction. Then the value is set to "0x00000001" and then when normal rotations were performed it is set back to "0x00000000" and never got incremented. The encoder has Index, PhaseA, and PhaseB signals but not home signals. Can you please let me the behavior of the "INXCNT" register of QEI? (INXCNT should be counting the number of revolutions)”.
2. "Second issue I see is, in the documentation (UM10503, LPC43xx_LPC43Sxx User manual), the definitions of both the "POS" register and the "INXCNT" register were the same. May I know the difference between both registers? "
Hi,
I have LPC_Link2 board, which populates the LPC4370FET100 chip, as you see above signal assignment, the QEI signal PHA/PHB and Index are not routed to pads for the LPC4370FET100.
I see that you use LPC4367JBD208, I will try to use the other boards to have a test
BTW,as I have said that the INXCNT register counts the pulse on Index pin, if you fails to count, pls try to add the PHA/PHB signals to QEI which has 90 degree shift.
BR
XiangJun Rong
Hi,
Because I have not Encoder signals, I use three GPIO pins to simulate the three Encoder signals:PHA/PHB and IDX, then connect the three simulated signals to QEI_PHA, QEI_PHB and QEI_IDX pins via cable, I develop the code based on Embedded Artist board with LPC4088FET208 populated and LPCOpen package, MCUXPresso IDE tools.
The conclusion is that the LPC_QEI->INXCNT counts the rising&falling edge number of both PHA and PHB, it is not related to QEI_IDX signal.
Hope it can help you
BR
XiangJun Rong
Hi Rong,
In the documentation (UM10503, LPC43xx_LPC43Sxx User manual), it is mentioned that "QEI_IDX is used as the Index (IDX) input to the Quadrature Encoder Interface".
But you have mentioned INXCNT is not related to QEI_IDX signal. If so, how can I calculate total revolutions by using rising and falling edge number of both PHA and PHB. Because clearly in our registers, INXCNT is not updating accordingly.
My requirement is to get the total revolutions after the motor spins. Do I need to have any special configurations to make INXCNT register to update to total revolutions?
Hi,
As the following Fig, the Index Counter is connected to Inx_pulse, dir and clk_pulse, it does not says that the Index Counter is just connected to Inx_pulse.
Assume that the rotor rotates 1000 revolution in clockwise, then it rotates in 500 revolution in anti-clockwise, if the INXCNT just counts the INDEX pulse, it will get 1500 revolution, obviously, it is wrong, because the final revolution is 1000-500=500.
The INXCNT counts the rising/falling edges number of both PHA and PHB in increasing direction in clockwise rotation, for example one revolution covers 1024 PHA pulse, the INXCNT will be 1000*1024*4, INXCNT=40960000
After 500 revolution in anti-clockwise, the INXCNT will counts the rising/falling edges number of both PHA and PHB in decreasing direction, the INXCNT will be 40960000-500*1024*4=20480000
You can get the final revolution by 2048/(1024*4)=500 revolution.
Note the PHA and PHB signal relative phase includes the rotation direction information.
Hope it can help you
BR
XiangJun Rong
Hi,
I have used the GPIO to simulate the encoder signals, I copy the code here, if you have time, pls have a try.
BR
XiangJun Rong
#include "board.h"
#include <stdio.h>
void QEI(void);
void GPIO_Output(void);
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
#define TICKRATE_HZ1 (1000) /* 10 ticks per second */
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
/*****************************************************************************
* Private functions
****************************************************************************/
/*****************************************************************************
* Public functions
****************************************************************************/
/**
* @brief Handle interrupt from SysTick timer
* @return Nothing
*/
uint32_t index,counter;
bool P2_15waveform[80]={true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,\
true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,\
true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,\
true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,\
true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false};
bool P2_23waveform[80]={false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,\
false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,\
false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,\
false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,\
false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false};
bool P2_19waveform[80]={true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,\
false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,\
false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,\
false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,\
false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false};
uint32_t revolutionReading[100];
void SysTick_Handler(void)
{
Board_LED_Toggle(0);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 15, P2_15waveform[index]);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 23, P2_23waveform[index]);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 19, P2_19waveform[index]);
index++;
if(index>=80)
{
index=0;
revolutionReading[counter]=LPC_QEI->INXCNT;
counter++;
if(counter>=100) counter=0;
}
}
/**
* @brief main routine for systick example
* @return Function should not exit.
*/
int main(void)
{
/* Generic Initialization */
SystemCoreClockUpdate();
Board_Init();
QEI();
/* Enable and setup SysTick Timer at a periodic rate */
SysTick_Config(SystemCoreClock / TICKRATE_HZ1);
GPIO_Output();
index=0;
counter=0;
/* LEDs toggle in interrupt handlers */
while (1) {
// __WFI();
}
return 0;
}
//QEI signal connection
//On Embedded Artist AB2103 mother board/daughter card board, the LPC4088EFT208 is populated
//P1_20 is connected to J1_88, QEI_PHA. pin32 of J5
//P1_23 is connected to J1_91. QEI_PHB, pin 23 of J5
//P1_24 is connected to J1_92, QEI_INdex, pin27 of J3
void QEI(void)
{
//pin assignment
//P1.20 QEI_PHA
Chip_IOCON_PinMuxSet(LPC_IOCON,0x1, 20, 0x03);
//P2.23 QEI_PHB
Chip_IOCON_PinMuxSet(LPC_IOCON,0x1, 23, 0x03);
//P1.24 QEI_IDX
Chip_IOCON_PinMuxSet(LPC_IOCON,0x1, 24, 0x03);
//QEI clock enable
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_QEI);
//QEI code
}
//on the LPC4088 board,
//GPIO70 <---->P2.15----------->pin 54 on J5
//GPIO74 <---->P2.23------------>pin 56 on J5
//GPIO71 <---->P2.19------------>pin46 on J5
void GPIO_Output(void)
{
/* Sets up DEBUG UART */
asm("nop");
/* Initializes GPIO */
Chip_GPIO_Init(LPC_GPIO);
Chip_IOCON_Init(LPC_IOCON);
Chip_GPIO_SetPortMask(LPC_GPIO, 2, 0x00);
//P2.25 configured as GPIO
Chip_GPIO_WriteDirBit(LPC_GPIO, 2, 15, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 15, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 15, false);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 15, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 15, false);
Chip_GPIO_SetPinToggle(LPC_GPIO, 2,15);
Chip_GPIO_SetPinToggle(LPC_GPIO, 2,15);
Chip_GPIO_SetPinToggle(LPC_GPIO, 2,15);
Chip_GPIO_SetPinToggle(LPC_GPIO, 2,15);
//P2.23 configured as GPIO
Chip_GPIO_WriteDirBit(LPC_GPIO, 2, 23, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 23, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 23, false);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 23, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 23,false);
Chip_IOCON_PinMuxSet(LPC_IOCON,2,19,0x00);
Chip_GPIO_WriteDirBit(LPC_GPIO, 2, 19, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 19, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 19, false);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 19, true);
Chip_GPIO_WritePortBit(LPC_GPIO, 2, 19, false);
}