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