Pages: [1]   Go Down
Author Topic: CAN-BUS Shield: Extended CAN Messaging  (Read 2161 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys, I was hoping there was someone on here that could help me out with some extended can messaging?  I am currently using the following library for my CANBUS Shield

https://github.com/franksmicro/Arduino/tree/master/libraries/MCP2515

Which has proven to be amazing, however, I am having some trouble with extended CAN messaging.  I found that on my car, there is the tire pressure monitor module which is at

ECU: 0x751
Address: 0xC901
Mask: 0x00FF

So with my test application, I am setting the following:

Code:
    message.adrsValue = 0x751;
    message.isExtendedAdrs = true;
    message.extendedAdrsValue = 0xC901;
    message.rtr = false;
    message.dataLength = 8;
    for(int i = 0; i < 8; i++) {
      message.data[i] = 0x00;
    }

I then have my software listen for the push of the joystick, and when pressed, it will transmit this message and listen on the bus, in a loop while the button is held down.  I am not sure if my syntax above is correct?  Here is a snippet of the library where the developer is setting the can message to transmit:

Code:
boolean MCP2515::transmitCANMessage(CANMSG msg, unsigned long timeout)
{
  unsigned long startTime, endTime;
  boolean sentMessage;
  unsigned short val;
  int i;
 
  startTime = millis();
  endTime = startTime + timeout;
  sentMessage = false;

  val = msg.adrsValue >> 3;
  writeReg(TXB0SIDH,val);
  val = msg.adrsValue << 5;
  if(msg.isExtendedAdrs)
    val |= 1 << EXIDE;
  writeReg(TXB0SIDL,val);
  if(msg.isExtendedAdrs)
  {
    val = msg.extendedAdrsValue >> 8;
    writeReg(TXB0EID8,val);
    val = msg.extendedAdrsValue;
    writeReg(TXB0EID0,val);
  }
 
  val = msg.dataLength & 0x0f;
  if(msg.rtr)
    bitWrite(val,TXRTR,1);
  writeReg(TXB0DLC,val);
 
  //Message bytes
  digitalWrite(SLAVESELECT,LOW);
  SPI.transfer(WRITE);
  SPI.transfer(TXB0D0);
  for(i = 0; i < msg.dataLength; i++)
    SPI.transfer(msg.data[i]);
  digitalWrite(SLAVESELECT,HIGH);

  //Transmit the message
  writeRegBit(TXB0CTRL,TXREQ,1);

  sentMessage = false;
  while(millis() < endTime)
  {
    val = readReg(CANINTF);
    if(bitRead(val,TX0IF) == 1)
    {
      sentMessage = true;
      break;
    }
  }

  //Abort the send if failed
  writeRegBit(TXB0CTRL,TXREQ,0);
 
  //And clear write interrupt
  writeRegBit(CANINTF,TX0IF,0);

  return sentMessage;

}

I would be beyond grateful if someone could help me out.  Greatful to the point of a donation if it has to come to that lol.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 610
Posts: 49080
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I am not sure if my syntax above is correct?
The compiler will tell you that. Unless you are referring to the actual message...

Quote
I then have my software listen for the push of the joystick, and when pressed, it will transmit this message and listen on the bus, in a loop while the button is held down.
So, what happens?

Quote
I would be beyond grateful if someone could help me out.
Help you with what? If you just want out, that can be arranged.

If you define what problem you are having, and what help you need, we'll quit snickering, and maybe even help.

Quote
I found that on my car
Even telling us about something obvious to you, such as what kind of car you have would be some help.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The compiler will tell you that. Unless you are referring to the actual message...

My mistake, I guess I should have re-read my post.  By syntax I meant the structure of the extended message.  When using standard CAN messaging, which I have confirmed works, my message looks like this:

Code:
    message.adrsValue = 0x7DF;
    message.isExtendedAdrs = false;
    message.rtr = false;
    message.dataLength = 8;
    message.data[0] = 0x02;
    message.data[1] = 0x01;
    message.data[2] = pid;
    for(int i = 3; i <= 7; i++)
      message.data[i] = 0x00;

After sending this message I successfully get a reply.

Quote
So, what happens?

The sequence of my program is as follows when the joystick is pressed:
1. Prepare CAN message
2. Transmit CAN message
3. Read the data on the CAN bus
4. Repeat

When I press the joystick, the only thing that is read is the current data on the bus.  I do not see a response for the message I have sent.  In retrospect, with the same application, if I send a non-extended message, I immediately see a response from the pid I requested.

Quote
Help you with what? If you just want out, that can be arranged.

If you define what problem you are having, and what help you need, we'll quit snickering, and maybe even help.

The main goal here is I am trying to understand exactly how to send and receive extended CAN messages.  I wasn't exactly sure if A. the structure shown above was correct, and B. if the supporting library was actually setting up the extended message properly.  I spoke to the developer of the library and unfortunately he hasn't had any experience with extended CAN which has me wondering if the library itself is properly coded.

Quote
Even telling us about something obvious to you, such as what kind of car you have would be some help.

The car is a 2010 Mazda RX8.  The project I am working on is being able to read data from the HSCAN and displaying the data on the LCD screen found in the car via the MSCAN.  All of this is done through the OBD2 port.  I have successfully obtained data, and printed data, and now I am trying to take it one step further and display data that is unique to the vehicle via extended messages.

Thanks for the reply and I hope this helps.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 610
Posts: 49080
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Unfortunately, I can't help you. I have no experience with the CAN-BUS library. I just wanted to prod you to provide as much information as possible.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No worries, I appreciate you looking out.  Hopefully someone can point me in the right direction  smiley-lol
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 206
Posts: 12856
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Do you check the value returned from transmitCANMessage?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hello,
I'm trying to transmit data between two nodes, but the only thing I get (on the receiving node) is 11111111111. I'm using the fol Library

https://github.com/franksmicro/Arduino/tree/master/libraries/MCP2515

and the firmware is as follows:



#include <SPI.h>;
#include <MCP2515.h>;
#include <stdio.h>
#include <string.h>

char buf[50];
CANMSG message;
void setup()
{
   Serial.begin(9600);
 
  //Reset
  if(!MCP2515::initCAN(CAN_BAUD_500K))
    Serial.print("Failed initCAN");

  //Set to normal mode
  if(!MCP2515::setCANNormalMode())
    Serial.print("Failed CANNormalMode");
}

void loop()
{
     
    message.adrsValue = 0x751;
    message.isExtendedAdrs = true;
    message.extendedAdrsValue = 0xC901;
    message.rtr = false;
    message.dataLength = 8;
   
   if(MCP2515::transmitCANMessage(message,10))
   {
     Serial.print("OK");
   }
 }


//----------------------------------------------------------------------------------------------------------------------------------


#include <SPI.h>;
#include <MCP2515.h>;
#include <stdio.h>
#include <string.h>

char buf[50];

void setup()
{
   Serial.begin(9600);
 
  //Reset
  if(!MCP2515::initCAN(CAN_BAUD_500K))
    Serial.print("Failed initCAN");

  //Set to normal mode
  if(!MCP2515::setCANNormalMode())
    Serial.print("Failed CANNormalMode");
}

void loop()
{
   CANMSG msg; 
   int dataCounter;

   
   MCP2515::receiveCANMessage(&msg, 10));

    Serial.print(msg.adrsValue, HEX);
    Serial.print(";");
    Serial.print(msg.rtr, DEC);
    Serial.print(";");
    for (dataCounter = 0; dataCounter < msg.dataLength; dataCounter++)
    {
        Serial.print(msg.data[dataCounter], HEX);
        Serial.print(" ");
    }
    Serial.println("");
}


thanks in advance
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 206
Posts: 12856
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Please click Modify ( or ) on your post, select the source code, click the button above the edit window, then click .

Just from looking at your code, I can tell it will not compile.  Unless you need help with a compiler error, you should try to post code that at least compiles.

You need to check the return value of MCP2515::receiveCANMessage.  I assume true is returned if a frame has been received.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

This is a old post, but i would like to contribute, trying to answer a question about extended messages using MCP2515.

Reading the Data Sheet of MCP2515 one can find a filtering capability of this chip. By default my code was ignoring extended messages.

To find out about this problem, you could put your MCP2515 in loopback mode and try to send some messages. First 11-bit address message, then 29-bit address message (extended message). In my case the second type of message was ignored by MCP2515.

Writing a code for CANBUS SAE J1939 i simply turned of the filtering based on the great code found on this site: http://modelrail.otenko.com/arduino/arduino-controller-area-network-can .

In the register: RXB0CTRL – RECEIVE BUFFER 0 CONTROL (ADDRESS: 60h), using the datasheet.

Using the code from the author, David Harding http://arduino.cc/forum/index.php/topic,8730.0.html. I added a simple line to the configuration function in MCP2515.cpp, MCP2515::_init .

Code:

#define RXB0CTRL 0x60
#define RXB1CTRL 0x70

Write(RXB0CTRL,B01100000);
Write(RXB1CTRL,B01100000);

Code:

bool MCP2515::_init(int CAN_Bus_Speed, byte Freq, byte SJW, bool autoBaud) {
 
  // Reset MCP2515 which puts it in configuration mode
  Reset();
 
  // Calculate bit timing registers
  byte BRP;
  float TQ;
  byte BT;
  float tempBT;

  float NBT = 1.0 / (float)CAN_Bus_Speed * 1000.0; // Nominal Bit Time
  for(BRP=0;BRP<8;BRP++) {
    TQ = 2.0 * (float)(BRP + 1) / (float)Freq;
    tempBT = NBT / TQ;
      if(tempBT<=25) {
        BT = (int)tempBT;
        if(tempBT-BT==0) break;
      }
  }
 
  byte SPT = (0.7 * BT); // Sample point
  byte PRSEG = (SPT - 1) / 2;
  byte PHSEG1 = SPT - PRSEG - 1;
  byte PHSEG2 = BT - PHSEG1 - PRSEG - 1;

  // Programming requirements
  if(PRSEG + PHSEG1 < PHSEG2) return false;
  if(PHSEG2 <= SJW) return false;
 
  byte BTLMODE = 1;
  byte SAM = 0;
 
  // Set registers
  byte data = (((SJW-1) << 6) | BRP);
  Write(CNF1, data);
  Write(CNF2, ((BTLMODE << 7) | (SAM << 6) | ((PHSEG1-1) << 3) | (PRSEG-1)));
  Write(CNF3, (B10000000 | (PHSEG2-1)));
  Write(TXRTSCTRL,0x00);
  //turn mask/filters off; receive any messages
  Write(RXB0CTRL,B01100000);
  Write(RXB1CTRL,B01100000);
 
  if(!autoBaud) {
    // Return to Normal mode
      if(!Mode(MODE_NORMAL)) return false;
  } else {
    // Set to Listen Only mode
      if(!Mode(MODE_LISTEN)) return false;
  }
  // Enable all interupts
  Write(CANINTE,255);
 
  // Test that we can read back from the MCP2515 what we wrote to it
  byte rtn = Read(CNF1);
  return (rtn==data);
}


After that modification, i could receive extended messages using MCP2515.

I hope this helps.
« Last Edit: October 10, 2012, 11:54:33 am by MarcQueiroz » Logged

Pages: [1]   Go Up
Jump to: