MAVLink and Arduino: step by step

thanks a lot!!! @jplopezll .
now i can get the message.

Congratulations @HUANG_ERIC!

And I wish you and all a merry Christmas and a happy new year!

1 Like

@jplopezll Great work helping people putting MAVLink to good use.

I do not mean to diminish your contribution, you have surely helped a lot of people, and made the topic easy to find, but minimOSD can also be used as example for reading messages, (again, no offense)

It would be very cool/useful, and complete your example perfectly, if you added an example where Arduino sends some custom packets, taking some input from the Arduino, and packaging it into a packet that can then be seen in MAVLink inspector or similar tools on GCS (if we assume GCS sysid to be 255)
and/or generate an statustext message.

HI @Andre-K:

No offense, of course!

Nice idea for a continuation of this post. I always prefer a real-life example, maybe you have an idea in particular about what could be the usage, the setup, the problem to be solved. You can PM me to start building a second post on MAVLink.

Regards.

I want to change from Manual Mode to Auto Mode using Mavlink
but I can not receive the #11 message id (MAVLINK_MSG_ID_SET_MODE).
Please suggest me how to change mode of the Pixhawk and monitor it.

Thank you

Dear @Thanapong_Phanthong:

Correct me if I am wrong, but what you want to do is send message #11, not receiving it. Is this correct?

Regards.

Before I will be able to change mode , I think that I should monitor msg.msgid that in these msg.msgid, it has the #11, or not?
To verify that when I change mode , I should monitor it.

in void loop() {…}

system_mode is assigned to be MAV_MODE_PREFLIGHT, with

uint8_t system_mode = MAV_MODE_PREFLIGHT;

in void comm_receive() {…} it has

Serial.print(“DEBUG msgid:”); Serial.println(msg.msgid);

it should print #11 in msg.msgid , but it does not have #11

in void Mav_Request_Data() {…}

I try to use several MAVStreams[maxStreams], such as MAV_DATA_STREAM_ALL, MAV_DATA_STREAM_EXTENDED_STATUS and MAV_DATA_STREAM_EXTRA1, but it is not work.

Please see the code.

This is the code

#include <mavlink.h>
#include <SoftwareSerial.h>
SoftwareSerial _MavLinkSerial(9, 10); // PIN 9=Telemetry TX->Pixhawk RX, PIN 10=Telemetry RX->Pixhawk TX

// Mavlink variables
unsigned long previousMillisMAVLink = 0; // will store last time MAVLink was transmitted and listened
unsigned long next_interval_MAVLink = 1000; // next interval to count
const int num_hbs = 60; // # of heartbeats to wait before activating STREAMS from Pixhawk. 60 = one minute.
int num_hbs_pasados = num_hbs;

void setup() {
// MAVLink interface start
_MavLinkSerial.begin(57600);

Serial.begin(57600);
Serial.println(“MAVLink starting.”);
}

void loop()
{

// MAVLink
/* The default UART header for your MCU */
int sysid = 1; ///< ID 20 for this airplane. 1 PX, 255 ground station
int compid = 158; ///< The component sending the message
int type = MAV_TYPE_GENERIC; ///< This system is an airplane / fixed wing

// Define the system type, in this case an airplane -> on-board controller
// uint8_t system_type = MAV_TYPE_FIXED_WING;
uint8_t system_type = MAV_TYPE_GENERIC;
//uint8_t system_type = MAV_TYPE_FIXED_WING;

uint8_t autopilot_type = MAV_AUTOPILOT_INVALID;

uint8_t system_mode = MAV_MODE_PREFLIGHT; ///< Booting up
//uint8_t system_mode = MAV_MODE_AUTO_ARMED; ///< 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

// Initialize the required buffers
mavlink_message_t msg;
uint8_t buf[MAVLINK_MAX_PACKET_LEN];

// Pack the message
mavlink_msg_heartbeat_pack(sysid,compid, &msg, type, autopilot_type, system_mode, custom_mode, system_state);
//mavlink_msg_heartbeat_pack(1, 0, &msg, type, autopilot_type, system_mode, custom_mode, system_state);

// Copy the message to the send buffer
uint16_t len = mavlink_msg_to_send_buffer(buf, &msg);

// Send the message with the standard UART send function
// uart0_send might be named differently depending on
// the individual microcontroller / library in use.
unsigned long currentMillisMAVLink = millis();
if (currentMillisMAVLink - previousMillisMAVLink >= next_interval_MAVLink)
{
// Record last HB update
previousMillisMAVLink = currentMillisMAVLink;

//Mav_Request_Data();
num_hbs_pasados++;
if (num_hbs_pasados >= num_hbs) 
{
  // Request streams from Pixhawk
  Serial.println("Streams requested!");
  Mav_Request_Data();
  num_hbs_pasados = 0;
}

}

// Check reception buffer
comm_receive();
}

void Mav_Request_Data()
{
mavlink_message_t msg;
uint8_t buf[MAVLINK_MAX_PACKET_LEN];
//--------

//--------------

// To be setup according to the needed information to be requested from the Pixhawk
const int maxStreams = 3;
//const uint8_t MAVStreams[maxStreams] = {MAV_DATA_STREAM_POSITION};
const uint8_t MAVStreams[maxStreams] = {MAV_DATA_STREAM_ALL, MAV_DATA_STREAM_EXTENDED_STATUS, MAV_DATA_STREAM_EXTRA1};
//const uint16_t MAVRates[maxStreams] = {0x02};
const uint16_t MAVRates[maxStreams] = {0x02,0x02,0x02};
for (int i = 0; i < maxStreams; i++)
{
mavlink_msg_request_data_stream_pack(6, 200, &msg, 1, 0, MAVStreams[i], MAVRates[i], 1);
uint16_t len = mavlink_msg_to_send_buffer(buf, &msg);
_MavLinkSerial.write(buf, len);
}

}

void comm_receive()
{
mavlink_message_t msg;
mavlink_status_t status;

while (_MavLinkSerial.available() > 0) {
uint8_t c = _MavLinkSerial.read();

// Try to get a new message
if (mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status))
{
  Serial.print("DEBUG msgid:"); Serial.println(msg.msgid);
  // Handle message
  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
        //Serial.println("HB:");
        mavlink_heartbeat_t hb;
        mavlink_msg_heartbeat_decode(&msg, &hb);
        //Serial.print("sc-mode:");  
        //Serial.println(hb.mode);
        //Serial.print("type:");  
        //Serial.println(hb.type);
          
      }
      break;
    case MAVLINK_MSG_ID_ATTITUDE:  // #30
      {
        mavlink_attitude_t attitude;
        mavlink_msg_attitude_decode(&msg, &attitude);
        //Serial.print("yaw:");  
        //Serial.println(attitude.yaw);
      }
      break;
    case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: //  #33
      {
       //see in the file of mavlink_msg_global_position_int.h in \common directory
       
        mavlink_global_position_int_t altitude;
        mavlink_msg_global_position_int_decode(&msg, &altitude);
        //int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters), above MSL
        //int32_t relative_alt; ///< Altitude above ground in meters, expressed as * 1000 (millimeters)
        //Serial.print("alt:");  
        //Serial.println(altitude.alt);
        //Serial.print("rel_alt:");  
        //Serial.println(altitude.relative_alt);
        //Serial.print("time:");  
        //Serial.println(altitude.time_boot_ms);
        
      }
      break;
    case MAVLINK_MSG_ID_SET_MODE :  // #11
     
      
      {
       mavlink_set_mode_t mode1;
       mavlink_msg_set_mode_decode(&msg, &mode1);

        Serial.print("smode:");  
        Serial.println(mode1.custom_mode);
        Serial.println(mode1.target_system);
        Serial.println(mode1.base_mode);
                       
      }
      break;


      default:
        //Serial.print("sys:");  
        //Serial.println(msg.msgid);


      break;
      
      
  }
}

}
}

This is the serial monitor in COM3, it does not have #11 msgid

Please suggest me about the problem to monitor the MAVLINK_MSG_ID_SET_MODE : // #11

Thank you.

HI, I noticed in the mavlink library .zip file you have for download everything works, but it does not include a few files necessary to implement a waypoint such as mavlink_msg_mission_item_int.h.

I have tried everything to complie my own version but for some reason, it does not work using the (https://github.com/mavlink/mavlink) link. It shows all sorts of errors and in the end, says it fails to compile on the arduino mega which I have. I have even tried to just copy the mavlink_msg_mission_item_int.h file and edit the #include inside common.h, but to no avail. Can you please upload the full .zip library?

Hi. I’m very new to this and would appreciate any help.

If I wanted to send a MAVLink message to a Pixhawk4 to start a mission (MAV_CMD_MISSION_START/MAV_CMD_NAV_LAND) can I do this from an Arduino? I haven’t seen it on the MAVLink libraries on GitHub and on the ArduPilot website it says that these commands are supported by ArduPilot copter. Does this just mean that I need to install the ArduPilot software on the Pixhawk in order to be able to use the commands? Would I need to create custom messages from the Arduino or is it incompatible?

Thank you.

1 Like

Dear Juan Pedro Lopez,
Thank you for your great work. Could you please explain the section below: “With this setup I could relay data to a second Arduino board as an interface with the PC. In this setup, the Pixhawk was not connected to the serial port of the Arduino, but to pins 9 and 10 as a softserial port.” you explain in How to use it all.
Thanks in Advance.

Hi, @drinnird:

The library I uploaded is the reduced version I needed to be able to run in my nano. The full version is in Github, you can download it from there.

If you are using a Mega, you might use v2 of MAVLink.

Copying simple messages neither worked for me. I guess that during compilation there are some cross-references that need to be calculated…

Hello, @plin:

Just check my comment above. The zip file I have included is not the full version of the library. If you need something complete, you must go to Github and download the full version.

If you flight controller supports the message, you do not need to upload anything different, just use the correct version of the library. Beware that there are two versions of MAVLink. I am using v1 because my Nano has almost no memory on the board and it does not support v2.

Dear @habib:

What I mean is that, as I was using a second Arduino for debugging and my Nano has only one UART, I needed serial port emulation. For that purpose I use the SoftSerial library and two digital pins on the board.

If you need further clarification, PM me.

1 Like

Thank you for all your help!

Inside the comm_receive() function i used MAVLINK_MSG_ID_SYS_STATUS: //#1 and print in serial monitor onboard_control_sersors_present it print 23133199, i can’t under stand what does it mean? i saw the
MAV_SYS_STATUS_SENSOR value but no similarity with the value mentioned for specific sensor. Can anybody explain please?

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.print("[Bat (V): ");
Serial.println(sys_status.voltage_battery);
if(sys_status.voltage_battery<1)
Serial.println(“No Battery in the Vehicle, Please insert the battery.”);
Serial.print("On board control sensor status: ");
Serial.println(sys_status.onboard_control_sensors_present);
Serial.print("On board control sensor enabled: ");
Serial.println(sys_status.onboard_control_sensors_enabled);
}
break;

Hi, @habib:

What you get is the binary “encoded” list of sensors available in a single number. The key to unencode is:

const (
    MAV_SYS_STATUS_SENSOR_3D_GYRO                = 1       // 0x01 3D gyro |
    MAV_SYS_STATUS_SENSOR_3D_ACCEL               = 2       // 0x02 3D accelerometer |
    MAV_SYS_STATUS_SENSOR_3D_MAG                 = 4       // 0x04 3D magnetometer |
    MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE      = 8       // 0x08 absolute pressure |
    MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE  = 16      // 0x10 differential pressure |
    MAV_SYS_STATUS_SENSOR_GPS                    = 32      // 0x20 GPS |
    MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW           = 64      // 0x40 optical flow |
    MAV_SYS_STATUS_SENSOR_VISION_POSITION        = 128     // 0x80 computer vision position |
    MAV_SYS_STATUS_SENSOR_LASER_POSITION         = 256     // 0x100 laser based position |
    MAV_SYS_STATUS_SENSOR_EXTERNAL_GROUND_TRUTH  = 512     // 0x200 external ground truth (Vicon or Leica) |
    MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL   = 1024    // 0x400 3D angular rate control |
    MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION = 2048    // 0x800 attitude stabilization |
    MAV_SYS_STATUS_SENSOR_YAW_POSITION           = 4096    // 0x1000 yaw position |
    MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL     = 8192    // 0x2000 z/altitude control |
    MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL    = 16384   // 0x4000 x/y position control |
    MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS          = 32768   // 0x8000 motor outputs / control |
    MAV_SYS_STATUS_SENSOR_RC_RECEIVER            = 65536   // 0x10000 rc receiver |
    MAV_SYS_STATUS_SENSOR_3D_GYRO2               = 131072  // 0x20000 2nd 3D gyro |
    MAV_SYS_STATUS_SENSOR_3D_ACCEL2              = 262144  // 0x40000 2nd 3D accelerometer |
    MAV_SYS_STATUS_SENSOR_3D_MAG2                = 524288  // 0x80000 2nd 3D magnetometer |
    MAV_SYS_STATUS_GEOFENCE                      = 1048576 // 0x100000 geofence |
    MAV_SYS_STATUS_AHRS                          = 2097152 // 0x200000 AHRS subsystem health |
    MAV_SYS_STATUS_TERRAIN                       = 4194304 // 0x400000 Terrain subsystem health |
    MAV_SYS_STATUS_SENSOR_ENUM_END               = 4194305 //  |
)

MAV_SYS_STATUS_SENSOR These encode the sensors whose status is sent as part of the SYS_STATUS message. 

Thus, if I am not wrong the number you get (23133199) means that your flight controller is reporting as active the following:

    MAV_SYS_STATUS_SENSOR_3D_GYRO                = 1       // 0x01 3D gyro |
    MAV_SYS_STATUS_SENSOR_3D_ACCEL               = 2       // 0x02 3D accelerometer |
    MAV_SYS_STATUS_SENSOR_3D_MAG                 = 4       // 0x04 3D magnetometer |
    MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE      = 8       // 0x08 absolute pressure |
    MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL   = 1024    // 0x400 3D angular rate control |
    MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION = 2048    // 0x800 attitude stabilization |
    MAV_SYS_STATUS_SENSOR_YAW_POSITION           = 4096    // 0x1000 yaw position |
    MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL     = 8192    // 0x2000 z/altitude control |
    MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL    = 16384   // 0x4000 x/y position control |
    MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS          = 32768   // 0x8000 motor outputs / control |
    MAV_SYS_STATUS_AHRS                          = 2097152 // 0x200000 AHRS subsystem health |
    MAV_SYS_STATUS_TERRAIN                       = 4194304 // 0x400000 Terrain subsystem health |

Please double check, as I have just done a quick analysis.

Regards.

Dear @jplopezll
I also think same as but i couldn’t able to find the relation between these (the no i got and the sensor list you gave above). Thank you so much. I appreciate your help. Can you please explain further?

Hi, @habib:

What in particular do you need to be explained in more detail?