Increase send-receive speed between Arduino and linux computer

Hi,

I have a problem where i send data from a Teensy 3.6 which runs arduino to the computer, do some calculations on that data and send it back to the arduino using serial communiciation over a USB.
And I would like to do this as fast as possible. ​The computer runs on real time linux, but i'm not smart enough to understand any of that.

Underneath I have code (based on code found on this forum), where i send and recieve a short string (see underneath) and it is very slow. I can do the send-recieve loop at 200Hz.

Is there any ​way that I can make this faster? I have full control over what I can change on the computer and hardware. Installing other kernels, maybe ethernet or things like that. So any solutions are welcome.

Code on the arduino:

const byte buffSize = 40;
char inputBuffer[buffSize];
const char startMarker = '<';
const char endMarker = '>';
byte bytesRecvd = 0;
boolean readInProgress = false;
boolean newDataFromPC = false;

char messageFromPC[buffSize] = {0};


//=============

void setup() {
  Serial.begin(57600);
}

//=============

void loop() {
  getDataFromPC();
  replyToPC();
}

//=============

void getDataFromPC() {

    // receive data from PC and save it into inputBuffer
   
  if(Serial.available() > 0) {

    char x = Serial.read();

      // the order of these IF clauses is significant
     
    if (x == endMarker) {
      readInProgress = false;
      newDataFromPC = true;
      inputBuffer[bytesRecvd] = 0;
      strcpy(messageFromPC, inputBuffer); //not sure if this is still needed
    }
   
    if(readInProgress) {
      inputBuffer[bytesRecvd] = x;
      bytesRecvd ++;
      if (bytesRecvd == buffSize) {
        bytesRecvd = buffSize - 1;
      }
    }

    if (x == startMarker) {
      bytesRecvd = 0;
      readInProgress = true;
    }
  }
}


//=============

void replyToPC() {

  if (newDataFromPC) {
    newDataFromPC = false;
    Serial.print("<");
    Serial.print(messageFromPC);
    Serial.print(">");
  }
}

//============

Code on python (pyserial):

#=====================================

#  Function Definitions

#=====================================

def sendToArduino(sendStr):
    ser.write(sendStr.encode('utf-8')) # change for Python3


#======================================

def recvFromArduino():
    global startMarker, endMarker
   
    ck = ""
    x = "z" # any value that is not an end- or startMarker
    byteCount = -1 # to allow for the fact that the last increment will be one too many
   
    # wait for the start character
    while ord(x) != startMarker:
        x = ser.read()
   
    # save data until the end marker is found
    while ord(x) != endMarker:
        if ord(x) != startMarker:
            ck = ck + x.decode("utf-8") # change for Python3
            byteCount += 1
        x = ser.read()
   
    return(ck)


#============================

def waitForArduino():

    # wait until the Arduino sends 'Arduino Ready' - allows time for Arduino reset
    # it also ensures that any bytes left over from a previous message are discarded
   
    global startMarker, endMarker
   
    msg = ""
    while msg.find("Arduino is ready") == -1:

        while ser.inWaiting() == 0:
            pass
       
        msg = recvFromArduino()

        print (msg) # python3 requires parenthesis
        print ()
       
#======================================

def runTest():
    waitingForReply = False

    for i in range(1,1000):

        if waitingForReply == False:
            sendToArduino('<'+str(i)+'>')
            waitingForReply = True

        if waitingForReply == True:

            while ser.inWaiting() == 0:
                pass
           
            dataRecvd = recvFromArduino()
            print ("Reply Received  " + dataRecvd)

            waitingForReply = False
            print ("-------------------")


#======================================
# THE DEMO PROGRAM STARTS HERE
#======================================
# as sudo -s, doing this doesn't make a difference: setserial /dev/ttyACM0 low_latency
import serial
import time


# NOTE the user must ensure that the serial port and baudrate are correct
portname = "/dev/ttyACM0"
baudrate = 57600
ser = serial.Serial(portname,baudrate,timeout=1)

startMarker = 60
endMarker = 62
t1 = time.time()
runTest()
print(time.time()-t1) #between 4.98 and 5.2 seconds
ser.close()

I have tried the same via LibSerialPort via the julia programming lanuage instead of pyserial and i get exactly the same 200Hz. So i have a feeling that it is at the side of the computer that something can be done faster.

You can use a baud rate that is much faster. I use 250000 sometimes.

Thanks for the quick response.

I tried that too, but got the same results. I read here that Teensies have a fixed baud rate of 12 MB/s.

Also doubling the length of the data that is sent to the Teensy from the computer doesn't seem to have an effect.

If a higher baud rate doesn't help then I would suspect that the delay is on the Linux box.

Try putting some logging in on the python side to see where it is spending its time.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.