Vorweg: bitte nagelt mich nicht ans Kreuz, ich habe mit dem
Programmieren bis lang noch nicht so viel Erfahrung gesammelt.
Ich habe einen 3-phasigen PFC Gleichrichter und soll für diesen einen
Regler programmieren. Das habe ich gemacht und das ganze funktioniert
bis jetzt eigentlich recht gut. Das Problem dabei ist die in meinen
Augen nicht schöne Umsetzung: meine CPU verbringt nämlich 3/4 der Zeit
in einer Interrupt Routine und rechnet dabei mit vielen floats einige
dq-Transformationen, Strom- und Spannungsregler und eine PLL (also unter
anderem einige sin/cos, sqrt und pow()). Die Plattform ist ein Zynq SoC.
Getriggert wird die ISR von meinem PWM Counter.
Die Fragen die ich mir nun stelle:
- Wie macht man sowas "richtig", also ohne 3/4 der Zeit in der ISR zu
stecken? Das ganze funktioniert prinzipiell, allerdings habe ich das
Gefühl, miserable Software mit gewaltigem Übermass an Rechenpower
erschlagen zu haben. Ohne gross Erfahrung zu haben gehe ich doch davon
aus, für eine "normale" PFC nicht einen ARM Cortex A9 so auszulasten.
- Ganz allgemein (nicht nur auf diese Anwendung bezogen) würde mich
interessieren, ob und falls ja wieviel Rechenleistung ich einsparen
könnte, wenn ich fixed point Arithmetik anstatt Gleitkommazahlen
verwende. Da ich sin/cos/sqrt Berechnungen verwendet gehe ich davon aus,
dass das Einsparpotential an der Stelle gering ist (solange diese
Operationen drin bleiben). Wie sieht das aber auf modernen CPUs
allgemein aus, vor allem wenn ich (wie hier) sehr wenig Daten habe
(alles passt in den Cache). Dauern Addieren/Multiplizieren/Dividieren
auf modernen CPUs mit FPU länger oder gleich lang wie äquivalente
Fixpunktoperationen?
Das ist schwer zu beantworten ohne weitere, detaillierte Angaben
deinerseits.
Wie oft wird die ISR aufgerufen und welche Schaltfrequenz verwendest du?
Führst du Berechnungen durch, die man einmalig zuvor ausführen kann, und
nur die Ergebnisse verwendet?
Die Interrupt-Frequenz (identisch mit der doppelten Schaltfrequenz) ist
ca. 75 kHz. Dinge vorausberechnen kann ich nicht, ich habe nur in die
ISR gesteckt was von den Messwerten abhängt.
Rechenleistungs-Verschwender schrieb:> Wie macht man sowas "richtig", also ohne 3/4 der Zeit in der ISR zu> stecken?
Was stört dich daran? Je nach Anwendung kann es für so eine Applikation
das performanteste sein. Ob der Code nun in der ISR läuft oder nicht,
ändert ja nix daran, dass die CPU zu 3/4 ausgelastet ist. Und wenn du
deterministisch genau zu jedem PWM/ADC-Zyklus den Regler rechnen musst,
bietet es sich halt an, das direkt im entsprechenden Interrupt laufen zu
lassen. Dass in der Hauptschleife dann nur noch untergeordneter Kram
dran kommt, erklärt sich von selbst.
Alles eine reine Architekturabwägung.
Rechenleistungs-Verschwender schrieb:> Ohne gross Erfahrung zu haben gehe ich doch davon> aus, für eine "normale" PFC nicht einen ARM Cortex A9 so auszulasten.
Ohne deine Schaltfrequenz und den Prozessor zu kennen: eher nein.
Aber ein Cortex A9 ist auch nicht die Architektur der Wahl für sowas.
Compileroptimierung eingeschaltet?
Du kannst dir jedenfalls sicher sein, dass in wesentlich kleineren
Prozessoren mit geeigneter Architektur und vernünftige Code (und das
Problem liegt nicht in der ISR!) komplexe antriebstechnische Aufgaben
wie Mehrachsantriebe realisiert werden. Selbst ohne Compileroptimierung.
Rechenleistungs-Verschwender schrieb:> Strom- und Spannungsregler und eine PLL (also unter> anderem einige sin/cos, sqrt und pow())
Es gibt ziemlich schnelle Softwareimplementierungen für sowas, die,
gegen die für einen A9 gelinkt wird, wird wohl eher nicht so darauf
optimiert sein.
Ein Beispiel wäre die C2800er-Reihe von TI (natürlich tendenziell
Overkill für eine PFC, aber das ist ein A9 auch). Texas bietet sowohl
schnelle Implementierungen in Software, als auch Prozessoren mit
Hardwarebeschleunigung für sowas.
Nebenbei ist pow() für quadrieren (je nach Compiler und Code)
tendenziell langsamer als x * x.
Rechenleistungs-Verschwender schrieb:> Ganz allgemein (nicht nur auf diese Anwendung bezogen) würde mich> interessieren, ob und falls ja wieviel Rechenleistung ich einsparen> könnte, wenn ich fixed point Arithmetik anstatt Gleitkommazahlen> verwende.
Kommt, wer hätte das gedacht, auf den Prozessor an. Eher nicht viel.
Wenn es keine wichtigen Gründe dafür gibt (bestehender Prozessor, der
$wichtiges_feature) sonst nicht packt, oder auf biegen und brechen ein
kleinerer Prozessor verwendet werden muss um im Einkauf ein paar Cent zu
sparen: den Aufwand nicht wert.
Rechenleistungs-Verschwender schrieb:> Wie sieht das aber auf modernen CPUs> allgemein aus, vor allem wenn ich (wie hier) sehr wenig Daten habe> (alles passt in den Cache).
Für sowas nimmt man keine Applikationsprozessoren, dann stellt sich die
Frage "Cache oder nicht" gar nicht erst.
Rechenleistungs-Verschwender schrieb:> Dauern Addieren/Multiplizieren/Dividieren> auf modernen CPUs mit FPU länger oder gleich lang wie äquivalente> Fixpunktoperationen?
Datenblatt lesen.
Rechenleistungs-Verschwender schrieb:> Die Interrupt-Frequenz (identisch mit der doppelten Schaltfrequenz) ist> ca. 75 kHz.
Ein 2000er macht dir die Stromregelschleife im einstelligen µs-Bereich.
Vielleicht wäre ein uC der C2000 von TI etwas für dich, der speziell für
3phasen Systeme passende dq Transformationen anbietet sowie
code-optimierte PI Regler.
Gruß,
Auf keinen Fall nimmt man einen Application Prozessor.
Cortex M4 oder Cortex M7 von beliebigem Hersteller reicht. Nicht TI,
viel zu teuer. NXP oder STM.
Maches kannst du in langsamere ISR auslagern. Statt PLL und Clark, Park
Transformation kann man auch mit Spannungs-Feedforward zur
Regelstrecken-Linearisierung arbeiten, das spart dann auch noch Zeit.
pow() und den ganzen anderen Schmarrn brauchst du nicht. Für sin/cos
nimmt man LUTs mit linearer interpolation.
Falls du einen Cortex M7 aussuchst, kann der zwar Floating Point, aber
Fixed Point reicht für alles, was du dir im Bereich PFC vorstellen
kannst.
Meist sind Fixed Point Befehle 1-2 Zyklen schneller als FP.
Rechenleistungs-Verschwender schrieb:> Ich habe einen 3-phasigen PFC Gleichrichter und soll für diesen einen> Regler programmieren. Das habe ich gemacht und das ganze funktioniert> bis jetzt eigentlich recht gut. Das Problem dabei ist die in meinen> Augen nicht schöne Umsetzung: meine CPU verbringt nämlich 3/4 der Zeit> in einer Interrupt Routine und rechnet dabei mit vielen floats einige> dq-Transformationen, Strom- und Spannungsregler und eine PLL (also unter> anderem einige sin/cos, sqrt und pow()).
Naja, ich hab hier eine 2phasige PFC, die läuft auf einem 60 MHz
PICCOLO von TI, da wird alles in Festkommaarithmetik in 32 Bit
gerechnet. Das reicht locker. "Nebenbei" laufen auch noch drei andere
PID-Regler im Interrupt @100kHz und erzeugen dadurch ca. 50%
CPU-Grundlast.
Aber selbst wenn es 75% wären, wäre das OK, wenn alle zeitkritischen
Anforderungen erfüllt werden. Es gibt kein Geld zurück für ungenutzte
CPU-Leistung.
> Gefühl, miserable Software mit gewaltigem Übermass an Rechenpower> erschlagen zu haben.
Damit liegst du voll im Trend! ;-)
> Ohne gross Erfahrung zu haben gehe ich doch davon> aus, für eine "normale" PFC nicht einen ARM Cortex A9 so auszulasten.
Nö.
> verwende. Da ich sin/cos/sqrt Berechnungen verwendet gehe ich davon aus,
Naja, wozu brauchst du die denn? Eine normale PFC braucht die nicht,
außer vielleicht die Wurzel, die aber nur am Ende einer Periode. In
meinem Projekt, das auf einem Eval-Kit von TI aufbaut, läuft neben der
100kHz ISR (in Assembler) noch eine 10kHz ISR in C. Dort wird der
Überwachungskram berechnet, spricht, Effektivwerte für Strom und
Spannung. Aber die werden nur einmal pro Periode berechnet, sonst läuft
nur die Akkumulation von U, I bzw. I^2.
> dass das Einsparpotential an der Stelle gering ist (solange diese> Operationen drin bleiben). Wie sieht das aber auf modernen CPUs> allgemein aus, vor allem wenn ich (wie hier) sehr wenig Daten habe> (alles passt in den Cache). Dauern Addieren/Multiplizieren/Dividieren> auf modernen CPUs mit FPU länger oder gleich lang wie äquivalente> Fixpunktoperationen?
Vermutlich gleich lang bis kürzer, ist ja schließlich eine Hardware-FPU.
Falk B. schrieb:> Naja, wozu brauchst du die denn? Eine normale PFC braucht die nicht,
Es geht hier nicht um normal oder nicht-normal, sondern um 1phasig oder
3phasig. Und da unterscheiden sich die beiden Lösungen nunmal gewaltig.
Es ist allgemein bekannt, dass PI Regler nur bei DC eine Regelabweichung
von 0 haben. Bei 50Hz AC kann ein PI Regler per Definition die
Regelabweichung nicht eliminieren, sondern höchsten reduzieren.
Das schöne an 3phasigen Systemen ist, dass man mittels Clark/Park
Transformation ein 3phasiges AC System in ein einphasiges DC System
überführen kann. Genau dieses Prinzip nutzt man, um das resultierende
magnetische Feld in 3phasigen AC Maschinen zu beschreiben. Sobald man
das 3phasige AC System ins 1phasige DC System transformiert hat, kann
man dort die Regelung mittels gewöhnlicher PI Regler ausführen, und dann
anschließend alles zurück ins 3phasige System transformiert.
Natürlich geht es auch ohne Clark/Park, das machen aber nur Amateure und
Bastler.
Gruß,
asdfjklö schrieb:> Cortex M4 oder Cortex M7 von beliebigem Hersteller reicht. Nicht TI,> viel zu teuer. NXP oder STM.
Als ob bei einem Einzelstück der Preis wichtig wäre.
Vielen Dank für die Antworten, ich habe einige interessante Inputs
bekommen. Allem voran ist mir der Begriff "Applikationsprozessor" nicht
wirklich geläufig und mir war auch nicht bewusst, so etwas vor mir zu
haben. Google spuckt auch keine exakte Definition dazu aus sondern mehr
eine Sammlung von verschiedenen Merkmalen die je nachdem vorhanden sein
können oder nicht. Könnt ihr mir ein paar konkrete Anhaltspunkte dazu
nennen?
Verschwender schrieb:> Ohne deine Schaltfrequenz und den Prozessor zu kennen: eher nein.> Aber ein Cortex A9 ist auch nicht die Architektur der Wahl für sowas.> Compileroptimierung eingeschaltet?
Compileroptimierung ist an und auf "-O3".
Verschwender schrieb:> Nebenbei ist pow() für quadrieren (je nach Compiler und Code)> tendenziell langsamer als x * x.
Das hätte ich eigentlich wissen können, hatte ich aber vergessen.
Falk B. schrieb:> Damit liegst du voll im Trend! ;-)
Genau das finde ich nicht unbedingt erstrebenswert ;) Ausserdem ist
deine CPU offenbar mehr als 10 mal langsamer und erledigt mehr Jobs als
mein Programm. Das schreit für mich nach grobem Unfug den ich fabriziert
habe.
Falk B. schrieb:> Vermutlich gleich lang bis kürzer, ist ja schließlich eine Hardware-FPU.
Ich war mir nicht sicher ob die Hardware FPU so schnell ist, habe es
aber vermutet. Solange als eine Hardware FPU vorhanden ist sollte es
keinen Unterschied machen, ob ich float oder int einsetze.
Wenn notwendig & auch möglich, versuche Berechnungen durch
Lookup-Tabellen zu ersetzen und v.a. Divisionen wegzubekommen (das frißt
Rechenzeit).
Speziell Deine winkelfunktionen lassen sich durch eine einzige
sin-Tabelle, erweitert um 90° für den Cos, locker ersetzen.
Rechenleistungs-Verschwender schrieb:> Allem voran ist mir der Begriff "Applikationsprozessor" nicht> wirklich geläufig und mir war auch nicht bewusst,
Ein "Application Processor" ist ein Prozessor, der für allgemeine
Anwendungsausführung (im Zusammenspiel mit einem Betriebssystem)
ausgelegt ist. Also mit MMU und Speicherschutz, Caches, höherem
Stromverbrauch und dem ganzen Pipapo.
Ein Gegenstück sind dann z.B. digitale Signalprozessoren (DSPs), wie die
genannten C2000. Die haben solche Spielereien eher nicht, aber dafür
garantierten Datendurchsatz, spezielle Hardware, spezielle Befehlssätze
(z.B. Fixpoint-Arithmetik oder FFT-Bausteine) und sowas.
Die sind in der Regel auch schneller in einer ISR. Hast du mal zum
Vergleich getestet, wie viel Last eine leere 75 kHz-ISR auf deinem
System verursacht? Vielleicht kann man da etwas optimieren.
Vorallendingen sind Applikationsprozessoren überhaupt nicht für
derartige Interruptraten ausgelegt. Dies sind dafür gedacht das da ein
Linux o.ä. drauf läuft. Da sprechen wir typischerweise von Taskwechseln
mit 100Hz, also alle 10ms. Hochfrequente Interrupte sind tödlich für
diese Cores. Der hat eine 8 stufige Pipeline die geleert und wieder
gefüllt werde muss, wenn die FPU benutzt wird müssen deren Register auch
mit gesichert werden und eine MMU ist da auch noch. Bis der überhaupt in
der ersten Anwenderinstruktion der ISR angekommen ist, hat ein M4 schon
die halbe ISR fertig gemacht: Die Interruptlatenz eines M4 beträgt 12
Takte bei Zero-Waitstate RAM, d.h. ein 100 Mhz Cortex-M4 braucht ca.
0.2µs bis er im Interrupt ist. Ein Cortex A9 braucht, wenn man eine
normale Applikation in der Main-Loop hat, im Mittel ca 800 Takte bis er
im Interrupt steht, d.h. selbst ein 1Ghz A9 braucht 7mal länger als der
CM4 um überhaupt erstmal in der ISR anzukommen.
Das hat hier jemand schön untersucht (Bare-Metal System):
https://www.jblopen.com/improving-interrupt-latency-on-the-cortex-a9/
Warum wird überhaupt der A9 benutzt? Der Zynq hat doch ein FPGA.
Vielen Dank für die Antworten. Was ihr schreibt macht für mich Sinn, war
mir aber nicht bewusst (zumindest nicht in dem Ausmass).
Andreas M. schrieb:> Das hat hier jemand schön untersucht (Bare-Metal System):>> https://www.jblopen.com/improving-interrupt-latency-on-the-cortex-a9/
Das hat mich echt überrascht, ich hätte nicht ansatzweise erwartet, dass
die CPU 800 Zyklen (oder bis zu 1780 im Worst Case in dem Beispiel)
braucht bis sie in der ISR steht. Ich wusste, dass bei modernen CPUs die
Ausführungszeit nicht genau im Voraus bestimmt werden kann (wegen
Cache-Hit/Miss, Branch Prediction, und solchen Dingen). Dass die
Unterschiede aber so gewaltig sind und vor allem so streuen hätte ich
nicht erwartet.
Das bringt mich auf den unguten Gedanken, dass ich bis jetzt auch
einfach Glück gehabt haben könnte. Wenn ich das Programm erweitere
könnte es in dem Fall passieren, dass die ISR in einem sehr ungünstigen
Fall plötzlich doppelt so lange dauert und damit nicht mehr vor dem
nächsten Trigger fertig wird. Bei einer PFC die am Netz hängt gefällt
mir der Gedanke überhaupt nicht. Zum Glück habe ich einen Watchdog im
Hintergrund laufen, der am Ende der ISR jedes Mal zurückgesetzt wird,
das würde mir in dem Fall wohl den Arsch retten.
Andreas M. schrieb:> Warum wird überhaupt der A9 benutzt? Der Zynq hat doch ein FPGA.
Man könnte das alles ins FPGA packen, die Entwicklung der entsprechenden
FPGA Cores hätte mich aber sehr viel mehr Zeit gekostet (bin leider auch
nicht so fit in VHDL, hatte schon mit den entsprechenden Einheiten für
PWM-Generierung usw. meine Mühe). Oder hättest du einen kleinen und
schnellen Software auf dem FPGA implementiert und das Programm dann für
diesen geschrieben?
Benutzt habe ich den Zynq im wesentlichen deshalb, weil er gerade rumlag
und ich nichts anderes zur Verfügung hatte. Offensichtlich nicht die
beste Wahl, der Lerneffekt durch das Projekt war auf jeden Fall recht
erheblich ;)
Rechenleistungs-Verschwender schrieb:> FPGA Cores hätte mich aber sehr viel mehr Zeit gekostet (bin leider auch> nicht so fit in VHDL, hatte schon mit den entsprechenden Einheiten für> PWM-Generierung usw. meine Mühe). Oder hättest du einen kleinen und> schnellen Software auf dem FPGA implementiert und das Programm dann für> diesen geschrieben?
Naja für mich wäre VHDL auch komplett neu, aber alleine aus Interesse
hätte ich die Zeit darein gesteckt, das Thema interessiert mich
brennend, habe nur keinen Anwendungsfall.
Ich kenne jetzt die Algorithmik die man für PFC braucht nicht, aber ich
würde erwarten, dass Effektivste under vermutliche auch Einfachere wäre
das ganze komplett im FPGA zu lösen ohne den Umweg über einen Softcore.
Ich denk mal es ist ein statischer Regelalgorithmus ohne irgendwelche
Verzweigungen, also immer der gleiche Ablauf. Den Softcore muss man ja
auch erst verstehen.
Andreas M. schrieb:> Naja für mich wäre VHDL auch komplett neu, aber alleine> aus Interesse hätte ich die Zeit darein gesteckt, [...]
Sagen wir's mal so... ich hab einen VHDL-Kurs belegt und hätte trotzdem
unglaublich viel Zeit darin versenkt, eine zuverlässige Lösung zu
bauen.
Das kann man so machen, wenn man VHDL lernen will - wenn es darum geht,
irgendwann eine Lösung zu haben (und diese auch zukünftig warten zu
können, wenn man mal länger kein VHDL angefasst hat), ist eine
Softwarelösung eher besser. Aus der Sicht hat der TO schonmal nicht
falsch gehandelt.
Andreas M. schrieb:> komplett im FPGA zu lösen ohne den Umweg über einen Softcore
Das ist schon ohne Softcore gelöst. :-)
Der Zynq ist ein "Dualcore-ARM mit FPGA drin".
Wenn du da den ARM nicht nutzt, ist er trotzdem da. Ich bin mir nur
gerade nicht sicher, ob man den FPGA auch komplett ohne ARM nutzen kann
(in unserem Projekt wurde der FPGA vom ARM-Linux aus konfiguriert).