Author Topic: Encoder Index Channel Coding  (Read 1139 times)

0 Members and 1 Guest are viewing this topic.

Offline abda2132Topic starter

  • Newbie
  • Posts: 4
  • Country: dk
Encoder Index Channel Coding
« on: April 21, 2022, 12:18:08 pm »
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 value

code 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?
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9933
  • Country: us
Re: Encoder Index Channel Coding
« Reply #1 on: April 21, 2022, 03:55:29 pm »
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: [Select]
#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 bit
RightWheelState ^= 0x01;
RightWheelCount += EncoderB[RightWheelState];
}

SIGNAL(SIG_INTERRUPT5) // encoder A for right wheel
{
EICRB         ^= 0x04;
RightWheelState ^= 0x02;
RightWheelCount += EncoderA[RightWheelState];
}

SIGNAL(SIG_INTERRUPT6) // encoder B for left wheel
{
EICRB          ^= 0x10;
LeftWheelState ^= 0x01;
LeftWheelCount += EncoderB[LeftWheelState];
}

SIGNAL(SIG_INTERRUPT7) // encoder A for left wheel
{
EICRB          ^= 0x40;
LeftWheelState ^= 0x02;
LeftWheelCount += EncoderA[LeftWheelState];
}

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..7
EICRB ^= (LeftWheelState  & 0x02) << 5; // if a signal is already set
EICRB ^= (LeftWheelState  & 0x01) << 4; // set the interrupt to falling edge
EICRB ^= (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: [Select]
#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


« Last Edit: April 21, 2022, 04:03:00 pm by rstofer »
 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 4701
  • Country: dk
Re: Encoder Index Channel Coding
« Reply #2 on: April 21, 2022, 04:51:47 pm »
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.


most of the STM32 timers can handle the quadrature decoding of the AB channels directly with no interrupts

an index pulse is a bit more tricky

 

Offline eugene

  • Frequent Contributor
  • **
  • Posts: 496
  • Country: us
Re: Encoder Index Channel Coding
« Reply #3 on: April 21, 2022, 06:44:41 pm »
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.
90% of quoted statistics are fictional
 

Offline Cerebus

  • Super Contributor
  • ***
  • Posts: 10576
  • Country: gb
Re: Encoder Index Channel Coding
« Reply #4 on: April 21, 2022, 10:45:19 pm »
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
Index Input
The counter can be reset by an Index signal coming from the encoder, indicating an absolute reference position. The Index signal must be connected to the tim_etr_in input. It can be filtered using the digital input filter.
The index functionality is enabled with the IE bit in the TIMx_ECR register. The IE bit must be set only in encoder mode, when the SMS[3:0] bitfield has the following values: 0001, 0010, 011, 1010, 1011, 1100, 1101, 1110, 1111.
Anybody got a syringe I can use to squeeze the magic smoke back into this?
 

Offline abda2132Topic starter

  • Newbie
  • Posts: 4
  • Country: dk
Re: Encoder Index Channel Coding
« Reply #5 on: April 22, 2022, 08:02:36 am »
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
 

Offline abda2132Topic starter

  • Newbie
  • Posts: 4
  • Country: dk
Re: Encoder Index Channel Coding
« Reply #6 on: April 22, 2022, 08:03:57 am »
Do you know how that would look like in code?
 

Offline abda2132Topic starter

  • Newbie
  • Posts: 4
  • Country: dk
Re: Encoder Index Channel Coding
« Reply #7 on: April 25, 2022, 10:55:53 am »
How would the code look like for the last part?
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf