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.