Reputation: 103
I've been trying to set up this sample snippet for communicating over Serial with Python. I intend to send a simple JSON packet and de-serialise it over the other end with an Arduino.
But the JSON Library taken from here throws an error of Invalid Input.
#include <ArduinoJson.h>
void setup() {
Serial.begin(115200);
while(!Serial) {
}
}
void loop() {
int size_ = 0;
char payload[256];
String string = "";
if (size_ = Serial.available()) {
for(int i =0; i < size_; i++) {
payload[i] = Serial.read();
string += payload[i];
}
const size_t capacity = 1024;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.println(error.c_str());
return;
}
if(doc["operation"] == "ACK") {
Serial.println("ACK has been received");
}
else {
Serial.println("Error!");
}
}
while (!Serial.available()) {
}
delay(20);
}
This is the python snippet.
import time
import json
import serial
import pprint
if __name__ == "__main__":
print ("Ready...")
data = {}
data["operation"] = "ACK"
ser = serial.Serial("COM3", baudrate= 115200, timeout=0.5)
data = json.dumps(data)
if ser.isOpen():
(ser.write(bytes(data, "utf-8"), ))
try:
incoming = ser.readline().decode("utf-8")
print ((incoming))
except Exception as e:
print (e)
ser.close()
else:
print ("opening error")
For some reason I can't figure out why, when python sends over the chunk it doesn't seem to recognise the input.
Is it because of the 'b' added infront of it? Is it because of the encoding method used?
When i try to input {"operation":"ACK"}
via the terminal, it recognises it perfectly, and sends back a success message.
Why isn't it working over python? [ I am using Python 3 ]
[UPDATE] I tried to change a bit of the python code to do some debugging.
if __name__ == "__main__":
print ("Ready...")
data = {}
data["operation"] = "ACK"
ser = serial.Serial("COM3", baudrate= 115200, timeout=1)
data = json.dumps(data)
buf = []
if ser.isOpen():
for x in (data):
buf.append(ord(x))
ser.write(bytearray(buf))
try:
incoming = ser.readline()
for x in incoming:
print ((x))
except Exception as e:
print (e)
ser.close()
else:
print ("opening error")
and changed the Arduino script to send back the string it received.
#include <ArduinoJson.h>
void setup() {
Serial.begin(115200);
while(!Serial) {
}
}
void loop() {
int size_ = 0;
char payload[256];
String string = "";
while (size_ = Serial.available()) {
for(int i =0; i < size_; i++) {
payload[i] = Serial.read();
string += payload[i];
}
const size_t capacity = 1024;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, payload);
if (error) {
//Serial.println(error.c_str());
Serial.print(string.length());
for (int i = 0; i < string.length() ; i++) {
Serial.write(string[i]);
}
return;
}
if(doc["operation"] == "ACK") {
Serial.println("ACK has been received");
}
else {
Serial.println("Error!");
}
}
while (!Serial.available()) {
}
delay(20);
}
This is the python output.
Ready...
50
50
240
240
123
34
111
112
101
114
97
116
105
111
110
34
58
32
34
65
67
75
34
125
As you can see the size is printed twice right after the "ready..." and there are two chars of value 240 sent from the Arduino. I don't understand why there are these two chars in the front.
Upvotes: 3
Views: 9674
Reputation: 103
After a while of figuring out what the problem was, There were couple of issues.
The baud-rate was too fast, I had to reduce it down to 9600.
The encoding from python was supposed to be sent as ASCII.
Statically allocating the JsonDocument to 512 bytes worked.
The arduino JSON-Assistant has a method of finding out the require allocation for the architecture used.
The python code below.
import time
import json
import serial
from pprint import pprint
import random
if __name__ == "__main__":
print ("Ready...")
ser = serial.Serial("COM3", baudrate= 9600,
timeout=2.5,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE
)
data = {}
data["operation"] = "sequence"
data=json.dumps(data)
print (data)
if ser.isOpen():
ser.write(data.encode('ascii'))
ser.flush()
try:
incoming = ser.readline().decode("utf-8")
print (incoming)
except Exception as e:
print (e)
pass
ser.close()
else:
print ("opening error")
The arduino code.
#include <ArduinoJson.h>
void setup() {
Serial.begin(9600);
while(!Serial) {
}
}
void loop() {
int size_ = 0;
String payload;
while ( !Serial.available() ){}
if ( Serial.available() )
payload = Serial.readStringUntil( '\n' );
StaticJsonDocument<512> doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.println(error.c_str());
return;
}
if (doc["operation"] == "sequence") {
Serial.println("{\"Success\":\"True\"}");
}
else {
Serial.println("{\"Success\":\"False\"}");
}
delay(20);
}
Hope someone finds this useful.
Upvotes: 7