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.
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
Hice algunas pruebas y lecturas más y encontré la solución:
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;
jimmyb
Marko Bursic
Marko Bursic
werner daehn