Search code examples
serial-portuartandroid-things

Android Things Raspberry Pi UART Reliability Issue


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?


Solution

  • "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.