I recently started using the Arduino Due for a high-speed ADC project, and I need to be able to write ~3MBit/s to a PC with the overhead of the Arduino code to communicate with that ADC. I have been doing some testing of the native arduino speed using SerialUSB (arduino_USB_slow.ino), and have got communication to work with a simple python script using pySerial.
With increasing block size I am able to increase the data rate (from 1.22MBit/s writing one byte at a time to SerialUSB to 7.58Mbit/s using 8 bytes at a time). This is great, but I'm cycle-constrained and need to do better than this. However, if I try to send more than 8 bytes at a time with the SerialUSB.write() command, I get no data transferred over the serial port at all. My pySerial input buffer stays at 0 bytes after opening the port, which I check using port.in_waiting. There are no problems compiling the code on the arduino side, no problems uploading it, and no problems with either the arduino or pyserial when trying to write 8 bytes. The problem only exists when I try to write more than 8 bytes (I've tried 9, 10, 16, 64, none of them have worked).
There's no indication in the Serial library documentation of a limitation on the input byte array size, and as I understand it if the buffer isn't large enough, the SerialUSB library on the Arduino side will just block further execution until the hardware buffer is refilled enough times to get through all the data. Other people have managed to use much larger block size without difficulty.
This does appear to be a pySerial issue, because when I open the USB device with minicom and run:
sudo cat /dev/tty.usbmodem11414
I get a bunch of binary barf that isn't present when the device isn't transmitting. This tells me the problem isn't with the Arduino (it's sending over its data just fine), but with pySerial or how I am using it. Is there a word limitation on pyserial when receiving a stream of data? This seems really bizarre. The pyserial code is dead simple:
import serial
import numpy as np
maxBytes = 1000000
byteCounter = 0
dataBuffer = np.zeros(maxBytes + 1020)
arduino = serial.Serial()
arduino.port = '/dev/cu.usbmodem14141'
arduino.open()
while byteCounter < maxBytes:
bytesAvailable = arduino.in_waiting
dataBuffer[byteCounter:byteCounter+bytesAvailable] = np.frombuffer(arduino.read(bytesAvailable), dtype='uint8')
byteCounter += bytesAvailable
print(byteCounter)
And the Arduino code is below:
char adcData[16] = {'a', 'a', 'a', 'a','a', 'a', 'a', 'a','a', 'a', 'a', 'a','a', 'a', 'a', 'a'};
void setup() {
SerialUSB.begin(9600);
}
void loop() {
SerialUSB.write(adcData);
}