Hallo, vielen Dank für eure Hilfe im voraus. Ich arbeite momentan mit einem LPC1769 Mikrocontroller und der Entwicklungsumgebung LPCXpresso v6.0.4. Der Mikrocontroller hat die Hauptaufgabe die Schrittvorgaben für einen Schrittmotor zu berechnen, was auch schon gut funktioniert. Die Schrittfrequenz kann ich vergrößern bzw. verkleinern, indem ich das MR0-Register von Timer0 verändere. Der Timer0_IRQHandler gibt die entsprechende Schrittfrequenz für jeden Strang per GPIOs aus. Da ich in naher Zukunft die Schrittfrequenz von ca. 50Hz bis hin zu 8kHz hochfahren (Rampe) möchte, habe ich etwas mit dem MR0-Register herumgespielt. Dabei habe ich den Wert von MR0 stetig verringt und dabei jeweils die Schrittfrequenz mit einem Frequenzzähler gemessen. Die Messwerte sind im Folgenden zu sehen: MR0 Freq in Hz 10000 6,25 7000 9 6000 11,1 5000 12,5 3000 22,22 2000 31,15 1500 41,6 1000 64,51 500 125 100 625 50 1250 25 2500 12 5000 An dieser Tabelle fiel mir sofort auf, dass die Auflösung im unteren Frequenzbereich recht gut ist und im oberen Frequenzbereich immer schlechter wird. Beispielsweise stehen für die Frequenzen zwischen 6,25Hz und 9Hz 3000 MR0-Werte zur Verfügung, während zwischen 2500Hz und 5000Hz nur 23 MR0-Werte zur Verfügung stehen. Wie kann ich die Auflösung im oberen Frequnenzbereich erhöhen?? Ich möchte gern Schrittfrequenzen von 50 bis 8kHz mit einer Auflösung von min. 1Hz in allen Bereichen erzeugen. Die Timer-Einstellungen sind auf dem Bild im Anhang zu sehen. Ich hoffe Ihr könnt mir helfen. Danke
Heiko1989 schrieb: > Die Timer-Einstellungen sind auf dem Bild im Anhang zu sehen. Hänge bitte das nächste mal die .c Datei an, das ist bedeutend einfacher und besser als ein Bild. Hier fehlt unter anderem ein interessanter Teil des IRQHandlers. > Der Timer0_IRQHandler gibt die entsprechende Schrittfrequenz für jeden > Strang per GPIOs aus. Das ist für hohe Frequenzen nicht optimal, denn da geht die meist variable Interrupt Lateniz mit ein. Der LPC176x hat eine extra PWM Einheit verbaut, die das möglicherweise ohne Interrupt hinbekommen würde. Außerdem gibt es noch die MCPWM. Siehe UM10360.pdf, Kapitel 24 und 25. Heiko1989 schrieb: > An dieser Tabelle fiel mir sofort auf, dass die Auflösung im unteren > Frequenzbereich recht gut ist und im oberen Frequenzbereich immer > schlechter wird. Das ist bei allen Timern so, denn da wird einfach eine Frequenz (PCLK) erst mit dem Prescaler und dann mit dem Match Register geteilt - und zwar in ganzzahligen Schritten. Bei Deinen Angaben komme ich allerdings auf eine PCLK von nur 1,2 MHz; Da muss der IRQHandler noch weiter teilen. Heiko1989 schrieb: > bis 8kHz mit einer Auflösung von min. 1Hz 8000 Hz * 8000 Schritte ergibt 64 MHz Timer Basis Frequenz (PCLK). Das ist grade noch so eben im Bereich des Möglichen - aber nicht mehr mit Unterteilung in Software.
:
Bearbeitet durch User
Der LPC1769 kann max. 120MHz. Wenn du alle Vorteiler und Prescaler entfernst, brauchst du für 8000Hz einen Teiler von 15000. Der Schritt auf 15001 würde 7999.47Hz ergeben. Glatte 1Hz wirst du mit dieser einfachen Methode nicht hinkriegen. Da die Timer 32bit sind, reichen die auch bei 50Hz noch locker. Deine Werte sind aber nicht plausibel. CLKSEL mit 0x03 bedeutet durch 8 nicht durch 4 teilen. Bei einem Prescaler von 10 und MR0 mit 10000 sollte 125Hz rauskommen und nicht 6.25. Mit welcher Frequenz läuft denn dein MC?
Vielen Dank erstmal für eure schnellen Kommentare :-) Im Anhang befindet sich nun die komplette c-Datei, sodass ihr das Problem leichter nachvollziehen könnt. > Mit welcher Frequenz läuft denn dein MC? Der MC läuft mit 100Mhz. > Bei einem Prescaler von 10 und MR0 mit 10000 > sollte 125Hz rauskommen und nicht 6.25. Die niedrige Frequenz von 6,25Hz ergibt sich aus den 19 Case-Blöcken im IRQ-Handler. (siehe Anhang) Kann man das oben beschriebene Problem also in den Griff bekommen, indem man die Vorteiler entfernt??
Heiko1989 schrieb: > Kann man das oben beschriebene Problem also in den Griff bekommen, indem > man die Vorteiler entfernt?? Nicht ohne weiteres, denn Du musst auch die Laufzeit des Interrupts beachten, d.h MR0 darf nicht zu klein werden. Der Interrupt Handler liesse sich signifikant kürzen, wenn man die Portzuweisungen zusammenfasst:
1 | case 0 : |
2 | |
3 | LPC_GPIO2->FIOCLR = (1<<1) |(1<<2) |(1<<4); |
4 | LPC_GPIO2->FIOSET = (1<<3)| (1<<5)|(1<<6); |
5 | |
6 | LPC_GPIO0->FIOCLR = (1<<2)| (1<<21); |
7 | LPC_GPIO0->FIOSET = (1<<3)|(1<<22); |
Die Verwendung von "|=" ist bei FIOSET und FIOCLR unnötig da nur die "1" Bits die Aktion auslösen. Durch Weglassen spart man jeweils den Lesezyklus.
Das interrupt-Flag killt man ebenfalls ohne |= sondern mit = . Das |= ist strenggenommen sogar falsch, sobald irgend eine andere Sache auch noch mit dem Timer gemacht werden soll. Im Manual genau lesen, wie die Register funktionieren, anstatt solche 'Angst/Unwissenheits-Konstrukte' zu verwenden. Die ISR ist ein bissl arg 'ueppig' gschrieben, willst Du das nicht mal mit einer Tabelle fuer die Sets/Clrs umsetzen? Wenn das mit der Aufloesung wirklich schoen werden soll, dass musst Du Dir mal Software-DDS anschauen. Dann darfst Du naemlich deinen Timer ziemlich schnell laufen lassen (und damit die ISR = Abtastrate) aber die Drehung davon unabhaengig berechnen. Gerade bei hohen Drehzahlen willst Du ja keine grossen (relativen) Geschwindigkeitsspruenge.
:
Bearbeitet durch User
Ich werde die ISR entsprechend eurer Ratschläge optimieren... Könnt ihr mir gute Literatur bezüglich ARM-Mikrocontroller Programmierung empfehlen? Ich bin nämlich in einigen Dingen noch unsicher... > Wenn das mit der Aufloesung wirklich schoen werden soll, dass musst Du > Dir mal Software-DDS anschauen. Das hört sich gut an :-) DDS habe ich schon öfter im Zusammenhang mit Funktionsgeneratoren gehört, aber leider noch nie damit gearbeitet. Wie kann man denn DDS im Rahmen meines Projektes anwenden? Kannst du mir das bitte etwas genauer erläutern? Danke
Zum Prinzip: http://www.mikrocontroller.net/articles/DDS In deinem speziellen Fall - falls ich das richtig verstanden hab - gehts um 20 diskrete Schritte (Signalwechsel) statt eines Sinus. Ist aber nicht schlimm, deine Lookup-Tabelle ist dann halt nicht der Sinus, sondern deine digitalen Signale fuer die Halbbruecken. DDS sampled ja irgendeine Funktion. Als Nachteil bekommst nur ein bisschen 'jitter' auf die Signale. Hilfreich w"are, wenn Du 16 oder 32 Schritte definieren wuerdest. Denn irgendwo musst Du einen Abschnitt des Phasenakku als Index in der Lookuptabelle verwenden. Statt Tabelle, darfst Du weiterhin ein grosses switch() verwenden, wenn's unbedingt sein muss. In der ISR (konstante, hohe Wiederholrate Fs) addierst du immer einen einstellbaren Wert (tuning word) tw auf den Phasenakku a (Integer mit vielen Bits, z.B. 32). von dem Phasenakku nimmst Du z.B. die hoechsten n=4 bits (28..31) und die sind der Index der Tabelle oder der Wert im switch(). Wenn tw = 2^32/Fs, dann kommt gerade f = 1Zyklus/Sekunde zustande. tw doppelt so gross => doppelt so schnell. tw halb so gross => halb so schnell. Kurz f ~ tw. Und das genau ist das coole daran. Direkt proportional. Und tw hat bei guter Wahl der Konstanten viele Bits (hohe Genauigkeit). Du musst in deinem Fall aber garantieren, dass keine Zwischenschritte fehlen, d.h. Fs > f * 2^n EDIT: Fehler in der tw-Formel behoben.
:
Bearbeitet durch User
Ok, das DDS-Prinzip habe ich verstanden. Echt geniale Sache^^ Allerdings habe ich dabei noch ein kleines Problem: > Hilfreich w"are, wenn Du 16 oder 32 Schritte definieren wuerdest. Denn > irgendwo musst Du einen Abschnitt des Phasenakku als Index in der > Lookuptabelle verwenden. Wenn ich 16 Werte in der Lookuptabelle adressieren will, brauche ich 3 MSB's von dem Phasenakku und wenn 32 Werte dann 4 Bits usw... In meinem Fall brauche ich genau 20 Werte, weil es sich um einen fünfsträngiggen Schrittmotor, welcher mit 5 H-Brücken angesteuert wird, handelt. Die Ansteuertabelle habe ich angehängt. Das + steht für Strom in positiver Richtung und das - für Strom in negativer Richtung. Diese Tabelle ist in der ISR in der großen Case-Anweisung abgebildet. Nun meine Frage: Ist das DDS-Prinzip auch mit einer Lookuptabelle, welche 20 Werte enthält, möglich? Oder habt Ihr/du noch eine andere Idee? Danke
Heiko1989 schrieb: > In meinem Fall brauche ich genau 20 Werte, weil es sich um einen > fünfsträngiggen Schrittmotor, welcher mit 5 H-Brücken angesteuert wird, > handelt. Kopfkratz Dann braucht's etwas Zusatzaufwand: oberste 5 bits fuer 32 moegliche Werte nehmen und bei jedem Durchlauf durch die ISR (Phasenakku-Update) diese 5 bits % 20 rechnen. Grob gesagt, musst Du den 'wrap-around' selber machen und darfst nicht den 32-bit Ueberlauf passieren lassen. Sonst bleibt alles gleich. PS: einen coolen Motor hast Du da!
:
Bearbeitet durch User
Marc P. schrieb: > Dann braucht's etwas Zusatzaufwand: oberste 5 bits fuer 32 moegliche > Werte nehmen und bei jedem Durchlauf durch die ISR (Phasenakku-Update) > diese 5 bits % 20 rechnen. Oder gleich einen Schritt weiter gehen: 8 bit oder mehr lookup, dann Sinus-Tabelle und den Motor mit 5 phasenverschobenen Sinus ansteuern. Dann wird's richtig cool (Mikroschritt). Dann wirst Du den Motor nicht mehr hoeren wenn er sich bewegt, Ehrenwort! Eine 2x3-Phasen-Variante davon koennte ich Dir vielleicht ueberlassen. Ich hab das schon mehrfach getan, auch noch zufaellig auf 'nem LPC17 .-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.