CAN Protocol issues

I've been trying to get CAN communications working on the portenta machine control for the past few days with no luck. Here are a number of observations I've made.

  • I've inspected the communication output from the board bit by bit and the message seems to formatted correctly.

  • I have not been able to receive any messages at my desired baud of 1Mbit/s.

  • If I enter any baud above 500kbit/s the output from the board appears to get stuck in a loop, repeating the same message over and over again. Even if I only send one message (as below). At a baud of 500kbit/s, one message is sent, but I don't have any devices able to communicate at that speed.

  • In another post here. @Petrovim claims to have got it working while operating at 250kbit/s. Which would support my previous point.

Any help would be greatly appreciated! I'm starting to loose it!
Code below:

#include <Arduino_MachineControl.h>
#include <CAN.h>
using namespace machinecontrol;

#define DATARATE_1MB 1000000

int counter = 0;
const uint8_t payload_size = 8;
unsigned char payload[payload_size];
bool sent = false;

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

  while (!Serial)
  {
    ; // wait for serial port to connect.
  }

  Serial.println("Start CAN initialization");
  comm_protocols.enableCAN();
  Serial.println(comm_protocols.can.frequency(DATARATE_1MB));
  Serial.println("Initialization done");
}

void loop()
{

  if (sent == false)
  {
    payload[0] = 0x72;
    payload[1] = 0x00;
    payload[2] = 0x3D;
    payload[3] = 0x00;
    payload[4] = 0x00;
    payload[5] = 0x00;
    payload[6] = 0x00;
    payload[7] = 0x00;

    mbed::CANMessage msg = mbed::CANMessage(0X780ul + 15ul, &payload[0], payload_size);

    if (comm_protocols.can.write(msg) == 1)
    {
      Serial.print("Sent:");
      for (uint8_t i = 0; i < payload_size; i++)
      {
        Serial.print(msg.data[i], HEX);
        Serial.print(" ");
      }
      Serial.println();
    }

    sent = true;
  }
  mbed::CANMessage msg;
  if (comm_protocols.can.read(msg))
  {

    // Print the sender ID
    Serial.print("ID: ");
    Serial.println(msg.id);

    // Print the first Payload Byte
    Serial.print("Message received:");
    Serial.println(msg.data[0], DEC);
  }

  delay(100);
}

I would try breaking out the read portion from the write portion and remove the delay. I wonder if you write, delay until after there's a message and then miss it.

Also haven't had enough coffee yet.

  mbed::CANMessage msg;
  if (comm_protocols.can.read(msg))
  {

    // Print the sender ID
    Serial.print("ID: ");
    Serial.println(msg.id);

    // Print the first Payload Byte
    Serial.print("Message received:");
    Serial.println(msg.data[0], DEC);
  }

  delay(100);
1 Like

Thanks for the suggestion. I have tried that, but the problem that I noticed is that the message that I send keeps repeating. As in, when one message ends, the next one immediately starts and so on.

I should also mention that I'm using about 700mm of twisted copper pair wire with a ground line and a 120Ohm termination resistor.

When I check the resistance of the entire loop, I'm getting 60Ohms. As expected.

For reference, this is the output I'm getting from the code above. I send one message and the same message is repeated over and over.

Great news it is working correctly, bad news you have no CAN module to receive it hence it errors because it did not receive an ACK (ACKnowledge) from somebody on the network. Simple fix: Download Corry Fowler's library use an old Arduino, CAN module and install the CAN receive code.

This gets a lot of people as they do not take the time to read that big book on CAN. It was and still is part of the specification. The ACK actually comes during the transmission of a message, somebody receiving the message does an ACK at the appropriate time while the message is being sent. The ACK bit from the transmitter is recessive and from the receiver(s) dominate. This is built into the hardware of the controller. Also if it is not acknowledged it will try for a given number of times then error out.

1 Like

Thanks for confirming this! Unfortunately that does appear to be the case. The instrument that I'm working with has a CAN port and the documentation for CAN, but it appears that port is purely for show and attached to nothing. Thanks for the help!

1 Like