I'm communicating serially with an Arduino Mega2560 from Raspberry Pi v1 model B. The Mega is connected to the Pi's USB slot.
I'm using the rxtx library on the Pi to send data at 1,000,000 baud. The Arduino requests data from the Pi by transmitting 1 byte to the Pi. The Pi receives the byte, then replies with 3072 bytes. The Arduino receives the 3072 bytes and replies with one byte... etc. This process continues forever.
In this process the Pi only sends 3072 bytes 15 times a second (that's 43,008 bytes/sec.) This surprises me because 15 times a second is only around 460,000 baud, not 1,000,0000 baud!
1,000,000 baud is 125,000 bytes/sec.
125,000 / 3072 is about 40.
So I expected to send more like 40 chunks of 3072 bytes a second.
Given the Arduino is doing NO processing here, other than receiving the data and sending 1 byte, why can't I transmit 40 times a second? My only guess is maybe USB serial communication is half duplex, and so my effective baud rate is 500,000 but that's pure speculation... any ideas?
Edit:
I'm using the Java RXTX library. I've included my FPS test code below. Also I've tried transmitting in larger chunks, without waiting for request from the Arduino just to determine what my best baud rate was. I sent the same amount of data.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
public class FPSTest {
private static SerialPort createSerialPort(String portName, int baudRate) throws IOException {
SerialPort serialPort = null;
CommPortIdentifier portIdentifier = null;
try {
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
} catch (NoSuchPortException e) {
throw new IOException("No such port " + portName, e);
}
if (portIdentifier.isCurrentlyOwned()) {
throw new IOException("Error: Port is currently in use");
}
//
else {
int timeout = 2000;
CommPort commPort;
try {
commPort = portIdentifier.open(FPSTest.class.getName(), timeout);
} catch (PortInUseException e) {
throw new IOException("Port " + portName + " is in use", e);
}
if (commPort instanceof SerialPort) {
serialPort = (SerialPort) commPort;
try {
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
System.out.println("Baud raute = " + serialPort.getBaudRate());
} catch (UnsupportedCommOperationException e) {
throw new IOException("Unable to set serial port parameters", e);
}
}
//
else {
throw new IOException("Error: This device is not a serial port.");
}
}
return serialPort;
}
public static void main(String[] args) throws IOException, UnsupportedCommOperationException {
int baud = 1000000;
byte[] bytes = new byte[3072];
SerialPort port = createSerialPort("/dev/ttyUSB0", baud);
InputStream stream = port.getInputStream();
OutputStream output = port.getOutputStream();
long time = 0;
int fps = 0;
long fpsTime = 0;
System.out.println("begin reading...");
while (true) {
int result = stream.read();
output.write(bytes);
output.flush();
++fps;
if (time != 0) {
long elapsed = System.currentTimeMillis() - time;
fpsTime += elapsed;
}
if (fpsTime >= 1000) {
System.out.println("fps: " + fps);
fpsTime = 0;
fps = 0;
}
time = System.currentTimeMillis();
}
}
}
Here's the sketch I've loaded onto my Arduino:
#include "FastLED.h"
#define NUM_LEDS 1024
#define DATA_PIN 7
CRGB leds[NUM_LEDS];
int colors[8][3]={
{255,0,0},
{0,255,0},
{0,0,255},
{255,255,0},
{0,255,255},
{255,0,255},
{255,255,255},
{0,0,0}
};
void setup() {
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
Serial.begin(1000000);
bootupColorSequence();
}
void bootupColorSequence(){
for(int i=0;i<8;i++){
fill(colors[i][0],colors[i][1],colors[i][2]);
FastLED.show();
delay(100);
}
}
int serialReadBlocking(){
while(!Serial.available()){}
return Serial.read();
}
int numRead = 0;
int readFromSerial2(){
int result = 0;
if(numRead!=NUM_LEDS*3)
Serial.write((byte)1);
else
Serial.write((byte)0);
Serial.flush();
numRead = Serial.readBytes((char*)leds, NUM_LEDS*3);
return result;
}
void fill(int r,int g, int b){
for(long i=0;i<NUM_LEDS;i++)
{
leds[i].r = r;
leds[i].g = g;
leds[i].b = b;
}
}
void loop() {
int status = readFromSerial2();
FastLED.show();
}
I've tried adjusting the uart baud and clock speed under /boot/config.txt
to no avail. I don't recall performing further configuration.
I've tried JSSC now and had similar the exact same maximum bandwidth. This makes me think my problem native, either hardware or driver related as 2 Java implementations have had the same issue.