Forum: Mikrocontroller und Digitale Elektronik PI-Regler in C macht was er will


von Alexander N. (remex_y)


Angehängte Dateien:

Lesenswert?

Hi

Ich baue aktuell einen Stromrichter für meine Diplomarbeit und 
programmiere dafür in C einen Pi-Regler. Nur jedes Mal, wenn ich den 
Code durchlaufen lasse, bekomme ich andere Ergebnisse. Ich habe die 
Vermutung das die FPU auf meinen Laptop (i7-12900) irgendwelch 0 
Division Fehler hat, aber weil die Fehler nur teilweise auftreten, bin 
ich ratlos. Ich habe im Anhang meine Main Datei und meine eigene Libary 
für den Regler.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander N. schrieb:
> Nur jedes Mal, wenn ich den Code durchlaufen lasse, bekomme ich andere
> Ergebnisse.
Dort kommt immer das Selbe raus:
- https://onlinegdb.com/5eVay_X2M
1
0.900000 
2
0.890820 
3
0.891743 
4
0.891454 
5
0.891311 
6
0.891150 
7
0.890991 
8
:
9
:
10
0.877411 
11
0.877255 
12
0.877098 
13
0.876941 
14
0.876785 
15
0.876628 
16
0.876472 
17
0.876315 
18
19
20
...Program finished with exit code 0
21
Press ENTER to exit console.

: Bearbeitet durch Moderator
von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

> Ich habe die Vermutung das die FPU auf meinen Laptop (i7-12900)
> irgendwelch 0 Division Fehler hat
Der Anfang einer jeden Katastrophe ist eine beschissene Vermutung.

Division durch Null schmeißt üblicherweise mit Laufzeitfehlern um sich, 
das müsstest Du merken. Fehlerhafte x86 CPUs sind mir jedenfalls nicht 
bekannt, etwas in der Richtung gab's zuletzt beim ersten Pentium 
(FDIV-Bug) und Du dürftest zu jung dafür sein, um auf einem solchen 
System gearbeitet zu haben.

von Alexander N. (remex_y)


Lesenswert?

Hi

Danke für deine schnelle Antwort. Ich arbeite in Clion und dort bekomme 
ich manchmal das gleiche Ergebnis wie die Webseite und manchmal 
irgendwelche absurde Ergebnisse wie z.B.:
1
0.900000 
2
-1809807.250000 
3
-1592626.500000 
4
-1618685.000000 
5
-1615554.750000 
6
-1615927.250000 
7
-1615879.250000 
8
-1615881.875000 
9
-1615878.375000 
10
-1615875.625000 
11
-1615872.750000 
12
-1615869.875000 
13
-1615867.000000
oder :
1
-62465235553878016.000000
2
-62344431008743424.000000
3
-62358810559250432.000000
4
-62356959428345856.000000
5
-62357058212593664.000000
6
-62356920773640192.000000
7
-62356817694425088.000000
8
-62356706025275392.000000
9
-62356590061158400.000000
10
-62356486981943296.000000
11
-62356371017826304.000000
12
-62356259348676608.000000
13
-62356147679526912.000000
14
-62356040305344512.000000
15
-62355928636194816.000000
16
-62355821262012416.000000
Ich habe keinen Plan, warum es nicht funktioniert.

[Mod: bitte das nächste Mal die pre-Tags selber einfügen]

: Bearbeitet durch Moderator
von Alexander N. (remex_y)


Lesenswert?

Ben B. schrieb:
>> Ich habe die Vermutung das die FPU auf meinen Laptop (i7-12900)
>> irgendwelch 0 Division Fehler hat
> Der Anfang einer jeden Katastrophe ist eine beschissene Vermutung.
>
> Division durch Null schmeißt üblicherweise mit Laufzeitfehlern um sich,
> das müsstest Du merken. Fehlerhafte x86 CPUs sind mir jedenfalls nicht
> bekannt, etwas in der Richtung gab's zuletzt beim ersten Pentium
> (FDIV-Bug) und Du dürftest zu jung dafür sein, um auf einem solchen
> System gearbeitet zu haben.

Ich bin aktuell erst 18 Jahre alt und noch eher unerfahren mit C oder 
allgemein Microcontroller Programmierung.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alexander N. schrieb:
> Ich arbeite in Clion
Das ist nur eine IDE. Welchen Compiler verwendest du?

von Rolf M. (rmagnus)


Lesenswert?

Du initialisierst bei deinen Objekten das Member val nicht. Damit steht 
da zu Beginn irgendwas drin. Das ist insbesondere für deinen Integrator 
ein Problem. Füge mal in config_Integrator ein:
1
    data->val = 0;

: Bearbeitet durch User
von Dieter S. (ds1)


Lesenswert?

Unabhängig von den bereits geposteten Antworten: Die einzige Division 
die ich auf die schnelle in dem Code siehe ist die hier:
1
        x=PI_Glied1.val/5.0f+0.001f;

von Alexander N. (remex_y)


Lesenswert?

Lothar M. schrieb:
> Alexander N. schrieb:
>> Ich arbeite in Clion
> Das ist nur eine IDE. Welchen Compiler verwendest du?

Es müsste gcc sein

von Alexander N. (remex_y)


Lesenswert?

Rolf M. schrieb:
> Du initialisierst bei deinen Objekten das Member val nicht. Damit steht
> da zu Beginn irgendwas drin. Das ist insbesondere für deinen Integrator
> ein Problem. Füge mal in config_Integrator ein:
>
1
>     data->val = 0;
2
>

Vielen Dank!!! Das war der Fehler.

Danke auch an alle die mir helfen wollten

von Vanye R. (vanye_rijan)


Lesenswert?

> Danke auch an alle die mir helfen wollten

Eine Hilfe sollte eigentlich darin bestehen dich zu ermutigen
den Debugger zu nutzen. Einmal im Singlestep durch deinen
Code und dabei die Variablen auf Unterschiede zwischen
Glauben und Sein abgeklopft und du waerst von selber darauf gekommen.

Vanye

von Klaus (feelfree)


Lesenswert?

Vanye R. schrieb:
> Eine Hilfe sollte eigentlich darin bestehen dich zu ermutigen
> den Debugger zu nutzen.

Und der findet nicht initialisierte Variablen? Ich ziehe sogar die 
Möglichkeit in Betracht, dass sich der Fehler im Debugger überhaupt nie 
zeigt.

von Roland F. (rhf)


Lesenswert?

Vanye R. schrieb:
> ...und du waerst von selber darauf gekommen.

Wenn von jedem erwartet würde das er so lange sucht bis er seine Fehler 
selber findet, würden wir alle noch Mammuts jagen und Beeren sammeln.
So hat Rolf einem Anfänger unter die Arme gegriffen und Alexander hat 
gelernt das die Verwendung uninitialisierter Variablen keine gute Idee 
ist.

rhf

P.S.
Müsste nicht eigentlich der Compiler eine entsprechende Warnung 
ausgeben?

von Klaus (feelfree)


Lesenswert?

Vanye R. schrieb:
> Einmal im Singlestep durch deinen Code

Bitte vormachen. Und mitzählen, beim wievielten Versuch die nicht 
initialisierte Variable tatsächllich einen Wert ungleich null hatte.

von Alexander N. (remex_y)


Lesenswert?

> P.S.
> Müsste nicht eigentlich der Compiler eine entsprechende Warnung
> ausgeben?

Nein Leider mein Compiler hat geschrieben mein code sei Fehler und 
Warnungsfrei. Normalerweise meckert der bei allem.

Danke für die Ermutigung vor allen Ich denke diesen Fehler hätte ich im 
Debugger nie gefunden.

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Hihi, wegen sowas verwenden fast alle meine 
Nicht-Interpretersprachen-Programme eine Art Backup-Lösung: der 
komplette für Variablen reservierte Speicher wird beim Start mit 0x00 
überschrieben. Falls man dann sowas mal vergisst, hat man einen 
doppelten Boden. Das mache ich sogar bei µCs, auf denen größere 
Programme laufen sollen, beim Start oder Reset wird das komplette RAM 
gelöscht.

: Bearbeitet durch User
von Rainer W. (rawi)


Lesenswert?

Alexander N. schrieb:
> Ich habe die Vermutung das die FPU auf meinen Laptop (i7-12900)
> irgendwelch 0 Division Fehler hat, aber weil die Fehler nur teilweise
> auftreten, bin ich ratlos.

Eine Division durch 0 funktioniert nun mal nicht. Stark schwankende 
Ergebnisse entstehen bei schlecht konditionierten Algorithmen, die dann 
sehr empfindlich auf Rauschen reagieren. Finde also die Stelle im Code, 
wo der Mist passiert. Eine Vermutung kann allenfalls der Ausgangspunkt 
für die Fehlersuche sein und wird sich dann bestätigen oder auch nicht.

von Klaus (feelfree)


Lesenswert?

Rainer W. schrieb:
> Finde also die Stelle im Code

In welcher Zeitzone lebst Du denn?

von Roland F. (rhf)


Lesenswert?

Hallo,
Alexander N. schrieb:
> Nein Leider mein Compiler hat geschrieben mein code sei Fehler und
> Warnungsfrei. Normalerweise meckert der bei allem.

Ich habe es gerade mal ausprobiert, wenn beim GCC -Wall eingeschaltet 
ist gibt er bei einer uninitialisierten Variablen (in diesem Fall 'a')

"warning: 'a' is used uninitialized in this function [-Wuninitialized]"

aus.

rhf

: Bearbeitet durch User
von Luca E. (derlucae98)


Lesenswert?

Alexander N. schrieb:
> Ich bin aktuell erst 18 Jahre alt

Diplomarbeit mit 18?

von Klaus (feelfree)


Lesenswert?

Roland F. schrieb:
> (in diesem Fall 'a')

probiere es doch mit dem geposteten code aus. Vielleicht ist dein gcc ja 
schlauer als meiner und der des TEs.

von Dieter S. (ds1)


Lesenswert?

Tools um nicht initialisierte Variablen zur Laufzeit zu erkennen gibt es 
schon sehr lange, wenn auch nicht unbedingt kostenlos. Unter Windows war 
das z.B. BoundsChecker (schon fast 30 Jahre her). Der hat sich in die 
Microsoft C++ IDE eingeklingt und den erzeugten Code modifiziert. Da 
wurde dann z.B. der Speicher mit speziellen Werten initialisiert und bei 
einem Zugriff auf so einen Wert eine Warnung ausgegeben (inklusive der 
dazu gehörigen Source Code Zeile).

Ähnliche Funktionalität gab es für die Speicherverwaltung (z.B. malloc - 
free).

von Roland F. (rhf)


Lesenswert?

Hallo,
Klaus schrieb:
> probiere es doch mit dem geposteten code aus. Vielleicht ist dein gcc ja
> schlauer als meiner und der des TEs.

Nein, ist er nicht. Du hast recht, auch bei mir wird nicht gewarnt, 
interessant.

rhf

von 900ss (900ss)


Lesenswert?

Roland F. schrieb:
> "warning: 'a' is used uninitialized in this function [-Wuninitialized]"

Soweit ich mich richtig erinnere, macht GCC den Check nur wenn auch der 
Optimierer eingeschaltet ist. Sonst nicht.

von Stefan F. (Gast)


Lesenswert?

Die Option -Wall sollte man nach Möglichkeit immer benutzen und auch 
alle monierten Stellen in Ordnung bringen.

Ich empfehle die QtCreator IDE, die erkennt viele potentielle Fehler 
schon vor dem Compilieren.

von Alexander N. (remex_y)


Lesenswert?

Luca E. schrieb:
> Alexander N. schrieb:
>> Ich bin aktuell erst 18 Jahre alt
>
> Diplomarbeit mit 18?

In Österreich gibt es Schulen, die gehen von der 9. bis zur 13. 
Schulstufe das nennt sich HTL. Dort gibt es Zweige wie Maschinenbau oder 
Elektrotechnik. Ich mache aktuell Elektrotechnik und wenn man diese 
Abschließen will, muss man die Matura(Abitur in Deutschland) machen. Und 
zur Matura gehört eine Diplomarbeit dazu. Ich will mit einen 
Klassenkollegen gemeinsam einen Stromrichter für einen PMSM Elektromotor 
bauen und dafür habe ich diesen Regler benötigt.

von Rolf M. (rmagnus)


Lesenswert?

Ben B. schrieb:
> Hihi, wegen sowas verwenden fast alle meine
> Nicht-Interpretersprachen-Programme eine Art Backup-Lösung: der
> komplette für Variablen reservierte Speicher wird beim Start mit 0x00
> überschrieben. Falls man dann sowas mal vergisst, hat man einen
> doppelten Boden. Das mache ich sogar bei µCs, auf denen größere
> Programme laufen sollen, beim Start oder Reset wird das komplette RAM
> gelöscht.

Für globale Variablen wird das bereits gemacht, sofern der Startup-Code 
nicht kaputt ist. Hier geht es aber um eine lokale Variable. Wenn da vor 
der Funktion schon was auf dem Stack war, sind die Nullen teilweise 
schon überschrieben worden.

Rainer W. schrieb:
> Eine Division durch 0 funktioniert nun mal nicht. Stark schwankende
> Ergebnisse entstehen bei schlecht konditionierten Algorithmen, die dann
> sehr empfindlich auf Rauschen reagieren.

Was für Rauschen? Das Programm nimmt keinerlei Daten von außen entgegen.

900ss D. schrieb:
> Roland F. schrieb:
>> "warning: 'a' is used uninitialized in this function [-Wuninitialized]"
>
> Soweit ich mich richtig erinnere, macht GCC den Check nur wenn auch der
> Optimierer eingeschaltet ist. Sonst nicht.

Das liegt daran, dass der Optimierer eine Codefluss-Analsyse macht, um 
zu erkennen, was er schon zur Compilezeit ausrechnen kann.

Stefan F. schrieb:
> Die Option -Wall sollte man nach Möglichkeit immer benutzen und auch
> alle monierten Stellen in Ordnung bringen.

-Wall -Wextra -pedantic ist für mich das Minimum.

> Ich empfehle die QtCreator IDE, die erkennt viele potentielle Fehler
> schon vor dem Compilieren.

Das können eigentlich alle vernünftigen Editoren/IDEs heutzutage mit dem 
passenden Language Server.

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