Hallo,
für ein Paper an der Uni suche ich momentan nach Quellen bezüglich
rechenzeitoptimierter Programmierung des STM32. Da dieser ja eine FPU
besitzt bin ich mir nicht sicher, ob typisch Code-Optimierungen, wie das
Verwenden von Integer-Variablen im Gegensatz zu Float, Teilen durch
Potenzen von 2^n wirklich einen erheblichen Vorteil bringen.
Bisher bin ich nicht im Netz fündig geworden und wollte mal in die Runde
fragen, ob jemand eine Quelle zu dem Thema kennt. Bzw. an die STM32
Programmierer: Habt ihr irgendwelche eigenen Code-Regeln, um euren Code
so schlank wie möglich zu halten? Achja das nicht Verwenden der HAL sei
mal ausgeschlossen, es geht in erster Linie um arithmetische
Operationen.
Danke im Voraus :-)
blub schrieb:> Eine Division kostet 14 Zyklen, eine Multiplikation nur einen, also wäre> es schneller mit 0,5 zu multiplizieren
Danke für den PDF-Hinweis!
Dunno.. schrieb:> Was hindert dich denn, es auszuprobieren?>> Wäre das zu praxisnah?
Habe ich auch schon überlegt. Ich möchte einen PID Algorithmus so
effizient wie möglich umsetzen. Dazu gehören auch Sachen wie das
Einlesen des ADC etc. Zum Testen habe ich jetzt mal einen
PI-Regelalgorithmus geschrieben, der das Auswerten des ADC schon auf die
DMA übertragen hat. Durch setzen eines GPIO vor und nach dem Algorithmus
teste ich die Laufzeit. Der Algorithmus wird über einen Timer IRQ
periodisch aufgerufen. Momentan benötige ich ca. 10 µs, da ich zwar die
DMA das Auslesen des ADC überlasse aber ja trotzdem auf dessen
Ergebnisse warten muss. Wegen starker Ungenauigkeit am ADC ist außerdem
noch ein Software Oversampling eingefügt. Alles zusammen alles andere
als effizient also...
Jetzt stelle ich mir die Frage, wie ich also den algorithmus optimiere.
Aktuell siehts ja in etwa so aus:
ISR Start -> ( 10x (ADCStartConversion -> PollForDMAEndOfTransfer ->
addiere auf Summe) -> bilde Mittelwert -> Wandle ADC Wert in Regelgröße
-> bilde e -x -> yk = yk + Kp * ( e - e_alt) + Ki * e -> e_alt = e ->
Ende des Regelalgorithmus
blub schrieb:> Eine Division kostet 14 Zyklen, eine Multiplikation nur einen, also wäre> es schneller mit 0,5 zu multiplizieren
Weißt du, ob die Verwendung FPU standardmäßig im Compiler aktiviert ist?
RH schrieb:> ISR Start -> ( 10x (ADCStartConversion -> PollForDMAEndOfTransfer ->> addiere auf Summe) -> bilde Mittelwert -> Wandle ADC Wert in Regelgröße> -> bilde e -x -> yk = yk + Kp * ( e - e_alt) + Ki * e -> e_alt = e ->
Wenn irgendwo "Poll" vorkommt, ist die Effizienz sowas von im Arsch...
Du musst lernen, wie man nebenläufig programmiert. Sprich: Starte DMA,
sorge dafür, dass die am Ende einen Interrupt auslöst. Das war's für den
ersten Zyklus. Ab dem zweiten läuft es anders.
Getriggert wird er (und auch alle folgenden) durch das Auftreten des
DMA-fertig-Interupts. Er fängt dann allerdings erstmal genauso wieder an
wie der erste: Starte DMA, sorge dafür, dass die am Ende einen Interrupt
auslöst. Aber jetzt wird's anders als beim ersten Zyklus. Du
verarbeitest nämlich jetzt die Daten des ersten DMA-Laufs PARALLEL zu
dem DMA-Lauf des zweiten Zyklus.
Sprich: dein Regler läuft mit ADC-Samplerate/10. Und der Code zur
Verarbeitung kann bis zu dieser Grenze dauern, ohne dass sich daran
irgendwas ändert.
Sven B. schrieb:> Also moment, du hast eine ISR und holst dir da ADC Samples, pollst> aber in der ISR ob das DMA fertig ist? Was genau bringt dir jetzt das> DMA?
Das ist ja der Punkt des nicht optimierten Codes. Ich will ja einen
"schlechten" Code mit einem "guten" vergleichen.
Allerdings weiß ich nicht genau wie ich das Samplen des ADC optimieren
soll. Der I Anteil des PI-Reglers schreibt ja vor, dass ich zu immer
genau festgelegten Zeitpunkten (t = k * T, t ist ein um k vielfaches der
Abtastrate) die Spannung am ADC messe. Wenn ich den ADC wild messen
lasse und in die DMA schreibe, habe ich ja keine definierten
Abtastzeitpunkte. Außerdem muss ich ja wegen Rauschen am ADC den
Mittelwert, mehrerer direkt aufeinander folgenden Messungen bestimmen,
was ja auch nur durch die CPU berechnet werden kann. Ist es vielleicht
sinnvoller die ADC Werte der jeweils letzten Abtastperiode zu nehmen und
sagen wir 10 Werte von der DMA in ein Array schreiben zu lassen, woraus
dann durch eine For-Schleife am Anfang der Regler-ISR der Mittelwert
gebildet wird? so spart man sich immerhin die Sampling-Zeit und den
DMA-Transfer...
Ist das verständlich erklärt?
Die Verwendung der floating point unit im F4 setzt voraus, dass es im
Compiler aktiviert wird. Der kann nur floats (32 bit) und keine doubles
(64 bit). Beim F7 ist das anders.
Falls Du fp im Interrupt nutzen willst, musst Du sicherstellen, dass die
fp Register auch auf dem Stack gesichert werden, sonst passiert
Unvorhersehbares. Beim STM32 geht das über ein Prozessorregister. Alle
Irq Aufrufe gehen dann langsamer. Deshalb ist das standardmäßig nicht
der Fall.
Im allgemeinen ist die Verwendung von fp Befehlen deutlich schneller als
die Rechnung mit Integerrechnung mit int32_t. Nur bei 16 bit Precision
kann die Integerrechnung schneller sein.
c-hater schrieb:> Getriggert wird er (und auch alle folgenden) durch das Auftreten des> DMA-fertig-Interupts. Er fängt dann allerdings erstmal genauso wieder an> wie der erste: Starte DMA, sorge dafür, dass die am Ende einen Interrupt> auslöst. Aber jetzt wird's anders als beim ersten Zyklus. Du> verarbeitest nämlich jetzt die Daten des ersten DMA-Laufs PARALLEL zu> dem DMA-Lauf des zweiten Zyklus.
Ah, das ist natürlich ein wesentlich besserer Ansatz...
Stefan ⛄ F. schrieb:> Dann würde ich als erste mal auf Fließkomma-Artihmetik verzichten.
Das ist ja eben die Frage, ob es wirklich so ist.
Martin B. schrieb:> Im allgemeinen ist die Verwendung von fp Befehlen deutlich schneller als> die Rechnung mit Integerrechnung mit int32_t. Nur bei 16 bit Precision> kann die Integerrechnung schneller sein.
Martin B. schreibt ja genau das Gegenteil.
RH schrieb:> Weißt du, ob die Verwendung FPU standardmäßig im Compiler aktiviert ist?
Ich glaube, der arm-gcc Compiler nutzt die FPU, wenn folgende Parameter
gesetzt sind:
-mfpu=fpv4-sp-d16 -mfloat-abi=hard
Siehe https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
"The default depends on the specific target configuration." Was auch
immer das heißen soll.
RH schrieb:> Sven B. schrieb:>> Also moment, du hast eine ISR und holst dir da ADC Samples, pollst>> aber in der ISR ob das DMA fertig ist? Was genau bringt dir jetzt das>> DMA?>> Das ist ja der Punkt des nicht optimierten Codes.
Ok, sehe ich auch so, aber das hat halt genau überhaupt nichts mit der
Frage aus dem Eingangsposting zu tun ;)
Dein Problem ist also nicht irgendwelche Floating-Point vs
Integer-Performance, sondern dass die CPU busy-loopt während sie auf
Peripherie wartet.
Ansätze zur Lösung wurden ja schon formuliert.
Sven B. schrieb:> Ok, sehe ich auch so, aber das hat halt genau überhaupt nichts mit der> Frage aus dem Eingangsposting zu tun ;)> Dein Problem ist also nicht irgendwelche Floating-Point vs> Integer-Performance, sondern dass die CPU busy-loopt während sie auf> Peripherie wartet.
OK, stimmt. Allerdings geht eben auch um die Frage, ob der Regler mit
Floating-Points oder Integer-Variablen schneller ist. Ich denke
letztendlich werde ich es Montag mal einfach am Oszi durchs Togglen
eines GPIO testen und mal in den Compiler-Einstellungen der CubeIDE nach
Einstellungen der FPU suchen.
RH schrieb:> OK, stimmt. Allerdings geht eben auch um die Frage, ob der Regler mit> Floating-Points oder Integer-Variablen schneller ist.
Du hast das nicht richtig verstanden. Diese Sache spielt nur dann eine
Rolle, wenn die Verarbeitung länger dauert als Samplefrequenz/10. (Oder
wenn noch für andere Sachen Rechenleistung benötigt wird).
Solange die Rechnerei kürzer ist als die Periode von fs/10 und es keine
weiteren Aufgaben zu erledigen gibt, ist es scheißegal, wie lange sie
genau dauert. Der MCU ist es ziemlich Wurscht, ob sie hochwichtige
Rechenaufgaben löst oder in einer leeren Endlosschleife rumidelt...
Die Nutzung von Fließkomma-Artihmetik bringt auch die Notwendigkeit der
Konvertierung von und zu Integer mit sich. Dazu kommt, dass Interrupts
langsamer werden, weil zusätzlich zu den CPU Registern die FPU Register
gesichert werden.
Ich schätze, dass man letztendlich nur durch einen Vergleich in der
konkreten Anwendung zu einer belastbaren Aussage kommt.
Vorher müssen natürlich die Warteschleifen in Ordnung gebracht werden,
sonst vergleicht man faule Äpfel mit faulen Birnen.
Stefan ⛄ F. schrieb:> Ich glaube, der arm-gcc Compiler nutzt die FPU, wenn folgende Parameter> gesetzt sind:>> -mfpu=fpv4-sp-d16 -mfloat-abi=hard
Jo, so sollte das aussehen. Aber dann kommen die geforderten Libraries
(libm) und da legt z.B. TrueStudio immer noch einige Steine in den Weg.
Kompiliert es, umso besser, aber ich kämpfe z.B. mit Meldungen wie
'Kompiler benutzt 'vfp' Instruktionen, obwohl der MC sie nicht
unterstützt' und rummeckern, das er die ARM includes zwar findet, aber
nicht die Library.
RH schrieb:> OK, stimmt. Allerdings geht eben auch um die Frage, ob der Regler mit> Floating-Points oder Integer-Variablen schneller ist.
Das ist aber ein akademisches Philosophie-Spaßprojekt. Die
Ingenieurs-Frage ist, wie schnell muss es denn sein und wie erreicht man
das. Dazu muss man sich mit hoher Wahrscheinlichkeit erstmal mit dem
genannten Punkt befassen und dann nochmal messen.
An einer Stelle drei CPU-Zyklen wegzuoptimieren während an anderer
Stelle hunderttausende verschwendet werden ist schlicht vergeudete
Lebenszeit.
Sven B. schrieb:> An einer Stelle drei CPU-Zyklen wegzuoptimieren während an anderer> Stelle hunderttausende verschwendet werden ist schlicht vergeudete> Lebenszeit.
Ja, sehe ich auch so.
c-hater schrieb:> Solange die Rechnerei kürzer ist als die Periode von fs/10 und es keine> weiteren Aufgaben zu erledigen gibt, ist es scheißegal, wie lange sie> genau dauert. Der MCU ist es ziemlich Wurscht, ob sie hochwichtige> Rechenaufgaben löst oder in einer leeren Endlosschleife rumidelt...
Nicht in allen Fällen: Wenn es darauf ankommt den Energieverbrauch des
Prozessors zu verringern (z.B. wg. Batteriebetrieb), macht es oft Sinn
den Prozessor schnell fertigrechnen zu lassen, und dann statt einer
Endlosschleife einen energiesparenden Schlafmodus zu aktivieren.
Gut, zusammenfassend lässt sich also sagen, dass definitiv das
Hauptproblem das Warten auf die Speicherung der DMA Werte ist (was mir
ja auch bewusst war). Weil das Warten aber im Verhältnis zur
Floating-Point oder Integer Rechnung einen wesentlich größeren Einfluss
hat sollte dies erstmal soweit minimiert werden, dass egal wie eine
Rechenzeit des Algorithmus von fs/10 ermöglicht wird. Angenommen ich
Trigger die ADCConversion mit 50 KHz muss ich bei 10 vorgenommenen ADC
Messungen diese in ungefähr 1/5000 s = 0,2 ms "abgearbeitet" haben.
c-hater schrieb:> Solange die Rechnerei kürzer ist als die Periode von fs/10 und es keine> weiteren Aufgaben zu erledigen gibt, ist es scheißegal, wie lange sie> genau dauert. Der MCU ist es ziemlich Wurscht, ob sie hochwichtige> Rechenaufgaben löst oder in einer leeren Endlosschleife rumidelt...
Ja gut das stimmt, gerne würde ich neben dem Regel-Algorithmus dann
allerdings soviel Rechenleistung zur Verfügung haben wie es geht, daher
ja der Optimierungsgedanke.
Danke auf jeden Fall schon einmal bis jetzt für die Tipps!
c-hater schrieb:> Solange die Rechnerei kürzer ist als die Periode von fs/10 und es keine> weiteren Aufgaben zu erledigen gibt, ist es scheißegal, wie lange sie> genau dauert. Der MCU ist es ziemlich Wurscht, ob sie hochwichtige> Rechenaufgaben löst oder in einer leeren Endlosschleife rumidelt...
Genau.
Aber mal etwas anderes:
Habe erst jetzt bemerkt, dass es zu jedem Beitrag Bewertungen gibt
und möchte gerne wissen welcher schwachsinniger Idiot jeden aber auch
jeden Beitrag von c-hater negativ bewertet...
Selbst konstruktive Beiträge von ihm werden negativ bewertet.
Wie winzig muß der IQ von diesem gehirnlosem Insekt sein, um so etwas
dauernd zu machen?
Glaubt der Retard wirklich, seine idiotischen Minuse bedeuten irgend
jemandem etwas?
Das holen eines ADC-Wertes per DMA bringt genau Null Gummipunkte.
Floats in ISRs sind auf ARMen eine schlechte Idee.
Richtiger Ansatz:
Per Timer die CPU wecken.
Dann in der Main:
Den ADC-Wert aus dem vorhergehenden Zyklus mit dem Algorithmus
verwursten. Da kann dann auch gerne mit FLoats gerechnet werden.
Stellwert ausgeben.
ADC Wandlung anstossen.
Schlafen legen.
Goto Oben
Martin B. schrieb:> Beim F7 ist das anders.
Eine D-FPU gibts erst ab F76x und F77x.
Martin B. schrieb:> Falls Du fp im Interrupt nutzen willst, musst Du sicherstellen, dass die> fp Register auch auf dem Stack gesichert werden, sonst passiert> Unvorhersehbares. Beim STM32 geht das über ein Prozessorregister. Alle> Irq Aufrufe gehen dann langsamer. Deshalb ist das standardmäßig nicht> der Fall.
Dafür gibts in dem Register noch ein Bit.
Irgendwas mit Lazy Stacking.
Für die FP Register wird Platz auf dem STack reserviert, aber kopiert
wird erst wenn der IRQ die FPU nutzen will.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0298a/DAFGGBJD.html
Miss Ratgeber schrieb:> Das holen eines ADC-Wertes per DMA bringt genau Null Gummipunkte.
Er holt ja zehn und nicht nur einen.
> Floats in ISRs sind auf ARMen eine schlechte Idee.
Er muss ja nicht notwendigerweise in der ISR rechnen. Er kann wunderbar
auch die Parallelverarbeitung in main abhandeln. Das Entscheidende ist
die Parallelität.
> Per Timer die CPU wecken.
Wozu soll der Timer gut sein? Er hat doch eine ADC am Laufen, die mit
konstanter Samplerate arbeitet. Das ist genauso gut wie ein Timer.
Eigentlich sogar noch besser, denn es macht weder Sinn, schneller zu
regeln, als die Messwerte reinkommen, noch langsamer. Sprich: die Quelle
der Messwerte ist die bestgeeignete Instanz, um den Verarbeitungszyklus
zu kontrollieren.
Martin B. schrieb:> Im allgemeinen ist die Verwendung von fp Befehlen deutlich schneller als> die Rechnung mit Integerrechnung mit int32_t. Nur bei 16 bit Precision> kann die Integerrechnung schneller sein.
Da wäre ich jetzt mal vorsichtig:
- bei Verwendung der Gleitkommaeinheit gibt es noch Overhäd durch das
Load/Store der Werte in die FPU hinein/heraus
- der int32 MUL arbeitet auch in einem Takt, das Ergebnis liegt dann
schon in den CPU Registern
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/CHDDIGAC.html
- bei int16, int8 operationen muss man noch ein Overhead durch die
Vorzeichen Normalisierung beachten;
daher lieber mit int32 rechnen
Da float Werte nur eine Mantisse von 24bit haben, sollte man sich schon
überlegen, ob da nicht informationen verloren gehen ...
Im Fall der angesprochenen Analogwandlung ist das aber wohl alle egal.
Ich würde dem Compiler so früh wie möglich die floats vorwerfen.
Der optimiert dann schon. Das ist sein Job.
Grüße, Adib.
--
The A. schrieb:> Ich würde dem Compiler so früh wie möglich die floats vorwerfen.> Der optimiert dann schon. Das ist sein Job.
Das ist ein Punkt, der mich interessiert. Ich vertraue darauf, dass der
Compiler fast immer besser optimiert, als ich es manuell könnte. Zum
Beispiel ist es ja vollkommen selbstverständlich, dass eine Integer
Division durch 2,4,8,16,... in eine viel schnellere shift Operation
optimiert wird - sofern der Divisor konstant ist.
Wie ist das bei Fließkomma-Arithmetik? Optimiert der Compiler da auch so
vollständig, wie man das von Integer gewohnt ist, oder sind da
signifikante Einschränkungen bekannt?
Stefan ⛄ F. schrieb:> Was willst du eigentlich mit 50 tausend Messungen pro Sekunde regeln?>> Welches Ding kann so schnell auf Änderungen des Stellgliedes reagieren?
Im konkreten Fall handelt es sich um eine digitale Regelung eines
Buck-Converters. Die hohe Zahl der Messung ist nur nötig, da dass
Messsignal stark schwankt, bzw. der die Werte im ADC Register echt
relativ stark schwanken (+/- 100 Schritte bei 12Bit-Auflösung). Da ich
auf die schnelle keinen passenden RC-Filter hatte hab ichs halt mit
Oversampling und MIttelwert-Bilden versucht.
Der eigentliche Regler regelt ja jetzt oben im Beispiel nur alle 10
Abtastperioden -> sprich bei 50 KHz Abtastrate mit 5 KHz was für eine
Spannungsregelung doch okay sein sollte oder?
RH schrieb:> Im konkreten Fall handelt es sich um eine digitale> Regelung eines Buck-Converters.
Nur so als keiner Hinweis: An der Idee sind hier schon viele
gescheitert. Die Regelung überlässt man speziellen IC's die dafür
gemacht sind. Mikrocontroller sind dafür im Allgemeinen die falsche
Wahl.
Was du aber gerne machen kannst: Mit einem Mikrocontroller die
Referenzspannung (Sollwert) erzeugen, und dann mit einem herkömmlichen
Schaltregler die Ausgangsspannung daran angleichen.
Stefan ⛄ F. schrieb:> Nur so als keiner Hinweis: An der Idee sind hier schon viele> gescheitert. Die Regelung überlässt man speziellen IC's die dafür> gemacht sind. Mikrocontroller sind dafür im Allgemeinen die falsche> Wahl.
Sag das meiner Lüftersteuerung in meiner E-Last ;)
Stefan ⛄ F. schrieb:> Das ist ein Punkt, der mich interessiert. Ich vertraue darauf, dass der> Compiler fast immer besser optimiert, als ich es manuell könnte. Zum> Beispiel ist es ja vollkommen selbstverständlich, dass eine Integer> Division durch 2,4,8,16,... in eine viel schnellere shift Operation> optimiert wird - sofern der Divisor konstant ist.
vollkommen selbstverständlich - Hausaufgaben nicht richtig gemacht.
Wenn Du das Cortex M3 Manual schon mal studiert hättest, wüsstest Du,
dass ein MUL genausoviele Prozessor-Zyklen braucht wie ein LSL (nämlich
einen).
Es ist also völlig wurscht, ob multiply oder shift.
Markus F. schrieb:> Wenn Du das Cortex M3 Manual schon mal studiert hättest, wüsstest Du,> dass ein MUL genausoviele Prozessor-Zyklen braucht wie ein LSL (nämlich> einen).
Danke für die Erklärung.
Ich habe das Cortex M3 Manual bisher nur überflogen, sollte ich mal
richtig lesen.
Ich kenne mich mit älteren Controllern besser aus, wo Multiplikationen
und Divisionen in Software-Routinen implementiert werden müssen.
Bezüglich der Division hast Du recht, die braucht 2 Zyklen.
Bei den Dingern ist es aber jedenfalls besser, das Optimieren dem
Compiler zu überlassen und sich - wenn's auf Geschwindigkeit ankommt -
auf schnelle Algorithmen zu konzentrieren.
Stefan ⛄ F. schrieb:> Nur so als keiner Hinweis: An der Idee sind hier schon viele> gescheitert. Die Regelung überlässt man speziellen IC's die dafür> gemacht sind. Mikrocontroller sind dafür im Allgemeinen die falsche> Wahl.
Klar gibt es ICs die es wahrscheinlich besser können aber grundsätzlich
funktioniert die Regelung auf dem µC gut! Im Anhang ist die
Sprungantwort beim Einschalten des Wandlers zu sehen. Generell lässt
sich die Spannung Regeln. Eine Regelung des Stroms ist sogar auch bis zu
einem gewissen Grad möglich.
Markus F. schrieb:> Wenn Du das Cortex M3 Manual schon mal studiert hättest, wüsstest Du,> dass ein MUL genausoviele Prozessor-Zyklen braucht wie ein LSL (nämlich> einen).
Also verstehe ich das so richtig, dass bei modernen ARM CPUs im Prinzip
relativ wurscht ist, ob Integers Addiere oder Subtrahiere? Ich sollte
drauf achten nicht zu dividieren und Floats lassen sich genauso schnell
berechnen allerdings ist standardmäßig die FPU nicht in ISR verwendbar.
Ein Aktivieren der FPU in Interrupts, würde diese allgemein etwas
langsamer machen, da die FPU Register jeweils mit gesichert werden
müssen..
es gibt auch µC die das in HW erledigen, so ein winziger LPC810 wurde
mal in einem make Projekt für eine Taschenlampe benutzt. Der LPC810 hat
nicht mal einen kompletten AD Wandler, nur einen Komparator, aber der
reicht schon in Verbindung mit dem State Controlable Timer SCT für so
eine Aufgabe. Auch wenn das Programm Blödsinn macht läuft die Regelung
weiter.
Ist natürlich nur das Wort zum Sonntag wenn man einen anderen µC hat :)
FP in Hardware haben so gut wie alle Cortex-M4, werden zwar auch gerne
M4F genannt aber ich kenne keinen M4 ohne HW FP.
In einer Schrittmotoransteuerung mit F407 @168 MHz habe ich mit einem
OnePulse Timer einen Interrupt ausgelöst und in der ISR Portpin für
Schrittmotor Takt auf 1 und 0 gesetzt und dazwischen die Zeit für den
nächsten Puls berechnet. Mit linearer Interpolation in FP. Das war
trotzdem so schnell das ich für die 1,x µs min. Pulsdauer noch eine
Verzögerungsschleife einbauen musste.
Johannes S. schrieb:> In einer Schrittmotoransteuerung mit F407 @168 MHz habe ich mit einem> OnePulse Timer einen Interrupt ausgelöst und in der ISR Portpin für> Schrittmotor Takt auf 1 und 0 gesetzt und dazwischen die Zeit für den> nächsten Puls berechnet. Mit linearer Interpolation in FP. Das war> trotzdem so schnell das ich für die 1,x µs min. Pulsdauer noch eine> Verzögerungsschleife einbauen musste.
Ui, aber wofür benötigst du die Schleife? Würde der µC nicht einfach in
die Main-Schleife zurückspringen?
Johannes S. schrieb:> es gibt auch µC die das in HW erledigen, so ein winziger LPC810 wurde> mal in einem make Projekt für eine Taschenlampe benutzt. Der LPC810 hat> nicht mal einen kompletten AD Wandler, nur einen Komparator, aber der> reicht schon in Verbindung mit dem State Controlable Timer SCT für so> eine Aufgabe. Auch wenn das Programm Blödsinn macht läuft die Regelung> weiter.
Alternativen gibts immer! :-)
In dem Projekt soll neben der Regelung noch im Main-Loop eventuell Daten
gesendet und empfangen werden, daher auch der "fette" µC für die
einfache Regelaufgabe. Damit der µC nicht die ganze Zeit mit den ISR der
Regelung und ADC-Auswertung beschäftigt ist, soll die CPU da eben so
wenig wie möglich zu Tun bekommen.
RH schrieb:> i, aber wofür benötigst du die Schleife? Würde der µC nicht einfach in> die Main-Schleife zurückspringen?
Der Takteingang möchte auf 1 und nach 1,x µs wieder auf 0 gesetzt
werden, das hatte ich eben einfach in der ISR gemacht.
Das geht natürlich schöner auch in HW mit dem Compare, dann müssen aber
auch die passen GPIO frei sein.
Ging ja auch nur darum das der µC 'zu schnell' ist, selbst mit früher
bösen FP Berechnungen in der ISR.
Das die FP Register dann zusätzlich gesichert werden müssen ist dann
evtl. zu berücksichtigen, aber wie gesagt, der F4 ist so
rattenschnell...
RH schrieb:> Damit der µC nicht die ganze Zeit mit den ISR der> Regelung und ADC-Auswertung beschäftigt ist, soll die CPU da eben so> wenig wie möglich zu Tun bekommen.
Mein Gott, so ein PID-Regler besteht im Kern aus lächerlichen drei
Multiplikationen und zwei Additionen. Das sollte ein Teil wie der STM32
doch wohl locker in einem Zeitfenster von 200µs leisten können und zwar
so, dass von dem Zeitfenster immer noch fast die gesamten 200µs über
bleiben...
Das wäre ja selbst mit einem AVR8@16MHz noch absolut kein Problem. OK,
der würde natürlich schon einen merklichen Teil des Zeitfensters
benötigen, aber auf jeden Fall nicht annähernd so viel, dass es kritisch
werden würde.
Falls doch, dann ist das ein deutliches Zeichen, dass der Algorithmus
suboptimal umgesetzt ist. Merkt man übrigens auch daran, dass halt mehr
als drei Multiplikationen und zwei Additionen darin vorkommen (Die
"Unwind"-Mimik für den I-Zweig sei mal außen vor).
c-hater schrieb:> Falls doch, dann ist das ein deutliches Zeichen, dass der Algorithmus> suboptimal umgesetzt ist. Merkt man übrigens auch daran, dass halt mehr> als drei Multiplikationen und zwei Additionen darin vorkommen (Die> "Unwind"-Mimik für den I-Zweig sei mal außen vor).
Ja, das Hauptproblem beim Anfangsbeispiel lag ja auch definitiv beim
Polling der ADC-DMA-Übertragung. Der PI sieht ja nur wie im Anhang zu
sehen ist aus.
Im Regelalgorithmus befinden sich allerdings noch weitere Überprüfungen
dazu, ob zwischen Strombegrenzung oder Spannungsbegrenzung gewechselt
werden muss etc. etc.. das möchte ich alles so effizient wie möglich
machen. Dazu kommt halt das Software Oversampling der ADCs. Bin bei
weitem kein Experte oder erfahrener STM32-Programmierer deswegen, war
halt die Frage, wie man manche Sachen am besten umsetzt. Bisher wurde
mir ja auch super geholfen!
RH schrieb:> Im konkreten Fall handelt es sich um eine digitale Regelung eines> Buck-Converters.
[...]
> Der eigentliche Regler regelt ja jetzt oben im Beispiel nur alle 10> Abtastperioden -> sprich bei 50 KHz Abtastrate mit 5 KHz was für eine> Spannungsregelung doch okay sein sollte oder?
Wie sieht es im Kurzschlussfall aus? Wenn Du den Strommesswert nur mit 5
kHz auswertest, erscheint mir das etwas zu langsam um den FET überleben
zu lassen. Oder hast Du dafür noch einen schnellen Komparator im
Einsatz?
Wie sieht es mit starken Lastschwankungen aus? Also wenn Du das Ding auf
Volllast betreibst und dann die Last schlagartig entfernst (z.B.
Kabelbruch) , um wieviel schießt die Spannung über den Sollwert?
Überlebt das der Rest Deiner Schaltung oder, falls die Last aus mehreren
Modulen besteht, diese anderen Module?
Gerd E. schrieb:> RH schrieb:>> Im konkreten Fall handelt es sich um eine digitale Regelung eines>> Buck-Converters.> [...]>> Der eigentliche Regler regelt ja jetzt oben im Beispiel nur alle 10>> Abtastperioden -> sprich bei 50 KHz Abtastrate mit 5 KHz was für eine>> Spannungsregelung doch okay sein sollte oder?>> Wie sieht es im Kurzschlussfall aus? Wenn Du den Strommesswert nur mit 5> kHz auswertest, erscheint mir das etwas zu langsam um den FET überleben> zu lassen. Oder hast Du dafür noch einen schnellen Komparator im> Einsatz?>> Wie sieht es mit starken Lastschwankungen aus? Also wenn Du das Ding auf> Volllast betreibst und dann die Last schlagartig entfernst (z.B.> Kabelbruch) , um wieviel schießt die Spannung über den Sollwert?> Überlebt das der Rest Deiner Schaltung oder, falls die Last aus mehreren> Modulen besteht, diese anderen Module?
@RH:
Das, was Gerd da schreibt, hat Hand und Fuss. Darauf solltest du dich
konzentrieren, statt auf endlose Erwägungen, ob der eigentliche Regler
nun in 0,5µs oder in 0,2µ fertig ist, wenn er 200µs Zeit hat für seinen
Job...
Gerd E. schrieb:> Wie sieht es im Kurzschlussfall aus? Wenn Du den Strommesswert nur mit 5> kHz auswertest, erscheint mir das etwas zu langsam um den FET überleben> zu lassen. Oder hast Du dafür noch einen schnellen Komparator im> Einsatz?
Im Kurzschlussfall löst ein Analog Watchdog IRQ aus. Die ADC Werte des
Stroms werden ja mit 50 KHz gesampled. Allerdings hatte ich das bisher
nur experimentell ausprobiert und mir dabei einen MOSFET zerschossen,
obwohl ja eigentlich blitzschnell der IR auslösen sollte...
Gerd E. schrieb:> Wie sieht es mit starken Lastschwankungen aus? Also wenn Du das Ding auf> Volllast betreibst und dann die Last schlagartig entfernst (z.B.> Kabelbruch) , um wieviel schießt die Spannung über den Sollwert?> Überlebt das der Rest Deiner Schaltung oder, falls die Last aus mehreren> Modulen besteht, diese anderen Module?
Da es sich um einen Abwärtswandler mit 50V Eingangsspannung handelt sind
alle Leistungskomponenten für ca. 80 - 100V ausgelegt. Wie es am Ausgang
aussieht wenn unter Volllast die Last entfernt wird habe ich noch nicht
geschaut aber mehr als 50V können ja nicht rauskommen. Fraglich ist wie
hoch die Spannung ansteigt bei z.B. 12V am Ausgang. Ich meine aber das
sah alles im Grünen Bereich aus. Ich wollte dazu aber morgen eh
Messungen machen! :-)
RH schrieb:> Allerdings hatte ich das bisher> nur experimentell ausprobiert und mir dabei einen MOSFET zerschossen,> obwohl ja eigentlich blitzschnell der IR auslösen sollte...
Hattest du da in einer anderen gleich oder höher priorisierten ISR eine
Warteschleife?
Vielleicht testest du besser mit einem erhöhten Strom, den der MOSFET
wenigstens für ein paar Sekunden aushält. An seine Leistungsgrenzen kann
man dann später gehen, wenn die Software fertig ist.
RH schrieb:> Fraglich ist wie> hoch die Spannung ansteigt bei z.B. 12V am Ausgang.
(Taschen-)Lampen mit PWM Dimmern sind ein schöner Härtetest, der dennoch
nicht allzu weit her geholt ist.
Stefan ⛄ F. schrieb:> Hattest du da in einer anderen gleich oder höher priorisierten ISR eine> Warteschleife?>> Vielleicht testest du besser mit einem erhöhten Strom, den der MOSFET> wenigstens für ein paar Sekunden aushält. An seine Leistungsgrenzen kann> man dann später gehen, wenn die Software fertig ist.
Dass es doof war direkt an die Grenzen zu gehen, ist mir im Nachhinein
auch aufgefallen. Das Notausschalten funktionierte auch erstmal aber
einmal dann eben nicht.
Ich habe mich noch nicht mit den IR Prioritäten des STM32
außeinandergesetzt. Ich kann mir vorstellen, dass beim Fehlerfall der
Watchdog IR den Ausgang auf Null gesetzt hat und der Regler im Anschluss
direkt wieder ein. Der Watchdog IR setzte nur den Pulse auf 0. Besser
wäre es wohl eventuell direkt auch den Timer danach zu stoppen.
Stefan ⛄ F. schrieb:> (Taschen-)Lampen mit PWM Dimmern sind ein schöner Härtetest, der dennoch> nicht allzu weit her geholt ist.
da Glätte ich die zerstückelte Spannung um sie mir direkt wieder
zerstückeln zu lassen :D Aber klar zum Testen der Reglereigenschaften
bestimmt ziemlich gut. An und für sich sollte der Ausgangselko ja auch
starke Lastschwankungen etwas abschwächen. Werde ich bei Gelegenheit mal
testen. Ich glaube die Elektronische Last die ich zum Testen habe, kann
auch Schwankende Lasten simulieren..
Hab nachgeschaut sinus-, trapez- und rechteckförmige Verläufe sind
einstellbar.
RH schrieb:> Im Kurzschlussfall löst ein Analog Watchdog IRQ aus. Die ADC Werte des> Stroms werden ja mit 50 KHz gesampled. Allerdings hatte ich das bisher> nur experimentell ausprobiert und mir dabei einen MOSFET zerschossen,> obwohl ja eigentlich blitzschnell der IR auslösen sollte...
das deckt sich voll mit meiner Erfahrung, das ist so zu langsam.
Ich würde das nicht mal mit einem ADC machen, sondern einen extra
Komparator für verwenden. Bei den STM32, die einen integrierten
Komparator haben, kann man den extra so konfigureren, dass er einen von
den PWM-Kanälen hardwaremäßig ausschaltet. Das ist für genau diesen Fall
gedacht und ich empfehle das auch so zu machen.
Wenn nicht mit dem internen Komparator, dann mit einem externen und
einem Logikgatter zwischen PWM-Ausgang des Controllers und dem Gate des
FET.
> Da es sich um einen Abwärtswandler mit 50V Eingangsspannung handelt sind> alle Leistungskomponenten für ca. 80 - 100V ausgelegt.
Damit meinst Du doch alles vor dem Abwärtswandler und den Abwärtswandler
selbst, nicht aber die Teile am Ausgang des Abwärtswandlers, oder?
> Wie es am Ausgang> aussieht wenn unter Volllast die Last entfernt wird habe ich noch nicht> geschaut aber mehr als 50V können ja nicht rauskommen. Fraglich ist wie> hoch die Spannung ansteigt bei z.B. 12V am Ausgang.
Genau. Stell mal 12V ein und ziehe den maximal möglichen Strom den Dein
Buck hergibt mit einer Dummy-Load. Dann die Last schlagartig
ausschalten/trennen und dabei die Spannung am Ausgang des Buck auf dem
Oszi beobachten.
Mehr als 50V werden es nicht werden, aber bei 5 kHz Regelschleife
vermute ich daß es deutlich mehr als 12 sein werden.
Wenn Du am Ausgang jetzt z.B. 2 Geräte parallel angeschlossen hast, das
eine zieht viel Strom, das andere nur wenig, und jetzt trennst Du den
Stromfresser, dann kann es das andere Modul grillen weil es mehr als die
gewünschten 12 V bekommt.
> Ich wollte dazu aber morgen eh> Messungen machen! :-)
Das empfehle ich.
Gerd E. schrieb:> Ich würde das nicht mal mit einem ADC machen, sondern einen extra> Komparator für verwenden. Bei den STM32, die einen integrierten> Komparator haben, kann man den extra so konfigureren, dass er einen von> den PWM-Kanälen hardwaremäßig ausschaltet. Das ist für genau diesen Fall> gedacht und ich empfehle das auch so zu machen.
Hm... ich muss mal nachschauen ich glaube mein verwendetes NUCLEO-F429ZI
Board hat solche Komparatoren nicht... Ich bin davon ausgegangen per
Watchdog und IR würde es reichen. Ist ja dann auch die Frage wie schnell
der Stromsensor ist. Verbaut ist ein ACS723.
Gerd E. schrieb:> Damit meinst Du doch alles vor dem Abwärtswandler und den Abwärtswandler> selbst, nicht aber die Teile am Ausgang des Abwärtswandlers, oder?
Ja genau, die Lasten am Ausgang werden ganz unterschiedlich sein.
Gerd E. schrieb:> Das empfehle ich.
Werde ich tun und hier reinposten..
Gerd E. schrieb:> Ich würde das nicht mal mit einem ADC machen, sondern einen extra> Komparator für verwenden. Bei den STM32, die einen integrierten> Komparator haben, kann man den extra so konfigureren, dass er einen von> den PWM-Kanälen hardwaremäßig ausschaltet. Das ist für genau diesen Fall> gedacht und ich empfehle das auch so zu machen.>> Wenn nicht mit dem internen Komparator, dann mit einem externen und> einem Logikgatter zwischen PWM-Ausgang des Controllers und dem Gate des> FET.
Ich könnte ja den Strom auch im Continous Conversion Mode auf einem
weiteren ADC mit maximaler Samplerate rattern lassen und dort mit einem
Analog Watchdog überwachen... dann sollte ich ja wirklich schnelle
Reaktionszeiten. Eine andere Lösung fällt mir für den STM32F4 nicht ein.
Analog Komparatoren haben meine ich nur die STM32F3x und manche STM32Lx.
RH schrieb:> Analog Komparatoren haben meine ich nur die STM32F3x und manche STM32Lx.
Und fast jeder verschissene AVR8, manche davon haben sogar mehrere...
c-hater schrieb:> Und fast jeder verschissene AVR8, manche davon haben sogar mehrere...
Meine sind nicht verschissen, sondern schön sauber. Was stellst du mit
den teilen an, und was hat das mit diesem Thread zu tun? Bist du heute
Abend wieder auf Mission?
Stefan ⛄ F. schrieb:> c-hater schrieb:>> Und fast jeder verschissene AVR8, manche davon haben sogar mehrere...>> Meine sind nicht verschissen, sondern schön sauber. Was stellst du mit> den teilen an, und was hat das mit diesem Thread zu tun? Bist du heute> Abend wieder auf Mission?
Die Abkürzung, die er nicht versteht, hat sich über seine Sammlung
verteilt.
;-)
RH schrieb:> Ich könnte ja den Strom auch im Continous Conversion Mode auf einem> weiteren ADC mit maximaler Samplerate rattern lassen und dort mit einem> Analog Watchdog überwachen...
Musst Du ausprobieren ob das in allen Fällen schnell genug ist. Ich
vermute wenn Du mit Deiner PWM einen Duty-Cycle nahe dem Maximum fährst,
ist das Risiko für ein Sterben des FETs am Größten. Diesen Fall würde
ich genauer austesten. Geh aber schon mal einen Eimer FETs kaufen...
> Eine andere Lösung fällt mir für den STM32F4 nicht ein.> Analog Komparatoren haben meine ich nur die STM32F3x und manche STM32Lx.
Dein F429 hat ein der Tat keine integrierten Komparatoren.
Verwendest Du einen der Advanced-control timers TIM1 oder TIM8 für Deine
PWM? Die haben einen TIMx_BKIN. Da kannst Du einen externen Komparator
anschließen und die PWM dann bei Erreichen des Maximalstroms auf
Hardwareebene abschalten lassen.
Dein ACS723 Stromsensor scheint nur 80kHz Bandbreite zu haben. Das
könnte in der Tat eng werden.
Was Du eigentlich bei so einem Projekt willst, ist Cycle-by-Cycle
Current Limiting. Also Du gibst einen maximalen Stromwert vor (z.B. per
DAC), und der Regler kann direkt innerhalb des PWM-Taktes abschalten
wenn dieser Stromwert erreicht wurde. Das hilft nicht nur für den Fall
des Kurzschlusses, sondern erlaubt auch auf Stromregelung (statt
Spannungsregelung) umzustellen.
RH schrieb:> Hm... ich muss mal nachschauen ich glaube mein verwendetes NUCLEO-F429ZI> Board hat solche Komparatoren nicht...
Lies mal das Kapitel über den ADC Watchdog im F4 Reference Manual.
Könnte sein, das du genau das suchst.