This post is an extension to Structures, Serialisation, XOR Checksums etc. thread.
The code published below is tested boilerplate code for serial transfer of data in the form of structs, from an Arduino to Python.
My thanks to both @frogandtoad and @ZeFerby for their tips and pointers.
An explanation: The values from sensors are gathered and stored in the Arduino in a pre-defined struct object and subsequently sent to Python as a data packet. This data packet is unwrapped by Python into a tuple (an array that can handle different data-types) for further processing.
It should be noted that to resolve any data misalignment the largest data-types are sent first with the smaller data types following in order of size (float = 4 bytes, int = 2 bytes, char = 1 byte).
First the Arduino sketch;
// to maintain data alignment the members of the struct object // are ordered largest to smallest data type i.e. float = 4 bytes // uint8_t = 1 byte typedef struct{ float afloat = -15.4; // 4 bytes uint8_t abyte = 12; // 1 byte uint8_t bbyte = 5; // 1 byte }data; data myData; void setup() { Serial.begin(115200); } void loop() { delay(5000); Serial.write((const byte*)&myData, sizeof(myData)); }
And now the cleaned up Python sketch:
import serial
import struct
my_comm_port = '/dev/cu.wchusbserial1460'; # *nix comm port notation
try:
# Change the baud rate here if different than 115200
ser = serial.Serial(
port='/dev/cu.wchusbserial1460',\
baudrate=115200,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=None
)
print("connected to: " + ser.portstr)
except IOError:
print("Invalid comm port!")
exit(1)
# f = float, B = unsigned Char (uint8_t equivalent)
size = struct.calcsize('fBB')
print(size)
def main():
while True:
data = ser.read(size)
#struct.unpack(format, bytestring)
tup = struct.unpack('fBB', data)
print(tup[0])
print(tup[1])
print(tup[2])
ser.close()
if __name__ == '__main__':
main ()
Have fun using this in your projects!
Very nice short and concise code Steve. Thanks for sharing.
I'm curious if this would work with SPI instead of using the serial ports?
Say I had the Python code running on a Raspberry Pi and I was connected to the Arduino via SPI. What would I need to change in these codes? And would it still work with SPI?
Thanks.
DroneBot Workshop Robotics Engineer
James
Say I had the Python code running on a Raspberry Pi and I was connected to the Arduino via SPI. What would I need to change in these codes? And would it still work with SPI?
This is where I would start experimenting, I doubt if this program would run correctly straight away, but it is my idea of a jumping-off point to be refined later.
Thanks for the links Steve, these will be very helpful. ?
DroneBot Workshop Robotics Engineer
James
Did you have any luck with the Python sketch?
I can't test it myself as I don't own a RasbPi and I know that the SpiDev library will not compile on my Mac!
I'm not prepared to do it at the moment. I don't currently have a rpi and an Arduino connected via SPI. I just thought that since Bill is planning on using SPI for the rpi/Arduino communication I might go that route myself. I've actually been using the Serial port when communicating between these two devices and I have never even used SPI for anything. So I thought I might look into it. So I'm saving this info for future ideas.
I might set up a rpi/Arduino SPI connection on the fly here to just gain some experience with it. Right now I'm playing with setting up dimensions in Blender. Too many toys I don't have time to play with them all. ?
DroneBot Workshop Robotics Engineer
James