Go Down

Topic: MCP25050 can message from MCP2515 (Read 476 times) previous topic - next topic

NusNus

I am new to CAN and having trouble getting my CAN device to answer. Can you help?

My Arduino is connected to an MCP2515 board. This communication is verified working with another Arduino with another MCP2515. One Arduino sends data and the other prints it to serial monitor, no problems. I have been using the mcp2515.h library.

I am now trying to ask for data from a MCP2505 programmable CAN node but cant figure out how to do it. What should I send to MCP2505 to get it to send me for example the control regs? Attached is a snip from the data sheet with the sequences.

As I see it, Arduino sends first "Read Control Regs" and then listens for the device to send back "Read Control Regs" from the lower table.

The big question is: How should my struct look like in the Arduino sketch? Something like below or not? My MCP2505 node has the address 0x01. Im confused about the address part. Does MCP2505 only use 7 bit addresses and the rest 4 bits of the addresses are for telling the registry?

The full datasheet is here: http://ww1.microchip.com/downloads/en/DeviceDoc/20001664E.pdf

Code: [Select]
canMsg1.can_id  = 0x01;
  canMsg1.can_rtr = 1;
  canMsg1.can_ide = 0;
  canMsg1.can_dlc = 8;
  canMsg1.data[0] = 0x00;
  canMsg1.data[1] = 0x00;
  canMsg1.data[2] = 0x00;
  canMsg1.data[3] = 0x00;
  canMsg1.data[4] = 0x00;
  canMsg1.data[5] = 0x00;
  canMsg1.data[6] = 0x00;
  canMsg1.data[7] = 0x00;






Klaus_K

I suspect you will need to pre-program the MCP25050 with the correct settings for the CAN bus speed and some CAN message IDs. Otherwise it would not know which speed to set and what IDs to look for. Did you do that?

Just out of curiosity, if yes, what tools did you use for that?

Did you note the "Not Recommended for New Designs" at the beginning of the datasheet?

NusNus

The MCP25050 is programmed already. Its an old device that I need to communicate with.

So cant answer any of your other questions, sorry.

sherzaad

#3
Oct 17, 2020, 08:49 am Last Edit: Oct 17, 2020, 08:50 am by sherzaad
I am new to CAN and having trouble getting my CAN device to answer. Can you help?

My Arduino is connected to an MCP2515 board. This communication is verified working with another Arduino with another MCP2515. One Arduino sends data and the other prints it to serial monitor, no problems. I have been using the mcp2515.h library.

I am now trying to ask for data from a MCP2505 programmable CAN node but cant figure out how to do it. What should I send to MCP2505 to get it to send me for example the control regs? Attached is a snip from the data sheet with the sequences.

As I see it, Arduino sends first "Read Control Regs" and then listens for the device to send back "Read Control Regs" from the lower table.

The big question is: How should my struct look like in the Arduino sketch? Something like below or not? My MCP2505 node has the address 0x01. Im confused about the address part. Does MCP2505 only use 7 bit addresses and the rest 4 bits of the addresses are for telling the registry?

The full datasheet is here: http://ww1.microchip.com/downloads/en/DeviceDoc/20001664E.pdf
Looking at the comments to those table:
Quote
If using non-RTR messages for information request messages (IRM), the RTR bit = 0, DLC bit field = 0, and bit 3 of the IRM ID = 1. Also, bit 3 of the output message ID = 0.

If using RTR messages for IRMs, the RTR bit = 1, DLC bit field = number of bytes in corresponding output message, and bit 3 of the IRM ID = x (don't care), also, bit 3 of the output message = x (don't care).
so IMHO, the CAN frame you share or the following should work assuming you set the baudrate correctly
Code: [Select]

canMsg1.can_id  = 0x09; //IRM for 'read control reg. output message shuold be 0x01
canMsg1.can_rtr = 0;
canMsg1.can_ide = 0;
canMsg1.can_dlc = 0;


hope that helps....

NusNus

Quote
so IMHO, the CAN frame you share or the following should work assuming you set the baudrate correctly
Code: [Select]
Code: [Select]

canMsg1.can_id  = 0x09; //IRM for 'read control reg. output message shuold be 0x01
canMsg1.can_rtr = 0;
canMsg1.can_ide = 0;
canMsg1.can_dlc = 0;




hope that helps....
Thanks for this idea. It sounds good... But the mcp2515.h library does not know the member can_rtr. I have a strong feeling that RTR and IDE should be implemented in the can_id field. But would like to hear how this is really done.

sherzaad

#5
Oct 18, 2020, 07:40 pm Last Edit: Oct 21, 2020, 05:12 am by sherzaad
Thanks for this idea. It sounds good... But the mcp2515.h library does not know the member can_rtr. I have a strong feeling that RTR and IDE should be implemented in the can_id field. But would like to hear how this is really done.
There are many MCP2515 libraries out there... please share the link to the library you are using.

NusNus

#6
Oct 20, 2020, 10:07 pm Last Edit: Oct 20, 2020, 10:08 pm by NusNus
There are may MCP2515 libraries out there... please share the link to the library you are using.
I have been using msp2515.h. You can find it here: https://github.com/autowp/arduino-mcp2515

sherzaad

I have been using msp2515.h. You can find it here: https://github.com/autowp/arduino-mcp2515
Had a look at the library and you are right about it. It does not allow you to modify rtr. However since as suggested in reply #9, rtr=0, IMHO you should be able to still use this library; just specify the CAN ID and dlc. By default, the library sets rtr=0.
if you want to play about with the rtr bit you can alway try to use the MCP2515 library I put together.
hope that helps....

NusNus

#8
Nov 03, 2020, 08:17 pm Last Edit: Nov 03, 2020, 08:18 pm by NusNus
Had a look at the library and you are right about it. It does not allow you to modify rtr. However since as suggested in reply #9, rtr=0, IMHO you should be able to still use this library; just specify the CAN ID and dlc. By default, the library sets rtr=0.
if you want to play about with the rtr bit you can alway try to use the MCP2515 library I put together.
hope that helps....

Thank you for the help! Now I have some sort of communication to my MCP25050!! I used your library and it seems to work. I will call MCP25050 slave now on.
The problem is now to find the suitable speed. When I change speeds, the reply from slave changes. It seems like 500 kbps gives the most reliable data but how do I know the right speed?

Also the slave answers with the same message to any address. So If I send with ID 11 I get an answer. If I change the ID to 20 I still get the same answer. And the answer is not correct.

Example:
My device ID is 0x11. I send RTR = 1, IDE = 0, DLC = 8. This is the question to ask for "Read A/D regs". I will get an answer: ID 464, data bytes = 0 when I should get ID 0x11, data bytes = 8.

What could be wrong? Below is the code I used with arduino and a snippet from the terminal.


Code: [Select]
#include <mcp2515.h>
#include <mcp2515_defs.h>

MCP2515 CAN_Ch1(10, 2); //SPI CS, interrupt
//MCP25150 - Arduino: INT = 2, SCK = 13, SI = 11, SO = 12, CS = 10

void setup() {

  pinMode(2, INPUT);

  tCAN message;

  uint8_t std_data[7] ={0,0,0,0,0,0,0};

  //define CAN standard message
  message.id.std = 0b00100010000;//get A/D regs
  message.header.rtr = 1;
  message.header.ide = 0;
  message.header.dlc = 8;
  memcpy(message.data,std_data,sizeof(std_data));


 
  Serial.begin(115200);
  Serial.println("LAite kaynnistetty. CAN tsekkaaja!");

  if (CAN_Ch1.CAN_init(CANSPEED_500kBPS))   //käynnistetään MCP nopeudella x
    Serial.println("CAN1 Init ok");
  else
    Serial.println("Can't Init CAN1");

}

void loop() {

  tCAN message;

  CAN_Ch1.send_message(&message);
  Serial.println("Data lahetetty");

 

  if (CAN_Ch1.check_message()) {
    if (CAN_Ch1.get_message(&message)) {
      Serial.print("CAN_1 ID: ");
      if(message.header.ide) { Serial.print(message.id.ex, DEC); Serial.print("EX");} //extended CAN ID
      else {Serial.print(message.id.std, DEC); Serial.print("STD");} //standard CAN ID
      Serial.print(", ");
      Serial.print("Data[");
      Serial.print(message.header.dlc, DEC);
      Serial.print("]: ");
      for (int i = 0; i < message.header.dlc; i++) {
        Serial.print(message.data[i], DEC);
        Serial.print(" ");
      }
      Serial.println("");
    }
  }
  delay(2000);
 
 
}


Snippet with the above code in the terminal:
Code: [Select]

LAite kaynnistetty. CAN tsekkaaja!
CAN1 Init ok
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237
Data lahetetty
CAN_1 ID: 903STD, Data[2]: 116 237

sherzaad

#9
Nov 04, 2020, 08:06 am Last Edit: Nov 04, 2020, 08:20 am by sherzaad
"The problem is now to find the suitable speed. When I change speeds, the reply from slave changes. It seems like 500 kbps gives the most reliable data but how do I know the right speed?"

if you have the manual for the device if should be able to tell you that! :)

otherwise using a scope might be one way to determing the correct baudrate. 500kbps is probably right though! ;)

"My device ID is 0x11. I send RTR = 1, IDE = 0, DLC = 8. This is the question to ask for "Read A/D regs". I will get an answer: ID 464, data bytes = 0 when I should get ID 0x11, data bytes = 8."
Code: [Select]
message.id.std = 0b00100010000;//get A/D regs

0b00100010000 = 0x110 NOT 0x11!!! :o

why not just use the HEX notation to input the device ID....





NusNus

#10
Nov 04, 2020, 07:05 pm Last Edit: Nov 04, 2020, 07:07 pm by NusNus
"if you have the manual for the device if should be able to tell you that! :)
otherwise using a scope might be one way to determing the correct baudrate. 500kbps is probably right though!"
 
I have the datasheet. But the problem is that slave is programmable and it is programmed somehow. I do not know how so the settings can be anything. But will keep trying different speeds until it works :)
 
"0b00100010000 = 0x110 NOT 0x11!!! :o
 why not just use the HEX notation to input the device ID...."

 
Yes I know. This is something I do not understand in the datasheet. Attached is a snip of the commands I can send to slave. If i undestand correct, the 10 leftmost bits are the CAN ID. But to the ID is blended the register I want to access? So this makes my ID change depending what information I want. For example I want to "Read A/D Regs". This makes my CAN ID shift 4 bits to left. And if I want to read Control regs it is (ID <<4) | 1??
Am I correct or totally lost?
 
If you understand how this works, could you please write a code to ID 0x11 that asks for "Read Config Regs"?



Klaus_K

The problem is now to find the suitable speed. When I change speeds, the reply from slave changes. It seems like 500 kbps gives the most reliable data but how do I know the right speed?
When you change the speed, you should not be able to get any data whatsoever. The CAN protocol ensures every bit is verified. When you set the wrong speed, your node would detect errors on the bus and then disconnect, wait for a while and then connect again.

Here is how you can test this:

Tools:

A. Use an oscilloscope attached to CAN TX pin at the MCP2515 (Logic level) not at the bus

B. Find a way to detect changes on that CAN TX pin. A low power led with resistor might be enough. Or if you have a cheap logic level analyzer. Maybe even a multi-meter. You just need to detect the difference between a static signal and a changing signal.

Test:

1. Send one message once via the MCP2515 without a bus attached. Because the message does not get acknowledged the message is repeated forever. You can clearly detect this with the oscilloscope, but this should also be detectable by the methods in B.

2. Next attach the MCP2515 to the bus and only the MCP25050. Now repeat A. If the speed in the MCP25050 is wrong the behavior will be the same as in 1, if the speed is correct the MCP25050 will acknowledge the message (any message, regardless whether it is for the MCP25050) and the message will be send one time only.

sherzaad

#12
Nov 05, 2020, 07:36 am Last Edit: Nov 05, 2020, 08:27 am by sherzaad
Yes I know. This is something I do not understand in the datasheet. Attached is a snip of the commands I can send to slave. If i undestand correct, the 10 leftmost bits are the CAN ID. But to the ID is blended the register I want to access? So this makes my ID change depending what information I want. For example I want to "Read A/D Regs". This makes my CAN ID shift 4 bits to left. And if I want to read Control regs it is (ID <<4) | 1??
Am I correct or totally lost?
 
If you understand how this works, could you please write a code to ID 0x11 that asks for "Read Config Regs"?
I had a look at your posted coded again and there is something not right in there:
Code: [Select]
#include <mcp2515.h>
#include <mcp2515_defs.h>

MCP2515 CAN_Ch1(10, 2); //SPI CS, interrupt
//MCP25150 - Arduino: INT = 2, SCK = 13, SI = 11, SO = 12, CS = 10

void setup() {

  pinMode(2, INPUT);

  tCAN message;

  uint8_t std_data[7] ={0,0,0,0,0,0,0};

  //define CAN standard message
  message.id.std = 0b00100010000;//get A/D regs
  message.header.rtr = 1;
  message.header.ide = 0;
  message.header.dlc = 8;
  memcpy(message.data,std_data,sizeof(std_data));


 
  Serial.begin(115200);
  Serial.println("LAite kaynnistetty. CAN tsekkaaja!");

  if (CAN_Ch1.CAN_init(CANSPEED_500kBPS))   //käynnistetään MCP nopeudella x
    Serial.println("CAN1 Init ok");
  else
    Serial.println("Can't Init CAN1");

}

void loop() {

  tCAN message;

  CAN_Ch1.send_message(&message);
  Serial.println("Data lahetetty");

 

  if (CAN_Ch1.check_message()) {
    if (CAN_Ch1.get_message(&message)) {
      Serial.print("CAN_1 ID: ");
      if(message.header.ide) { Serial.print(message.id.ex, DEC); Serial.print("EX");} //extended CAN ID
      else {Serial.print(message.id.std, DEC); Serial.print("STD");} //standard CAN ID
      Serial.print(", ");
      Serial.print("Data[");
      Serial.print(message.header.dlc, DEC);
      Serial.print("]: ");
      for (int i = 0; i < message.header.dlc; i++) {
        Serial.print(message.data[i], DEC);
        Serial.print(" ");
      }
      Serial.println("");
    }
  }
  delay(2000);
 
 
}


In your code you declare "tCAN message;" in "setup" then again in "loop"!
For your message to be transmitted as defined in the "setup" part your code, "tCAN message;" should be a GLOBAL variable ie declared outside of "setup" AND "loop".

additionally in "loop", declare a new variable "tCAN rx_msg;" for example that you would then use to read any received message using "CAN_Ch1.get_message(&rx_msg)" and print to serial monitor.


I don't have the an MCP25050 so I all can do is suggest you try this should the suggested corrections fail:
1. READ A/D REGS information request message using RTR message format
Code: [Select]
#define READ_AD_REGS 0x0000
#define DEVICE_ID 0x0110
  //define CAN standard message
  message.id.std = DEVICE_ID|READ_AD_REGS;
  message.header.rtr = 1;
  message.header.ide = 0;
  message.header.dlc = 8;
  memcpy(message.data,std_data,sizeof(std_data));
  CAN_Ch1.send_message(&message);

2. READ A/D REGS information request message using non-RTR message format
Code: [Select]
#define READ_AD_REGS 0x0000
#define DEVICE_ID 0x0118 //device ID + bit 3 set
  //define CAN standard message
  message.id.std = DEVICE_ID|READ_AD_REGS;
  message.header.rtr = 0;
  message.header.ide = 0;
  message.header.dlc = 0; //try this set as 8 as well
  memcpy(message.data,std_data,sizeof(std_data));
  CAN_Ch1.send_message(&message);


hope that helps....

Go Up