Uso del codificador de cuadratura con MCU STM32

3

Estoy tratando de usar un codificador de cuadratura con mi placa NUCLEO-F303K8 (ver código a continuación) y está funcionando ok pero no perfecto Conecté el codificador de acuerdo con la figura 4. en hoja de datos (no tenía ningún condensador de 0.01uF, así que usé 0.1uF). Noté que ocasionalmente el contador se incrementa dos veces al girar el codificador un paso. Cuando modifico el valor del prescaler noté que el comportamiento del contador cambia mucho. Por ejemplo, un valor de prescaler de 11 requiere que gire los pasos del codificador 6 para incrementar el contador una vez; El comportamiento opuesto se puede ver con un valor de prescaler muy pequeño. Usando prueba y error, he determinado que un valor de prescaler de 3 funciona mejor.

Soy nuevo en codificadores y siento que estoy haciendo muchas adivinanzas aquí y podría necesitar algo de ayuda. ¿Puede ver algo en la hoja de datos que sugiera qué valor de prescaler debería usar? Se menciona algún momento pero no sé qué hacer con él. El reloj central del sistema está funcionando a 72MHz. ¿O hay algo extraño en el código de abajo o algo en la forma en que conecté el codificador que podría cambiar?

EDITAR:

Conecté el codificador a un osciloscopio (midiendo en los pines de entrada de la placa NUCLEO) y giré el codificador hacia la derecha; estos son los resultados.

Con los condensadores (0.1uF):

Sincondensadores:

Paramí,sevemuchomejorsincondensadores,peroenrealidad,cuandogiroelcodificador,funcionamuymalsincondensadores.¿Alguienpuedeexplicarestosresultados?Pareceextrañoparaunaficionadocomoyo.

EDIT2:

Cambiélabasedetiempocomosesugiereyahoraveoelrebotedelaseñal.Pormisobservacionesdehoy,parecepeordespuésdelbordedescendenteencomparaciónconelbordeascendenteporalgunarazón.

Sincondensadores:

Lamayoríadelasvecessevebienconloscondensadores,peroavecesseveasíoalgopeor:

Compré más capacitores hoy y probé 0.01uF, 0.022uF y 0.047uF. Diría que obtuve los mejores resultados cuando utilicé los más grandes, es decir, 0.047uF y 0.1uF. Los tiempos de subida y bajada son más lentos, pero no parece tener un efecto negativo y dan una señal más limpia. ¿Es correcto que los tiempos de subida / bajada puedan reducirse eligiendo resistencias más pequeñas? ¿Qué otros efectos tendría?

Código que estoy usando:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_6);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_6);

NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

PrescalerValue = (uint16_t) ((SystemCoreClock ) / 18000000) - 1; // Prescaler is 3

TIM_TimeBaseStructure.TIM_Period = 6;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

TIM_PrescalerConfig(TIM1, PrescalerValue, TIM_PSCReloadMode_Immediate);

TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

TIM_Cmd(TIM1, ENABLE);

uint32_t counter = 0;

for(;;)
{
    counter = TIM_GetCounter(TIM1);

    // ...use the value...
}
    
pregunta dbostream

1 respuesta

0

El codificador que está utilizando es un simple limpiador mecánico, es casi imposible rebotar con un simple circuito RC como se muestra en la hoja de datos.

El capacitor que usó es demasiado grande con retardos superiores a 1 mS, el valor sugerido de 0.01 uF dará un retardo de aproximadamente 0.1 mS en un impulso ascendente y algo más en un cambio negativo. Sin embargo, ninguno de los valores detendrá el rebote del interruptor que afecte su conteo, ya que el limpiaparabrisas no es en sí mismo un retén en este tipo de interruptor (en ninguno de los que he trabajado), los retenes son un simple retén de posición del eje externo.

Internamente se verán así (o con una disposición física similar):

Una forma en la que he manejado estos codificadores mecánicos en el pasado es usar un tictac del temporizador (la interrupción de 1 kHz o algo así suele estar disponible) para leer los valores A / B en un registro temporal de 8 bits y configurar mi programa como accesible copia de los valores A / B solo cuando hay 4 '1' bits acumulados para cada uno de A / B.
Esto garantiza que los valores no sean accesibles al programa a menos que no haya habido ningún cambio en el estado A / B durante al menos 4 mS. Obviamente, puede cambiar la marca para obtener el valor de rebote que desee.

    
respondido por el Jack Creasey

Lea otras preguntas en las etiquetas