0

In my recent project, I have to parse incoming JSON data in Arduino and I successfully did it. But it is only for one constant data string.

For example, if my incoming JSON string like:

{"TPS":"0.40","MAP":"0.95","LOAD":"14"}

And Arduino code for parsing this data is below:

#include <LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() { 
  StaticJsonBuffer<100> jsonBuffer;
  while(Serial.available() || !begin) {
    char in = Serial.read();
    if (in == '{') {
      begin = true;
    }
    if(begin) {
      response += (in);
    }
    if(in == '}') {
        break;
    }
    delay(1);
  }
  JsonObject& root = jsonBuffer.parseObject(response);
  String TPS = root["TPS"];
  String MAP = root["MAP"];
  String LOAD = root["LOAD"];
  lcd.setCursor(0, 0);
  lcd.print(TPS);
  lcd.setCursor(8, 0);
  lcd.print(MAP);
  lcd.setCursor(0, 1);
  lcd.print(LOAD);  
}

Then the output looks like:

TPS  : 0.40
MAP  : 0.95
LOAD : 14

That's fine, but when the incoming JSON string changes, what should I do?

Suppose the incoming JSON string looks like:

{"LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

Because I have to handle both incoming JSON strings, I can't replace any part like:

  String LOAD = root["LOAD"];
  String RPM = root["RPM"];
  String INJECTION_TIME = root["INJECTION_TIME"];
  lcd.setCursor(0, 0);
  lcd.print(LOAD);
  lcd.setCursor(8, 0);
  lcd.print(RPM);
  lcd.setCursor(0, 1);
  lcd.print(INJECTION_TIME);

Instead of

  String TPS = root["TPS"];
  String MAP = root["MAP"];
  String LOAD = root["LOAD"];
  lcd.setCursor(0, 0);
  lcd.print(TPS);
  lcd.setCursor(8, 0);
  lcd.print(MAP);
  lcd.setCursor(0, 1);
  lcd.print(LOAD);
  • 1
    Any reason you don't just jsonBuffer.parse(Serial)? – Edgar Bonet Jun 28 '17 at 8:42
  • @EdgarBonet Means? I can't understand what you mean? Is this catch Serial data and parse it? Something like that? – Hasan Jun 28 '17 at 10:14
  • My question is: Why did you choose to not use jsonBuffer.parse(Serial)? – Edgar Bonet Jun 28 '17 at 10:31
  • @EdgarBonet Actually, I have no idea about this sentence. This is the first time I see something like this means to use "Serial" directly and we can parse incoming string or data. – Hasan Jun 29 '17 at 6:11
  • What kind of JSON do you expect to receive? Always an object with 3 key-value pairs of type string, but unknown key names? – gre_gor Jun 29 '17 at 21:45
1

If you want to read 3 values of a object that you don't know the names of the key, you can use an iterator as shown in the ArduinoJson library's docs.

And as already mentioned in the comments, you can also replace all the serial reading code with just Serial passed into the jsonBuffer.parseObject function.

#include <LiquidCrystal.h>
#include <ArduinoJson.h>

const struct LCDPos {
  uint8_t x;
  uint8_t y;
} lcd_pos[] = {
  {0, 0},
  {8, 0},
  {0, 1},
};

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Serial);
  if (root == JsonObject::invalid())
    return;

  uint8_t i = 0;
  for (JsonObject::iterator it = root.begin(); it != root.end() && i<(sizeof(lcd_pos)/sizeof(lcd_pos[0])); ++it, i++)
  {
    lcd.setCursor(lcd_pos[i].x, lcd_pos[i].y);
    lcd.print(it->value.asString());
  }
}

You will need to make sure, that the values are sent in the order that you want them on your LCD.

EDIT:
I don't have an LCD screen, so I didn't test the code with an LCD, but the code that just dumps the parsed data back to serial works.

//#include <LiquidCrystal.h>
#include <ArduinoJson.h>

const struct LCDPos {
  uint8_t x;
  uint8_t y;
} lcd_pos[] = {
  {0, 0},
  {8, 0},
  {0, 1},
};

//LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

void setup() {
  Serial.begin(115200);
  //lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Serial);
  if (root == JsonObject::invalid())
    return;

  Serial.println("JSON received");
  uint8_t i = 0;
  for (JsonObject::iterator it = root.begin(); it != root.end() && i < (sizeof(lcd_pos) / sizeof(lcd_pos[0])); ++it, i++)
  {
    //lcd.setCursor(lcd_pos[i].x, lcd_pos[i].y);
    //lcd.print(it->value.asString());
    Serial.print(i);
    Serial.print(':');
    Serial.print(lcd_pos[i].x);
    Serial.print(',');
    Serial.print(lcd_pos[i].y);
    Serial.print(' ');
    Serial.println(it->value.asString());
  }
  Serial.println();
}

If I send

{"TPS":"0.40","MAP":"0.95","LOAD":"14"}{"LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

over the serial, it returns

JSON received
0:0,0 0.40
1:8,0 0.95
2:0,1 14

JSON received
0:0,0 2.40
1:8,0 4200
2:0,1 4.87
  • I tried out your code, but nothing is displaying on LCD. – Hasan Jul 4 '17 at 5:46
  • 1
    I don't have an LCD, so I don't know why the LCD doesn't work, but the JSON parsing works. – gre_gor Jul 5 '17 at 2:26
0

Finally got the solution. I'm using the extra key name.

So, my modified serial data string now looks like:

{"ActionOne":"ONE","TPS":"0.40","MAP":"0.95","LOAD":"14"}
{"ActionTwo":"TWO","LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

and so now using containsKey() function, just check which one is coming. If ActionOne is coming then according to that serial data we got. And If ActionTwo is coming then according to that serial data we got.

#include <LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false, finished;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() { 
  StaticJsonBuffer<100> jsonBuffer;

  while (finished == false)
  {
    if (Serial.available())
    {
      const char in = Serial.read();
      if (in == '{')
      {
        response = "";  // Blank the string
        begin = true;
      }
      if (begin)
      {
        response += (in); // Only write if within the {}
      }
      if (in == '}')
      { 
        begin = false;   // Prevent any chars between } and { leaking through.
        break;
      }
    }
    delay(1);
  }

  JsonObject& root = jsonBuffer.parseObject(response);

  const char* ActionOne = root["ActionOne"];
  const char* ActionTwo = root["ActionTwo"];

  if(root.containsKey("ActionOne"))
  {
    float TPS = root["TPS"];
    float MAP = root["MAP"];
    int LOAD = root["LOAD"];

    lcd.setCursor(0, 0);
    lcd.print(TPS);

    lcd.setCursor(8, 0);
    lcd.print(MAP);

    lcd.setCursor(0, 1);
    lcd.print(LOAD);  
  }

  if(root.containsKey("ActionTwo"))
  {
    float LOAD = root["LOAD"];
    int RPM = root["RPM"];
    float INJECTION_TIME = root["INJECTION_TIME"];

    lcd.setCursor(0, 0);
    lcd.print(LOAD);

    lcd.setCursor(8, 0);
    lcd.print(RPM);

    lcd.setCursor(0, 1);
    lcd.print(INJECTION_TIME);    
  }  
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.