【问题标题】:Android Things Raspberry Pi UART Reliability IssueAndroid Things Raspberry Pi UART 可靠性问题
【发布时间】:2018-12-16 04:44:04
【问题描述】:

我正在通过 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 吗?

【问题讨论】:

    标签: serial-port uart android-things


    【解决方案1】:

    “我应该只使用 I2C 吗?” - 不。 R Pi 没有问题,因为“所有数据都在那里”。它们(可以)拆分(或不拆分,特别是如果它很短)为 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;
        }
    }
    

    另外,看看Android Things user-space drivers 中的NmeaGpsModule.javaAndroid Things samples 中的LoopbackActivity.java

    【讨论】:

    • 谢谢,这对我来说似乎是一个小故障,但正如你所说,数据就在那里。我只需要完成正确存储它的工作,这基本上是您为我完成的,我很感激。会试一试并报告。
    • 附带说明,对于那些可能感兴趣的人:数据的长度并不总是相同的。我将多个传感器读数作为浮点数发送。因此,例如,如果距离读数为 100 厘米,则它的字节数比 99 厘米多。我只会有一个结束字符而不是有一个 maxSizeOfAllData。如果有更好的方法,请告诉我。
    • 一般来说,一个数据包要么有一个固定大小的包头指示完整的包大小,要么包含一个结束字符
    • @RumplyIntegral NmeaGpsModule.java 是非固定长度数据接收的好例子。
    • @RumplyIntegral 正确的方法是使用一些交换协议:如果从未收到 maxSizeOfAllData 字节(您的 Arduino 设备关闭电源或其他什么)怎么办?
    【解决方案2】:

    我最终添加了一个结束字符 (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);
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-29
      • 2023-03-13
      • 1970-01-01
      • 2018-06-01
      相关资源
      最近更新 更多