Disable CAN heartbeat

I’m looking to talk to and control multiple ODrives over CANbus with an Arduino Due. I got a basic script going that just reads the heartbeat that the ODrive periodically sends, but now that I"ve confirmed the CAN communication is working, I want to disable the heartbeat. I read on a previous post that setting odrv0.axis0.config.can_heartbeat_rate_ms = 0 would disable the heartbeat, but I still get a heartbeat after setting that parameter and saving the config. The message I get for the heartbeat is:

ID: 0x21 Len: 8 Data: 0x0 0 0 0 1 0 0 0

This message is a bit confusing to me since I expected ID to be either 0x700 for the CMD ID as listed in the protocol docs or 0x01 for the CAN node ID I set for the ODrive (1). Could someone explain what exactly I’m looking at with this message?

My Arduino test code is below:

/**
 * Experimentation script using https://github.com/collin80/due_can/blob/master/examples/CAN_AutoBaud/CAN_AutoBaud.ino
 * as guidance.
 * 
 * ============= SEQUENCE THAT NEEDS TO BE IMPLEMENTED IN CAN PROTOCOL
 * 1) odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE (startup)
 * 2) odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL (startup)
 * 3) odrv0.axis0.controller.input_pos = <float> (repeat)
 * 
 * documentation of ODrive CAN protocol -> https://docs.odriverobotics.com/can-protocol
 * example of data frame for pos control -> https://discourse.odriverobotics.com/t/can-interface-available-for-testing/1448/8?u=andrew_103
 * 
 */

#include <due_can.h>
// #include <DueTimer.h>

void setup() {
  Serial.begin(115200);
  Can0.begin(CAN_BPS_250K);

  for (int filter = 0; filter < 3; filter++) {
    Can0.setRXFilter(filter, 0, 0, true);
  }
  for (int filter = 3; filter < 15; filter++) {
    Can0.setRXFilter(filter, 0, 0, false);
  }
}

void print_frame(CAN_FRAME &frame) {
  Serial.print("ID: 0x");
  Serial.print(frame.id, HEX);
  Serial.print(" Len: ");
  Serial.print(frame.length);
  Serial.print(" Data: 0x");
  for (int count = 0; count < frame.length; count++) {
    Serial.print(frame.data.bytes[count], HEX);
    Serial.print(" ");
  }
  Serial.print("\r\n");  
}

void loop() {
  if (Can0.available() > 0) {
    CAN_FRAME incoming;
    Can0.read(incoming);
    print_frame(incoming);
  }
}

Why? :thinking:

You can change the heartbeat frequency in the config, send it once a second if you want. But it’s useful to know that nothing has died, that’s what it’s for.

I agree that a heartbeat is useful, but for my application I won’t be using or checking for it. In that case, it just becomes bloat. I could filter for the specific ID of what I want but as I mentioned the ID for the heartbeat isn’t what it was in the docs so I’m not sure how to go about this from here or what message IDs to send/expect for other commands.

Should just have to set it to 0.

CANOpen heartbeat isn’t used. Just the “regular” heartbeat at 0x001.

** Note: These CANOpen messages are reserved to avoid bus collisions with CANOpen devices. They are not used by CAN Simple.

Thanks for the responses. As it turns out, I did successfully disable the heartbeat by setting it to 0 but only for axis0. The heartbeat was still active for axis1 which is what I was reading with my script. After setting the axis1 heartbeat to 0, I didn’t get a heartbeat message anymore.