Python, Serial Port, Arduino and JSON

I always wanted to find an efficient way to share information between an Arduino and a computer. You can send raw strings, use a protocol or even create your own. In this context, I will use as example a DHT11 sensor with an Arduino Uno to retrieve data back.


DHT11 Sensor

This sensor is very basic and slow, but is perfect for some basic data logging. There is a chip inside that does the analog to digital conversion and returns a digital signal with the temperature and humidity. You can find out more with the DHT11 datasheet or here.

Note: like it’s very slow, the delay between 2 data acquisition should not be under 2 seconds, otherwise, you will receive nothing because the chip won’t stop processing the data.

Wiring

For the PCBless version, it’s recommended to use a 4.7kΩ resistor on the data line. If you don’t have it, it should still working.

Note: You should pay attention to the wiring according to the small pin’s description. There is one setup left where the wire order can be different according to your PCB.

Arduino Setup

With your Arduino IDE, let’s install some additional library:

We can install the “DHT sensor library” by Adafruit:

If the IDE is asking to install a third-party library (Adafruit Unified Sensor Lib), it’s normal, just accept.
As a base, you can use the example given for this library called “DHTTester” in the File -> Examples sub-menu.

Everything is already well commented, but don’t forget to change the DHTPIN to 4 (according to the scheme above) and uncomment the DHT11 type. After downloading the program to Arduino, the serial monitor should tell us everything.

Now, let’s see how to deal with that on the computer side.

Python and Serial Port

Python has a great asset, it’s that you have a package for almost everything. Among them, you can communicate through serial port with PySerial library. If you would like to setup a virtualenv, see here, or you can install the package directly:

pip install pyserial

Now, the code:

import serial

connection = serial.Serial(port="COM3", baudrate=9600)
connection.reset_input_buffer()

while True:
    data = connection.readline().decode("utf-8")
    print(data)

Which will show the same thing as in Arduino IDE:

Here we are. Now, you might want to datalog all this. But a string like that does not seem convenient to manage. It requires to iterate through the string and isolate information we want or adjust the Serial.print() on Arduino side. Or even create your own protocol saying that it will look like: “t23.5;h34”. I will propose next a way that I’ve found much easier to manage.

Arduino and JSON

JSON (for JavaScript Object Notation) is a common data interchange format that uses human-readable text to store and transmit data objects. It looks like this:

{
  "temp": 18.5,
  "humidity": 33
}

This format is very close to one in Python, a dictionary. So what if we are using it to get our sensor data?

JSON Arduino Setup

I’ve found the ArduinoJson library randomly and it can serialize/de-serialize data in JSON format. Combined with Python JSON library, I think it’s really powerful.

On Arduino

You need to install the ArduinoJson library:

After adding the header in your Arduino code (#include <ArduinoJson.h>), we create a document object that will contain our data.

StaticJsonDocument<48> doc;

The <48> is the size of your document. To know how to calculate it, there is an assistant which will help you. You need to enter in JSON format, an example of data that you want to send. Then, we will read the data from the sensor and store it in the JSON document before sending it.

#include "DHT.h"
#include <ArduinoJson.h>

#define DHTPIN 4 // Digital pin connected to the DHT sensor

#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);
StaticJsonDocument<48> doc;

void setup() {
  Serial.begin(9600);
  //Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements (slow sensor).
  delay(2000);

  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();

  doc["temp"] = t;
  doc["humidity"] = h;

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  serializeJson(doc, Serial);
  Serial.println();
}

Note the last Serial.println(), if you don’t put it, the JSON document will not be send.

With Python

By default, Python has the json library, so let’s import it, and store our data into a dictionary.

import json
import serial

connection = serial.Serial(port="COM3", baudrate=9600)
connection.reset_input_buffer()

while True:
    data = connection.readline().decode("utf-8")
    # print(data)
    try:
        dict_json = json.loads(data)
        print(dict_json)
    except json.JSONDecodeError as e:
        print("JSON:", e)

Which shows: {‘temp’: 22.2, ‘humidity’: 27}. If you want to read data independently, you can access with: dict_json.get(“temp”) or dict_json.get(“humidity”).

2 thoughts on “Python, Serial Port, Arduino and JSON

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.