Heartbeat messages

Hello,

I’m trying to read heartbeat messages from my Pixhawk 6X but unfortunately I can’t read any messages. I have connected the Telem2 Port to my Arduino
TX of the Pixhawk to the Arduino RX pin
GND to GND
Does anyone have an idea why it is not working?

#include <mavlink.h>

const int ledPin = 13; 

void setup() {
  Serial.begin(57600); 
  pinMode(ledPin, OUTPUT); 
}

void loop() {
  if (Serial.available() > 0) {
    uint8_t c = Serial.read();
    mavlink_message_t msg;
    mavlink_status_t status;

    if (mavlink_parse_char(MAVLINK_COMM_2, c, &msg, &status)) {
      // Check if this message is a hertbeat message
      if (msg.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
        mavlink_heartbeat_t heartbeat;
        mavlink_msg_heartbeat_decode(&msg, &heartbeat);

        // Print heartbeat message data
        Serial.print("Received Heartbeat Message:\n");
        Serial.print("Autopilot: ");
        Serial.println(heartbeat.autopilot);
        Serial.print("Base mode: ");
        Serial.println(heartbeat.base_mode);
        Serial.print("Custom mode: ");
        Serial.println(heartbeat.custom_mode);
        Serial.print("System status: ");
        Serial.println(heartbeat.system_status);
        Serial.print("Type: ");
        Serial.println(heartbeat.type);

        

        // Turn LED on if message is received
        digitalWrite(ledPin, HIGH);
        delay(1000); // LED on for 1 sec
        digitalWrite(ledPin, LOW); // LED ausschalten
      }
    }
    
    }
     else {      
     Serial.print("No Heartbeat\n");
      // LED blinken if there is no heartbeat
        digitalWrite(ledPin, LOW);
        delay(500); 
        digitalWrite(ledPin, HIGH); 
  }
 

I also tried this code to see if there is anything received on the port, but also no messages:

// Seriel Checker
#include <mavlink.h>

const int ledPin = 13; 

void setup() {
  Serial.begin(115200); 
  pinMode(ledPin, OUTPUT); 
}

void loop() {
  if (Serial.available() > 0) {
     Serial.print("Signal detected\n");
     Serial.print
    }
     else {      
     Serial.print("No Heartbeat\n");
     
        digitalWrite(ledPin, LOW);
        delay(500); 
        digitalWrite(ledPin, HIGH); }
  }
 

You’re writing blocking code while trying to communicate. You can’t delay 500-1000 ms and expect to capture much serial traffic. There are other logic issues as well (reading one byte per entire loop and re-declaring what look to be persistent state variables on each iteration).

And your second example shouldn’t even build. It’s missing parentheses, arguments, and a semi-colon after the unused Serial.print statement as well as missing a closing brace at the end. Additionally, it’s using a different baud rate than your primary sketch, and it will suffer from the same blocking issue anytime the serial buffer is empty.

I’m afraid if you’re making mistakes this fundamental that it will be extremely difficult to proceed with anything more complex.

1 Like

Thanks for your reply!
I modified the code and instead of an if-else statement I’m reading the serial traffic in a while loop do you think this is the right way?
Also I’m not sure about the baudrate, I tried 57600 and 115200 but both with the same result (115200 is the baudrate in my groundcontrol software).
I could compile the code but I receive only “No Heartbeat”…

#include <mavlink.h>

const int ledPin = 13; 

void setup() {
  Serial.begin(115200); 
  pinMode(ledPin, OUTPUT); 
}

void loop() {
  while (Serial.available() > 0) {
    uint8_t c = Serial.read();
    mavlink_message_t msg;
    mavlink_status_t status;

    if (mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status)) {
      // Check if there is a Heartbeat
      if (msg.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
        mavlink_heartbeat_t heartbeat;
        mavlink_msg_heartbeat_decode(&msg, &heartbeat);

        // Show information from Heartbeat message
        Serial.print("System type: ");
        Serial.println(heartbeat.type);
        Serial.print("Autopilot type: ");
        Serial.println(heartbeat.autopilot);
        Serial.print("Base mode: ");
        Serial.println(heartbeat.base_mode);

        //digitalWrite(ledPin, HIGH);
        //delay(1000);
        //digitalWrite(ledPin, LOW);
      }
    }
  }

  // If there is no message, print "No Heartbeat" and blink LED
  if (!Serial.available()) {
    Serial.print("No Heartbeat\n");
    //digitalWrite(ledPin, LOW);
    //delay(500);
    //digitalWrite(ledPin, HIGH);
  }
}

You are redeclaring your message buffer and status variables after every byte of the message, so of course it’s not working (not to mention you don’t know what baud rate is in use).

And there is a further flaw in the logic, in that a lack of serial message on any given run of the main loop doesn’t indicate an invalid heartbeat. It only indicates that no serial traffic was read on that pass. Heartbeat messages are passed periodically, which will mean that many loop cycles will happen without any message at all.

Read the documentation for the library you are using. Try using examples verbatim.

Alternatively, find a way to achieve your goal (which you have yet to state) with off the shelf hardware rather than rolling your own, since you’re clearly struggling.

1 Like

The goal is to read heartbeat messages with an arduino to get more familiar with handling mavlink messages (read/write or receive and send).

I think I get your point, my idea now is to store all received data into an array and decode it then.
I mean it would be helpful to know if I receive anything from the serial port…

The msg variable is already the buffer you need. Don’t try to pass an array where a single byte is intended. Just scope your variables properly.

2 Likes

There is an other issue that I think about which I maybe did wrong…the heartbeat messages should be requested first from the Pixhawk, right?
Or does the Pixhawk always send the messages?

I think you should start here and try and modify something that already works rather than starting from scratch

1 Like

This issue is solved, my code is working now, thank you for your help!
For everyone who is interested:

#include <mavlink.h>

void setup() {
  Serial.begin(115200);  
}
void loop() {
  mavlink_message_t msg;
  mavlink_status_t status;

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

    
    if (mavlink_parse_char(MAVLINK_COMM_0, c, &msg, &status)) {
      
      if (msg.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
        mavlink_heartbeat_t heartbeat;
        mavlink_msg_heartbeat_decode(&msg, &heartbeat);

        
        uint8_t systemType = heartbeat.type;
        uint8_t autopilotType = heartbeat.autopilot;
        uint8_t baseMode = heartbeat.base_mode;

        
        Serial.print("Message received\n");
        Serial.print("System type: ");
        Serial.println(systemType);
        Serial.print("Autopilot type: ");
        Serial.println(autopilotType);
        Serial.print("Base mode: ");
        Serial.println(baseMode);
      }
      //else{
        //Serial.print("No Heartbeat\n");
      //}
    }
  }
}