Code-Optimierung uC PID Regler

OP #7386772
Lesenswert?

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!

Angehängte Dateien:
#7386798
Lesenswert?

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.

OP #7386859
Lesenswert?

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.

OP #7386868
Lesenswert?

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.

#7386875
Lesenswert?

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.

OP #7386877
Lesenswert?

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?

Angehängte Dateien:
#7386883
Lesenswert?

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.

OP #7386884
Lesenswert?

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?

#7386890
Lesenswert?

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 ;-)

OP #7386901
Lesenswert?

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!

#7386906
Lesenswert?

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 ;-)

Gast #7386933
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren