I have a setup that reads from serial when I sense that there is something to be read (and always assume that what is sent to the arduino is valid json):
void setup(){
Serial.begin(9600);
while (!Serial) continue;
}
void loop() {
if(Serial.available()){
StaticJsonDocument<256> doc;
deserializeJson(doc, Serial);
serializeJson(doc, Serial);
Serial.println();
}
}
Given the following input from ArduinoIDE's serial monitor (Set to newline
setting, 9600
baud):
{"hello": "world"}
This produces the following:
{"hello": "world"}
null
I have two questions:
- Is this setup correct/ how I should be waiting and retrieving json from serial?
- Why the additional
null
input? Looks like there is something still in the serial buffer even after the first iteration? (削除) How to detect the second case where the resulting document gets re-serialized asFigured this one out, found out aboutnull
? Comparing to0
,NULL
, andnullptr
seem to not work (削除ここまで)DeserializationError
Upon utilizing DeserializationError
, looks like the null
parsing had an error of EmptyInput
1 Answer 1
As observed on your serial console
settings, it mentions both newline and 9600 baud. Let's break this down:
Issue with Serial Communication
Partial Payloads: You are currently assuming that when
Serial.available()
returnstrue
, the entire JSON payload has been received. However, due to the nature of serial communication (especially at 9600 baud), data can arrive in fragmented chunks. InvokingdeserializeJson()
on a partial JSON payload can result in incomplete or corrupted data.End-of-Message Ambiguity: Lacking a definitive end-of-message marker makes it challenging to discern when a complete JSON payload has been received. For instance, when sending
{"hello": "world"}
from the Arduino IDE's serial monitor, it automatically appends a newline (or a carriage return based on your configuration). This newline is then misinterpreted as another JSON payload, leading to the undesirednull
output.
How you can solve this:
Use a Delimiter: Choose a specific character or sequence to act as an end-of-message delimiter. The newline character (
\n
) is a typical choice, especially if data is exclusively sent from the Arduino IDE's serial monitor. Nevertheless, if you anticipate newlines within your JSON data, you might consider another distinct character, like#
.Read Until Delimiter: Adjust your code to continuously read characters from the serial port until the chosen delimiter is encountered. Upon receipt of the entire message, it can then be parsed.
Code Example
Here's a sample code employing the newline character as a delimiter:
const int maxBuffer = 256;
char serialBuffer[maxBuffer];
int bufferPos = 0;
void setup() {
Serial.begin(9600);
while (!Serial) continue;
}
void loop() {
if (Serial.available()) {
char inChar = Serial.read();
if (inChar == '\n') { // EOM
serialBuffer[bufferPos] = '0円';
processMessage(serialBuffer);
bufferPos = 0; // Reset buffer pos
} else if (bufferPos < maxBuffer - 1) { // Avoid buffer overflow
serialBuffer[bufferPos++] = inChar;
}
}
}
void processMessage(char* message) {
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.println("Failed to parse JSON");
} else {
serializeJson(doc, Serial);
Serial.println();
}
}
This way you ensure the entirety of message is parsed and received and therefore avoiding unwanted null
outputs.
I hope this helps ^_^
serial console
settings