Ich habe Schwierigkeiten zu verstehen und eine Lösung zu finden, um die Drehzahl eines BLDC-Motors zu ermitteln. Hier sind die Spezifikationen:
Das folgende Bild zeigt die Situation:
Ich habe im Mikro einen Timer im XOR-Modus eingerichtet. Der PSC ist [19 - 1] und die Zählerperiode ist [10000 - 1], während der Zeitgebertakt 80 MHz beträgt.
Mein Motor hat eine maximale Drehzahl von 3000 U / min.
Der Timer ist im XOR-Modus eingerichtet und generiert bei jedem Übergang ein Ereignis. Gemäß dem STM32F407- Referenzhandbuch setzt in diesem Modus jeder Übergang das CCR-Register auf 0 zurück. Wenn ich dieses Register also sechsmal addiere, sollte ich eine vollständige "elektrische Drehung" oder eine halbe "physikalische Drehung" erhalten, da der Motor zweipolig ist Paare.
Meine Fragen:
A) Ich habe diese Zahlen für den Timer PSC und die Zählerperiode zufällig ausgewählt ... wie werden sich diese Zahlen auf meine Messung auswirken? Kann ich mit diesen Zahlen zB Drehzahlen von 1 bis 3000 U / min abdecken?
B)
Ich habe den folgenden Code in der XOR ISR ... ist dieser Code sinnvoll?
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;
}
Hier die Geschwindigkeit (angenommen, mein Code ist korrekt, sollte Timer-Werte für eine ganze Periode des Hallsensors addieren). Dann werde ich es in Drehzahl umwandeln, indem ich die Frequenz in Zeit umwandele und wegen der Polpaare mit 2 multipliziere.
Ist das richtig?
Ich habe den Code gelesen, und ich habe ein paar Kommentare oder Dinge, die helfen könnten (oder auch nicht).
Ihr Code: Das finde ich noch heraus. Laut dem Bild, das Sie hinzugefügt haben, wird der Zustand niemals sein 0b101
? Versuchen Sie, die Zeit zwischen jedem XOR-Impuls zu messen? Ich stelle mir vor, dass dies void XOR_ISR()
bei der Aufwärtsflanke jedes Impulses aufgerufen wird. Das sollte ziemlich einfach sein, zum Beispiel:
void XOR_ISR(){
long time = TIM4->CCR1;
int rpm = 10/time; // 60 * 1/(time*6)
}
Ich würde einen gleitenden Durchschnittsrechner hinzufügen, um die Messungen auch ein wenig zu glätten.
Obergrenze: Bei einer maximalen Drehzahl von 3000 U/min dreht sich das Rad 3000/60 = 50 Mal pro Sekunde. Da es insgesamt 6 Stangen auf dem Rad gibt, bedeutet dies, dass jedes 6. Mal ISR
eine volle Drehung genannt wird. Das heißt, es gibt einen Puls 50*6=300 Mal pro Sekunde. Oder alle 1,6 Millisekunden ein Impuls. Da Ihre Zeitschaltuhr mit 80 MHz läuft, zählt sie für jeden Impuls bis 66640. Dadurch erhalten Sie sehr genaue Messwerte bei hohen Geschwindigkeiten.
Untere Grenze: Es könnte jedoch die Messwerte für die niedrigere Geschwindigkeit etwas komplexer machen. Angenommen, das Rad dreht sich mit 10 U / min. Das ergibt 10/60*6=1 Impuls pro Sekunde. Das bedeutet, dass der Timer mit jedem Impuls bis 80 000 000 zählt. Wie @Harry sagte, passt dies nur in eine long
Variable mit 5 Bits übrig.
Meine Gedanken: Das Betreiben Ihres Timers mit 80 MHz ist ein wenig übertrieben. Ich würde die Taktfrequenz etwas senken, um die Messung bei sehr niedrigen Drehzahlen etwas robuster zu machen. Aber es hängt alles davon ab, was die kleinste Drehzahl ist, die Sie messen möchten. 10 U/min? 1 U/min? 0,1 U/min? Sie müssen sicherstellen, dass Ihr Zähler nicht überläuft.
Die Genauigkeit: Der größtmögliche Messfehler liegt maximal um die Hälfte der Timer-Periode daneben. Dies ist 1/80 MHz/2 = 6,25 ns. Bei einer maximalen Drehzahl von 3000 U/min führt dies zu einem Fehler von 6,25 ns/1,6 ms = 0,00036 %. Dies ist ein Fehler von 0,11 RPM RPM. Dies ist für die meisten Anwendungen sehr gut.
Ich hoffe das hilft! Und wenn jemand ein Problem mit meiner Mathematik findet, sagt es mir bitte :)
Bearbeiten: Danke @Harry für die Korrektur meiner Late-Night-Mathematik.
jms
Sean87
jms
Sean87
DEKKER
Lundin