RumplyIntegral
RumplyIntegral

Reputation: 85

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?

Upvotes: 1

Views: 452

Answers (2)

RumplyIntegral
RumplyIntegral

Reputation: 85

I ended up adding an end character (0x36) and using a dataCompleteFlag:

       private void readUartBuffer(UartDevice uart) throws IOException {
        // Maximum amount of data to read at one time
        final int maxCount = 32;
        byte[] buffer = new byte[maxCount];
        boolean dataCompleteFlag = false;

        uart.read(buffer, maxCount);
        Log.i(TAG, Arrays.toString(buffer));

        if (!dataCompleteFlag) {
            for (int i = 0; i < maxCount; i++) {
                if (buffer[i] == 36) {
                    dataCompleteFlag = true;
                    dataCount = 0;
                }
                else if(dataCount > maxCount) {
                    dataCount = 0;
                }
                else if(buffer[i] != 0) {
                    finalDataBuffer[dataCount] = buffer[i];
                    dataCount++;
                }
            }
        }

        if (dataCompleteFlag) {
            //process data
        }
    }

    @Override
    public void onUartDeviceError(UartDevice uart, int error) {
        Log.w(TAG, uart + ": Error event " + error);
    }
};

Upvotes: 0

Andrii Omelchenko
Andrii Omelchenko

Reputation: 13343

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

Upvotes: 1

Related Questions