Arduino通过Mavlink从Pixhawk请求数据失败求助
问题描述
Arduino的Serial1接口连接Pixhawk的Serial2接口,目前可正常接收心跳消息、改写RC通道,但无法从Pixhawk请求到SYS_STATUS、RAW_IMU等数据。Pixhawk系统ID为1、组件ID为1,已尝试修改目标ID/系统ID、切换MAVLink1/2协议、调整SERIAL2_BAUD参数,仅能收到msgid为0(心跳)和66(数据请求)的消息。
相关代码如下:
#include "mavlink.h" // Mavlink variables int sysid = 1; ///< ID 20 for this airplane. 1 PX, 255 ground station int compid = 158; ///< The component sending the message uint8_t target_system = 1; uint8_t target_component = 1; int type = MAV_TYPE_GROUND_ROVER; ///< This system is an airplane / fixed wing uint8_t autopilot_type = MAV_AUTOPILOT_PIXHAWK; uint8_t system_mode = MAV_MODE_PREFLIGHT; ///< Booting up uint32_t custom_mode = 0; ///< Custom mode, can be defined by user/adopter uint8_t system_state = MAV_STATE_STANDBY; ///< System ready for flight unsigned long request_timer = millis(); unsigned long heartbeat_timer = millis(); void setup() { // MAVLink interface start Serial1.begin(57600); Serial.begin(115200); } void loop() { doSendHeartbeat(); dorequest(); comm_receive() ; rc_override(1200, 1200); } void doSendHeartbeat() { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; if (heartbeat_timer < millis()) { mavlink_msg_heartbeat_pack(sysid, compid, &msg, type, autopilot_type, system_mode, custom_mode, system_state); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); heartbeat_timer = millis() + 100; } } void dorequest() { if (request_timer < millis()) { Mav_Request_Data(); request_timer = millis() + 5000; } } void Mav_Request_Data() { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; mavlink_msg_request_data_stream_pack(target_system, target_component, &msg, sysid, compid, MAV_DATA_STREAM_ALL, 0x01, 1); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); } void comm_receive() { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; mavlink_status_t status; while (Serial1.available() > 0) { uint8_t c = Serial1.read(); // Try to get a new message if (mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status)) { // Handle message Serial.println(msg.msgid); switch (msg.msgid) { case MAVLINK_MSG_ID_HEARTBEAT: // #0: Heartbeat { // E.g. read GCS heartbeat and go into // comm lost mode if timer times out } break; case MAVLINK_MSG_ID_SYS_STATUS: // #1: SYS_STATUS { /* Message decoding: PRIMITIVE mavlink_msg_sys_status_decode(const mavlink_message_t* msg, mavlink_sys_status_t* sys_status) */ //mavlink_message_t* msg; mavlink_sys_status_t sys_status; mavlink_msg_sys_status_decode(&msg, &sys_status); Serial.println("2-"); } break; case MAVLINK_MSG_ID_PARAM_VALUE: // #22: PARAM_VALUE { /* Message decoding: PRIMITIVE mavlink_msg_param_value_decode(const mavlink_message_t* msg, mavlink_param_value_t* param_value) */ //mavlink_message_t* msg; mavlink_param_value_t param_value; mavlink_msg_param_value_decode(&msg, ¶m_value); Serial.println("3-"); } break; case MAVLINK_MSG_ID_RAW_IMU: // #27: RAW_IMU { /* Message decoding: PRIMITIVE static inline void mavlink_msg_raw_imu_decode(const mavlink_message_t* msg, mavlink_raw_imu_t* raw_imu) */ mavlink_raw_imu_t raw_imu; mavlink_msg_raw_imu_decode(&msg, &raw_imu); Serial.println(raw_imu.zgyro); } break; case MAVLINK_MSG_ID_REQUEST_DATA_STREAM : // #66 { } break; case MAVLINK_MSG_ID_ATTITUDE: // #30 { /* Message decoding: PRIMITIVE mavlink_msg_attitude_decode(const mavlink_message_t* msg, mavlink_attitude_t* attitude) */ mavlink_attitude_t attitude; mavlink_msg_attitude_decode(&msg, &attitude); Serial.println("5-"); } break; default: break; } } } } void rc_override(int mav_steer, int mav_speed) { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; mavlink_msg_rc_channels_override_pack(sysid, compid, &msg, 0, 0, mav_steer, mav_speed, 65535, 65535, 65535, 65535, 65535, 65535); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); }
问题排查与解决办法
核心问题:数据请求消息参数顺序错误
mavlink_msg_request_data_stream_pack函数的参数顺序被颠倒,导致Pixhawk无法识别合法的数据请求:
- 正确参数顺序:
(发送方系统ID, 发送方组件ID, 消息指针, 目标系统ID, 目标组件ID, 数据流类型, 更新频率, 开启/关闭) - 原代码错误地将目标系统ID/组件ID放在了发送方参数位置,Pixhawk收到后会认为是来自自身的请求,自然不会响应。
具体修复步骤
1. 修正数据请求函数
修改Mav_Request_Data函数,调整参数顺序,同时合理设置数据流频率(比如10Hz,避免过低或过高):
void Mav_Request_Data() { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; // 修正参数顺序:发送方(sysid, compid)在前,目标(target_system, target_component)在后 mavlink_msg_request_data_stream_pack(sysid, compid, &msg, target_system, target_component, MAV_DATA_STREAM_ALL, 10, 1); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); }
2. 修正RC通道覆盖的目标ID
原rc_override函数中目标系统ID/组件ID填了0,虽能生效但不符合规范,改为指定Pixhawk的ID:
void rc_override(int mav_steer, int mav_speed) { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; mavlink_msg_rc_channels_override_pack(sysid, compid, &msg, target_system, target_component, mav_steer, mav_speed, 65535, 65535, 65535, 65535, 65535, 65535); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); }
3. 调整心跳发送频率
原代码100ms发送一次心跳过于频繁,符合MAVLink规范的频率是1Hz(1000ms),减少带宽占用:
void doSendHeartbeat() { mavlink_message_t msg; uint8_t buf[MAVLINK_MAX_PACKET_LEN]; if (heartbeat_timer < millis()) { mavlink_msg_heartbeat_pack(sysid, compid, &msg, type, autopilot_type, system_mode, custom_mode, system_state); uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); Serial1.write(buf, len); heartbeat_timer = millis() + 1000; // 修改为1000ms间隔 } }
4. 确认Pixhawk串口配置
- 确保SERIAL2_PROTOCOL与代码中使用的MAVLink版本一致:设为1(MAVLink1)或2(MAVLink2)
- SERIAL2_BAUD必须与Arduino的
Serial1.begin(57600)一致(比如设为57) - 检查SERIAL2_OPTIONS无错误配置,确保串口处于正常工作状态
内容的提问来源于stack exchange,提问作者Slava Golitsin
相关产品推荐
相关产品推荐

