3

I'm new to Arduino and I'm building a project that fetches data from a website (using ESP8266) and then transfers them to my Arduino UNO via serial port.

Data coming from ESP8266 every 20s - [{"x": 0,"y": 0,"rgb": [255, 200, 174]},{"x": 1,"y": 0,"rgb": [255, 200, 174]},{"x": 2,"y": 0,"rgb": [255, 200, 174]}]

But when I print the data like this


void loop() {
  
  if (Serial.available()) {
    Serial.write(Serial.read()); // This line prints only one character out of whole string
    
    data =  Serial.read(); // so this doesn't work

    DeserializationError error = deserializeJson(response, data);
    if (error) {
      Serial.print(F("deserializeJson() failed: "));
      Serial.println(error.f_str());
      return;
    }
    for (JsonObject elem : response.as<JsonArray>()) {
      int x = elem["x"]; // 2, 2, 2
      int y = elem["y"]; // 2, 2, 2
      JsonArray rgb = elem["rgb"];
    
      int rgb_0 = rgb[0]; // 255, 255, 255
      int rgb_1 = rgb[1]; // 255, 255, 255
      int rgb_2 = rgb[2]; // 255, 255, 255
      //Serial.print(x);
    }
  }
  delay(1000);   //then it waits 1 second and goes from the start
}

How can I make it to get the whole string and save it into a variable?

Thanks, much for answering.

krystof18
  • 315
  • 4
  • 10
  • 1
    There is no such thing as "a whole string" in serial. There is only single bytes. It is *your* job to decide (and program it so it understands) *what* a string is. – Majenko May 22 '21 at 15:06
  • Then how can I watch for example for line break? – krystof18 May 22 '21 at 15:15
  • WHy do yoiu ithink you need to? And if you want to get serial data into a variable and then use that serial data for some other thing, just use whatever you stored in your variable. Once you read from serial it's gone from serial forever. But you saved it in `data`, so just use it from there? – Majenko May 22 '21 at 15:19
  • What about `Serial.readStringUntil()` and read to e. g. `\n`? – Python Schlange May 22 '21 at 16:05

1 Answers1

6

I was going to put this as a comment, but maybe it belongs as an answer:

For what it's worth, ArduinoJSON seems to be able to deserialize directly from a stream, i.e. Serial, which may obviate the question as asked. Presumably it knows where to stop deserializing, because it knows when it has received an entire JSON object; being a proper JSON parser, it can probably work this out better than you can without, you know, writing a JSON parser.

The following was just thrown together, now the author is here you should probably just follow their direction, but here's the code anyway:

#include <ArduinoJson.h>


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  Serial.setTimeout(30000);
}


void print_transmission_counter( {
    static unsigned long received_object_counter;
    Serial.println(F("\n\n\n\n"));
    for (int i = 0; i < 30; ++i) {
        Serial.write('-');
    }
    Serial.write('[');
    Serial.print(received_object_counter++);
    Serial.println(']');
}


void loop() {
    static StaticJsonDocument<256> json_doc;
    static bool led_state;

    print_transmission_counter();

    const auto deser_err = deserializeJson(json_doc, Serial);
    if (deser_err) {
        Serial.print(F("Failed to deserialize, reason: \""));
        Serial.print(deser_err.c_str());
        Serial.println('"');
    } else  {
        Serial.print(F("Recevied valid json document with "));
        Serial.print(json_doc.size());
        Serial.println(F(" elements."));
        Serial.println(F("Pretty printed back at you:"));
        serializeJsonPretty(json_doc, Serial);
        Serial.println();
    }


    // Just give some visual indication that the loop is progressing
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
}


//  vim:sw=2:ts=2:et:nowrap:ft=cpp:
timemage
  • 4,690
  • 1
  • 10
  • 24
  • Thanks much, this sounds like the thing I need. – krystof18 May 22 '21 at 15:18
  • **If** this ends up being the route you take, **and** doing so doesn't invalidate any other answers (that may appear between now and then), you might consider changing the question title slightly to "Getting all data of my JSON object from Serial.read() at once" to improve findability and matching between question and answer. – timemage May 22 '21 at 15:39
  • It definitely looks like a great way to do it, but I can't seem to make it work, when I change the `data` variable to `Serial.read()` like this `DeserializationError error = deserializeJson(response, Serial.read());` I get ` Error compiling for board arduino UNO` – krystof18 May 22 '21 at 15:43
  • It may be a while, but I'll reread your comment above and see if I can't provide a minimal example. The ArduinoJSON documentation is quite good though, so I expect there will be one there as well. – timemage May 22 '21 at 15:53
  • 1
    @krystof18, please have a look at [How to do serial communication between two boards?](https://arduinojson.org/v6/how-to/do-serial-communication-between-two-boards/) – Benoit Blanchon May 22 '21 at 16:08
  • @krystof18, with regard to the specific line given above, it's expecting a reference to a `Stream`, which `Serial` is. By calling `.read()` there you're trying to pass a single character (or indication of the lack of a character; -1) into the `deserializeJson` function. – timemage May 22 '21 at 16:31
  • @BenoitBlanchon, do you mind if I draw your comment up into the answer body? – timemage May 22 '21 at 16:33
  • @timemage, I don't mind; please do. – Benoit Blanchon May 24 '21 at 08:27