I am receiving data via UART from an Arduino. I followed the documentation and I get the data as expected most of the time. Sometimes the read does not finish, gets a few zeroes then starts a new read with the rest of the data. This can be seen in the example output, all the data is there but split into 2 reads. I am only sending data once a second so there should be plenty time.
My Code:
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
@Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
private void readUartBuffer(UartDevice uart) throws IOException {
// Maximum amount of data to read at one time
final int maxCount = 20;
byte[] buffer = new byte[maxCount];
uart.read(buffer, maxCount);
Log.i(TAG, Arrays.toString(buffer));
}
@Override
public void onUartDeviceError(UartDevice uart, int error) {
Log.w(TAG, uart + ": Error event " + error);
}
};
Example output:
[50, 48, 54, 46, 52, 53, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 57, 51, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 48, 52, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 55, 46, 51, 52, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 53, 48, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 55, 46, 51, 54, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
[50, 48, 54, 46, 57, 51, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 0, 0, 0, 0]
[51, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[50, 48, 55, 46, 51, 56, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 0, 0, 0, 0]
[51, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[50, 48, 54, 46, 52, 57, 32, 50, 49, 46, 55, 48, 32, 51, 51, 46, 51, 48, 32, 0]
I am quite sure the problem is the R Pi since I am looping back from the Arduino to my PC with no problems. I also found that unless I make maxCount the exact number of bytes I am sending, the problem is more prevalent. Whereby, the data comes in random packages but in the correct order. Am I wasting my time? Should I just use I2C?
"Should I just use I2C?" - no.
There is no problem with R Pi because "all the data is there". They (can be) split (or not, especially if it short) into 2 (or more) reads, because onUartDeviceDataAvailable()
can be fired before ALL data available (but only part of it was available), so you should read them in a loop until you receive all of them. And, from your code: maxCount - Maximum amount of data to read at one time
is not size for ALL data, it's max. size for one-time read. You code can be something like that (NB! it's just example, not complete solution):
private void readUartBuffer(UartDevice uart) throws IOException {
// Buffer for all data
final int maxSizeOfAllData = 30;
byte[] completaDataBuffer = new byte[maxSizeOfAllData];
// Buffer for one uart.read() call
final int maxCount = 20;
byte[] buffer = new byte[maxCount];
int bytesReadOnce; // number of actually available data
int totalBytesRead = 0;
// read all available data
while ((bytesReadOnce = uart.read(buffer, maxCount))) > 0) {
// add new data to "all data" buffer
for (int i = 0; i < bytesReadOnce; i++) {
completaDataBuffer[totalBytesRead + i] = buffer[i]
if (totalBytesRead + i == maxSizeOfAllData - 1) {
// process complete buffer here
...
totalBytesRead = 0;
break;
}
}
totalBytesRead += bytesReadOnce;
}
}
Also, take a look at NmeaGpsModule.java from Android Things user-space drivers and LoopbackActivity.java from Android Things samples.