bblanchon / ArduinoJson

📟 JSON library for Arduino and embedded C++. Simple and efficient.
https://arduinojson.org
MIT License
6.63k stars 1.1k forks source link

ArduinoJson - overflow float only at ESP8266 #1466

Closed martinius96 closed 3 years ago

martinius96 commented 3 years ago

Hello there! I am using the ArduinoJson library in version 6.17.2 (last release) from November 14, 2020. I have an Ethernet / WiFi thermostat project, which I designed myself. The microcontroller, which acts as a thermostat, runs in web server mode, where it has various HTML pages that provide a frontend to the user and includes a simple backend (in C-Wiring language) for processing data from HTML forms that serve as control data. One of the running pages is also /get_data.json, the output of which is JSON data on the set control values of the thermostat -> Target temperature, hysteresis and the currently measured temperature by the DS18B20 sensor.

For example, the output of /get_data.json looks like this: { "Hysteresis":0.25, "Target_Temperature":21.25, "Actual_Temperature":20.81 }

I read this output by a ANOTHER microcontroller, let's call it JSON client. I have used Arduino with an Ethernet shield Wiznet W5100 and a W5500 module. Also ESP8266 (NodeMCU v3 Lolin) and ESP32 (DevKit V1) for that JSON client implementation. Client part is identical for all platforms. I am able to connect to the IP address where the thermostat is running, read the HTTP header, Content-type: application / json and finally payload.

Source code snippet for attaching and parsing data from a loaded string - same for all platforms:

client.stop();
if (client.connect(host, httpPort)) {
  String url = F("/get_data.json");
  Serial.println(F("Pripojenie uspesne, nacitavam JSON data"));
  client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: W5100\r\n" + "Connection: close\r\n\r\n");
  while (client.connected()) {
    String line = client.readStringUntil('\n'); //HTTP HEADER
    //Serial.println(line);
    if (line == "\r") {
      break;
    }
  }
  DynamicJsonDocument doc(128);
  String line = client.readString(); //PAYLOAD
  Serial.println(line);
  deserializeJson(doc, line);
  JsonObject obj = doc.as<JsonObject>();
  float hystereza = obj[String("Hysteresis")];
  float cielova_teplota = obj[String("Target_Temperature")];
  float actual_temperature = obj[String("Actual_Temperature")];
  Serial.print(F("Hystereza: "));
  Serial.println(hystereza);
  Serial.print(F("Cielova teplota: "));
  Serial.println(cielova_teplota);
  Serial.print(F("Namerana (aktualna) teplota: "));
  Serial.println(actual_temperature);

Then I read the server's response , which is formed (Output above). Then I deserialize the string through the functions of the ArduinoJson library and then I can extract the value that belongs to it based on the key.

To better understand the UART output of all platforms:

It works on all platforms that I am using (ESP32, Arduino + Ethernet W5100 / W5500), except ESP8266. All values are of type float, I expect them and I assign a value to a variable with such a data type. For ESP8266, the value of the variables is always ovf (overflow). What surprises me in particular is that with both Arduino and ESP32 it works smoothly and I get data, is there any difference in the data type float, or do I need to use another way of getting data from a .json file? Can anyone think of how to solve the problem? Or some problem at library? @bblanchon

The entire source code for all platforms for the JSON client I use is available at: https://github.com/martinius96/WiFi-termostat/tree/main/examples Thanks for reply

bblanchon commented 3 years ago

Hi,

This works perfectly on my Adafruit Huzzah ESP8266.

It seems to be a problem with Serial.println(), not with ArduinoJson. Can you check that your ESP8266 core for Arduino is up-to-date? I was using 2.7.4 for my test.

BTW, I advise to check the error code returned by deserializeJson(), and I highly recommend changing obj[String("Hysteresis")] into obj["Hysteresis"] to save RAM and CPU cycles.

Best regards, Benoit

martinius96 commented 3 years ago

Hello there. I fixed it for now by using macro: #define ARDUINOJSON_USE_DOUBLE 1 and I am able to read these values as float or double and print them correctly.

But also that macro #define ARDUINOJSON_USE_DOUBLE 0 from documentation I see, it should save variables as floats, but I am unable to read and print them as float or double. Value is still ovf in Serial monitor. I think, problem is in Serial output as u said. Because now when I was googling i found ovf in Serial.print related forum threads... And I was googling it related to ArduinoJson and I was unable to find it :-)

I also tried your error check for deserializeJson() from example code for switch, and return is Deserialization succeeded, so datas are valid. I am using older Arduino core for ESP8266 --> 2.5.2. I think we can close issue thread., problem was fixed for my older Arduino core. Thanks a lot for help, I appreciate it, Martin

bblanchon commented 3 years ago

Hi Martin,

I don't understand how ARDUINOJSON_USE_DOUBLE could fix your issue. I wonder if this could be a bug in ArduinoJson. Can you check with the latest core or provide an MCVE?

Best regards, Benoit

martinius96 commented 3 years ago

Hello Benoit, MVCE is there:

I updated my Arduino core for ESP8266 to 2.7.4. - latest stable Output WITHOUT and WITH macro ARDUINOJSON_USE_DOUBLE 1 is same Output with macro

It looks, it is fixed and problem was NOT in ArduinoJson library, but in older Arduino core for ESP8266. Best regards, Martin

bblanchon commented 3 years ago

Martin, thank you very much for taking the time to test. I think we can safely close this issue now.