Hallo,
ich will eine lineare Rampe für einen Schrittmotor implementieren. Als
Endstufe verwende ich das Triple Beast, das über den LPT-Port-Eingang
die
Schritt- und Richtungssignale vom µC erhält. Die Application Note von
Atmel (AVR446) und diese Seite
http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
habe ich mir dazu schon angesehen.
Mein Problem ist, dass die Berechnung des nächsten Reloadwertes für die
Beschleunigungsrampe nach dieser Formel
zu lange dauert, sodass ich keine genügend hohen Schrittfrequenzen
erzeugen kann. Benötigen würde ich maximal ca. 5 U/s also eine
Schrittfrequenz von 5kHz bei 1000 Mikroschritten pro Umdrehung. Die ISR
muss dazu aber leider mit 10kHz aufgerufen werden, da die Endstufe nur
auf steigende Flanken beim Schrittsignal reagiert und ich in der ISR den
Pin nur toggeln kann.
Die Berechnung dauert momentan laut Simulator ca. 120 µs.
Eine Tabelle mit den Reloadwerten möchte ich nicht verwenden, da später
auch die Beschleunigung variabel sein soll.
Ich programmiere mit Bascom. Bei der Berechnung des nächsten
Reloadwertes habe ich mich an den Beispielcode aus der AVR446 gehalten,
also diese Zeilen:
stepper motor schrieb:> Eine Tabelle mit den Reloadwerten möchte ich nicht verwenden, da später> auch die Beschleunigung variabel sein soll.
Dann mach mehrere Tabellen für verschiedene Beschleunigungen.
Überprüf mit deinen konkret auftretenden Zahlenwerten, welche der
Variablen
1
Dim C_n_alt As Word
2
Dim C_n_neu As Word
3
Dim Rest As Word
4
Dim 4n_plus1 As Long
5
Dim 2c_n_alt As Long
6
Dim Reload_akt As Word
7
Dim Restsumme As Long
8
Dim N As Long
9
Dim Motor_nr As Byte
tatsächlich Long sein müssen, und bei welchen Berechnungen (auch
Zwischenergebnissen), du dem µC eine Menge Fleissaufgaben aufbürdest,
indem du ihn zwingst in 32 Bit zu rechnen, wo es 16 Bit auch tun.
Ich mag mich auch täuschen, aber ob BASCOM zb das hier
1
4n_plus1 = 4 * N
in einen Links-Shift umwandelt, da bin ich mir nicht sicher.
Auf jeden Fall sind 0.12ms für diese simple Berechnung bei 11Mhz recht
indiskutabel. Aber fang mal damit an, die Datentypen an das anzupassen,
was du tatsächlich brauchst.
Also ich habe jetzt die Multiplikationen durch Shifts ersetzt und die
Datentypen auf Word geändert. Jetzt dauert die Berechnung ca. 60 µs.
Das reicht leider noch nicht, da bei Maximalgeschwindigkeit jede 100 µs
die ISR aufgerufen wird und das Hauptprogramm auch noch zum Zuge kommen
soll. Kann man das Problem mit dem Toggeln nicht irgendwie lösen? Die
Impulsbreite des Schrittsignals muss für die Endstufe jedoch mindestens
2 µs betragen.
>Kann man das Problem mit dem Toggeln nicht irgendwie lösen?
Ich würde Timer 1 im CTC-Modus laufen lassen. Nach jeder Neuberechnung
OCR1A auf C_n_neu setzen, und OCR1B auf die Hälfte davon. Du kannst den
Timer so konfigurieren, dass bei Erreichen des OCR1B-Wertes von der
Hardware ein Pin gesetzt oder gelöscht wird. Weitere Infos siehe
Datenblatt.
Ich habe gerade bemerkt, dass ich 2c_n_alt doch 32 Bit groß machen muss,
da der Rest auch noch hinzuaddiert wird und leider auch sehr groß werden
kann.
Damit sind Division(Festkomma) und Modulo auch wieder 32 Bit
Operationen.
Mit dem zweimaligen Toggeln und neuen µC-Takt von 18,432 MHz komme ich
auf eine Berechnungsdauer von ca. 80 µs, was für 4 U/s reichen sollte,
da die ISR nur jede 250 µs aufgerufen wird.
Der Bascom-Simulator setzt TCNT1 immer auf 0 sobald der kleinste Wert
von OCR1A und OCR1B erreicht ist. Wenn jetzt z.B. OCR1B auf 10000 und
OCR1A auf 20000 gesetzt ist, würde der Interrupt von OCR1A nie ausgelöst
werden.
Ist das ein Fehler im Simulator?
>Damit sind Division(Festkomma) und Modulo auch wieder 32 Bit Operationen.
Du hast zwei Alternativen: (1) Solange rumprobieren, bis es irgendwie
geht und Du mit dem Ergebnis leben kannst, oder (2) den Algorithmus und
den Code von vorne bis hinten durchanalysieren und auf Basis der
gewonnenen Erkenntnisse fundierte Entscheidungen treffen. (1) ist
schnell und (2) ist sauber.
>Mit dem zweimaligen Toggeln und neuen µC-Takt von 18,432 MHz komme ich>auf eine Berechnungsdauer von ca. 80 µs, was für 4 U/s reichen sollte,>da die ISR nur jede 250 µs aufgerufen wird.
Aber ist es eigentlich nötig, mit jedem Motorstep eine Neuberechnung
durchführen? Würde es nicht auch reichen, das nur z. B. 80 mal pro
Sekunde zu machen? Um einen entsprechenden Takt zu erzeugen, kannst Du
Timer 0 nehmen, und die "lahme" Rechenroutine gehört dann ins Main,
damit sie von den schnellen Timer 1-Interrupts unterbrochen werden kann.
Die Aktualisierung des OCR1A-Werts musst Du in der ISR vom Timer1-OCRA
erledigen, und die Bereitstellung des Ergebnisses durch die
Rechenroutine atomar machen. You understand? Ist aber alles relativ easy
zu bewerkstelligen.
>Ist das ein Fehler im Simulator?
Wahrscheinlich... keine Ahnung, sorry. Das von Dir beschriebene
Verhalten ist jedenfalls nicht konform zu dem eines realen Controllers.