STM32-HAL library motor development encoder

Encoder programming is based on STM32F407IG, and the pre basic knowledge is timer input capture.

Detailed explanation of principle

The types of encoders include incremental encoder, absolute encoder and hybrid absolute encoder.
This experiment uses incremental encoder
The schematic diagram of the basic encoder is shown in the figure below. Rotary encoder is mostly composed of code disk, photoelectric detection device and signal processing circuit. The code disk is engraved with several circles of wire slots, which are equidistant and transparent. When the code disk rotates, it will periodically pass through and block the light from the photoelectric detection device, so that the detection device will periodically generate several electrical signals. However, these electrical signals are usually weak, so a set of processing circuit needs to be added to amplify and shape the signal, and finally shape the signal into a pulse signal and output it to the outside. Basic schematic diagram of encoder

Both incremental encoders have A and B channel signal output, which is because there are two cycles of trunking on the code disk of the incremental encoder, and the two cycles of trunking will be staggered by A certain angle, which will make the two-phase signals output by the photoelectric detection device differ by 1 / 4 cycle (90 °).

The purpose is to judge the movement direction according to the change order of the two-phase signals, record the number of output pulses, know the displacement, and get the speed through the frequency of the output signal.
The use of quadruple frequency technology in signal acquisition is to increase the resolution
Resolution: refers to the smallest unit that the encoder can distinguish.
Accuracy refers to the maximum error between each reading of the encoder and the actual position of the rotating shaft, which is usually expressed in angle, angular minute or angular second.

The resolution is increased by four times through frequency division, and the accuracy does not change, so the accuracy is increased. Accuracy is determined by resolution and accuracy.

Code explanation

/**
  * @brief  Configure TIMx encoder mode
  * @param  nothing
  * @retval nothing
  */
static void TIM_Encoder_Init(void)
{ 
  TIM_Encoder_InitTypeDef Encoder_ConfigStructure;
  
  /* Enable encoder interface clock */
  ENCODER_TIM_CLK_ENABLE();
  
  /* Timer initialization settings */
  TIM_EncoderHandle.Instance = ENCODER_TIM;
  //When the value of the acquisition prescaler is 0, it means that the acquisition is performed for each edge
  TIM_EncoderHandle.Init.Prescaler = 0;
  //Count up
  TIM_EncoderHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  //The total number of times to capture a cycle is 65535
  TIM_EncoderHandle.Init.Period = 65535;
  //No frequency division
  TIM_EncoderHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  TIM_EncoderHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  
  /* Set encoder frequency multiplier */
  Encoder_ConfigStructure.EncoderMode = ENCODER_MODE;
  /* Encoder interface channel 1 is set to start at the rising edge*/
  Encoder_ConfigStructure.IC1Polarity = TIM_ICPOLARITY_RISING;
  //Encoder polarity setting, no tube if there is no reverse direction
  Encoder_ConfigStructure.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  //No frequency division
  Encoder_ConfigStructure.IC1Prescaler = TIM_ICPSC_DIV1;
  Encoder_ConfigStructure.IC1Filter = 0;
  /* Encoder interface channel 2 setting */
  Encoder_ConfigStructure.IC2Polarity = TIM_ICPOLARITY_RISING;
  Encoder_ConfigStructure.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  Encoder_ConfigStructure.IC2Prescaler = TIM_ICPSC_DIV1;
  Encoder_ConfigStructure.IC2Filter = 0;
  /* Initialize encoder interface */
  HAL_TIM_Encoder_Init(&TIM_EncoderHandle, &Encoder_ConfigStructure);
  
  /* Reset counter */
  __HAL_TIM_SET_COUNTER(&TIM_EncoderHandle, 0);
  
  /* Clear interrupt flag bit */
  __HAL_TIM_CLEAR_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);
  /* The update event of the enable timer is interrupted */
  __HAL_TIM_ENABLE_IT(&TIM_EncoderHandle,TIM_IT_UPDATE);
  /* Set update event request source as: counter overflow */
  __HAL_TIM_URS_ENABLE(&TIM_EncoderHandle);
  
  /* Set interrupt priority */
  HAL_NVIC_SetPriority(ENCODER_TIM_IRQn, 0, 1);
  /* Enable timer interrupt */
  HAL_NVIC_EnableIRQ(ENCODER_TIM_IRQn);
  
  /* Enable encoder interface */
  HAL_TIM_Encoder_Start(&TIM_EncoderHandle, TIM_CHANNEL_ALL);
}

/**
  * @brief  Encoder interface pin initialization
  * @param  nothing
  * @retval nothing
  */
static void Encoder_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  /* Timer channel pin port clock enable */
  ENCODER_TIM_CH1_GPIO_CLK_ENABLE();
  ENCODER_TIM_CH2_GPIO_CLK_ENABLE();
  
  /**TIM3 GPIO Configuration    
  PC6     ------> TIM3_CH1
  PC7     ------> TIM3_CH2 
  */
  /* Set input type */
  GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
  /* Set pull-up */
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  /* Set pin rate */
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  
  /* Select the GPIO pin to control */	
  GPIO_InitStruct.Pin = ENCODER_TIM_CH1_PIN;
  /* Set reuse */
  GPIO_InitStruct.Alternate = ENCODER_TIM_CH1_GPIO_AF;
  /* Call the above GPIO function library_ Initstructure initialize GPIO */
  HAL_GPIO_Init(ENCODER_TIM_CH1_GPIO_PORT, &GPIO_InitStruct);
  
  /* Select the GPIO pin to control */	
  GPIO_InitStruct.Pin = ENCODER_TIM_CH2_PIN;
  /* Set reuse */
  GPIO_InitStruct.Alternate = ENCODER_TIM_CH2_GPIO_AF;
  /* Call the library function and use the GPIO configured above_ Initstructure initialize GPIO */
  HAL_GPIO_Init(ENCODER_TIM_CH2_GPIO_PORT, &GPIO_InitStruct);
}

/**
  * @brief  Encoder interface initialization
  * @param  nothing
  * @retval nothing
  */
void Encoder_Init(void)
{
  Encoder_GPIO_Init();    /* Pin initialization */
  TIM_Encoder_Init();     /* Configure encoder interface */
}

. h file

#ifndef __BSP_ENCOEDER_H
#define	__BSP_ENCOEDER_H

#include "stm32f4xx.h"

/* Timer selection */
#define ENCODER_TIM                            TIM3
#define ENCODER_TIM_CLK_ENABLE()  				     __HAL_RCC_TIM3_CLK_ENABLE()

/* Timer overflow value */		
#define ENCODER_TIM_PERIOD                     65535
/* Timer prescaled value */
#define ENCODER_TIM_PRESCALER                  0      

/* timer interrupt  */
#define ENCODER_TIM_IRQn                       TIM3_IRQn
#define ENCODER_TIM_IRQHandler                 TIM3_IRQHandler

/* Encoder interface pin */
#define ENCODER_TIM_CH1_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
#define ENCODER_TIM_CH1_GPIO_PORT              GPIOC
#define ENCODER_TIM_CH1_PIN                    GPIO_PIN_6
#define ENCODER_TIM_CH1_GPIO_AF                GPIO_AF2_TIM3

#define ENCODER_TIM_CH2_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
#define ENCODER_TIM_CH2_GPIO_PORT              GPIOC
#define ENCODER_TIM_CH2_PIN                    GPIO_PIN_7
#define ENCODER_TIM_CH2_GPIO_AF                GPIO_AF2_TIM3

/* Frequency multiplier of encoder interface */
#define ENCODER_MODE                           TIM_ENCODERMODE_TI12

/* Encoder interface input capture channel phase setting */
#define ENCODER_IC1_POLARITY                   TIM_ICPOLARITY_RISING
#define ENCODER_IC2_POLARITY                   TIM_ICPOLARITY_RISING

/* Encoder physical resolution */
#define ENCODER_RESOLUTION                     16

/* Total resolution after frequency doubling */
#if (ENCODER_MODE == TIM_ENCODERMODE_TI12)
  #define ENCODER_ TOTAL_ Resolution (encoder_resolution * 4) / * total resolution after frequency doubling*/
#else
  #define ENCODER_ TOTAL_ Resolution (encoder_resolution * 2) / * total resolution after frequency doubling*/
#endif

/* Reduction ratio of reduction motor */
#define REDUCTION_RATIO                        30

extern __IO int16_t Encoder_Overflow_Count;
extern TIM_HandleTypeDef TIM_EncoderHandle;

void Encoder_Init(void);

#endif   /* __BSP_ENCODER_H */


Keywords: Single-Chip Microcomputer stm32 Autonomous vehicles

Added by nsarisk on Wed, 09 Mar 2022 09:47:54 +0200