Forum: Mikrocontroller und Digitale Elektronik AVR: optimaler Code für Schrittmotor Microstepping


von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Hallo zusammen,

ich bin grad dabei, einen Schrittmotor über einen L6228 
(Stepper-Controller) und einen ATmega328P anzusteuern, und zwar im 
Microstepping-Betrieb. Die fürs Microstepping notwendigen 
Referenzspannungen erzeuge ich bereits erfolgreich per Fast-PWM (ohne 
Interrupts, rein hardwaremäßig).

Für die Taktung läuft ein 16-Bit-Timer, die Beschleunigungs-und 
Bremsrampen errechnet ein zweiter Timer.

Soweit funktioniert schon mal alles, allerdings musste ich feststellen 
dass sich bei höheren Drehzahlen und/oder höheren Beschleunigungen die 
Interrupts gegenseitig im Weg stehen.

Ich möchte nun versuchen die Interrupts so weit möglich zu optimieren. 
leider ist reiner Assembler keine wirkliche Option, schlicht weil ich 
das nicht kann. In C bin ich aber einigermaßen fit.

Ich kämpfe grad mit der Behandlung des Microsteppings, versuche 
rauszufinden wie der Code optimal aufgebaut werden könnte, sehe dafür 
mehrere Möglichkeiten, und hoffe auf eure Hilfe...

Grundsätzlich ist es so: Es gibt eine Lookup-Tabelle mit derzeit 32 
Einträgen (kann sich noch ändern, allerdings ist die Größe immer eine 
glatte Zweierpotenz, maximal 256), diese enthält den PWM-Wert als 
uint8_t. Die Werte selbst entsprechen einer Sinus-Halbwelle. In diese 
Lookup-Tabelle zeigt ein Index, der wird bei Drehung je nach Richtung 
inkrementiert oder dekrementiert. Ich brauch aber eigentlich zwei Werte: 
den aktuellen Wert und einen um 90° verschobenen Wert (da die 32 
Einträge 180° entsprechen also um 16 verschoben)

Einfach 16 zum Index dazuzählen reicht natürlich nicht, ich muss ja 
"umbrechen" wenns über die 32 hinausgeht soll er bei 0 wieder anfangen, 
sprich: Modulo 32. Da es Zweiterpotenzen sind, geht das schneller mit 
&31

"Umbrechen" muss ich aber auch beim Inkrementieren bzw. dekrementieren, 
0-1 = 31 und 31+1 = 0, ebenfalls wieder modulo 32 bzw. & 31

Die eigentliche Adressberechnung (2 mal) zusammen mit dem umbrechen 
braucht nun doch einige Takte...

Meine Ideen dazu:

a) nicht einen Index, sondern zwei, wobei der zweite immer um 16 
verschoben läuft (dann muss ich aber beim Inkrementieren/Dekrementieren 
auch beide Indices umbrechen)

b) zwei Lookup-Tabellen, die zweite schon um 16 verschoben: ich muss nur 
mehr einen Index betrachten, hab aber zweimal die Adressberechnung

c) die Lookup-Tabelle doppelt so groß machen, zweite Hälfte ist eine 
exakte Kopie der ersten: Damit spar ich mir das Umbrechen bei +16

d) die Lookup-Tabelle generell 256 Byte groß machen, 8 x identischer 
Inhalt, damit läuft das umbrechen "explizit" durch die Begrenzung des 
Index auf 8 bit. (Platz dafür im RAM wäre vorhanden)

e) erst gar nicht mit Array-Indices arbeiten, sondern gleich mit 
Pointern?

f) eine beliebige Kombination aus a..e?

Vielen Dank für eure Anregungen!


lg Michi

von Fabian O. (xfr)


Lesenswert?

Im Zweifel ausprobieren, schaun, was der Compiler draus macht und die 
Takte der Befehle zählen. Solche Tricks wie Modulo durch Bitmaske 
ersetzen kennt der Compiler sicherlich, das braucht man nicht explizit 
hinschreiben.

Im Array könntest Du jeweils einen Wert und den um 90° verschobenen 
direkt hintereinander speichern. Dann muss nur einmal die Basisadresse 
berechnet und umgebrochen werden. Wenns noch auf den einen Takt zum 
Ausmaskieren ankommt, kannst Du natürlich auch auf 256 Bytes erweitern, 
das geht bei jeder Option.

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
Noch kein Account? Hier anmelden.