Comunicação gpio serie de números entre Arduino e Raspberry Pi com Python3 – completo

Nesta versão, os números passam como inteiros (int) ou flutuantes (float), e os textos como caracteres.

No Raspeberry o int é de 4 bytes, o long do Arduino. O float é o float ou o double do arduino.

Por outro lado, no Python3 do Raspberry Pi os int e os floats tem os bytes na ordem inversa do Arduino. Ou seja: 0 0 0 1 no pi, é 1 0 0 0 no arduino.

Programa do Arduino

serial_mod3_v2

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

//byte recGpio[64];
union u_tag {
byte b[4];
int i[2];
double d;
long l;
};
union u_tag recGpio[16];
boolean newGpio = false;

byte recUsb[64];
boolean newUsb = false;

#define GPIO_SEND_INTERVAL 1000
unsigned long gpioSendTimer;

unsigned long loopTimeStart;
int loopTime;

void setup() {
Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
mySerial.begin(9600);
gpioSendTimer = millis() + GPIO_SEND_INTERVAL;
loopTimeStart = millis();
}

void loop() {
if(millis() > gpioSendTimer) {
gpioSendTimer = millis() + GPIO_SEND_INTERVAL;
mySerial.print(gpioSendTimer); mySerial.print(" ");
mySerial.print(loopTime); mySerial.print(" ");
byte f;
mySerial.print(" ");
for(f = 0; f < 64; f++) {
if(recUsb[f] == '\n') break;
mySerial.print((char)recUsb[f]);
}
mySerial.print(" done"); mySerial.println("");
}

getUsbSerialUpdate();
getGpioSerialUpdate();

if(newGpio) {
byte f;
Serial.println("GPIO: ");
for(f = 0; f < 16; f++) {
Serial.print(recGpio[f].b[0]);Serial.print(" ");
Serial.print(recGpio[f].b[1]);Serial.print(" ");
Serial.print(recGpio[f].b[2]);Serial.print(" ");
Serial.print(recGpio[f].b[3]);Serial.print(" ");
}
Serial.println();
for(f = 0; f < 16; f++) {
Serial.print((char)recGpio[f].b[0]);
Serial.print((char)recGpio[f].b[1]);
Serial.print((char)recGpio[f].b[2]);
Serial.print((char)recGpio[f].b[3]);
}
Serial.println();
for(f = 0; f < 16; f++) {
Serial.print(recGpio[f].l); Serial.print(" ");
}
Serial.println();
for(f = 0; f < 16; f++) {
Serial.print(recGpio[f].d); Serial.print(" ");
}
Serial.println();
newGpio = false;
}

if(newUsb) {
byte f;
Serial.println("USB: ");
for(f = 0; f < 64; f++) {
Serial.print(recUsb[f]);Serial.print(" ");
//if(recUsb[f] == '\n') break;
}
Serial.println();
for(f = 0; f < 64; f++) {
Serial.print((char)recUsb[f]);
//if(recUsb[f] == '\n') break;
}
Serial.println();
newUsb = false;
}

loopTime = millis() - loopTimeStart;
loopTimeStart = millis();
}

void getUsbSerialUpdate() {
boolean complete = false;
static byte i = 0;
static byte rec[64];
while(Serial.available()) {
rec[i] = Serial.read();
if(rec[i] == '\n')complete = true;
i++;
}
if(complete) {
byte f;
// copy to global var
for(f = 0; f < 64; f++) {
recUsb[f] = rec[f];
}
// reset local var
for(f = 0; f < 64; f++) {
rec[f] = 0;
}
// reset control
newUsb = true;
i = 0;
}
}

void getGpioSerialUpdate() {
boolean complete = false;
static byte i = 0;
static byte rec[64];
while(mySerial.available()) {
rec[i] = mySerial.read();
//Serial.println(rec[i]);
if(rec[i] == '\n') {
complete = true;
rec[i] = 0;
}
i++;
}

if(complete) {
byte f;
// copy to global var
for(f = 0; f < 16; f++) {
// inverse bytes received
// from python3 raspberry pi
recGpio[f].b[3] = rec[f*4 + 0];
recGpio[f].b[2] = rec[f*4 + 1];
recGpio[f].b[1] = rec[f*4 + 2];
recGpio[f].b[0] = rec[f*4 + 3];
}
// reset local var
for(f = 0; f < 64; f++) {
rec[f] = 0;
}
// reset control
newGpio = true;
i = 0;
}
}


Programa do Raspberry

gpioserial4.py

#!/usr/bin/python3
import threading
import queue
import time
import serial
import struct

def is_float(input):
try:
num = float(input)
except ValueError:
return False
return True

def is_int(input):
try:
num = int(input)
except ValueError:
return False
return True

def read_kbd_input(inputQueue):
print('Ready for keyboard input:')
while (True):
input_str = input()
inputQueue.put(input_str)
def main():
EXIT_COMMAND = "exit"
inputQueue = queue.Queue()

inputThread = threading.Thread(target=read_kbd_input, args=(inputQueue,), daemon=True)
inputThread.start()

ser = serial.Serial('/dev/ttyAMA0',9600)

while (True):
if (inputQueue.qsize() > 0):
input_str = inputQueue.get()
print("input_str = {}".format(input_str))
if (input_str == EXIT_COMMAND):
print("Exiting serial terminal.")
break

# Insert your code here to do whatever you want with the input_str.


args = input_str.split(" ")
count = 0
total = len(args)
while (count < total):
sent = 0;
if (len(args[count]) == 0):
break

if(is_int(args[count])):
tmp = int(args[count])
tmp = struct.pack('>I', tmp)
ser.write(tmp)
sent = 1
if(sent == 0):
if(is_float(args[count])):
tmp = float(args[count])
tmp = struct.pack('>f', tmp)
ser.write(tmp)
sent = 1
if(sent == 0):
str = bytes(args[count], 'utf-8')
ser.write(str)
sent = 1

count += 1

str = bytes('\n', 'utf-8')
ser.write(str)

# The rest of your program goes here.
read_serial=ser.readline().decode('ascii').replace('\n', '')
print (read_serial)

# Sleep for a short time to prevent this thread from sucking up all of your CPU resources on your PC.
#time.sleep(0.02)

print("End.")

if (__name__ == '__main__'):
main()