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

Arduino Nano 33 BLE与Due通过UART传输float传感器数据异常如何解决?

你当前代码的核心故障原因如下:

  1. Serial.write() 直接传入float类型参数时,仅会输出该float在内存中存储的首字节,无法完整传输占用4字节存储空间的float数据
  2. 接收端Serial.read()仅返回单字节的int类型值,无法直接还原为原始float数据

方案1:二进制传输(无精度损失、传输效率最高)

通过共用体将float拆分为4字节数组传输,增加帧头帧尾避免数据错位,适合高频率数据采集场景。

Nano端修改后核心代码

float h = 22.5;
float x, y, z;
int i = 0;
unsigned long previousMillis = 0;
const long interval = 500;

// 定义共用体,用于float和字节数组的互转
union FloatConvert {
  float value;
  uint8_t bytes[4];
};

void Acceleration();
void setup()
{
    Serial.begin(9600);
    Serial1.begin(9600);
    if (!IMU.begin())
    {
        Serial.println("Failed to initialize IMU!");
        while (1);
    }
    Serial.println("Read the serial");
}

void loop()
{
    Acceleration();
}

void Acceleration()
{
    if (IMU.accelerationAvailable())
    {
        IMU.readAcceleration(x, y, z);
    }
    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval)
    {
        previousMillis = currentMillis;
        FloatConvert xConv, yConv;
        xConv.value = x;
        yConv.value = y;

        // 帧结构:帧头0xAA + X的4字节 + Y的4字节 + 帧尾0xBB
        Serial1.write(0xAA);
        Serial1.write(xConv.bytes, 4);
        Serial1.write(yConv.bytes, 4);
        Serial1.write(0xBB);
        
        i++;
        Serial.print("X ist:  ");
        Serial.println(x);
        Serial.print("y ist:  ");
        Serial.println(y);
    }
}

Due端修改后核心代码

// 共用体定义和发送端保持一致
union FloatConvert {
  float value;
  uint8_t bytes[4];
};

uint8_t rxCache[10];
uint8_t rxPos = 0;
float recX, recY;

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop()
{
  if(Serial1.available() > 0) {
    uint8_t curByte = Serial1.read();
    // 未找到帧头时直接丢弃无效字节
    if(rxPos == 0 && curByte != 0xAA) return;

    rxCache[rxPos++] = curByte;
    // 一帧总长度为10字节,收满后解析
    if(rxPos == 10) {
      // 校验帧尾是否正确
      if(rxCache[9] == 0xBB) {
        FloatConvert xConv, yConv;
        memcpy(xConv.bytes, &rxCache[1], 4);
        memcpy(yConv.bytes, &rxCache[5], 4);
        recX = xConv.value;
        recY = yConv.value;

        Serial.print("接收X: ");
        Serial.println(recX);
        Serial.print("接收Y: ");
        Serial.println(recY);
      }
      // 重置缓存等待下一次接收
      rxPos = 0;
      memset(rxCache, 0, sizeof(rxCache));
    }
  }
}

方案2:字符串传输(调试简单、容错性高)

将float转为字符串格式传输,用分隔符区分不同参数,调试时可直接查看串口原始数据,适合低频率采集场景。

Nano端发送代码修改

仅需替换Acceleration函数中的发送逻辑:

void Acceleration()
{
    if (IMU.accelerationAvailable())
    {
        IMU.readAcceleration(x, y, z);
    }
    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval)
    {
        previousMillis = currentMillis;
        // 用逗号分隔两个参数,换行作为帧结束标记
        Serial1.print(x);
        Serial1.print(",");
        Serial1.println(y);
        
        i++;
        Serial.print("X ist:  ");
        Serial.println(x);
        Serial.print("y ist:  ");
        Serial.println(y);
    }
}

Due端接收代码修改

float recX, recY;
void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop()
{
  if(Serial1.available() > 0) {
    recX = Serial1.parseFloat();
    // 跳过分隔符逗号
    if(Serial1.read() == ',') {
      recY = Serial1.parseFloat();
      // 跳过结束标记换行
      while(Serial1.read() != '\n' && Serial1.available()>0);
      
      Serial.print("接收X: ");
      Serial.println(recX);
      Serial.print("接收Y: ");
      Serial.println(recY);
    }
  }
}

通用注意事项

  • 两端串口波特率必须严格一致,建议使用115200替代9600提升传输效率
  • 二进制传输场景下如果出现偶发数据错位,帧头帧尾校验机制会自动恢复后续数据的正确性
  • 字符串传输场景下不要在参数内容中使用和分隔符、结束标记相同的字符

内容的提问来源于stack exchange,提问作者Alaa Mousa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 20:54:07