¿Puedes medir la frecuencia a través de interrupciones cuando un codificador usa los pines? SMT32F4

Para calcular la velocidad actual, una opción es leer la posición actual cada 20 ms. La velocidad media es position_old menos position_current. Esto funciona bien si hay muchos pulsos por 20 ms, pero a bajas velocidades, la precisión disminuye. Una vez que obtenga velocidad = 0, luego velocidad = 2 y luego velocidad = 0 nuevamente.

El mejor enfoque sería medir el tiempo entre los flancos ascendentes. Esto le proporciona la hora exacta, por lo tanto, la velocidad.

  • Pero, ¿puedes tener dos temporizadores activos en los mismos pines? Entonces Input Capture sería el camino a seguir.
  • ¿Puedes configurar un ISR para disparar al flanco ascendente mientras el temporizador se usa como codificador? Entonces puedo usar los syssticks para derivar la velocidad.

Estoy usando TIM5 CH1&2 en PA0&1.

(Obviamente, podría conectar el pin de entrada a otro pin de MCU y hacer la medición allí, pero no me gusta esa solución).

https://github.com/wernerdaehn/CC3D-CableCam-Controller/blob/master/Implementation.md

Si tiene un disparo IRQ en los pulsos del codificador, ¿por qué usar otro temporizador como codificador? En el ISR, puede hacer ambas cosas, contar los pulsos totales para la posición y tomar tiempos para la velocidad actual.
+1 por el problema general que muchos aficionados al bricolaje no tienen en cuenta. el equipo profesional generalmente usa un FPGA que mide la frecuencia/período y cambia automáticamente. En cuanto a la serie STM32 para el control de motores, esperaría un dispositivo similar incorporado, pero aún no he oído hablar de él. Entonces puede inspeccionar su biblioteca FOC, cómo se implementa la medición de retroalimentación del codificador.
Es posible con TI DSP con módulo eQEP: ti.com/lit/ug/sprug05a/sprug05a.pdf
@JimmyB: Sí, usar interrupciones y contarme a mí mismo es una opción. Pero el codificador de hardware integrado en el STM32 tiene muchas ventajas a las que no quiero renunciar.

Respuestas (1)

Hice algunas pruebas y lecturas más y encontré la solución:

  1. En lugar de HAL_TIM_Encoder_Start() utilice HAL_TIM_Encoder_Start _IT (). Ambos ejecutan el mismo código, excepto que el último también se prepara para las interrupciones.
  2. Habilite la interrupción: HAL_NVIC_SetPriority(TIM5_IRQn, 0, 1); HAL_NVIC_EnableIRQ(TIM5_IRQn);
  3. Implementar el vacío TIM5_IRQHandler(void) { HAL_TIM_IRQHandler(&htim5); } para que haya un controlador de interrupciones que reenvíe la interrupción a la capa HAL.
  4. Implemente (o amplíe) la función de devolución de llamada void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) y agregue su código.

En mi caso el código es

if (htim->Instance == TIM5)
  {
    last_possensortick = HAL_GetTick();
    possensorduration = last_possensortick - possensortick_old;
    possensortick_old = last_possensortick;
  }

Entonces almaceno el tiempo entre dos interrupciones y velocidad = 1/tiempo. Casi. Solo casi porque la interrupción se dispara en un solo pin y el tiempo debe ser entre eventos idénticos, por lo tanto, se dispara solo en un flanco ascendente.

El codificador, por otro lado, está configurado como codificador X4 (sConfig.EncoderMode = TIM_ENCODERMODE_TI12;), por lo que la posición se actualiza en ambos flancos y en ambos canales. ver página 29 en AN4013

Por lo tanto, la velocidad = 4/tiempo en lugar de 1/tiempo.

Y se necesita algo de lógica adicional si el tiempo = 0 y si la interrupción no se activa porque la rueda no se mueve en absoluto. Esa es la razón por la que almaceno ambos, la duración y el lasttick. Si lasttick > 2000 entonces velocidad = 0;

La lógica anterior funciona solo para velocidades bajas. A altas velocidades, la resolución de milisegundos y el tiempo de ejecución de la interrupción crean más y más errores. Por lo tanto, usaré ambas entradas de velocidad, speed=old_pos-current_pos; y la velocidad=4/duración;

Esto se conoce como medición de frecuencia/período. El error es +/- 1/N_recuentos de cualquier tipo de medida, por lo que debe comparar N_recuentos_método_freq VS. N_count_method_period para cambiar el resultado en el medio para obtener el mejor resultado.