In this part of the Meshtastic with Raspberry Pi (Serial) series, we will be writing some code to test the connection, then adding to our code to send sample data. When sending data, we will format the message to allow us to reject data if it is not formatted correctly and do some simple error detection.
A good resource, which will be used to write this code may be found on the “Raspberry Pi UART Communication using Python and C” page on the ElectronicWings site.
Preparation
You need to start off by editing the cmdline.txt file to remove the console=serial0,115400 argument and value. If you don’t do this, you will see errors similar to ‘device reports readiness to read but returned no data’. More information and background is available at https://raspberrypi.stackexchange.com/questions/111817/serial-serialutil-serialexception-device-reports-readiness-to-read-but-returned
On the Raspberry Pi, open a terminal window or use PuTTY to run the following command.
sudo nano /boot/cmdline.txt

Comment out or delete the “console=serial0,115400” in the line.

Once the cmdline.txt has been modified, restart the Raspberry Pi.
NOTES: If the console=serial0,115400 is missing, you skipped enabling the serial port from the raspi-config tool. Look back at the earlier posts in this series for instructions on how to enable the serial port. It is also possible that the baud rate in the command is something other than 115400 so you may see a different baud rate, which is fine, but you will need to remove that argument from the file.
Test Program
Now that the serial port is properly configured, we can write a simple program and test the T-Beam connection to the Raspberry Pi. On both Raspberry Pi boards, create a uart.py file with the following code.
'''
UART communication on Raspberry Pi using Python
http://www.electronicwings.com
'''
import serial
from time import sleep
ser = serial.Serial ("/dev/ttyS0", 38400) #Open port with baud rate
while True:
raw_data = ser.read() #read serial port
sleep(0.03)
if raw_data:
data_len = ser.inWaiting()
raw_data += ser.read(data_len) #read serial port
received_data = str(raw_data, "utf-8")
print (received_data) #print received data
The code will listen for data on the serial port and will print the received data in the terminal window. Run the code on both Raspberry Pi boards by typing the following command.
sudo python uart.py
On the Android device, open the Meshtastic application and type a message and press the send button.

The message will be displayed in the terminal window of the receiving Raspberry Pi device.

Sample code sending and receiving data
Before using the following example, it is suggested to change the serial configuration to “Simple” and creating an additional channel named “serial”. Screenshots were taken of the Meshtastic application and placed into a Google Album. Refer to the album if you have any questions regarding what configuration values were used for this example.
The sample code will send CPU Temperature data twice per minute. Below are a few notes/requirements.
- The data will be sent as JSON.
- The data will be contained in a Python Dictionary with string values for the keys.
Sample keys:- t: Time in UTC ISO 8601 format without milliseconds
- nam: The host name of the Raspberry Pi
- cput: CPU Temperature in degrees Celsius
- Float values will be sent as formatted strings with the precession required for the application. As an example, temperature will be sent with two decimal values.
- The total length of the message shall not exceed 200 bytes. In practice, it should be kept well below 200 bytes. This requires that the keys for the key value pairs to be kept short.
Example Code:
The following example code was written to meet the above requirements.
'''
- References -
--------------
ISO 8601
https://pynative.com/python-iso-8601-datetime/
UART communication on Raspberry Pi using Pyhton
http://www.electronicwings.com
'''
import serial
import time
from datetime import datetime, timezone
import re
import socket
import json
def get_temp():
with open('/sys/class/thermal/thermal_zone0/temp', 'r') as infile:
return float(infile.read()) * 1e-3
# Open port with baud rate
ser = serial.Serial("/dev/ttyS0", 38400)
# Set the start time in the past so that the first data point will be sent at the startF
start = time.time() - 600
# Create a variable for the received data.
received_data = ""
# Flag for knowning if the error for T-Beam being disconnected has been displayed
no_serial = False
try:
while True:
data_len = 0
data_len = ser.in_waiting
utc_dt = datetime.now(timezone.utc).replace(microsecond=0)
if data_len > 0:
raw_data = ser.read(data_len) # read serial port
try:
received_data += str(raw_data, "utf-8")
x = re.search("\{.*\}", received_data)
if x:
# PuTTY changes tab characters to spaces so we will use the pipe symbol
# print(F"{utc_dt.isoformat()}\tRECV\t{x[0]}")
print(F"{utc_dt.isoformat()}|RECV|{x[0]}")
received_data = ""
if no_serial:
no_serial = False
except UnicodeDecodeError:
received_data = ""
if not no_serial:
print("ERROR: The serial connection may be down")
no_serial = True
if time.time() - start > 30:
start = time.time()
temp = get_temp()
dat = {
"t": utc_dt.isoformat(),
"nam": socket.gethostname(),
"cput": F"{temp:0.2f}",
}
if len(json.dumps(dat)) < 200:
ser.write(bytes(json.dumps(dat), "utf-8"))
# PuTTY changes tab characters to spaces so we will use the pipe symbol
# print(F"{utc_dt.isoformat()}\tSENT\t{json.dumps(dat)}")
print(F"{utc_dt.isoformat()}|SENT|{json.dumps(dat)}")
else:
print(
F"ERROR: Data length is greater than 200 bytes (length={len(json.dumps(dat))})")
except KeyboardInterrupt:
print("\r\nExiting")
# finally:
# GPIO.cleanup()
Below is the output from both Raspberry Pi boards running the code with the same T-Beam Meshtastic settings.

An Excel workbook was put together to check the delay from transmit and receive as well as identifying packets being received out of order. Previous runs with slightly different code did contain out of order packets so it should not be assumed that packets will be received in order. Below is the Check.xlsx file that you may download.
Below are some statistics from the Check.xlsx Excel Workbook with data produced from 27 minutes runtime of the sample code.
- pi-sensor01
- Receive Delay (hh:mm:ss)
- Min: 00:00:07
- Max: 00:04:12
- Average: 00:01:28
- Median: 00:00:57
- Data Received out of order: 0
- Data Points
- Total: 104
- Sent: 56
- Received: 48
- Sent Packets Received by pi-sensor01:
- Received: 55
- Not Received: 1
- Percent of Packets Received: 98.21%
- Receive Delay (hh:mm:ss)
- pi-sensor02
- Receive Delay (hh:mm:ss)
- Min: 00:00:07
- Max: 00:01:35
- Average: 00:00:23
- Median: 00:00:15
- Data Received out of order: 1
- Data Points
- Total: 111
- Sent: 56
- Received: 55
- Sent Packets Received by pi-sensor01:
- Received: 48
- Not Received: 8
- Percent of Packets Received: 85.71%
- Receive Delay (hh:mm:ss)
Going Further
This is the end of this series at least for now. It was put together to provide some information with one way to send data between two Raspberry Pi devices using serial communications. There are other ways to send data using the serial port. One of the more interesting ways may be using the PROTO mode for the Meshtastic serial port. It looks like using the PROTO mode may allow for the code to setup and configure the Meshtastic device. If that is the case, it may provide much more control and standardization across connections. (Meshtastic Serial Port Configuration)
Another area to look into is how to improve the successful delivery of messages in a timely manor. It may be sending messages every 30 seconds was too fast and flooded the available channels. It may also be possible that the store and forward setting was misunderstood and caused message flooding on the channel. The devices may have been too close together to provide reliable communications. All of these things and others could be looked into to see if it is possible to create more reliable communications.
You must be logged in to post a comment.