Error sending data to CAN

HI all,

I've been trying to read from a time of flight sensor and publish the data to CAN. I know for a fact (using serial monitor) that data is correct. It is able to connect to CAN in the setup function however, every time I attempt to send to CAN, it is never successful (!= CAN_OK).

I am currently using an Arduino UNO equipped with a seeed CAN-BUS shield, and using a PCAN to connect to my laptop running Mint distro of Linux OS. On my end, I run sudo --stdin ip link set can0 up type can bitrate 1000000

Code below:

#include <mcp_can.h>
#include <SPI.h>  // spi devices

#include <Wire.h> // For actually reading from i2c device

/**
 * @brief File containing functionality to read and publish tf02 data to CAN. using generic UNO boards
 * see https://www.robotshop.com/media/files/content/b/ben/pdf/benewake-tf02-pro-lidar-led-rangefinder-ip65-40m-manual_.pdf
 */

#define SPI_CS_PIN 9
MCP_CAN can_dev(SPI_CS_PIN) ;

#define CAN_ID 0x100
#define CAN_DLC 2
static uint8_t distance_bytes[CAN_DLC] = {0} ; // variable to put mm distance measurement in

void setup()
{
  Wire.begin() ; // Join I2c bus

  Serial.begin(9600) ;

  while(CAN_OK != can_dev.begin(MCP_ANY, CAN_1000KBPS, MCP_16MHZ))
  {
    Serial.println("Awaiting CAN bus connection") ;
    delay(10) ;
  }
  can_dev.setMode(MCP_NORMAL) ; // Change to normal mode to allow messages to be transmitted
  Serial.print("CAN bus initialised @ 1000KBPS. Sending to ") ;
  Serial.print(CAN_ID, HEX) ;
  Serial.print("\n") ;
}

/**
  * @brief publish_distance - sends provided message (cm) along CAN bus (little endian format)
  * @param const uint8_t* - pointer to start of 2 byte-array to be read and sent
  */
void publish_distance(const uint8_t* bytes)
{
  const byte send_status = can_dev.sendMsgBuf(CAN_ID, CAN_DLC, bytes) ;

  if(send_status == CAN_OK)
  {
    Serial.print("Successfully sent message to 0x") ; Serial.print(CAN_ID, HEX) ;
    Serial.print(". Assembled value: ") ; Serial.print(*((uint16_t*)bytes)) ;  
    Serial.print("\n") ;
  }
  else {
    Serial.println("An error occured when sending latest CAN frame") ;
  }
}

/**
  * @brief read_distance - does full read AND sending (using publish_distance) of message along CAN bus. cm value
  * @param uint8_t* - pointer to start of 2 byte-array to be written to
  */
void read_distance(uint8_t* bytes)
{
  /* step 1: instruct sensor to read echoes */
  Wire.beginTransmission(0x10) ; // transmit to device 0x10
  Wire.write(0x5A) ; // some read command.
  Wire.write(0x05) ;
  Wire.write(0x00) ;
  Wire.write(0x01) ; // note 0x01 is cm, 0x06 is mm
  Wire.write(0x60) ;
  Wire.endTransmission() ; // stop transmitting

  /* step 2: wait for readings to happen
   * instead of idly waiting, call function in gap to publish old distance before update
   * this should take a good amount of time to suffice as the delay
   */
  publish_distance(bytes) ;

  /* step 3: request reading from sensor */
  Wire.requestFrom(0x10, 4) ; // request first 4 bytes from slave device #0x10
  Wire.read() ; Wire.read() ; //ignore header bytes
  // remaining two bytes for distance (DIST_L, DIST_H)
  bytes[0] = Wire.read() ;
  bytes[1] = Wire.read() ; // calculate distance value, bit shift high distance
}

void loop()
{
  read_distance(distance_bytes) ;
}

Any help would be much appreciated. Thank you!

Hello daleksla, good day.
I have checked the mcp_can package at git and the examples work with standard speed CAN_500KBPS. Have you tried to reduce to CAN_500KBPS? Is the CAN prepared with 120Ohm resitor to avoid reflections on CAN?
Best regards Markus

have you correctly terminated the bus?
whar is the length of the bus?
try reducing the speed?
have you an oscilloscpe or logic analyser so look at signals on the bus?
I find a useful tool when working with canbus is a USB-CAN dongle to monitor the traffic on the bus

Hi,

Right so YES, i do have a 12O ohm terminating resistor added.

Following that advice, I took one of the example programs from the library - the CAN_SEND example - and tried running that - didn't work in that the data wouldn’t send yet again

#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(9);     // Set CS to pin 9 - default chip select of shield

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

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  while(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) != CAN_OK)
  {
      Serial.println("MCP2515 not initialized!");
  }
  Serial.println("Initialized MCP2515");

  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
}

byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void loop()
{
  // send data:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
  byte sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data);
  if(sndStat == CAN_OK){
    Serial.println("Message Sent Successfully!");
  } else {
    Serial.println("Error Sending Message...");
  }
  delay(100);   // send data per 100ms
}

Ran this when both sudo --stdin ip link set can0 up type can bitrate 500000 was and wasn't running on my laptop

Any suggestions?

I believe I have corrected terminated it using a 120 ohm resistor. I'm quite new to working with CAN so admittedly I am not sure what you mean by length. I also tried reducing the speed to 500KBPS to not avail. & I have not got any of those kind of tools unfortunately

2022-04-29-225500

Thought i'd upload my setup

Figure 2 of CAN-bus-physical-layer shows bus topology - check your wiring against it.
could you supply details of the TOF sensor, e.g. a link to a datasheet?
it is worth getting a CAN-USB dongle (look on ebay) they are not expensive and help debugging CAN networks.

Datasheet: https://www.robotshop.com/media/files/content/b/ben/pdf/benewake-tf02-pro-lidar-led-rangefinder-ip65-40m-manual_.pdf

As for the usb dongle, would this suffice or not:

the datasheet does not mention Canbus only UART serial and I2C ??
do you have a different interface?

the CAN-USB doggle looks OK

My code essentially reads from the i2c bus (read_distance) then pushes the (previously) read value to CAN (publish_distance)

Is this the shild you are using? Can_Bus_Shild

On this link you can find several informations at "Getting Started". There is also a pinning info of the SubD connector. Are your CAN pins right connected?


Can you observe the CAN_H and CAN_L with an Oszi? Two channels are needed to see as CAN is a differential signal.
I feel if the example from git is not working fine then you may have a hardware connection topic behind the subD.

are you sure you have the canbus speed correct on your canbus devices?
if the devices are set to different speeds you can get rubbish on the bus
if I run your program with a canbus test board at 500Kb/s I receive

Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607
Rx Std ID 00000100 data 0001020304050607

the ID and data you are transmitting
and the Arduino Serial monitor displays

Entering Configuration Mode Successful!
Setting Baudrate Successful!
Initialized MCP2515
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!

if I change the speed of the other canbus board

Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!
Error Sending Message...
Error Sending Message...
Error Sending Message...
Message Sent Successfully!
Message Sent Successfully!
Message Sent Successfully!

as soon as change the speed of the other board to 250Kb/s I get errors, change it back to 500Kb/s and all is OK
in addition if the other canbus device is not operating the transmission will report an error as the acknowledgement fails - if received the receiving node will overwrite the recessive acknowledge bit (ACK) with a dominant bit

2 Likes

Hello horace, well done made check on your side! This makes it clear where to search for the not transmitting. Best regards Markus

did you find the problem?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.