You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino Serial.readBytes读取值异常问题排查

解决Arduino蓝牙接收指令乱序问题

问题根源

你遇到的乱序问题主要来自三个核心问题:

  1. 未等待完整帧就读取:原代码中Serial.available()仅判断缓冲区有数据,但不确保存在完整的4字节指令,导致每次读取的是不完整的片段与之前残留字节的拼接,出现乱码。
  2. 缓冲区重置错误:rcvData[4] = {};只清空了数组的第5个元素(索引4),而非整个数组,旧数据残留会干扰新接收内容。
  3. 无帧边界校验:蓝牙串口是流式传输,没有天然的帧分隔,必须通过逻辑确保每次接收完整的一条指令。

解决方案

方案一:等待完整字节数后读取

修改Arduino接收逻辑,确保缓冲区积累足够的4字节再处理,同时正确清空缓冲区:

// 全局变量定义
char rcvData[4];
String rcvIdent;

void loop() {
    // 等待缓冲区有至少4个字节再读取
    if (Serial.available() >= 4) {
        // 清空整个接收数组
        memset(rcvData, 0, sizeof(rcvData));
        rcvIdent = "";
        
        // 读取完整的4字节指令
        int bytesRead = Serial.readBytes(rcvData, 4);
        if (bytesRead == 4) {
            // 提取标识符
            for (int i = 0; i < 3; i++) {
                rcvIdent += (char)rcvData[i];
            }
            // 提取亮度值
            int brightness = rcvData[3];
            
            // 调试输出
            Serial.print("标识符: ");
            Serial.print(rcvIdent);
            Serial.print(" | 亮度: ");
            Serial.println(brightness);
            
            // 此处添加控制LED亮度的业务逻辑
        }
    }
}

方案二:添加帧分隔符(更可靠)

给每条指令添加结束符(比如换行符\n),让Arduino按完整行读取,避免字节数判断的误差:

移动端APP修改发送代码

try
{
    // 在指令末尾添加换行符作为帧结束标记
    byte[] charArr = new byte[] { (byte)'B', (byte)'R', (byte)'T', (byte)e.Progress, (byte)'\n' };
    myConnection.thisSocket.OutputStream.Write(charArr);
    System.Threading.Thread.Sleep(10);
}

Arduino端接收代码

void loop() {
    if (Serial.available()) {
        // 读取到换行符为止的完整指令
        String input = Serial.readStringUntil('\n');
        // 验证指令长度是否符合要求(原4字节指令)
        if (input.length() == 4) {
            String rcvIdent = input.substring(0, 3);
            int brightness = input[3];
            
            Serial.print("标识符: ");
            Serial.print(rcvIdent);
            Serial.print(" | 亮度: ");
            Serial.println(brightness);
            
            // 此处添加控制LED亮度的业务逻辑
        }
    }
}

额外优化建议

  • 滑块防抖:如果用户快速滑动滑块,APP会频繁发送指令,可能导致蓝牙缓冲区溢出。可改为滑块停止滑动后再发送指令,减少发送频率。
  • 指令校验:可以给指令添加校验位(比如异或校验),确保接收的指令没有传输错误,进一步提升可靠性。

内容的提问来源于stack exchange,提问作者Sam Pro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:24:46