I'm working on writing a reusable Arduino <-> Python communications library for scientific instruments, and as part of that I would like to transfer data at high speed to Python running on a host PC. I tested the transfer rate from both the programming and native USB ports and don't fully understand the results. I tried transferring strings with 1 to 10000 characters (call the number of characters N). Each string was written with one call to Serial.print() or SerialUSB.print(), and read by a Python script on the host computer. In each case, the port was opened with baudrate = 115200 (which doesn't seem to be relevant on the native USB port). I included my full code below.
with Serial (programming port), the length of the string didn't matter:
N = 1 --> ~ 11700 bytes/s
N = 10000 --> ~ 11700 bytes/s
Assuming 9 bits (1 stop bit) per byte transferred, this gives 105300 bits/second (not far from 115200), which makes sense.
with SerialUSB (native port), there was a huge dependence on N:
N = 1 --> ~ 4800 bytes/s (0.2 ms per print statement)
N = 10 --> ~ 48000 bytes/s (0.2 ms per print statement)
N = 100 --> ~ 480000 bytes/s (0.2 ms per print statement)
N = 1000 --> ~ 4500000 bytes/s (0.2 ms per print statement)
N = 10000 --> ~ 5200000 bytes/s (1.9 ms per print statement)
So, the native port is fast (~5 Megabytes per second) with long arrays. However, it seems that there is some overhead with transfers over the native USB port, since transfers of 1 or 100 characters take about the same time. My question is: where does this come from and what is the best way to deal with it? Is it time associated with starting a transfer (~ 0.2 ms), is the native port using something like a fixed large (~ 1024 byte) packet size per print statement, or am I just misunderstanding? I don't know much about the underlying USB transfer and I have not seriously tried to look through the Arduino library code.
For high speed transfers, does it really make sense to buffer a bunch of smaller transfers to an array and send them all at once, or is there some parameter in the Arduino libraries that could be adjusted? I don't want to waste a > 1000 byte buffer and spend extra time moving around data if it is not necessary.
Here is the Arduino DUE code I used (Arduino 1.5.2). Set BUF_N to the number of chars in the string + 1 for termination.
#define BUF_N 10001
char buf[BUF_N];
void setup() {
//Serial.begin(115200);
SerialUSB.begin(115200); // baud rate ignored for usb virtual serial
memset(buf, 'A', BUF_N-1);
buf[BUF_N-1] = '\0';
}
void loop() {
//Serial.print(buf);
SerialUSB.print(buf);
}
And running in Python (Python 2.7.3 on Windows XP):
import time
import serial
ser = serial.Serial(
port='COM10',
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
last_time = time.time()
n = 10000000 # this doesn't change the reported rate noticeably
while True:
ser.read(n);
new_time = time.time()
print str(float(n)/(new_time-last_time)) + ' bytes/s'
last_time = new_time
Earlier discussions of the available baud rates (which are related to my question) include: