Hallo,
ich programmiere gerade einen Regelalgorithmus welcher mit 32 Bit Floats
rechnet (--> soll so sein!).
Der Algorithmus gibt eine Float Zahl zurück. Für die Ansteuerung der PWM
benötige ich allerdings eine 16 Bit Unsigned Int.
Ich steh gerade echt auf dem Schlauch was die Typkonvertierung anbelangt
kann mir jemand weiterhelfen?
(Achja ich benutze den C30 Compiler von Micrchip falls das von Bedeutung
ist).
Viele Grüße,
Sebastian
Hey!
Das, was du vermutlich suchst, nennt sich "casten".
Hierbei kann man einfache Typumwandlungen nach folgendem Beispiel
durchführen:
float a;
unsigned int b;
b = (unsigned int) a;
Oder siehe auch:
http://home.fhtw-berlin.de/~junghans/cref/CONCEPT/cast.html
Beste Grüße
Seemann
Sebastian schrieb:> Ich steh gerade echt auf dem Schlauch was die Typkonvertierung anbelangt> kann mir jemand weiterhelfen?
Einfach den float benutzen? Wenn der Empfänger einen unsigned int
benötigt, dann fügt der Compiler schon eine entsprechende Konvertierung
ein.
Ein bischen Komfort kann man von einem Compiler schon erwarten. Sonst
hätte man ja Hochsprachen nicht erfinden müssen, wenn man sich dann
sowieso um jeden Kleinscheiss erst recht wieder selber kümmern muss.
John_der_Seemann schrieb:> Das, was du vermutlich suchst, nennt sich "casten".
nein, casten ist hier überhaupt nicht notwendig. Einfach zuweisen und
gut ist.
Das dachte ich auch zuerst allerdings funktioniert weder der cast noch
die direkte Zuweisung (andersherum allerdings schon). Kann es sein, dass
das Problem an der Konvertierung 32 Bit --> 16 Bit liegt?
Sebastian schrieb:> Das dachte ich auch zuerst allerdings funktioniert weder der cast noch> die direkte Zuweisung (andersherum allerdings schon). Kann es sein, dass> das Problem an der Konvertierung 32 Bit --> 16 Bit liegt?
das kommt auf die werte an. In einem float können auch zahlen >
MAX_INT32 sein und dann steht unsinn drin.
Natürlich wird der Nachkommateil des Floats abgeschnitten. Ein
Interger-Typ beinhaltet nunmal nur Ganzzahlen.
Sebastian schrieb:> Das dachte ich auch zuerst allerdings funktioniert weder der cast noch> die direkte Zuweisung (andersherum allerdings schon).
Ohne konkrete Fehlermeldung des Compilers bzw. einer Beschreibung des
Fehlverhaltens können wir nicht ermitteln wo das Problem liegt.
Gruß lowlevel
Der Compiler gibt keine Fehlermeldung oder Warning raus.
Folgender Code soll das Problem verdeutlichen:
float regelStellWert; //32 Bit float!
unsigned int pwm; //16 Bit unsigned int!
pwm = regelStellWert; //Es steht nur Käse in PWM
pwm = (unsigned int) regelStellWert; //Auch so steht nur Käse in PWM
Gibts da vielleicht irgend ne spezielle Funktion etc.?
Sebastian schrieb:> float regelStellWert; //32 Bit float!>> unsigned int pwm; //16 Bit unsigned int!>>> pwm = regelStellWert; //Es steht nur Käse in PWM
Dann schau dir doch mal den originalen Wert in regelStellWert an.
Wie schon gesagt: ein unsigned int hat nach oben eine Grenze. Mehr geht
nun mal mit den verfügbaren Bits nicht. Ist dein regelStellWert größer
als diese Grenze, dann geht das nicht.
> Gibts da vielleicht irgend ne spezielle Funktion etc.?
Dein Problem liegt höchst wahrscheinlich in den Wertebereichen. Also
musst du dir erst mal einen Überblick verschaffen über welche
Wertebereich (hier: beim float) überhaupt geredet wird.
Sebastian schrieb:> pwm = regelStellWert; //Es steht nur Käse in PWM
bitte ein genaues beispiel:
Was steht und regelStellWert drin und was steht dann in pwm drin?
Wie Karl Heinz andeutete, prüfe mal was bei deinen Berechnung so
herausgekommt, denn bevor Du eine typecast durchführst solltest Du
sicher sein, dass der Wert in die zu "castenden" Variable passt. Casts
sind erlaubt wenn nötig, aber verpönnt:-)
Habs gerade mal im Debugger nachgeschaut (beide Zahlen in hex)
regelStellWert = 0x4293 6E24
pwm = 0x6E24
Es wird also letzlich nur die hinteren 16 Bit übernommen, was natürlich
Quatsch ist.
Gibt es da irgend ne Konvertierungsfunktion um eine float korrekt in
eine unsigned int zu wandeln?
Kann es sein, daß du nicth mit float/double sondern mit fixed point
rechnest. Sieht nach Q16 aus, auch wenn PID usw in Q15 gerechnet wird.
Zur Info: Q15=16bit fixed point im 1.15 Format und Q16=16.16 Format.
John_der_Seemann schrieb:> @Peter II:>> "Schneidet" der Compiler bei deiner Methode ebenfalls die> Nachkommastellen einfach weg?
Das ist "Implementation Defined" laut Standard.
Es gibt folgende Möglichkeiten, wie die Implementierung das erlegigt; je
nach Compiler auch einstellbar per Kommandozeile:
• Round to Zero
• Round to Nearest
• Round down (towards -oo)
• Round up (towards +oo)
C30 ist GCC. Wenn wie hier Beschrieben:
Sebastian schrieb:> regelStellWert = 0x4293 6E24>> pwm = 0x6E24
dann heisst das, regelStellWert ist irgendein Int, deutet stark auf
fixed point float hin und hat nichts mit float zu tun.
Um diese Zahlen umzuwandeln zu konvertieren gibt es entsprechende
Funktionen. viele DSP Libs von Microchip verwenden fixed point float,
jedoch wird generell Q15 genommen, vielleicht wurde auch das gemischt.
Johann L. schrieb:> • Round to Zero> • Round to Nearest> • Round down (towards -oo)> • Round up (towards +oo)
Mit der Gaußklammer [·] schreiben sich diese Möglichkeiten als:
Sebastian schrieb:> Habs gerade mal im Debugger nachgeschaut (beide Zahlen in hex)>> regelStellWert = 0x4293 6E24>> pwm = 0x6E24>>> Es wird also letzlich nur die hinteren 16 Bit übernommen, was natürlich> Quatsch ist.> Gibt es da irgend ne Konvertierungsfunktion um eine float korrekt in> eine unsigned int zu wandeln?
Zeig doch mal deinen Code.
die Variable regelStellWert ist vom Datentyp 'float'? Das steht da
explizit so im Code?
die Variale pwm ist vom Datentyp unsigned int (oder int)? Auch das steht
da so explizit im Code?
Deine Zuweisung sieht so und nicht anders aus?
pwm = regelStellWert;
Da sind nirgends Pointer involviert?
Sobald stellWert an pwmui "übergeben" wird, passiert das obere Problem.
Werden die Werte Dezimal betrachtet ist der Wert von stellWert richtig
der Wert von pwmui ist Quatsch.
Das sind doch alles Q15 Werte, !!!
Mal das Handbuch zur Lib lesen, ist sehr gut beschrieben.
Ansonsten für Dummys:
float varfloat;
varfloat = Fract2Float(pidReglerDaten.measuredOutput);
varfloat = Fract2Float(pidReglerDaten.controlReference);
varfloat = Fract2Float(pidReglerDaten.controlOutput);
Sebastian schrieb:> Hier noch die Werte aus dem Debugger wie oben beschrieben
Was mir viel mehr Sorgen macht, ist die 0x0 in der zweiten Spalte.
Ist das die Adresse der Variablen?
Wenn du im Debugger dir die Werte ansiehst, steht dann die
Programmausführung in der Funktion?
Die Programmausführung steht dann bei der Funktion PWMChangeDuty.
Kann mich mal jemand aufklären was Q15 Werte sind - hab das noch nie
gehört und denke doch einiges an Erfahrung zu haben?
Sebastian schrieb:> Die Programmausführung steht dann bei der Funktion PWMChangeDuty.>> Kann mich mal jemand aufklären was Q15 Werte sind - hab das noch nie> gehört und denke doch einiges an Erfahrung zu haben?
Ist doch ganz einfach.
Was sagt die Doku zur Funktion PidController?
Da stehts drinnen.
Du musst dir angewöhnen, die Doku zu benutzen und weniger zu raten.
Dafür gibt es Doku. Wenn du keine hast, dann musst du dir eben eine Doku
online suchen.
//Berechnung des I-Anteils mit Begrenzung der Integralsumme (Anti-Windup)
20
iAnteil=pid->integralSum+regelAbw;
21
...
22
..
23
.
Der Regler beeinhaltet spezielle Routinen die ich nicht öffentlich
machen darf, aber ich habe den Regler selber geschrieben.
Der Regler ist gestestet und funktioniert. Ich habe einfach nur dieses
"lästige" Problem mit der Konvertierung float nach int oder IEEE nach
Decimal ...
Vermutlich ist bei diesem speziellen Compiler der float-Typ mit anderen
Formaten überlagert und daher funktionieren die standard Konventionen
nicht mehr.
Sowas ist sehr ungünstig, da wäre ein neuer Typ besser gewesen.
Es läßt sich bestimmt auch irgendwo einstellen, ob float wirklich als
float oder als was anderes verwendet wird.
Peter
float wird im IEEE 754 Format gespeichert. Ich müsste also eine Routine
geben um von diesem in das integer Format zu konvertieren.
Ich weiß leider nicht mehr weiter. Hätte nicht gedacht, dass durch
solche "Kleinigkeiten" ein Projekt nicht mehr weiter geht.
Sebastian schrieb:> float wird im IEEE 754 Format gespeichert.
Genau darum kümmert sich normalerweise der Compiler. Du hast da evtl.
etwas verstellt, oder kannst (wie schon vermutet) noch was umstellen...
A. K. schrieb:> Sebastian schrieb:>> float wird im IEEE 754 Format gespeichert.>> Sicher? Gibt bei PICs m.W. auch Exotisches als float. Sowas wie 24-Bit> Format.
Selbst dann müsste der Compiler die Umwandlung machen.
Das ergibt keinen Sinn, wenn er zwar die Umwandlung von int->float drauf
hat, aber die Umkehrung nicht.
Da ist was anderes faul.
Und ich denke mal, das hat was mit den 0x0 zu tun. An dieser Adresse
steht im Flash/ROM die Bytefolge 6E 24 42 93
Und bei einer Anzeige im Debugger, die auf 4 Bytes rausläuft (wie zb
float), wird eben alles angezeigt, während bei einem int eben nur die
ersten beiden Bytes angezeigt werden.
Was kommt eigentlich raus, wenn du dir diese Bytefolge als float (also
nicht in Hex-Form sondern richtig mit Dezimalpunkt und allem Drum und
Drann) anzeigen lässt?
Geh mal in die "Build Options" Deines Projektes, dann im Reiter "MPLAB
LINK30" die Category "Libraries" auswählen.
Was steht da?
Ist "Fast floating-point math" ausgewählt?
Ändert sich das Programmverhalten, wenn Du da etwas änderst?
Könnte es eventuell sein, daß du die Funktion nicht declarierst und
der Compiler dann einen Int annimmt, und die int->float und float->int
einfach wegoptimiert und gleich den int Wert zuweist.
Ansonsten die Float value müsste 172 sein, auch das wäre ausserhalb
deines
Bereiches von 0-100. Sind das reale Werte oder nur eine buggy
Simulation.
Dein Code oben dürfte nur die Werte entweder 0, 100, 101 annehmen.
und auch die Vergleiche sind falsch codiert.
Bronco schrieb:> Geh mal in die "Build Options" Deines Projektes, dann im Reiter "MPLAB> LINK30" die Category "Libraries" auswählen.>> Was steht da?> Ist "Fast floating-point math" ausgewählt?> Ändert sich das Programmverhalten, wenn Du da etwas änderst?
Das war des Rätsels Lösung!!
Vielen herzlichen Dank an Bronco und all die Anderen hilfsbereiten hier
im Forum - Ihr habt mir den Tag gerettet!