PowerBroker2/pySerialTransfer

Transferring Integers Rather than Float/Double

haydos opened this issue · 2 comments

My project involves sending slew and luff motion control signals that range from 700 to 2300 from a Python program to an Arduino.
I have been able to successfuly transfer the data using the float(Python)/double(Arduino) object types.
I'd like to reduce the packet size as much as possible to maximise motion control scanrate, however I cannot seem to get integer transfers to work.
Any advice on how to transfer integers rather than floats is appreciated.

Arduino code and the test Python script below

'`#include "SerialTransfer.h"
#include <Servo.h>


Servo slewServo;
int slewServoPIN = 13;
int slewServoPosMin =  1100;
int slewServoPosMid =  1500;
int slewServoPosMax =  1800;


Servo luffServo;
int luffServoPIN = 12;
int luffServoPosMin =  1400;
int luffServoPosMid =  1600;
int luffServoPosMax =  2050;


SerialTransfer myTransfer;

struct STRUCT {
  double slew;
  double luff;
} ST_servoCtrlData;

bool BL_waitingForData = true;

int slewPos;
int luffPos;
int slewSV;
int luffSV;
int slewPosOld;
int luffPosOld;


void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
  slewServo.attach(slewServoPIN);
  slewServo.writeMicroseconds(slewServoPosMid);
  luffServo.attach(luffServoPIN);
  slewServo.writeMicroseconds(luffServoPosMid);
  
  slewPos = slewServoPosMid;
  luffPos = luffServoPosMid;

  
}


void loop()
{
  // Receive data
  if(myTransfer.available())
  {
    uint16_t recSize = 0; 
    recSize = myTransfer.rxObj(ST_servoCtrlData, recSize);
    BL_waitingForData = false;
    slewPos = int(ST_servoCtrlData.slew);
    luffPos = int(ST_servoCtrlData.luff);
  }



  //Servo control
  if((slewPos >= slewServoPosMin) && (slewPos <= slewServoPosMax))
  {
    slewServo.writeMicroseconds(slewPos);
  }
  if((luffPos >= luffServoPosMin) && (luffPos <= luffServoPosMax))
  {
    luffServo.writeMicroseconds(luffPos);
  }


  // Send data
  if(!BL_waitingForData) 
  {
    uint16_t sendSize = 0;
    sendSize = myTransfer.txObj(ST_servoCtrlData, sendSize);
    myTransfer.sendData(sendSize);
    BL_waitingForData = true;
  }


}`
from time import sleep
from pySerialTransfer import pySerialTransfer as txfer


class struct(object):
    slew = 300.0
    luff = 123.0

BL_waitingForReady = False


if __name__ == '__main__':
    try:
        testStruct = struct
        link = txfer.SerialTransfer('COM5')
        print("Serial port successfully connected")
        link.open()
        sleep(5)
    
        while True:
            
            if not(BL_waitingForReady):

                sendSize = 0
                sendSize = link.tx_obj(testStruct.slew, start_pos=sendSize)
                sendSize = link.tx_obj(testStruct.luff, start_pos=sendSize)
                link.send(sendSize)
                BL_waitingForReady = True
                print("Data transmitted")
            

            elif link.available():

                recSize = 0
                testStruct.slew = link.rx_obj(obj_type='f', start_pos=recSize)
                recSize += txfer.STRUCT_FORMAT_LENGTHS['f']
                testStruct.luff = link.rx_obj(obj_type='f', start_pos=recSize)
                recSize += txfer.STRUCT_FORMAT_LENGTHS['f']
                print('{} {}'.format(testStruct.slew, testStruct.luff))
                BL_waitingForReady = False
                
            elif link.status < 0:
                if link.status == txfer.CRC_ERROR:
                    print('ERROR: CRC_ERROR')
                elif link.status == txfer.PAYLOAD_ERROR:
                    print('ERROR: PAYLOAD_ERROR')
                elif link.status == txfer.STOP_BYTE_ERROR:
                    print('ERROR: STOP_BYTE_ERROR')
                else:
                    print('ERROR: {}'.format(link.status))


        
    except KeyboardInterrupt:
        link.close()

What might work is replacing all instances of 'f' with 'h'. See here for more details. You might also want to specify int32_t in your variable definitions on the Arduino side.

I did not understand that finding a good way of sending and receiving to and from an Arduino to Python was so difficult to do reliably. This solution seems to be the best and although it took time to understand and adapt the examples, I got there.
I can confirm if you change the data type to int in both sides, when sending from Python you will lose data, in may case the STRUCT was two integers and I consistently only got the first. Worked fine with float or double.
The solution was here, as suggested, you need to use the int32_t to define the integers in the STRUCT definition. Then it all works fine.
Thanks for this great piece of code.
serial-test.zip