ArduinoJson und floats

Hi zusammen,

kurz & knapp:

Sketch:

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200);
  delay(2000);

  float test_1 = 0.28;
  float test_2 = 3.43;
  
  StaticJsonDocument<96> test_arr;
  
  test_arr[0]["test_1"] = test_1;
  test_arr[0]["test_2"] = test_2;
  
  String jsonString;
  serializeJson(test_arr, jsonString);
  Serial.println(jsonString);
}

void loop() {

}

Ausgabe am Serial Monitor:

[{"test_1":0.280000001,"test_2":3.430000067}]

Ich hab weder getrunken, noch stand ich zu lange in der Sonne.
Warum macht es das?

Wo kommen die ganzen zusÀtzlichen Nullen her.

Hilfe!

Das hier dagegen funktioniert:

#include <ArduinoJson.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(2000);
  
  StaticJsonDocument<96> test_arr;
  
  test_arr[0]["test_1"] = 0.28;
  test_arr[0]["test_2"] = 3.43;
  
  String jsonString;
  serializeJson(test_arr, jsonString);
  Serial.println(jsonString);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Ich bin verwirrt ... wieder mal

Und nochmal ein Nachschlag:

Das hier funktioniert auch, kommt mir aber extrem dÀmlich vor:

#include <ArduinoJson.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(2000);

  float test_1 = 0.28;
  float test_2 = 3.43;
  
  StaticJsonDocument<96> test_arr;
  
  test_arr[0]["test_1"] = ((int)(test_1 * 100))/100.0;
  test_arr[0]["test_2"] = ((int)(test_2 * 100))/100.0;
  
  String jsonString;
  serializeJson(test_arr, jsonString);
  Serial.println(jsonString);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Ausgabe:

[{"test_1":0.28,"test_2":3.43}]

Ich verstehs wieder mal echt nicht.

Auf einen originalen ARDUINO UNO kompiliert und ĂŒbertragen:

Der Sketch verwendet 6908 Bytes (21%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 252 Bytes (12%) des dynamischen Speichers, 1796 Bytes fĂŒr lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
/home/user1/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/user1/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:/tmp/arduino_build_559971/sketch_aug23e.ino.hex:i 

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/user1/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/home/user1/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyACM0
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "/tmp/arduino_build_559971/sketch_aug23e.ino.hex"
avrdude: writing flash (6908 bytes):

Writing | ################################################## | 100% 1.24s

avrdude: 6908 bytes of flash written
avrdude: verifying flash memory against /tmp/arduino_build_559971/sketch_aug23e.ino.hex:
avrdude: load data flash data from input file /tmp/arduino_build_559971/sketch_aug23e.ino.hex:
avrdude: input file /tmp/arduino_build_559971/sketch_aug23e.ino.hex contains 6908 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.98s

avrdude: verifying ...
avrdude: 6908 bytes of flash verified

avrdude done.  Thank you.

Ausgabe:

20:59:43.092 -> [{"test_1":0.28,"test_2":3.43}]

der Sketch aus #1? Echt jetzt?
Ich verwende einen ESP32 von AZDelivery, die machen eigentlich schon gute QualitÀt.
Ist ja echt skurril. Dann test ich das auch mal auf einem anderen ESP oder einem Arduino.

Ja. Darum habe ich das Protokoll mitgeliefert.

:see_no_evil:

Hat das dann was damit zu tun, dass der ESP32 besser mit Integers kann?
Muss gleich auch mal auf einem ESP8266 testen.

TatsÀchlich:
Auf dem Arduino Nano funktionierts, auf dem ESP8266 und dem ESP32 kommen die Kommastellen dazu. Was soll das :hot_face:

Hab ne Lösung gefunden:
Wenn ich die floats in double Ànder, funktionierts auch mit den ESPs

Ich ahne was....
Mach mal:

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(F("VariablengrĂ¶ĂŸe in Byte"));
  Serial.print(F("float: "));
  Serial.println(sizeof(float));
  Serial.print(F("double: "));
  Serial.println(sizeof(double));
}

void loop()
{}

Start...
VariablengrĂ¶ĂŸe in Byte
float: 4
double: 8

Hab auch grad auf der ArduinoJson.org Seite gesehen, dass da double anscheinend die bessere Wahl ist.

Aaaaber: Der Spuk geht weiter

#include <ArduinoJson.h>

uint32_t wert_eins=3;
uint32_t wert_zwei=100;
uint32_t wert_drei=10300;
uint32_t wert_vier=9178;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(2000);

  double wert_fuenf = wert_eins * (wert_zwei/10000.0) * (wert_drei/10000.0) * (wert_vier/10000.0);

  Serial.println("wert_fuenf ist hier:");Serial.println(wert_fuenf);
  
  StaticJsonDocument<96> test_arr;
  
  test_arr[0]["wert_fuenf"] = wert_fuenf;
  String jsonString;
  serializeJson(test_arr, jsonString);
  Serial.println("Und hier:");
  Serial.println(jsonString);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Ausgabe am Serial-Monitor:

wert_fuenf ist hier:
0.03
Und hier:
[{"wert_fuenf":0.02836002}]

Wie krieg ich das jetzt wieder im JSON-Array gerundet auf 2 Nachkommastellen?
Was mich auch irritiert:

Wenn ich am Taschenrechner eintipp:
3 * 0,01 * 10,3 * 0,9178 bekomm ich als Ergebnis genau diese Zahl 0,2836002
D.h. hier hat der JSON-Array Recht und ich frag mich, warum der Serial-Monitor hier die gerundete Version ausgibt.

Und was ist, wenn du statt float double verwendest?

Hier schau dir mal Pi an:

Ich hatte ja zuerst float.
Aber da hatte ich ja dann das Problem, dass die Zahlen im JSON-Array zu viele Nachkommastellen hatten (siehe #1).

Auf der ArduinoJSON.org-Seite fand ich dann dass (Auszug aus dem Troubleshooter):

Standard fĂŒr SerMon sind zwei Nachkomma stellen :wink:

Ah hier stehts:

Neue Variablere anlegen runden weg ist der Spuck :wink:

22:14:06.916 -> wert_fuenf ist hier:
22:14:06.916 -> 0.0283600187
22:14:06.916 -> Und hier:
22:14:06.916 -> [{"wert_fuenf":0.02836}]

:slight_smile:

  Serial.println("wert_fuenf ist hier:");Serial.println(wert_fuenf,10);

OK.... bei mir warens zwei Nachkommastellen. Evtl. kann man das ja einstellen oder das Verhalten ist beim ESP32 wieder anders wie beim Arduino?

Was mich aber immer noch verwirrt und vorhin bissl aus der Bahn geworfen hat:

float test_1 = 0.28 wird im JSON-Array als "0.2800001" angezeigt, jedoch
double test_1=0.28 korrekt als "0.28" --> Warum? Egal. Jetzt weiß ichs ja :wink:

Ah - grad erst gelesen.
Da war ich zu schnell