Android 事物 Raspberry Pi UART 可靠性问题

Android Things Raspberry Pi UART Reliability Issue

我正在通过 UART 从 Arduino 接收数据。我按照文档进行操作,大部分时间都按预期获得数据。有时读取没有完成,得到几个零,然后用其余数据开始新的读取。这可以在示例输出中看到,所有数据都在那里,但分为 2 个读取。我每秒只发送一次数据,所以应该有足够的时间。

我的代码:

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);
    }
};

示例输出:

    [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]

我很确定问题出在 R Pi 上,因为我可以毫无问题地从 Arduino 返回到我的 PC。我还发现,除非我将 maxCount 设置为我发送的确切字节数,否则问题会更加普遍。因此,数据以随机包的形式出现,但顺序正确。我在浪费时间吗?我应该只使用 I2C 吗?

"Should I just use I2C?" - 没有。 R Pi没有问题,因为"all the data is there"。它们(可以)拆分(或不拆分,尤其是如果它很短)分成 2 个(或更多)读取,因为 onUartDeviceDataAvailable() 可以在所有数据可用之前触发(但只有一部分可用),所以你应该阅读它们循环播放,直到您收到所有这些。而且,根据您的代码:maxCount - Maximum amount of data to read at one time 不是所有数据的大小,而是最大值。一次性读取的大小。您的代码可以是这样的(注意!这只是示例,不是完整的解决方案):

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;
    }
}

另外,看看 NmeaGpsModule.java from Android Things user-space drivers and LoopbackActivity.java from Android Things samples

我最后添加了一个结束字符 (0x36) 并使用了 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);
    }
};