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:
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:
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.
③ 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 .
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