MAVLink and Arduino: step by step

OK, now I understand. I am sorry, no GUI here.

I would like to congratulate and thank you as this is the first (and only so far i found) practical and clear example and how to use mavlink (for a non programmer expert like me)!
This explanation should be added to the official Ardupilot wiki documentation. Can you please contact Randy or anyone else to make sure it is copied in the Ardupilot doc ?

3 Likes

@Hugues Thank you very much for your kind words!

OK, I will propose a change on the documentation, any proposal about on what section? What about here?: http://ardupilot.org/dev/docs/mavlink-commands.html

Yes and I was also thinking here in the “non developer” wiki area : http://ardupilot.org/dev/docs/companion-computers.html

@Hugues OK, it is done. I have proposed just adding a link to this post in both pages. You can see the pull request here: https://github.com/ArduPilot/ardupilot_wiki/pull/1098

Regards.

that is great , thx !

@jplopezll How do I draw out the Pixhawk altitude onto the Arduino Uno, in real time. I will be using Telem 2 port, MAVLink2 protocol.

Dear @MAWaayne, what altitude are you looking for? Barometric altitude internal to the Pixhawk or GPS altitude.from an external GPS module?

Thanks for replying! Both preferably, so I can compare the outcome individually and chose the better result.

@MAWaayne, I have not direct experience with those messages, but in the library I can see that internal altitude info is replied in messageMAVLINK_MSG_ID_HIL_STATE with ID 90. Units are mm. You can find all the details in the file common\mavlink_msg_hil_state.h. The most interesting part is the structure where message payload is stored:

#define MAVLINK_MSG_ID_HIL_STATE 90

typedef struct __mavlink_hil_state_t
{
 uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot)
 float roll; ///< Roll angle (rad)
 float pitch; ///< Pitch angle (rad)
 float yaw; ///< Yaw angle (rad)
 float rollspeed; ///< Roll angular speed (rad/s)
 float pitchspeed; ///< Pitch angular speed (rad/s)
 float yawspeed; ///< Yaw angular speed (rad/s)
 int32_t lat; ///< Latitude, expressed as * 1E7
 int32_t lon; ///< Longitude, expressed as * 1E7
 int32_t alt; ///< Altitude in meters, expressed as * 1000 (millimeters)
 int16_t vx; ///< Ground X Speed (Latitude), expressed as m/s * 100
 int16_t vy; ///< Ground Y Speed (Longitude), expressed as m/s * 100
 int16_t vz; ///< Ground Z Speed (Altitude), expressed as m/s * 100
 int16_t xacc; ///< X acceleration (mg)
 int16_t yacc; ///< Y acceleration (mg)
 int16_t zacc; ///< Z acceleration (mg)
} mavlink_hil_state_t;

For GPS altitude I think you can use MAVLINK_MSG_ID_GPS_RAW_INT with ID 24. Units are also mm. You can find all the details in the file common\mavlink_msg_gps_raw_int.h. The structure for the message payload in this case is:

#define MAVLINK_MSG_ID_GPS_RAW_INT 24

typedef struct __mavlink_gps_raw_int_t
{
 uint64_t time_usec; ///< Timestamp (microseconds since UNIX epoch or microseconds since system boot)
 int32_t lat; ///< Latitude in 1E7 degrees
 int32_t lon; ///< Longitude in 1E7 degrees
 int32_t alt; ///< Altitude in 1E3 meters (millimeters) above MSL
 uint16_t eph; ///< GPS HDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535
 uint16_t epv; ///< GPS VDOP horizontal dilution of position in cm (m*100). If unknown, set to: 65535
 uint16_t vel; ///< GPS ground speed (m/s * 100). If unknown, set to: 65535
 uint16_t cog; ///< Course over ground (NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. If unknown, set to: 65535
 uint8_t fix_type; ///< 0-1: no fix, 2: 2D fix, 3: 3D fix. Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix.
 uint8_t satellites_visible; ///< Number of satellites visible. If unknown, set to 255
} mavlink_gps_raw_int_t;

You will probably also need info on GPS status to make sure you have proper signal lock, check the number of satellites, precission, etc. This info is in mavlink_msg_gps_status.h. Message structure:

#define MAVLINK_MSG_ID_GPS_STATUS 25

typedef struct __mavlink_gps_status_t
{
 uint8_t satellites_visible; ///< Number of satellites visible
 uint8_t satellite_prn[20]; ///< Global satellite ID
 uint8_t satellite_used[20]; ///< 0: Satellite not used, 1: used for localization
 uint8_t satellite_elevation[20]; ///< Elevation (0: right on top of receiver, 90: on the horizon) of satellite
 uint8_t satellite_azimuth[20]; ///< Direction of satellite, 0: 0 deg, 255: 360 deg.
 uint8_t satellite_snr[20]; ///< Signal to noise ratio of satellite
} mavlink_gps_status_t;

Now you need to know what are the streams to trigger messages to be sent from the Pixhawk. As I told you, I have not direct experience on this. I would say that GPS messages are triggered with MAV_DATA_STREAM_RAW_SENSORS for the GPS altitude message and MAV_DATA_STREAM_EXTENDED_STATUS for GPS status message. Regarding internal altitude, I would try with MAV_DATA_STREAM_POSITION and see if it works. I cannot help more here.

Now I can’t help much more, I have diassembled the quad to do some adjustments and I will not be able to test anything until I find some time to finish it.

If you find the right combination of streams and messages, please revert!

2 Likes

Thank you ever so much for your kind assistance Juan! I’ll try it out, and revert back to you on the progress or if there are any difficulties faced.

Hi @jplopezll Could i seek your help in programming out the code. My email is waaynea1@gmail.com. Thanks!

Excellent tutorial. I have mavlijnk “running” on the arduino and trying to see something on the qgroundcontrol or missionplanner and not getting too far. I was hoping to see decoded hearbeats or something. What is a good “hello world” to test this either to PH or something on the PC?

My ultimate goal is to collect sensor data on the arduino, route it through the PixHawk in TELEM2 and out TELEM1 radio during flight and also to log locally. It will ultimately be my own user defined mavlink data.

Thanks,
jv

Hi, @newts:

Thanks for your nice words!

Unfortunatelly, I do not think that the Pixhawk could behave like a bridge and route messages from Telem2 to Telem1. Thus, you cannot “feed” info in Telem2 and expect to see something in your Ground Control Station via a radio link connected to Telem1.

The idea of an Arduino (or any other MAVLink enabled system) on board is to have a second on-board brain (small in this case) to release the “pilot” flight controller from “crew” duties. In my example, the “pilot” is informing about attitude and emergency situations and the “crew” is in charge of managing the led lights.

If you are interested on sensors information to be transmitted to the Ground Station there are other alternatives. It will depend on what setup you have. If you elaborate a bit more on your goals, maybe I could help. You can PM me if you prefer. I will be glad to try to help!

1 Like

HI
I got this error while compiling the code
sketch_mar31a.ino: In function ‘void loop()’:
sketch_mar31a:39: error: ‘previousMillisMAVLink’ was not declared in this scope
sketch_mar31a:39: error: ‘next_interval_MAVLink’ was not declared in this scope
sketch_mar31a:46: error: ‘num_hbs_pasados’ was not declared in this scope
sketch_mar31a:47: error: ‘num_hbs’ was not declared in this scope
sketch_mar31a:49: error: ‘Mav_Request_Data’ was not declared in this scope
sketch_mar31a:55: error: ‘comm_receive’ was not declared in this scope

it seems that these parameters are really not defined in this code
can you help me solve it
thank you

Hi, @mfzavareh:

Yes, sorry for that. There are some errors in the code I had not noticed before (this is one of them) as I added just yesterday to the post.

Meanwhile I correct the code and rewrite the post, you only need to add this before the void setup() in the sketch:

// 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;
''' 

Those are variables I use to control how often you send heartbeats and data to the Pixhawk. You can modify them as per your needs.

If you need any further help, do not hesitate to ask!

you are very kind man
I didnt expect to get answer as quickly as you did
thank you so much for that
your help is appreciated
hope to reply it soon
thank you

but still there are two functions which are not declared
//Mav_Request_Data();
//comm_receive();
should those be declared in the code or in the liberary?

Hi again, @mfzavareh:

You must code them in your sketch. It is explained in detail in the post…

I’m glad to help!

so you mean I have to define it by my own
"Actually I am new to coding and mavlink so …"

thank you any way
thank you so much

Dear @mfzavareh:

I mean that you have sample code in the post above. If you need something different you can ask me. Better by PM (private message).