The objective of this esp32 tutorial is to explain how to establish a Serial connection between a Python program and an Arduino program running on the ESP8266 and on the ESP32. The tests on the ESP32 were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 development board.
Introduction
The objective of this post is to explain how to establish a Serial connection between a Python program and an Arduino program running on the ESP8266 and on the ESP32.
The Arduino program will act as an echo program, which will return back the bytes received through serial.
In the Python program, we will use the PySerial module to be able to establish the Serial connection. The easiest way to install PySerial is by using pip, the Python package installer. To do it, we simply need to give the following command on the Windows command line:
pip install pyserial
The tests on the ESP32 were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.
The Arduino code
The Arduino code for this tutorial is very simple. In the Arduino setup function, we will open a serial communication with a call to the begin method of the Serial object. Note that the Serial object is of class HardwareSerial.
The begin method receives as input the baud rate in bits per second [1]. We will use a value of 115200, which we will also need to use later on the Python program.
void setup() {
Serial.begin(115200);
}
Now we will move on to the Arduino loop function, where we will handle de data received. There, we will check if there are bytes available for reading by calling the available method of the Serial object.
This method receives no arguments and returns the number of bytes available for reading [2]. Thus, we can write a loop that will keep reading the bytes of the Serial port while the available method indicates that there are bytes available.
while(Serial.available()){
// Handle bytes reception
}
To read a byte from the Serial port, we simple call the read method on the Serial object, which will return the next byte available.
Since our application will echo the content received back to the sender, we will then write it back by calling the write method on our Serial object. This method receives as input the byte we want to send [4].
while(Serial.available()){
Serial.write(Serial.read());
}
The final Arduino code can be seen below. Note that we have added a small delay between each iteration of the main loop.
void setup() {
Serial.begin(115200);
}
void loop() {
while(Serial.available()){
Serial.write(Serial.read());
}
delay(10);
}
The Python code
We will start out Python code by importing the serial module, which will be needed for us to establish a serial connection with the ESP board.
import serial
Next, we will create an object of class Serial. We will use the default constructor with no arguments and set the connection parameters after that.
ser = serial.Serial()
Next we need to configure our Serial connection parameters. Thus, we need to set the baud rate to match the one used on the ESP. To to do, we assign the value 115200 to the baudrate data member of the Serial class object.
ser.baudrate = 115200
We will also need to specify the COM port of the ESP. Note that this is the same COM port we use on the Arduino IDE to upload programs to the ESP. In my case it is COM5, yours will most likely be different. Note that this is set as a string.
ser.port = 'COM5'
Now that we have configured everything needed, we simply open the Serial port by calling the open method on the Serial object.
ser.open()
Since the connection is already opened, we can start sending some bytes to the ESP. We do it by calling the write method. We will send some arbitrary array of bytes which we will create with the bytearray function.
values = bytearray([4, 9, 62, 144, 56, 30, 147, 3, 210, 89, 111, 78, 184, 151, 17, 129])
ser.write(values)
Since our ESP program will echo all the bytes back to the Python program, we will create a while loop that will keep reading from the Serial port byte by byte, until a number of bytes equal to the size of the array sent is returned back.
To read a byte from the serial port, we call the read method of the Serial object. This method receives as input the number of bytes to read in each call and thus we will pass the value 1, to read byte by byte.
Note that if no timeout is set, this call will block until the number of bytes specified is returned [5].
An important thing to mention is that in some versions of Python the call to the read method will return an instance of str rather than of bytes [5], which we can convert back to bytes by calling the ord function.
total = 0
while total < len(values):
print(ord(ser.read(1)))
total=total+1
The final Python full code can be seen below and already includes this function call.
import serial
ser = serial.Serial()
ser.baudrate = 115200
ser.port = 'COM5'
ser.open()
values = bytearray([4, 9, 62, 144, 56, 30, 147, 3, 210, 89, 111, 78, 184, 151, 17, 129])
ser.write(values)
total = 0
while total < len(values):
print ord(ser.read(1))
total=total+1
ser.close()
Testing the code
To test the whole system, first compile and upload the code to your ESP board using the Arduino IDE.
Please note that in both ESP boards some characters get printed to the serial monitor when the Arduino program boots. Thus, if we run the Python program straight away, we will not receive the bytes we have sent. The easiest way to prevent this is by first opening the serial monitor to get those characters and then close it.
After that, we can start the Python script. You should get something similar to figure 1 on the Python prompt of the environment you are using, which shows the bytes we defined on the array being printed. In my case, I’m using IDLE, the Python IDE.
Figure 1 – Output of the program.