Tengo dificultades para entender y encontrar una solución para encontrar la velocidad de un motor BLDC. Aquí están las especificaciones:
La siguiente imagen muestra la situación:
He configurado un temporizador en modo XOR en el micro. El PSC es [19 - 1] y el período del contador es [10000 - 1] mientras que el reloj del temporizador es de 80 MHz.
Mi motor tiene la velocidad máxima de 3000RPM.
El temporizador está configurado en modo XOR y con cada transición genera un evento. De acuerdo con el manual de referencia STM32F407 , en este modo cada transición restablece el registro CCR a 0. Significa que si sumo este registro 6 veces, debería obtener una "rotación eléctrica" completa o la mitad de "rotación física" ya que el motor es de 2 polos pares
Mis preguntas:
A) Acabo de elegir esos números para el temporizador PSC y el período del contador al azar... ¿cómo afectarán estos números a mi medición? por ejemplo con esos numeros puedo cubrir velocidades de 1 a 3000 RPM?
B)
Tengo el siguiente código dentro del XOR ISR... ¿tiene sentido este código?
static uint32_t speed = 0;
static uint32_t time = 0;
static int isMeasuring = 0;
void XOR_ISR() {
uint8_t state = readHallStateFromGPIO();
if(state == 0b101 && isMeasuring == 0) {
time = 0;
isMeasuring = 1;
time += TIM4->CCR1;
} else if(isMeasuring == 1 && state != 0b101) {
time += TIM4->CCR1;
} else if(isMeasuring == 1 && state == 0b101) {
time += TIM4->CCR1;
speed = time;
isMeasuring = 0;
}
Aquí, la velocidad (supongamos que mi código es correcto, debería sumar los valores del temporizador para un período completo del sensor de pasillo). Luego lo convertiré a RPM convirtiendo la frecuencia en tiempo y lo multiplicaré por 2 debido a los pares de polos.
¿Es esto correcto?
Leí el código y tengo algunos comentarios o cosas que podrían ayudar (o no).
Su código: todavía estoy averiguando eso. De acuerdo con la imagen que agregó, ¿el estado nunca será 0b101
? ¿Está tratando de medir el tiempo entre cada pulso XORed? Me imagino que void XOR_ISR()
se llamará en el borde ascendente de cada pulso. Eso debería ser bastante sencillo, por ejemplo:
void XOR_ISR(){
long time = TIM4->CCR1;
int rpm = 10/time; // 60 * 1/(time*6)
}
También agregaría una calculadora de promedio móvil para suavizar un poco las mediciones.
Límite superior: funcionando a un máximo de 3000 RPM, la rueda girará 3000/60 = 50 veces por segundo. Dado que hay un total de 6 polos en la rueda, significa que cada 6 veces ISR
ocurre una rotación completa. Esto significa que hay un pulso 50*6=300 veces por segundo. O un pulso cada 1,6 milisegundos. Al ver que su reloj temporizador funciona a 80 MHz, contará hasta 66640 por cada pulso. Esto le dará lecturas muy precisas a altas velocidades.
Límite inferior: sin embargo, podría hacer que las lecturas de velocidad más bajas sean un poco más complejas. Digamos que la rueda gira a 10 RPM. Eso da como resultado 10/60*6=1 pulso cada segundo. Esto significa que el temporizador contará hasta 80 000 000 con cada pulso. Como dijo @Harry, esto solo cabrá en una long
variable con 5 bits de sobra.
Mis pensamientos: ejecutar su temporizador a 80 MHz es un poco excesivo. Bajaría un poco la frecuencia del reloj para que la medición sea un poco más robusta a RPM muy bajas. Pero todo depende de cuál sea el RPM más pequeño que quieras medir. 10RPM? 1RPM? 0.1RPM? Deberá asegurarse de que su contador no se desborde.
La precisión: el error de medición más grande que podría tener será un máximo de la mitad del período del temporizador. Esto será 1/80 MHz/2 = 6,25 ns. A un RPM máximo de 3000 RPM, esto dará como resultado un error de 6,25 ns/1,6 ms = 0,00036 %. Este es un error de 0.11RPM RPM. Esto es muy bueno para la mayoría de las aplicaciones.
¡Espero que esto ayude! Y si alguien encuentra un problema con mis matemáticas, por favor dígame :)
Editar: Gracias @Harry por corregir mis matemáticas nocturnas.
jms
Sean87
jms
Sean87
DEKKER
Lundin