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

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, &param_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:10:16