[Producción de carro de equilibrio] (3) Explicación del codificador (explicación súper detallada)

  Hola a todos, soy Xiaozheng. En este artículo, explicaré el codificador del motor del carro de equilibrio. Permita que cada socio tenga una comprensión más clara de la estructura del hardware y la programación del software del codificador.

1. Estructura de hardware

1. ¿Qué es un codificador?

  El codificador es un sensor giratorio que convierte el desplazamiento angular o la velocidad angular en una serie de pulsos eléctricos digitales. Los codificadores se dividen en codificadores fotoeléctricos y codificadores Hall.

2. El principio de funcionamiento del codificador

  Aquí presentamos principalmente el codificador Hall (la precisión del codificador fotoeléctrico es 38 veces mayor que la del codificador Hall). El codificador Hall está compuesto por una placa de caballo Hall y un elemento Hall. La placa de Hallma está dividida en diferentes polos magnéticos sobre una placa circular de cierto diámetro. El disco de caballo Hall es coaxial con el motor.Cuando el motor gira, el elemento Hall detecta y emite varias señales de pulso.Para juzgar la dirección de rotación, generalmente emite dos conjuntos de señales de onda cuadrada con una cierta diferencia de fase. El diagrama esquemático es el siguiente:
Inserte la descripción de la imagen aquí

Figura 1 Codificador Hall

3. Pin de interfaz del codificador
  El motor que utilizo es un motorreductor de CC GM25-370 (con codificador Hall), y el diagrama de pines del codificador correspondiente es el siguiente:
Inserte la descripción de la imagen aquí

Figura 2 Pines de interfaz del codificador Hall

4. El principio de medición de velocidad del codificador
  por unidad de tiempo, calcula la velocidad real del motor de acuerdo con la distancia recorrida por el pulso, aquí se usa una interrupción del temporizador de 10ms.

5. Por lo general, hay dos formas de recopilar datos
  : la primera tecnología de software utiliza directamente interrupciones externas para recopilar, y la positiva o negativa se puede juzgar de acuerdo con la diferencia de la diferencia de fase AB. La segunda tecnología de hardware usa directamente el modo de codificador de temporizador, y la segunda se usa aquí. También es el método de cuadriplicar la frecuencia que a menudo se dice que mejora la precisión de la medición. De hecho, solo recopila los bordes ascendente y descendente de la fase AB, por lo que 1 cambia a 4. Se necesitan más recursos para implementarlo usando el modo de interrupción externa Se recomienda usar el modo de codificador del temporizador para medir el valor de cambio de pulso.

Dos, programación de software

1. Función de codificador-Codificador.c
1)
 Parámetros de entrada de la función de inicialización del codificador 1 y del codificador 2 : Ninguno
  ① Inicialización de GPIO Inicialización de
  la estructura básica del temporizador
  ③ Función de configuración del codificador
  ④ Función de captura de entrada del temporizador
  ⑤ Borrar el indicador de actualización del temporizador
  ⑥ Ejecutar la interrupción de actualización
  ⑦ Borrar el tiempo datos
  ⑧ Activar temporizador

Aquí hay una explicación específica de la función de configuración del codificador.

// 编码器配置函数: 定时器2,模式3,上升沿
TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);  

① El primer parámetro es la selección del temporizador.
② El segundo parámetro es el modo de inicio del codificador; TIM_EncoderMode_TI12: cuenta en cada flanco de transición de T1 y T2.
[Modo]:
modo Tl1: cuenta en todos los bordes de T1.
Modo Tl2: cuente con todos los bordes de T2.
Modo Tl1l2: Cuente en todos los bordes de T1 y T2.
Para dar un ejemplo simple: cuando Tl1 está en el borde ascendente, Tl2 está en un nivel bajo, lo que significa que la señal Tl1FP1 correspondiente cuenta hacia arriba. Por analogía, en la figura siguiente, encerré en un círculo el modo de conteo derivado de la operación de conteo del codificador.
Inserte la descripción de la imagen aquí

Figura 3 Polaridad de T1 y T2

Inserte la descripción de la imagen aquí

Figura 4 Modo de conteo correspondiente

③ El tercer y cuarto parámetro son configuración de polaridad; aquí se dividen en flanco ascendente y flanco descendente, ¿por qué dice que establecer la polaridad se convierte en establecer el flanco ascendente y el flanco descendente? Se puede encontrar ingresando la función stm32f10x.tim.c que la configuración de la polaridad está realmente relacionada con el registro TIM_CCER_CC1P. Podemos averiguarlo consultando el Manual de referencia chino STM32.
  Como puede ver aquí, lo configuramos para que no se invierta, lo que corresponde al flanco ascendente de IC1 .
Inserte la descripción de la imagen aquí

Figura 5 Búsqueda de polaridad IC

Código de función del codificador :

#include "encoder.h"
#include "sys.h"

void Encoder_TIM2_Init(void)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;
  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 ,ENABLE);  // 开启定时器时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); // 开启GPIO时钟
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;    // 浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;   // 编码器1:PA0/PA1
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA ,&GPIO_InitStruct);	
  
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;        // 不分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 65535;                      // 重装载值65535
	TIM_TimeBaseInitStruct.TIM_Prescaler =0;                        // 分频系数0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
  
	// 编码器配置函数: 定时器2,模式3,上升沿
	TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);  
  
	TIM_ICStructInit(&TIM_ICInitStruct);
	TIM_ICInitStruct.TIM_ICFilter = 10;       // 滤波器设置为10
	TIM_ICInit(TIM2,&TIM_ICInitStruct);
  
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);      // 清除定时器标志位
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  // 定时器2,溢出更新,使能
	TIM_SetCounter(TIM2,0);                   // 定时数据清零
	TIM_Cmd(TIM2,ENABLE);                     // 定时器2使能
}

void Encoder_TIM4_Init(void)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;
  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 ,ENABLE);  // 开启定时器时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE); // 开启GPIO时钟
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;    // 浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;   // 编码器2:PB6/PB7
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB ,&GPIO_InitStruct);	
  
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;      // 不分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 65535;                    // 重装载值65535
	TIM_TimeBaseInitStruct.TIM_Prescaler = 0;                     // 分频系数0
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);
  
	// 编码器配置函数:定时器4,模式3,上升沿
	TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);  
  
	TIM_ICStructInit(&TIM_ICInitStruct);
	TIM_ICInitStruct.TIM_ICFilter = 10;       // 滤波器设置为10
	TIM_ICInit(TIM4,&TIM_ICInitStruct);
  
	TIM_ClearFlag(TIM4,TIM_FLAG_Update);      // 清除定时器溢出更新标志位
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);  // 定时器4,溢出更新,使能
	TIM_SetCounter(TIM4,0);                   // 定时数据清零
	TIM_Cmd(TIM4,ENABLE);                     // 定时器2使能
}

2)
 Parámetro de entrada de la función de lectura de datos del codificador : temporizador x
  ① Seleccionar temporizador x
  ② Recoger el valor de recuento del codificador y guardarlo
  ③ Borrar el valor de recuento del
  temporizador ④ Devolver el valor de recuento del temporizador
Nota: Debido a que TIM_GetCounter se vuelve corto int (short int), entonces aquí tenemos que realizar una coerción.

int Read_Speed(int TIMx)
{
    
    
  int value_1;
  switch(TIMx)
  {
    
    
    case 2:
      value_1 = (short)TIM_GetCounter(TIM2);  // 采集编码器的计数值并保存
      TIM_SetCounter(TIM2,0);   // 将定时器的计数值清零
      break;
    case 4:
      value_1 = (short)TIM_GetCounter(TIM4);  // 采集编码器的计数值并保存
      TIM_SetCounter(TIM4,0);   // 将定时器的计数值清零
      break; 
    default: value_1 = 0;
  }
  return value_1;
}

3) Función de servicio de interrupción del temporizador

// 定时器2中断服务函数
void TIM2_IRQHandler()
{
    
    
  if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)  // 中断标志位置1
  {
    
    
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  // 清楚中断标志位
  }
}

// 定时器4中断服务函数
void TIM4_IRQHandler()
{
    
    
  if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)  // 中断标志位置1
  {
    
    
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  // 清楚中断标志位
  }
}

2. Archivo de encabezado de función de codificador-Encoder.h

#ifdef  _ENCODER_H
#define _ENCODER_H

void Encoder_TIM2_Init(void);   // 编码器1初始化函数
void Encoder_TIM4_Init(void);   // 编码器2初始化函数
int Read_Speed(int TIMx);       // 编码器速度读取函数
void TIM2_IRQHandler(void);     // 定时器2中断服务函数
void TIM4_IRQHandler(void);     // 定时器4中断服务函数
#endif

  Lo anterior es la tercera conferencia del codificador de artículos de la serie Balance Car, que incluye la explicación de la estructura del hardware y la explicación de la programación del software STM32. Hay errores en el artículo o los amigos tienen preguntas sobre el contenido anterior. Bienvenidos a todos a deje un mensaje en el área de comentarios, Xiaozheng ve que le responderé lo antes posible.
[Producción de carro de equilibrio] (4) Gyro MPU6050 (super detallado) https://blog.csdn.net/weixin_44270218/article/details/113656398

Supongo que te gusta

Origin blog.csdn.net/weixin_44270218/article/details/113195466
Recomendado
Clasificación