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