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

浏览器与Arduino串口通信丢字节及done变量异常问题求助

问题分析与解决方案

关于done变量始终为false的问题

串口的ReadableStream是持续数据流,只有在以下场景下read()才会返回done: true:

  • 串口端口被主动关闭
  • 调用reader.cancel()终止读取
  • 设备断开连接导致port.readable变为null

正常通信过程中,done保持false是预期行为,无需强行让它变为true。

解决首字符丢失、数据包异常的问题

这两个问题的核心是串口数据是分块到达的,单次read()返回的Uint8Array可能只是完整数据包的一部分,直接处理会导致数据截断或乱码。需要手动维护缓冲区,按约定的协议拼接并解析完整数据包。

示例代码(基于换行符分隔数据包)

假设Arduino端使用Serial.println()发送数据(每个数据包结尾带换行符\n),浏览器端可以这样处理:

const reader = port.readable.getReader();
const decoder = new TextDecoder();
let buffer = '';

async function readSerial() {
  while (true) {
    const { value, done } = await reader.read();
    if (done) {
      reader.releaseLock();
      break;
    }
    // 将新接收的字节解码为字符串,追加到缓冲区
    buffer += decoder.decode(value, { stream: true });
    // 按换行符分割出所有可能的完整数据包
    const packets = buffer.split('\n');
    // 最后一个元素可能是不完整的半数据包,留到下次处理
    buffer = packets.pop();
    // 处理每一个完整数据包
    for (const packet of packets) {
      if (packet.trim()) { // 跳过空行
        console.log('完整数据包:', packet);
        // 在这里添加你的业务逻辑处理
      }
    }
  }
}

readSerial();

配套Arduino代码建议

确保Arduino发送的数据包带有明确分隔符,比如:

void setup() {
  Serial.begin(9600); // 波特率需与浏览器端设置一致
}

void loop() {
  // 示例:每秒发送一次带换行的数据包
  Serial.println("Hello Arduino Serial");
  delay(1000);
}

额外优化建议

  • 波特率匹配:浏览器打开串口时的波特率必须和Arduino的Serial.begin()参数完全一致,否则会出现乱码或数据丢失。
  • 握手机制:如果Arduino在连接后立即发送数据,可能遇到浏览器还未准备好读取的情况,导致首字符丢失。可以让Arduino等待浏览器发送的握手信号(比如浏览器发送'ready',Arduino收到后再开始发送数据)。

内容的提问来源于stack exchange,提问作者Igor Scherbickij

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:42:22