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) ;
}
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
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
}
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
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.
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