Unable to read data on arduino serial monitor

Thanks for the speedy reply! I have tried using mavlink_parse_char before and I am always unable to get it to equate anything other than 0. For example, I used this line to parse the characters and then go into a switch case that dealt with each message.

if (mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status) { 
 

However, it would never go through the if statement.

I will try again after implementing your other suggestions and update again.

I have tried using mavlink_parse_char before and I am always unable to get it to equate anything other than 0

That means something else must be wrong as well. What mavlink headers are you using? I recommend the mavlink 2 headers autogenerated here: GitHub - mavlink/c_library_v2: Official reference C / C++ library for the v2 protocol

Also, you need to be sure the settings for the serial device as well as the baudrate are all correct.

I have been using https://github.com/mavlink/c_library_v1 .

After making some changes, I am still unable to do the parsing. How would I make sure that the baudrate is correct? I have tried a few different ones but am unsure of the right one.

Also, in mavlink_parse_char, how do I know which channel to use?

My updated code

#include <mavlink.h>

void setup() {

  Serial.begin(57600); 
  Serial1.begin(57600);

}


void dispIMU() {

  mavlink_message_t msg;
  mavlink_highres_imu_t highres;
  mavlink_msg_highres_imu_decode(&msg, &highres);

  float xacc = highres.xacc;
  float yacc = highres.yacc;
  float zacc = highres.zacc ;

  Serial.print("HiRes IMU Msgid: ");  Serial.println(msg.msgid);
  Serial.print("Xacc: "); Serial.println(xacc , 5);
  Serial.print("Yacc: "); Serial.println(yacc, 5);
  Serial.print("Zacc: "); Serial.println(zacc , 5);
  Serial.print("\n");
  delay(1000);

}//void

void loop() {

  uint8_t msgReceived = false;
  mavlink_message_t message;
  mavlink_status_t status;

  while (Serial.available() > 0) {

    char b = Serial.read();

    if (b == '1')
    {
      Serial.println("B");

      if (Serial1.available() > 0) {
      uint8_t result = Serial1.read();
        if (result > 0) {

          Serial.println("result > 0");

          msgReceived = mavlink_parse_char(MAVLINK_COMM_1, result, &message, &status);

          if (msgReceived) {
            Serial.println("Message received");

            switch (message.msgid) {
              case MAVLINK_MSG_ID_HIGHRES_IMU:
                {
                  dispIMU();
                }
              default:
                {
                  Serial.println(message.msgid);
                }
            }//switch

          }//if msg

        }//if result
      }//if serial 1
    }//if b
  }//while
}//void

Where are you connecting this to and what is this port set to?

Also, in mavlink_parse_char, how do I know which channel to use?

It doesn’t matter as long as you keep using the same one, so 1 is fine.

Also, you need to make sure that your dispIMU() function actually used the mavlink_message_t that you’re getting from mavlink_parse_char, so you need to pass it to dispIMU(). Right now you just create yet another message object in dispIMU() which is not initialized so probably just random memory.

It looks like you’re only reading one byte and then you’re going back to Serial.read(). You should be disabling everything checking for your input for now and just loop and read on Serial1 until a message is parsed.

I am now able to get the message parsed and I can display heartbeat messages and a few other messages. However, the messages that I can display seem to be only a certain few that I do not have control over. How can I display a specific message? For example, I need to display the Highres IMU values.

You can request a message by sending this command: https://mavlink.io/en/messages/common.html#MAV_CMD_SET_MESSAGE_INTERVAL

Alternatively, you can look at the configuration: https://dev.px4.io/en/companion_computer/pixhawk_companion.html and you set the correct mode which includes the message you need. You can see the modes with their messages here: https://github.com/PX4/Firmware/blob/b7b5b89969935acd57133f327f640dc1db657fed/src/modules/mavlink/mavlink_main.cpp#L1746-L1904

To send this command, would I use the command long message like this?

mavlink_msg_command_long_pack(1, 1, &message, 1, 1, MAV_CMD_SET_MESSAGE_INTERVAL, 1, 105, 0, 0, 0, 0, 0, 0);
uint16_t len = mavlink_msg_to_send_buffer(buf, &message);
Serial1.write(buf, len);

I was able to achieve it by changing the mode but I want to explore this option too.

This looks almost right but you need to use a different component ID for your arduino, e.g. 241 (Messages (common) · MAVLink Developer Guide).

I have been using this function and after parsing the messages, I can see that the command message is parsed and that the Result=0 (which means that it was accepted and executed). However, the IMU values never get parsed. Strangely, the heartbeat message also never gets parsed. What could be the problem?

void send_command() {
mavlink_message_t message;
uint8_t buf[MAVLINK_MAX_PACKET_LEN];

  mavlink_msg_command_long_pack(1, 241, &message, 1, 1, MAV_CMD_SET_MESSAGE_INTERVAL, 1, 105, 0, 0, 0, 0, 0, 0);
  uint16_t len = mavlink_msg_to_send_buffer(buf, &message);
  Serial1.write(buf, len);
}

I’m a bit confused what works and what does not at this point.

You need to post the whole code and say exactly what goes wrong where.

Okay, this is my full code. I am trying to send the request command so that I can read the IMU values (without changing the mode).

#include <mavlink.h>

void setup() {
  Serial.begin(57600);
  Serial1.begin(57600);
}

void loop() {

mavlink_message_t message;
uint8_t msgReceived = false;
mavlink_status_t status;


uint8_t buf[MAVLINK_MAX_PACKET_LEN];
mavlink_msg_command_long_pack(1, 241, &message, 1, 1, MAV_CMD_SET_MESSAGE_INTERVAL, 1, 105, 0, 0, 0, 0, 0, 0);
uint16_t len = mavlink_msg_to_send_buffer(buf, &message);
Serial1.write(buf, len);

if (Serial1.available() > 0) {
    uint8_t result = Serial1.read();

    msgReceived = mavlink_parse_char(MAVLINK_COMM_1, result, &message, &status);

    if (msgReceived) {
      switch (message.msgid) {
        case MAVLINK_MSG_ID_HEARTBEAT:
          {
            mavlink_heartbeat_t hb;
            mavlink_msg_heartbeat_decode(&message, &hb);
            Serial.print("\n");
            Serial.println("Heartbeat Message");
            Serial.print("Msgid: ");  Serial.println(message.msgid);
            Serial.print("Type: ");  Serial.println(hb.type);
            Serial.print("Autopilot type: ");  Serial.println(hb.autopilot);
            Serial.print("System mode: ");  Serial.println(hb.base_mode);
            Serial.print("Custom mode: ");  Serial.println(hb.custom_mode);
            Serial.print("System status: ");  Serial.println(hb.system_status);
            Serial.print("Mavlink version: "); Serial.println(hb.mavlink_version);
            delay(1000);
          }
        case MAVLINK_MSG_ID_HIGHRES_IMU:
          {
            mavlink_highres_imu_t highres;
            mavlink_msg_highres_imu_decode(&message, &highres);

            Serial.print("HiRes IMU Msgid: ");  Serial.println(message.msgid);
            Serial.print("Xacc: "); Serial.println(highres.xacc);
            Serial.print("Yacc: "); Serial.println(highres.yacc);
            Serial.print("Zacc: "); Serial.println(highres.zacc);
            Serial.print("Xgyro: "); Serial.println(highres.xgyro);
            Serial.print("Ygyro: "); Serial.println(highres.ygyro);
            Serial.print("Zgyro: "); Serial.println(highres.zgyro);
            Serial.print("Xmag: "); Serial.println(highres.xmag);
            Serial.print("Ymag: "); Serial.println(highres.ymag);
            Serial.print("Zmag: "); Serial.println(highres.zmag);
            Serial.print("Absolute Pressure: "); Serial.println(highres.abs_pressure);
            Serial.print("Diff Pressure: "); Serial.println(highres.diff_pressure);
            Serial.print("Pressure Alt : "); Serial.println(highres.pressure_alt);
            Serial.print("Temperature : "); Serial.println(highres.temperature);
            Serial.print("\n");
            delay(1000);
          }
        default :
          {
            Serial.println(message.msgid);
          }

      }//switch
    }//if msg
  }//if serial 1
}//loop

However, I cannot get the HIGHRES_IMU message ID to go through the switch case even after sending the command. The switch case goes straight to default and prints some inconsistent message IDs like #77 and #30.

Ok, this looks mostly correct now, two things that you should try:

  1. Remove the delay(1000) because like this you stop the loop and you potentially miss data from serial because you are not reading fast enough.
  2. Looking at the arguments of mavlink_msg_command_long_pack I see that param1 is 105 which is for the IMU_HIGHRES message, so that’s correct, but then param2 is 0 which according to the MALink message definitions stands for:

The interval between two messages, in microseconds. Set to -1 to disable and 0 to request default rate.

You set it to 0 which means default, however, presumably the default is not to send it all, otherwise it would already be sent when you connect anyway. Therefore, I’d try to set it to a certain rate. E.g. if you want 20 Hz, then you would use 1/20s = 50000 us.

I was able to get it to work in the end, and this is the code I ended up with. I also found that changing the mode as in this reply helps with some messages.

#include <mavlink.h>

//mavlink_msg_command_long_pack() function
uint8_t target_system = 1;
uint8_t target_component = 1;
uint16_t CMD_LONG_command = 0;
uint8_t CMD_LONG_confirmation = 0;
float CMD_LONG_param1 = 0;
float CMD_LONG_param2 = 0;
float CMD_LONG_param3 = 0;
float CMD_LONG_param4 = 0;
float CMD_LONG_param5 = 0;
float CMD_LONG_param6 = 0;
float CMD_LONG_param7 = 0;

int currenttime = 0;
int previoustime = 0;

int numberhb = 10;
int numberhbpast = 0;

uint8_t system_id = 1;
uint8_t component_id = 241;

void setup() {
  Serial.begin(57600);
  Serial1.begin(57600);

  send_command();
}

void loop() {
  mavlink_message_t message;

  uint8_t type = MAV_TYPE_QUADROTOR;
  uint8_t system_type = MAV_TYPE_GENERIC;
  uint8_t autopilot = MAV_AUTOPILOT_PX4;
  uint8_t base_mode;
  uint32_t custom_mode;
  uint8_t system_status;

  uint8_t buf[MAVLINK_MAX_PACKET_LEN];

  mavlink_msg_heartbeat_pack(1, 241, &message, type, autopilot, base_mode, custom_mode, system_status);

  uint16_t len = mavlink_msg_to_send_buffer(buf, &message);

  currenttime = millis();
  if (currenttime - previoustime >= 1000) {
    previoustime = currenttime;
    Serial1.write(buf, len);

    numberhbpast++;

    if ( numberhbpast >= numberhb ) {
      send_command();
      Serial.println("Command sent");
      numberhbpast = 0;
    }
  }
  readmessage();
}//loop



void send_command() {
  mavlink_message_t message;
  uint8_t buf[MAVLINK_MAX_PACKET_LEN];

  CMD_LONG_param1 = MAVLINK_MSG_ID_HIGHRES_IMU;
  CMD_LONG_param2 = 10000; //100Hz
  CMD_LONG_command = MAV_CMD_SET_MESSAGE_INTERVAL;

  mavlink_msg_command_long_pack(system_id, component_id, &message, target_system, target_component, CMD_LONG_command, CMD_LONG_confirmation, CMD_LONG_param1, CMD_LONG_param2, CMD_LONG_param3, CMD_LONG_param4, CMD_LONG_param5, CMD_LONG_param6, CMD_LONG_param7);
  uint16_t len = mavlink_msg_to_send_buffer(buf, &message);
  Serial1.write(buf, len);

}

void readmessage() {

  uint8_t msgReceived = false;
  mavlink_message_t message;
  mavlink_status_t status;

  if (Serial1.available() > 0) {
    uint8_t result = Serial1.read();

    msgReceived = mavlink_parse_char(MAVLINK_COMM_1, result, &message, &status);

    if (msgReceived) {
      switch (message.msgid) {
        case MAVLINK_MSG_ID_HIGHRES_IMU:
          {
            mavlink_highres_imu_t highres;
            mavlink_msg_highres_imu_decode(&message, &highres);

            Serial.println("High Res IMU Message");
            Serial.print("Xacc: "); Serial.print(highres.xacc); Serial.println(" m/s/s");
            Serial.print("Yacc: "); Serial.print(highres.yacc); Serial.println(" m/s/s");
            Serial.print("Zacc: "); Serial.print(highres.zacc); Serial.println(" m/s/s");
            Serial.print("Xgyro: "); Serial.print(highres.xgyro); Serial.println(" rad/s");
            Serial.print("Ygyro: "); Serial.print(highres.ygyro); Serial.println(" rad/s");
            Serial.print("Zgyro: "); Serial.print(highres.zgyro); Serial.println(" rad/s");
            Serial.print("Xmag: "); Serial.print(highres.xmag); Serial.println(" gauss");
            Serial.print("Ymag: "); Serial.print(highres.ymag); Serial.println(" gauss");
            Serial.print("Zmag: "); Serial.print(highres.zmag); Serial.println(" gauss");
            Serial.print("Absolute Pressure: "); Serial.print(highres.abs_pressure); Serial.println(" mbar");
            Serial.print("Diff Pressure: "); Serial.print(highres.diff_pressure); Serial.println(" mbar");
            Serial.print("Pressure Alt : "); Serial.println(highres.pressure_alt);
            Serial.print("Temperature : "); Serial.print(highres.temperature); Serial.println(" degC");

            Serial.print("\n");
          }

        default :
          {

          }

      }
    }
  }
}//void

I have, it seems, the same problem,
I can successfully request certain parameters (#27), but I am unable to request #132.

I use this command:
mavlink_msg_command_long_pack(2, 0, &msg, 1, 1, 511, 0, 132, 100000, 0,0,0,0,0);
Which works correctly for 27 but not for 132.

I did not manipulated with modes, but #511 should work even for parameters not included in the mode and #132 is included in the default mode (Onboard) anyway.

Help would be much appreciated.

Hi,
I am having similar problem. I am trying to request STATUSTEXT to be sent from pixhawk to onboard controller over TELEM2.
I have added debug message in Pixhawk as follows:

MavlinkReceiver::set_message_interval(int msgId, float interval, int data_rate)
{
	if (msgId == MAVLINK_MSG_ID_HEARTBEAT) {
		return PX4_ERROR;
	}

	printf("set_message_interval( %d, %f, %d)\n", msgId,  (double)(interval), data_rate);

In debug port receive the message, “set_message_interval( 253, 1000000.000000, 0)”, however, STATUSTEX messages ar being sent only to QGC.

I also tried adding stream to mavlink_main.cpp:

case MAVLINK_MODE_ONBOARD:
		// Note: streams requiring low latency come first
		printf("[Mavlink Main] configure_stream STATUSTEXT \n");
		configure_stream_local("STATUSTEXT", 20.0f);

This also does not enable STATUSTEXT message sending to onboard controller.

Onboard controller usually connects to mavlink channel 2, because of this I also tried adding these lines to STATUSTEXT.hpp where the message is sent to QGC:

mavlink_msg_statustext_send_struct(_mavlink->get_channel(), &msg);
printf("Mavlink channel %d\n", _mavlink->get_channel());
mavlink_msg_statustext_send_struct(MAVLINK_COMM_2, &msg);

Pixhawk never sends this message to channel 2, only to channel 0 which is QGC in my case.

I also tried using MESSAGE_INTERVAL ( #244 ). However, it seems that handling of this message is not implemented in mavlik_receiver.cpp, atleast in v1.12.3

Are there any explanation why none of these methods work?

Just for record I am able to send and receive heartbeat and various other messages.

Hello,

I’m trying mavlink communication over GPS 1 port in CUBE orange. I tried using this code to receive some parameter information. However, the code is not compiling. I keep getting the error MAVLINK_MSG_ID_HIGHRES_IMU’ was not declared in this scope

Please let me know what to do, I’m completely lost.

I don’t think that should be that complicated. All that you need is to set MAV_0_CONFIG (or 1 or 2) and set it to GPS 1.

Hello, MAV_0_CONFIG is not available in mission planner

I’m actually getting some data in my serial connection, when I check if Serial2.available , however,
mavlink_parse_char if statement is returning zero.

I’m attaching my code here

#include <mavlink.h>
//#include <SoftwareSerial.h>

//#define RXpin 0
//#define TXpin 1
//SoftwareSerial SerialMAV(RXpin, TXpin); // sets up serial communication on pins 3 and 2

void setup() {
Serial2.begin(57600); //RXTX from Pixhawk (Port 19,18 Arduino Mega)
Serial.begin(115200); //Main serial port for console output

request_datastream();

}

void loop() {

MavLink_receive();

}

//function called by arduino to read any MAVlink messages sent by serial communication from flight controller to arduino
void MavLink_receive()
{
mavlink_message_t msg;
mavlink_status_t status;

while(Serial2.available())
{Serial.println(“Serial port available”);
uint8_t c= Serial2.read();

//Get new message
if(mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status))
{

//Handle new message from autopilot
  switch(msg.msgid)
  {

    case MAVLINK_MSG_ID_GPS_RAW_INT:
  {
    mavlink_gps_raw_int_t packet;
    mavlink_msg_gps_raw_int_decode(&msg, &packet);
    
    Serial.print("\nGPS Fix: ");Serial.println(packet.fix_type);
    Serial.print("GPS Latitude: ");Serial.println(packet.lat);
    Serial.print("GPS Longitude: ");Serial.println(packet.lon);
    Serial.print("GPS Speed: ");Serial.println(packet.vel);
    Serial.print("Sats Visible: ");Serial.println(packet.satellites_visible);
   
  }
  break;

  }
}

}
}

void request_datastream() {
//Request Data from Pixhawk
uint8_t _system_id = 255; // id of computer which is sending the command (ground control software has id of 255)
uint8_t _component_id = 2; // seems like it can be any # except the number of what Pixhawk sys_id is
uint8_t _target_system = 1; // Id # of Pixhawk (should be 1)
uint8_t _target_component = 0; // Target component, 0 = all (seems to work with 0 or 1
uint8_t _req_stream_id = MAV_DATA_STREAM_ALL;
uint16_t _req_message_rate = 0x01; //number of times per second to request the data in hex
uint8_t _start_stop = 1; //1 = start, 0 = stop

// STREAMS that can be requested
/*

  • Definitions are in common.h: enum MAV_DATA_STREAM and more importantly at:
    Messages (common) · MAVLink Developer Guide
  • MAV_DATA_STREAM_ALL=0, // Enable all data streams
  • MAV_DATA_STREAM_RAW_SENSORS=1, /* Enable IMU_RAW, GPS_RAW, GPS_STATUS packets.
  • MAV_DATA_STREAM_EXTENDED_STATUS=2, /* Enable GPS_STATUS, CONTROL_STATUS, AUX_STATUS
  • MAV_DATA_STREAM_RC_CHANNELS=3, /* Enable RC_CHANNELS_SCALED, RC_CHANNELS_RAW, SERVO_OUTPUT_RAW
  • MAV_DATA_STREAM_RAW_CONTROLLER=4, /* Enable ATTITUDE_CONTROLLER_OUTPUT, POSITION_CONTROLLER_OUTPUT, NAV_CONTROLLER_OUTPUT.
  • MAV_DATA_STREAM_POSITION=6, /* Enable LOCAL_POSITION, GLOBAL_POSITION/GLOBAL_POSITION_INT messages.
  • MAV_DATA_STREAM_EXTRA1=10, /* Dependent on the autopilot
  • MAV_DATA_STREAM_EXTRA2=11, /* Dependent on the autopilot
  • MAV_DATA_STREAM_EXTRA3=12, /* Dependent on the autopilot
  • MAV_DATA_STREAM_ENUM_END=13,
  • Data in PixHawk available in:
    • Battery, amperage and voltage (SYS_STATUS) in MAV_DATA_STREAM_EXTENDED_STATUS
    • Gyro info (IMU_SCALED) in MAV_DATA_STREAM_EXTRA1
      */

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

// Pack the message
mavlink_msg_request_data_stream_pack(_system_id, _component_id, &msg, _target_system, _target_component, _req_stream_id, _req_message_rate, _start_stop);
uint16_t len = mavlink_msg_to_send_buffer(buf, &msg); // Send the message (.write sends as bytes)

Serial2.write(buf, len); //Write data to serial port
}

If you’re using MissionPlanner you’re likely using ArduPilot. This forum is for PX4 users. Please ask in discuss.ardupilot.org instead.

1 Like