I have working code that sends a struct from a Raspberry Pi to an Arduino using pySerialTransfer when the devices are connected via a USB cable. I'd like to do that over bluetooth instead of with a USB cable, however.
Independently, using separate python code and a separate Arduino sketch, I've been able to get the Raspberry Pi & Arduino to communicate over bluetooth via a continuous stream of text or binary data.
My issue is that I don't see how to combine the two approaches - i.e.: if I send a binary-encoded structure over bluetooth, I don't see how I get the benefits of the pySerialTransfer / SerialTransfer libraries to parse it on the receiving end. I see how I can do the parsing "manually", looking for special terminating characters, etc., but I was hoping to avoid the need for that with pySerialTransfer.
Thanks for any pointers / suggestions / examples. All the working code I've been able to construct so far is here.
pySerialTransfer
Working Arduino C serial code
#include "SerialTransfer.h"
SerialTransfer myTransfer;
int const ONBOARD_LED_PIN = 13;
struct POSITION {
int id;
float azimuth;
float altitude;
} position;
void Blink(int n) {
for (int i=0; i<n; i++) {
digitalWrite(ONBOARD_LED_PIN, HIGH);
delay(75);
digitalWrite(ONBOARD_LED_PIN, LOW);
delay(75);
}
delay(150);
}
void setup()
{
Serial.begin(115200);
myTransfer.begin(Serial);
pinMode(ONBOARD_LED_PIN, OUTPUT);
digitalWrite(ONBOARD_LED_PIN, LOW);
}
void loop()
{
if(myTransfer.available())
{
//////////////////////////////////////////////
// handle call from Python
myTransfer.rxObj(position, sizeof(position));
//////////////////////////////////////////////
//////////////////////////////////////////////
// send response
myTransfer.txObj(position, sizeof(position));
myTransfer.sendData(sizeof(position));
//////////////////////////////////////////////
}
else if(myTransfer.status < 0)
{
Serial.print("ERROR: ");
if(myTransfer.status == -1)
Serial.println(F("CRC_ERROR"));
else if(myTransfer.status == -2)
Serial.println(F("PAYLOAD_ERROR"));
else if(myTransfer.status == -3)
Serial.println(F("STOP_BYTE_ERROR"));
}
}
Working Raspberry Pi serial code
import time
import struct
from pySerialTransfer import pySerialTransfer
def StuffObject(txfer_obj, val, format_string, object_byte_size, start_pos=0):
"""Insert an object into pySerialtxfer TX buffer starting at the specified index.
Args:
txfer_obj: txfer - Transfer class instance to communicate over serial
val: value to be inserted into TX buffer
format_string: string used with struct.pack to pack the val
object_byte_size: integer number of bytes of the object to pack
start_pos: index of the last byte of the float in the TX buffer + 1
Returns:
start_pos for next object
"""
val_bytes = struct.pack(format_string, *val)
for index in range(object_byte_size):
txfer_obj.txBuff[index + start_pos] = val_bytes[index]
return object_byte_size + start_pos
if __name__ == '__main__':
try:
link = pySerialTransfer.SerialTransfer('/dev/cu.usbmodem14201', baud=115200)
link.open()
time.sleep(2) # allow some time for the Arduino to completely reset
base = time.time()
while True:
sent = (4, 1.2, 2.5)
format_string = '<lff'
format_size = 4+4+4
StuffObject(link, sent, format_string, format_size, start_pos=0)
link.send(format_size)
start_time = time.time()
elapsed_time = 0
while not link.available() and elapsed_time < 2:
if link.status < 0:
print('ERROR: {}'.format(link.status))
else:
print('.', end='')
elapsed_time = time.time()-start_time
print()
response = bytearray(link.rxBuff[:link.bytesRead])
response = struct.unpack(format_string, response)
print('SENT: %s' % str(sent))
print('RCVD: %s' % str(response))
print(' ')
except KeyboardInterrupt:
link.close()
Bluetooth Communication
Working Arduino bluetooth communication
#include "SerialTransfer.h"
// Connect the HC-05 TX to Arduino pin 2 RX.
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.
//
long n = 0;
struct POSITION {
float azimuth=5;
float altitude=10;
};
SerialTransfer myTransfer;
void setup()
{
Serial.begin(9600);
// HC-06 default serial speed for communcation mode is 9600
Serial1.begin(9600);
myTransfer.begin(Serial1);
}
void loop()
{
n++;
POSITION x;
x.azimuth=n;
x.altitude=n+1;
myTransfer.txObj(x, sizeof(x));
myTransfer.sendData(sizeof(x));
if(Serial1.available() > 0){ // Checks whether data is comming from the serial port
Serial.println(Serial1.read());} // Reads the data from the serial port
delay(1000);
}
Working python bluetooth communication
import bluetooth
sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
bd_addr = '98:D3:11:FC:42:16'
port = 1
sock.connect((bd_addr, port))
d = sock.recv(10240000)
print(d)
sock.send("hello")