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

通过串口从Python向Arduino传输浮点数时数据异常的高效解决办法

问题描述

向Arduino传输1440个浮点数时出现部分数值错误,考虑过添加延迟解决,但希望找到更高效的传输方案。

Python代码片段

arduino = serial.Serial(port=args.port, baudrate=115200, timeout=5000)

print(feature[0:50])
# Send each float in a feature
for num in feature:
    arduino.write(bytes(str("%f" % num), "ascii") + bytes("\n", "ascii"))

# Receive the input back
recv_features = []
for _ in range(len(feature)):
    recv = arduino.read_until()
    recv_features.append(float(recv.decode(encoding="ascii")))
print(recv_features[0:50])

Arduino代码片段

#define INPUT_LEN 10
char X_test_byteArr[INPUT_LEN];
float data[1440];
void setup() {
    Serial.begin(115200);
    Serial.setTimeout(5000);
}

void loop() {
    size_t num_read;
    // Receive every input as string, convert to float
    while (Serial.available()==0) {}
    for (int i = 0; i < 1440; i++) {
        // Wait for input data
        while (Serial.available()==0) {}
        // Read input string
        num_read = Serial.readBytesUntil('\n', X_test_byteArr, INPUT_LEN);
        X_test_byteArr[num_read] = '\0';
        // Convert input string to float
        data[i] = float(atof(X_test_byteArr));
    }

    for (int i = 0; i < 1440; ++i) {
        Serial.println(data[i]);
    }
}

数据对比

发送的前50个数据

[-1.12,  0.32, -0.48, -0.84,  3.01,
  0.03, -0.80,  0.23, -0.69,  1.02,
  0.55,  0.24, -0.13, -0.55, -1.42,
  4.20,  0.05,  0.04,  0.29, -0.45,
 -0.12,  0.21, -0.81, -0.07,  1.03,
 -0.09, -0.01,  0.38, -0.99,  1.59,
  0.21, -0.18,  0.03,  0.39,  1.38,
  0.76, -0.15, -0.25,  0.23, -0.02,
  0.00, -0.48, -0.27,  0.19, -0.09,
 -1.77,  0.24, -0.52, -0.08,  0.43]

接收的前50个数据

[-1.12,  0.32, -0.48, -0.84,  3.01,
  0.03, -0.80,  0.23, -0.69,  1.02,
  0.55,  0.24, -0.13, -0.55, -1.42,
  4.20,  0.05,  0.04,  0.29, -0.45,
 -0.12,  0.21, -0.81, -0.07,  1.03,
 -0.09, -0.01, 37987,  0.00, -0.99,
 59294,  0.21, -0.18,  0.03,  0.39,
  1.38,  0.76,  0.00, -0.15, -0.25,
 22918,  0.00, -0.02,  0.00, -0.48,
 -0.27, 19308, -0.09, -1.77,  0.24]
问题分析与解决方案

错误原因

  1. 缓冲区溢出:Arduino端INPUT_LEN=10的缓冲区过小,当浮点数的ASCII字符串长度超过10时,readBytesUntil会截断数据,残留的旧缓冲区内容被atof解析成错误的大整数。
  2. 同步问题:Python连续发送数据时,Arduino的while(Serial.available()==0)可能在数据未完全接收时就开始读取,导致字符串不完整。

高效替代方案

1. 二进制传输(最快最可靠)

跳过ASCII转换,直接传输浮点数的二进制字节,速度比ASCII快3-5倍,且无解析错误:

  • Python端
import struct

# 将float列表打包为小端模式的二进制字节流(每个float占4字节)
byte_data = b''.join([struct.pack('<f', num) for num in feature])
arduino.write(byte_data)

# 接收时解包二进制数据
recv_bytes = arduino.read(len(feature)*4)
recv_features = [struct.unpack('<f', recv_bytes[i:i+4])[0] for i in range(0, len(recv_bytes), 4)]
  • Arduino端
float data[1440];
void setup() {
    Serial.begin(115200);
    Serial.setTimeout(5000);
    Serial.setBufferSize(8192); // 增大串口缓冲区避免溢出
}

void loop() {
    // 等待所有数据到达(1440个float共5760字节)
    if (Serial.available() >= 1440*4) {
        Serial.readBytes((char*)data, 1440*4);
        // 回传二进制数据
        Serial.write((char*)data, 1440*4);
    }
}

2. 优化ASCII传输(保留文本格式)

如果必须用ASCII传输,解决核心问题:

  • 增大缓冲区:将INPUT_LEN改为15,足够容纳带符号的长浮点数ASCII字符串(如-123.456789)
  • 加入校验机制:每个数据包开头加START标记,结尾加END标记,确保数据完整接收
  • 批量传输:Python一次性发送所有数据(用分隔符分隔),Arduino一次性读取后拆分解析,减少往返次数

3. 硬件与配置优化

  • 确保Python和Arduino的波特率完全一致
  • 用Serial.setBufferSize()增大Arduino的串口缓冲区,避免数据溢出
  • 减少回传次数:比如只回传校验值(如所有浮点数的总和),而不是全部数据,节省传输时间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 06:29:53