如何从Python向Arduino高效发送数据结构体?
用struct序列化实现Python与Arduino的串口命令传输
你可以通过struct模块在Python端将命令打包成固定格式的字节流,Arduino端按对应格式解析字节,完全替代字符串解析的繁琐步骤,以下是具体实现:
Python端:打包命令并发送
用struct.pack()将命令类型和参数转换成统一字节格式,确保和Arduino端的数据类型、字节序一致:
import serial import struct # 串口初始化(根据你的端口调整) ser = serial.Serial('COM3', 9600, timeout=1) # 命令类型定义(和Arduino端完全对应) CMD_MOVE = 0x01 CMD_REQUEST_DATA = 0x02 # 发送MOVE命令:传入左右电机速度 def send_move(speed_left, speed_right): # 打包格式:<Bhh(小端模式:1字节命令 + 2个16位整数速度) packet = struct.pack('<Bhh', CMD_MOVE, speed_left, speed_right) ser.write(packet) # 发送REQUEST_DATA命令 def send_request_data(): packet = struct.pack('<B', CMD_REQUEST_DATA) ser.write(packet) # 示例调用 send_move(60, 70) # send_request_data()
Arduino端:解析字节流并执行命令
定义对应的数据结构体,按字节读取串口数据并重构为命令结构,处理不同指令:
#include <HardwareSerial.h> // 命令类型和Python端严格一致 #define CMD_MOVE 0x01 #define CMD_REQUEST_DATA 0x02 // 对应MOVE命令的结构体(字节布局和Python打包格式匹配) struct MoveCommand { uint8_t cmd; int16_t speed_left; int16_t speed_right; }; void setup() { Serial.begin(9600); // 初始化电机驱动引脚(根据你的硬件调整) pinMode(9, OUTPUT); pinMode(10, OUTPUT); } void loop() { if (Serial.available() > 0) { uint8_t cmd = Serial.read(); switch(cmd) { case CMD_MOVE: { MoveCommand move_cmd; move_cmd.cmd = cmd; // 按小端模式读取剩余4字节(两个16位整数) Serial.readBytes((uint8_t*)&move_cmd.speed_left, sizeof(move_cmd.speed_left)); Serial.readBytes((uint8_t*)&move_cmd.speed_right, sizeof(move_cmd.speed_right)); // 执行电机驱动逻辑 driveMotor(9, move_cmd.speed_left); driveMotor(10, move_cmd.speed_right); break; } case CMD_REQUEST_DATA: { // 模拟获取传感器数据 float battery_voltage = 12.3; float gps_lat = 39.9042; float gps_lon = 116.4074; // 打包返回数据(同样用字节流发送) Serial.write((uint8_t*)&battery_voltage, sizeof(battery_voltage)); Serial.write((uint8_t*)&gps_lat, sizeof(gps_lat)); Serial.write((uint8_t*)&gps_lon, sizeof(gps_lon)); break; } default: // 未知命令,清空串口缓存避免残留数据干扰 while(Serial.available()) Serial.read(); break; } } } // 电机驱动示例函数(根据你的硬件修改) void driveMotor(int pin, int16_t speed) { int pwm_val = abs(speed); pwm_val = constrain(pwm_val, 0, 255); // 限制PWM范围0-255 analogWrite(pin, pwm_val); // 若需正反转,可添加方向引脚控制逻辑 }
关键注意事项
- 字节序统一:Python用
<指定小端模式,Arduino的AVR系列默认是小端,确保两边一致。 - 数据类型匹配:Python的
h对应Arduino的int16_t,B对应uint8_t,所有类型必须严格对应。 - 波特率一致:Python和Arduino的串口波特率必须相同(示例中为9600)。
- 缓存处理:遇到未知命令时清空串口缓存,避免残留数据破坏后续解析。
内容的提问来源于stack exchange,提问作者Dinh Trung Che
相关产品推荐
相关产品推荐

