Encoder Index Channel Coding - Page 1
Forum section: electronics / beginners

author: abda2132
author_rank: Newbie
timestamp: April 21, 2022, 12:18:08 pm
content: Hello Everyone!Wanted to ask because I have a problem with getting the z pulse, or index channel to work on my encoder. I am using an encoder on a motor, and a nucleo board, and programming everything on stm32cubeide.What is the correct way of doing this?What I did:- first I got the channels a and b to work, so now i get the counter valuecode in main.c:volatile uint32_t counter = 0;volatile int16_t count = 0;volatile int16_t position = 0;//int16_t index = 0;void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){counter = __HAL_TIM_GET_COUNTER(htim);count = (int16_t)counter;position = count/4;}int main(void){HAL_TIM_Encoder_Start_IT(&htim1,TIM_CHANNEL_ALL);while (1){void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);}- then i activated an interrupt- then went to the stm32f7xx_it file and added this:volatile int16_t counter;if (HAL_GPIO_ReadPin(GPIOE, 13) == GPIO_PIN_SET) {counter = 0;}Is this how to do that?

author: rstofer
author_rank: Super Contributor
timestamp: April 21, 2022, 03:55:29 pm
content: In my opinion, that is not a good way to do it. Don't the pins have 'interrupt on change'? Every time A or B changes, you get an interrupt. It is up to the code to make sure which edge is interrupting (and changing it on every interrupt) {maybe you are looking for a falling edge because the signal is known to be high then you are looking for a rising edge signal because the signal is known to be low}I wrote this type of code for an ATmega128 quite a few years back.Code:#include <avr/io.h>#include <avr/interrupt.h>#include <stdio.h>#include <ctype.h>#include "defines.h"volatile int8_t RightWheelState = 0;volatile int32_t RightWheelCount = 0;volatile int8_t LeftWheelState = 0;volatile int32_t LeftWheelCount = 0;volatile uint8_t urx;volatile uint8_t urx_recv;/*Quadrature Encoder Scheme**There are two pairs of quadrature signals, one for each wheel.* The right wheel is on EXINT4 (PE4) and EXINT5 (PE5)* The left wheel is on EXINT6 (PE6) and EXINT7 (PE7)* Each encoder has two outputs A & B. For convenience, A is considered the MSB*while B is considered the LSB.*/const int32_t EncoderB[] = {+1,-1,-1,+1};const int32_t EncoderA[] = {-1,+1,+1,-1};SIGNAL(SIG_INTERRUPT4)// encoder B for right wheel{EICRB ^= 0x01;// toggle the edge bitRightWheelState ^= 0x01;RightWheelCount += EncoderB;}SIGNAL(SIG_INTERRUPT5)// encoder A for right wheel{EICRB ^= 0x04;RightWheelState ^= 0x02;RightWheelCount += EncoderA;}SIGNAL(SIG_INTERRUPT6)// encoder B for left wheel{EICRB ^= 0x10;LeftWheelState ^= 0x01;LeftWheelCount += EncoderB;}SIGNAL(SIG_INTERRUPT7)// encoder A for left wheel{EICRB ^= 0x40;LeftWheelState ^= 0x02;LeftWheelCount += EncoderA;}void IOInit(void){UBRR0H = 0;UBRR0L = BAUD;UCSR0B = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE);}static int uart_putchar(char c, FILE * stream){if (c == '\n')uart_putchar('\r', stream);while (! (UCSR0A & _BV(UDRE)));UDR0 = c;return c;}SIGNAL(SIG_UART0_RECV){uint8_t s;s = UCSR0A;urx = UDR0;if (bit_is_clear(s, FE))urx_recv = 1;}void QuadInit(void){LeftWheelState = (PORTE & 0xC0) >> 6;RightWheelState = (PORTE & 0x30) >> 4;EICRB = 0xff;// enable rising edge triggering on INT4..7EICRB ^= (LeftWheelState & 0x02) << 5;// if a signal is already setEICRB ^= (LeftWheelState & 0x01) << 4;// set the interrupt to falling edgeEICRB ^= (RightWheelState & 0x02) << 1;EICRB ^= (RightWheelState & 0x01);EIMSK = 0xf0;// enable these 4 interrupts}int main(void){IOInit();QuadInit();sei();fdevopen(uart_putchar, NULL);printf("Hello World\n");while (1) {printf("LWS =%2d LWC =%6ld RWS =%2d RWC =%6ld\n",LeftWheelState, LeftWheelCount, RightWheelState, RightWheelCount);}}The defines.h file:Code:#ifndef DEFINES_H#define DEFINES_H#define F_CPU (1474560UL)#define CYCLES_PER_US ((F_CPU + 500000UL)/1000000UL)#define BAUD (7)// 7 for 115200 baud with 14.745600 MHz clock#endif

author: langwadt
author_rank: Super Contributor
timestamp: April 21, 2022, 04:51:47 pm
content: Quote from: rstofer on April 21, 2022, 03:55:29 pmmost of the STM32 timers can handle the quadrature decoding of the AB channels directly with no interruptsan index pulse is a bit more tricky

author: eugene
author_rank: Frequent Contributor
timestamp: April 21, 2022, 06:44:41 pm
content: It's not clear to me what you want to do. The STM32 can handle A and B channel quadrature encoder input in hardware. Presumably you've set that up and can simply read the counter register when ever position information is needed. But the thread title suggests that this is about the Z input, which is handled in hardware by some Arm processors, but I am not familiar with the STM32.Generally, if not handled automatically in hardware, a pin change interrupt will be setup on whatever pin the Z channel is connected to. If you simply want to zero the encoder count when the index is found, then that would be done in the ISR. If you want to keep track of rotations with the index pulse, then a rotation counter is incremented or decremented depending on rotation. In that case you need to determine direction, but it's all done in the ISR that is triggered by a change in the Z channel pin. There would be zero code in your main loop to handle it. It's all done in the ISR.

author: Cerebus
author_rank: Super Contributor
timestamp: April 21, 2022, 10:45:19 pm
content: Yes, somewhere buried in the highly impenetrable STM32 timer/counter documentation there is a way to tie the Z input to the counter (in quadrature mode) as well.Ah, there it is (this is for the STM32G4 series, but others are similar):Quote

author: abda2132
author_rank: Newbie
timestamp: April 22, 2022, 08:02:36 am
content: yeah! I want to zero out my counter when the index pulse is hit.Does the code I have make sense then? The main.c and the isr code, or is there more to that?Thnx btw

author: abda2132
author_rank: Newbie
timestamp: April 22, 2022, 08:03:57 am
content: Do you know how that would look like in code?

author: abda2132
author_rank: Newbie
timestamp: April 25, 2022, 10:55:53 am
content: How would the code look like for the last part?