Hallo, ich verwende für eine kleine Stromregelung einen Arduino DUE. Die Regelung sollte bis mind. 50kHz gut funktionieren. Das Soll- sowie das Ist-Signal werden über die Analog Inputs eingelesen, daraus (momentan als PI-Regler implementiert) ein Ausgangswert gebildet und dieser über einen analogen Leistungsverstärker auf die Strecke geschickt. Mein Problem ist aber, dass der eigentlich recht einfache Code relativ lange braucht und somit bereits bei 10kHz eine beträchtliche Phasenverschiebung rein aufgrund des uC entsteht. Gibt es Ansätze oder Lösungsvorschläge, wie ich das Programm effizienter schreiben kann? (Anbei noch mein Code) Vielen Dank!
Also an den Codezeilen kann es denke ich mal nicht liegen, wie lange bleibt er denn in der While() hängen? Setz mal in der While() einen Pin auf High und oszillografiere.
Markus P. schrieb: > ich verwende für eine kleine Stromregelung einen Arduino DUE. Ok, der hat 84 MHz mit Cortex M3 CPU. > Die > Regelung sollte bis mind. 50kHz gut funktionieren. Das ist schon recht anspruchsvoll. Ich hab vor Jahren mal ein Design mit einem PICCOLO gemacht, der läuft auf 60MHz. Die 100kHz ISR für die Regelung und ADC-Auslesung läuft rein in Assembler. OK, dort sind 5 PID-Regler und noch Krümelkram drin, aber dafür braucht sie auch ca. 60% der CPU-Leistung. > Das Soll- sowie das > Ist-Signal werden über die Analog Inputs eingelesen, daraus (momentan > als PI-Regler implementiert) ein Ausgangswert gebildet und dieser über > einen analogen Leistungsverstärker auf die Strecke geschickt. Da ist noch ein Fehler drin. Der I-Anteil muss VOR der Berechnung des Stellwerts addiert werden, sonst hast du eine runde Verspätung, sprich Phasenverschiebung. Eine Warteschleife hat in so einer ISR eigentlich nix zu suchen. Deine ADCs und der DAC müssen so synchronisiert sein, daß man ohne Wartepausen die ADCs lesen und den DAC schreiben kann.
:
Bearbeitet durch User
Wenn kI und kP (aus Sicht des Compilers) konstanten wären, könnte er die Multiplikation besser optimieren. Mit den gezeigten Werten würden sie sogar ganz entfallen.
Wenn du von 2 Kanälen liest, muss der ADC warten bis der S&H Kondensator umgeladen ist. Hast du schon getestet, ob du die Default-Zeiten verringern kannst?
Ingo L. schrieb: > Also an den Codezeilen kann es denke ich mal nicht liegen, wie lange > bleibt er denn in der While() hängen? Setz mal in der While() einen Pin > auf High und oszillografiere. in der While() Schleife dürfte er vermutlich gar nicht hängen geblieben sein, zumindest erfasst es das Oszi gar nicht. Ich habe die Zeile jetzt trotzdem mal entfernt.
Xanthippos schrieb: > Wenn du von 2 Kanälen liest, muss der ADC warten bis der S&H Kondensator > umgeladen ist. Er liest aus den Ergebnisregistern des ADC. Der muss synchronisiert laufen, daß zum Zeitpunkt des Timer-Interrupts die Messung schon abgeschlossen ist. In der Timer-ISR ist KEINE Zeit zum Start der ADC-Wandlung und Warten auf das Ergebnis!
Über welche IDE hast du das Programm geschrieben? z. B. hat alles was du über Arduino IDE schreibst einen riesen Overhead.
Falk B. schrieb: > Eine Warteschleife hat in so einer ISR eigentlich nix zu suchen. Deine > ADCs und der DAC müssen so synchronisiert sein, daß man ohne Wartepausen > die ADCs lesen und den DAC schreiben kann. Wie kann ich den ADC und DAC synchronisieren? Den ADC Clock kann man über einen Prescaler einstellen, aber beim DAC habe ich nichts dementsprechendes gefunden. Die Warteschleife ist wie gesagt jetzt mal entfernt worden.
Steve van de Grens schrieb: > Wenn kI und kP (aus Sicht des Compilers) konstanten wären, könnte er die > Multiplikation besser optimieren. Mit den gezeigten Werten würden sie > sogar ganz entfallen. Also einfach außerhalb definieren? kI und kP sind nämlich konstant.
Markus P. schrieb: >> Eine Warteschleife hat in so einer ISR eigentlich nix zu suchen. Deine >> ADCs und der DAC müssen so synchronisiert sein, daß man ohne Wartepausen >> die ADCs lesen und den DAC schreiben kann. > > Wie kann ich den ADC und DAC synchronisieren? Das kommt auf den Mikrocontroller an. Beim PICCOLO kann man den ADC über verschiedene Events in Hardware auslösen. In meinem Projekt per Timer mit der passenden Phasenverschiebung. Wie das bei deinem COntroller funktioniert weiß ich nicht. Für den DAC braucht man sowas AFAIK nicht, den kann man direkt beschreiben, denn der ist sauschnell. Das sollte im Datenblatt stehen. > Den ADC Clock kann man > über einen Prescaler einstellen, Das reicht nicht, der Meßzeitpunkt muss genau bestimmt sein.
Falk B. schrieb: > In der Timer-ISR ist KEINE Zeit zum Start der > ADC-Wandlung und Warten auf das Ergebnis! Die ADC-Wandlung wird auch schon vorher gestartet. Der Ausgang wird jetzt im 1us - Takt am DAC ausgegeben, siehe Bild im Anhang. Interessanterweise schreibt er maximal im 1us - Takt, selbst wenn ich die Zeit beim Timer auf z.B. 500ns herabsetze. Ich weiß allerdings auch nicht genau, wie ich ADC und DAC miteinander synchronisieren kann. Ich habe dazu nicht wirklich etwas im Datenblatt gefunden - irgendwelche Ideen?
Markus P. schrieb: > Also einfach außerhalb definieren? kI und kP sind nämlich konstant. Dann kannst du aber während der Laufzeit nix mehr einstellen. Das ist eher ungünstig. Die Multiplikation zweier Variablen ist für so eine 32 Bit CPU ein Klacks, der wenige Takte dauert. Dort kann man nicht sinnvoll optimieren.
Markus P. schrieb: > Die ADC-Wandlung wird auch schon vorher gestartet. Der Ausgang wird > jetzt im 1us - Takt am DAC ausgegeben, siehe Bild im Anhang. > Interessanterweise schreibt er maximal im 1us - Takt, selbst wenn ich > die Zeit beim Timer auf z.B. 500ns herabsetze. Und du glaubst, daß ein 500ns (NANOSEKUNDEN) Timer ISR immer mit 500ns aufgerufen wird? Ich nicht. > Ich weiß allerdings auch > nicht genau, wie ich ADC und DAC miteinander synchronisieren kann. Ich > habe dazu nicht wirklich etwas im Datenblatt gefunden - irgendwelche > Ideen? Siehe oben. Du musst einen Weg finden, den ADC synchron zu starten. Im einfachsten Fall am Ende der Regler-ISR mittels CPU. Dann läuft die Messung in der Zeit bis zum nächsten Timer-Interrupt und man kann die Ergebnisse direkt auslesen, so wie du es jetzt schon machst.
Falk B. schrieb: > Das kommt auf den Mikrocontroller an. Beim PICCOLO kann man den ADC > über verschiedene Events in Hardware auslösen. In meinem Projekt per > Timer mit der passenden Phasenverschiebung. Wie das bei deinem > COntroller funktioniert weiß ich nicht. > Für den DAC braucht man sowas AFAIK nicht, den kann man direkt > beschreiben, denn der ist sauschnell. Das sollte im Datenblatt stehen. "The DACC uses the master clock (MCK) divided by two to perform conversions. This clock is named DACC Clock. Once a conversion starts the DACC takes 25 clock periods to provide the analog result on the selected analog output." --> das steht dazu im Datenblatt. Braucht mein DAC also für jede Wandlung 25 clock periods? Das wären dann bei 84MHz eine Dauer von ~ 300ns. Wie kann ich den ADC dann triggern?
Markus P. schrieb: > "The DACC uses the master clock (MCK) divided by two to perform > conversions. This clock is named DACC Clock. Once a conversion starts > the DACC takes 25 clock periods to provide the analog result on the > selected analog output." > > --> das steht dazu im Datenblatt. Braucht mein DAC also für jede > Wandlung 25 clock periods? Das wären dann bei 84MHz eine Dauer von ~ > 300ns. Immer noch sehr schnell. Also kann man ohne Prüfung und Warten mit 50kHz den DAC direkt beschreiben. > Wie kann ich den ADC dann triggern? Frag dein Datenblatt ;-)
Falk B. schrieb: > Markus P. schrieb: >> "The DACC uses the master clock (MCK) divided by two to perform >> conversions. This clock is named DACC Clock. Once a conversion starts >> the DACC takes 25 clock periods to provide the analog result on the >> selected analog output." >> >> --> das steht dazu im Datenblatt. Braucht mein DAC also für jede >> Wandlung 25 clock periods? Das wären dann bei 84MHz eine Dauer von ~ >> 300ns. > > Immer noch sehr schnell. Also kann man ohne Prüfung und Warten mit 50kHz > den DAC direkt beschreiben. > >> Wie kann ich den ADC dann triggern? > > Frag dein Datenblatt ;-) Das heißt quasi, ich könnte die Interrupt Routine starten, wenn der ADC fertig gewandelt hat, die Daten einlesen, neuen Wert berechnen und wieder rausschreiben? Also den Trigger des Interrupts auf die Fertigstellung des ADCs legen? P.S. Vielen Dank für die vielen Antworten!
Markus P. schrieb: > Das heißt quasi, ich könnte die Interrupt Routine starten, wenn der ADC > fertig gewandelt hat, die Daten einlesen, neuen Wert berechnen und > wieder rausschreiben? Also den Trigger des Interrupts auf die > Fertigstellung des ADCs legen? Kann man machen.
Es sollte möglich sein, den ADC per Timer direkt zu triggern, sodass er die beiden Kanäle nacheinander misst und nach der Messung per DMA die Messwerte speichert und einen Interrupt erzeugt, sodass der Regler aufgerufen werden kann. Dann kannst du in aller Ruhe regeln...
Ingo L. schrieb: > Es sollte möglich sein, den ADC per Timer direkt zu triggern, sodass er > die beiden Kanäle nacheinander misst und nach der Messung per DMA die > Messwerte speichert Muss er gar nicht, denn es gibt anscheinend für jeden Kanal ein Ergebnisregister. > und einen Interrupt erzeugt, sodass der Regler > aufgerufen werden kann. Dann kannst du in aller Ruhe regeln... Bei 50kHz gibt es keine Ruhe ;-)
Markus P. schrieb: > Also einfach außerhalb definieren? kI und kP sind nämlich konstant. Ich würde es mal mit "const" vor der Deklaration versuchen. Wenn das nichts bringt, dann versuche sie mit #define zu definieren, anstatt als reguläre Variable. Also
1 | const in16_t kP = 1; |
2 | const in16_t kI = 0; |
3 | const in16_t kD = 0; |
oder
1 | #define kP 1
|
2 | #define kI 0
|
3 | #define kD 0
|
32 Bit Controller können 32 Bit Variablen manchmal schneller verarbeiten als 16 Bit, weil eine Konvertier-Schritt entfällt. Das wäre auch noch einen Versuch wert.
Falk B. schrieb: > Peter D. schrieb: >> Code als PNG, gehts noch!!! > > Da haben wir schon DEUTLICH größeren Mist gesehen. Stimmt ;o) Er hätte es ja auch noch mit dem Handy vom Bildschirm abfotografieren und dann als ~10MB-JPEG hochladen können...
Falk B. schrieb: > Muss er gar nicht, denn es gibt anscheinend für jeden Kanal ein > Ergebnisregister. Das is ja mal deluxe
Wenn ADC & DAC das Timing bestimmen, wuerde ich die grad nacheinander oder gleichzeitig starten und den Rest drum herum ohne warten anpassen.
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.