ich habe ein Problem, an dem ich mir die Zähne ausbeiße und nicht weiterkomme.
Folgendes: In einem Menue soll ein float wert mit 4 Nachkommastellen eingegeben werden können, und zwar so, dass die einzelne stelle mit dem Taster hochgezählt werden kann.
Das funktioniert auch alles, aber bei der letzten Stelle verrechnet er sich immer wieder.
Ich konnte den kritischen Teil in einen extra sketch extrahieren, der das selbe Fehlverhalten zeigt:
double _Wert = 0.0007;
void setup(){
Serial.begin(57600);
}
void loop(){
byte _Fliess_0001= long(_Wert *10000.0) % 10; // die vierte Nachkommastelle wird separiert als Byte.
Serial.print("Anfangs-Wert: ");Serial.println(_Wert,8);
Serial.print("4. Nachkommastelle separiert: ");Serial.print(_Fliess_0001);Serial.println();
// wieder zu einer double Zahl zusammenfügen
_Wert = _Fliess_0001 * 0.0001;
double a = _Wert *10000.0; // eine Kontrollrechnung fürs debuggen, um den Fehler zu finden.
Serial.print(" neuer Wert ");Serial.println(_Wert,8);
Serial.println(" Kontrollrechnung: ");Serial.print(_Wert,8);Serial.print(" * 10000: ");Serial.print(a,8);
Serial.println();Serial.println();
delay(2000);
}
Arduino verrechent sich nicht; Du kennst Dich nicht mit Float-Variablen aus.
Float-Variablen haben zwar einen großen Wertebereich den sie abbilden können, aber nur 6-7 gültige Stellen. Jede Stelle mehr ist zufällig.
Wenn Du mehr Genaugigkeit brauchst mußt Du dir eine Long Zahl mit einem Komma an der 4, 5, 6 ecc Stelle vorstellen (indem fürs rechnen mit 10000 100000 ecc multipliziert wird) oder Kommazahl aus 2 INT oder LONG Variablen zusammenbasteln.
Das nutzt aber alles nichts. Bei floats wird die Mantisse normalerweise binär abgelegt --> nicht einmal 0.1 kann genau dargestellt werden. Wenn man 4 Nachkommastellen braucht, dann nimmt man eben Integers und nimmt einfach die letzten 4 Stellen als Nachkommastellen. Alles Andere ist ziemlicher Pfusch und funktioniert am Ende doch nicht richtrig.
letztlich habe ich das ganze ja nur in double gemacht, weil es sich hierbei um die Parameter für die PID library handel, die ja in Double haben wollen.
Ich werde die Variablen also in Integer halten, und erst kurz vor der Übergabe an den PID in double konvertieren.
Nach längerer Überlegung habe ich beschlossen, das Ganze doch nicht über Integer zu lösen, weil ich sonst alles komplett umbauen müsste.
Das Problem liegt ja in der Rechnung:
double a = 0.0007 * 10000;
wobei "a" nachher den Wert 6,9999 annimmt.
Und beim anschliessenden Wandeln in int steht dann da eine "6" wo ich eigentlich eine "7" brauche.
Ich habe das Problem jetzt durch einen (nicht ganz sauberen) Trick gelöst:
double a = 0.0007 * 10000 + 0.001;
dadurch bekomme ich ein Ergebnis, das auf alle Fälle eine "7" vor dem Komma stehen hat, und beim Wandeln in int fällt der Rest sowieso weg.
Aber ich hatte wirklich nicht auf dem Radar, das float und double beim Arduino das Selbe sind!