cancel
Showing results for 
Search instead for 
Did you mean: 

Why voltage drops while using GPIO as a timer input

Nikita.Mikhailovskiy
Associate II

Greetings.

I've entirely stuck with this problem.

MCU: STM32F407VGT6

Realization: custom PCB and F4 Discovery board.

Problem: Microcontroller can't gather information from encoders.

Description: 

  There are three motors with built-in encoders that I want to control. These motors have a controller that power encoder and drives motor by a PWM signal. It works with the TTL voltage level(5V). I used a discovery board to make a prototype where encoders were connected directly to the STM32. Everything works just fine. I made a custom PCB where all inputs are isolated. 

  For motor controllers, I've used ADuM1402 isolators (Quad-channel digital isolator), where two channels are output signals (PWM and direction), and two channels are inputs from the encoder (CHA and CHB). After some tests, I realized that only one of three encoders is processing right, and I get only zeroes from the others.

  I checked the voltage and signal on the pin and saw that maximal amplitude is equaled to 0.7 V, which is not enough to trigger a counter.

  I disabled an MCU by loading it in the bootloader and tested the voltage on that pin again. It equals to a Vdd voltage that powers the isolator and MCU(3.3V). After editing the pin mode from "alternate" to "input", an amplitude was equal to 3.3V too.

  

The working encoder is connected to Timer 1 through PA8 and PA9 (AF 1).

Non-processing encoders are connected to Timer 2 through PA0, PA1 (AF 1), and Timer 3 through PA6 and PA7 (AF 2).  

All pins are configured with pull-up resistors and push-pull output mode.

Timers are configured in encoder mode (LL_TIM_ENCODERMODE_X4_TI12) with active inputs.

Defines for examples:

/*

* Odometry configuration

* Encoder times configuration

*/

#define ENCODER_TIM_CNT_INITIAL_VALUE (uint16_t) 0x7530

#define ENCODER_TIM_ARR 0xffff

#define ENCODER_1_TIM_MODULE TIM2

#define ENCODER_1_CNT ((uint16_t *)&(ENCODER_1_TIM_MODULE->CNT))

#define ENCODER_2_TIM_MODULE TIM3

#define ENCODER_2_CNT ((uint16_t *)&(ENCODER_2_TIM_MODULE->CNT))

#define ENCODER_3_TIM_MODULE TIM1

#define ENCODER_3_CNT ((uint16_t *)&(ENCODER_3_TIM_MODULE->CNT))

#define ENCODER_2_CHA_PORT GPIOA

#define ENCODER_2_CHA_PIN LL_GPIO_PIN_7

#define ENCODER_2_CHB_PORT GPIOA

#define ENCODER_2_CHB_PIN LL_GPIO_PIN_6

#define ENCODER_2_PIN_AF LL_GPIO_AF_2

GPIO configuration example:

/*

* Initialization second encoder gpios

*/

LL_GPIO_SetPinMode(ENCODER_2_CHA_PORT, ENCODER_2_CHA_PIN,

LL_GPIO_MODE_ALTERNATE);

LL_GPIO_SetAFPin_0_7(ENCODER_2_CHA_PORT, ENCODER_2_CHA_PIN,

ENCODER_2_PIN_AF);

LL_GPIO_SetPinPull(ENCODER_2_CHA_PORT, ENCODER_2_CHA_PIN,

LL_GPIO_PULL_UP);

LL_GPIO_SetPinOutputType(ENCODER_2_CHA_PORT, ENCODER_2_CHA_PIN,

LL_GPIO_OUTPUT_PUSHPULL)

LL_GPIO_SetPinMode(ENCODER_2_CHB_PORT, ENCODER_2_CHB_PIN,

LL_GPIO_MODE_ALTERNATE);

LL_GPIO_SetAFPin_0_7(ENCODER_2_CHB_PORT, ENCODER_2_CHB_PIN,

ENCODER_2_PIN_AF);

LL_GPIO_SetPinPull(ENCODER_2_CHB_PORT, ENCODER_2_CHB_PIN,

LL_GPIO_PULL_UP);

LL_GPIO_SetPinOutputType(ENCODER_2_CHB_PORT, ENCODER_2_CHB_PIN,

LL_GPIO_OUTPUT_PUSHPULL)

Timer configuration example:

/*

    * Second encoder mode timer

     */

    LL_TIM_CC_EnableChannel(ENCODER_2_TIM_MODULE,

     LL_TIM_CHANNEL_CH1 | LL_TIM_CHANNEL_CH2);

    LL_TIM_IC_Config(ENCODER_2_TIM_MODULE, LL_TIM_CHANNEL_CH1,

             LL_TIM_ACTIVEINPUT_DIRECTTI);

    LL_TIM_IC_Config(ENCODER_2_TIM_MODULE, LL_TIM_CHANNEL_CH2,

             LL_TIM_ACTIVEINPUT_DIRECTTI |

             LL_TIM_IC_POLARITY_RISING);

    LL_TIM_SetAutoReload(ENCODER_2_TIM_MODULE, ENCODER_TIM_ARR);

    LL_TIM_SetEncoderMode(ENCODER_2_TIM_MODULE,

               LL_TIM_ENCODERMODE_X4_TI12);

    *(odom_ctrl->p_enc_ticks[1]) = ENCODER_TIM_CNT_INITIAL_VALUE;

12 REPLIES 12

What was wrong?

JW

After a little research. I figured out that there was incorrect usage of LL_TIM_IC_Config() function. For this function it's necessary to use full LL lib with timer and GPIO structures. CubeIDE generated the code with dedicated commands for configuring input config.

Generated code snippet:

LL_TIM_SetEncoderMode(ENCODER_1_TIM_MODULE, LL_TIM_ENCODERMODE_X4_TI12);
LL_TIM_IC_SetActiveInput(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
LL_TIM_IC_SetActiveInput(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(ENCODER_1_TIM_MODULE, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
LL_TIM_SetCounterMode(ENCODER_1_TIM_MODULE, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetAutoReload(ENCODER_1_TIM_MODULE, ENCODER_TIM_ARR);
LL_TIM_SetClockDivision(ENCODER_1_TIM_MODULE, LL_TIM_CLOCKDIVISION_DIV1);
LL_TIM_DisableARRPreload(ENCODER_1_TIM_MODULE);
LL_TIM_SetTriggerOutput(ENCODER_1_TIM_MODULE, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(ENCODER_1_TIM_MODULE);

Best regards,

Nikita Mikhailovskiy

Thanks for the info.

JW