Sparkfun CAN bus sheild

Hello,

I have a Sparkfun CAN bus shield mounted on an UNO and I am reading CAN signals from a data acquisition unit that transmits sensor data over CAN.

So far so good. My problem is, I want to read the data from a CAN signal and store it as a variable so I can work with the signal data.

Currently I am using example code that uses Serial.print commands to display the data, but I cannot find a way to store the data in a variable.

Can anyone point me in the right direction?

Kind Regards

for Canbus I use the library

if you download and install the libarary and look under File > Examples > mcp-can you will find plenty of samples programs

here is some code which reads some data from Canbus and then transmits over Lora to The Things network server

// check for received message - display if data available
void loopReceive()
{
    unsigned char len = 0;
    unsigned char buf[8];

    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        unsigned int canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.print("Get data from ID: ");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i], HEX);
            Serial.print("\t");
            mydata[i]=buf[i];
        }
        Serial.println();
        os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(1), do_send);

    }
}

Thank you for your speedy replay!

Will the "Seed Studio" library work with the
Sparkfun CAN sheild?

I have the following Canbus shield
http://wiki.seeed.cc/CAN-BUS_Shield_V1.2/

this uses the same Microchip MCP2515 CAN controller as the Sparkfun CAN sheild so the following library may well work

which library did you use?

I used the Sparkfun library.

I will download this library and try the sample code you provided. I will get back with you
to let you know how it worked.

Thanks!

looking at the CAN_Read_Demo in File > Examples > SparkFun CAN-Bus you can save you data to a local array so

void loop(){

  tCAN message;
if (mcp2515_check_message()) 
	{
    if (mcp2515_get_message(&message)) 
	{
        //if(message.id == 0x620 and message.data[2] == 0xFF)  //uncomment when you want to filter
             //{
               int data[20]={0};   // <<< local array
               Serial.print("ID: ");
               Serial.print(message.id,HEX);
               Serial.print(", ");
               Serial.print("Data: ");
               Serial.print(message.header.length,DEC);
               for(int i=0;i<message.header.length;i++) 
                {	
                  Serial.print(data[i]=message.data[i],HEX); // <<< copy message to data[]
                  Serial.print(" ");
                }
               Serial.println("");
             //}
           }}

Thanks for looking deeper into this.

You found the exact code that I am using. Now the next step I am trying to get to is
extracting this data and assigning it to a variable. That is what I am struggling with.

It looks like you are close to finding me a solution.

thank you!

data is a local variable and the is set up by the assignment data*=message.data*
*_ <em>*Serial.print(data[i]=message.data[i],HEX); // <<< copy message to data[]*</em> _*
you could make data[] a globable variable

Your suggestion seems to be exactly what I am looking for.
I want to read a signal from a CAN message and turn it to a global variable.
Based on the code you posted, would something like this work in your opinion?

temperature = 0 //declaring a variable

temperature =(data_=message.data*,HEX); // I assume the “i” in the bracket is the byte that contains the data*_
Below is a picture of what I am seeing on the CAN bus.
CAN_DATA (1).jpg

which bytes in the 8 byte CAN message represent the temperature?
Data: 80 D4 80 0 80 0 80 0

is it the D4? if so

 int temperature = message.data[1];
printf("temperature = %d", temperature);

would print temperature = 212

Hello,

Yes, you are right, the D4 is the byte that represents the temperature in Celsius.
The device transmitting the data has a multiplier factor of .1, so the temp
that is being measured is 21.2 degrees C. Roughly room temp.

You are being a big help, thanks!

I am trying to understand your line of code:
First you define the variable, temperature, as an integer equal to message.data[1];
When you asked about the D4 being the byte of interest, is this the byte location
in data[1], and how did you determine this? Is it left to right, 0-7 bytes?
Lastly, what is the %d symbol used for in the print statement?

Once again, thanks for being so helpful!

Kind Regards,

in Documents\Arduino\libraries\SparkFun_CAN-Bus_Arduino_Library-master\src\mcp2515.h the tCAN structure is defined which is used to pass data to/from the Canbus functions

typedef struct
{
	uint16_t id;
	struct {
		int8_t rtr : 1;
		uint8_t length : 4;
	} header;
	uint8_t data[8];
} tCAN;

when data is received

  1. id is the 11 or 29 bit message ID
  2. rtr incicates if data or Remote transmission request frame
  3. length is the number of bytes in the message (maximum 8 )
  4. array data[8] holds the data received

in CAN_Read_Demo you would display the temperature so (post #9 used C printf() where %d is to convert and print a decimal integer)

void loop(){
tCAN message;
if (mcp2515_check_message()) 
	{
    if (mcp2515_get_message(&message)) 
     	{
               Serial.print("ID: ");
               Serial.print(message.id,HEX);
               Serial.print(", ");
               Serial.print("Data: ");
               Serial.print(message.header.length,DEC);
               for(int i=0;i<message.header.length;i++) 
                  {	
                  Serial.print(message.data[i],HEX);
                  Serial.print(" ");
                  }
               float temperature = message.data[1]/10.0f;
               Serial.print("\ntemperature = ");
               Serial.println(temperature);
            }}
}

when data is received
Data: 80 D4 80 0 80 0 80 0
the temperature (value D4 hex) is in the second byte data[1] (remember C indexes arrays from 0)
the statements

               float temperature = message.data[1]/10.0f;
               Serial.print("\ntemperature = ");
               Serial.println(temperature);

define a float varaible temperature, assigns it the value message.data[1]/10.0f and prints the result to Serial - it should display temperature = 21.2

Hi,
Can you post the code you are using at the moment please, so we can all be on the same page.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks Tom.. :slight_smile:

Thanks Horace!

Your input has been extremely helpful! I learned a lot from you!

Hi Tom,

I am using example code that I want to modify. Basically, I am working on learning how to extract data from a CAN bus and turn it into a variable that I can work with in the code.

Horace has been helping me out with this a great deal.

Here’s the example code that I started with:

void loop(){

  tCAN message;
if (mcp2515_check_message()) 
	{
    if (mcp2515_get_message(&message)) 
	{
        //if(message.id == 0x620 and message.data[2] == 0xFF)  //uncomment when you want to filter
             //{
               int data[20]={0};   // <<< local array
               Serial.print("ID: ");
               Serial.print(message.id,HEX);
               Serial.print(", ");
               Serial.print("Data: ");
               Serial.print(message.header.length,DEC);
               for(int i=0;i<message.header.length;i++) 
                {	
                  Serial.print(data[i]=message.data[i],HEX); // <<< copy message to data[]
                  Serial.print(" ");
                }
               Serial.println("");
             //}
           }}

Horace,

in the CAN message:

Data: 80 D4 80 0 80 0 80 0

The bytes that do not have data are all "80" hex values.

Do you know why that is? It appears to me that the hex 8 number
is used as an index between bytes since the binary number
8 only has the one bit high and the rest all zeros. Is this the case or am I way off?

Thanks!

Mike

Hello Horace,

In your line of code you divided by 10.0f to account for the .1 multiplication factor.
What is the "f" being used for?

Kind Regards,
Maker_Dude (Mike)