How to Read the value of a CAN signal from a 8 byte message

I have connected an arduino with CAN shield to a CAN bus to read messages from the bus and check the status/value of a particular signal within a message. For example, there are 3 messages on the CAN and each is of 8 bytes. The message IDs are 0X111, 0X222, 0X333 and I want to receive only 0X111 from the bus and then check a specific 2 bit signal within this message (0X111). How can I do that?

0X111 is 8X8 matix:

      bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

0
1 X X I want to check the 5th and 6th bits of the byte[1]
2
3
4
5
6
7
8

Below is my incomplete code:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);

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

mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS);
mcp2515.setNormalMode();

}

void loop()
{

if (mcp2515.readMessage(&canMsg) == 0X111)
{
here I want to check the status of the 5th & 6th bits within the 1st byte of 0X111 but don't
know about the instructions/code.
}

}

1 Like

The data is in canMsg.data[1]

If you want bits 5 and 6 at the same time, you right-shift by 5 and mask with 0b11

For example if canMsg.data[1] is 0b11001010 :

   0b11001010
>> 5
 = 0b00000110
 & 0b00000011
 = 0b00000010

uint8_t bits_5_and_6 = ( canMsg.data[1] >> 5 ) & 0b11;

1 Like

Thanks for your prompt feedback. Let me know if my understanding about bitRead is correct or not.

1st- select the byte position (1st in my case) of the message 0X311 by canMsg.data[1]
2nd- then extract the bits 5 and 6 through 2 separate bitRead commands as shown below:
int a,b;
a=bitRead(canMsg.data[1],5);
b=bitRead(canMsg.data[1],6);
if( (a==0 && b==1))
Serial.print("test case passed");
else
Serial.print("test case failed");

For your information, the signal occupying the bits 5 and 6 of byte 1 indicates the status of a device:
6th bit 5th bit
0 0 Invalid
0 1 OFF
1 0 ON
1 1 Reserved

I want to test the condition to check if the device is ON or not.

Thanks for your prompt feedback. Let me know if my understanding about bitRead is correct or not.

1st- select the byte position (1st in my case) of the message 0X311 by canMsg.data[1]
2nd- then extract the bits 5 and 6 through 2 separate bitRead commands as shown below:
int a,b;
a=bitRead(canMsg.data[1],5);
b=bitRead(canMsg.data[1],6);
if( (a==0 && b==1))
Serial.print("test case passed");
else
Serial.print("test case failed");

For your information, the signal occupying the bits 5 and 6 of byte 1 indicates the status of a device:
6th bit 5th bit
0 0 Invalid
0 1 OFF
1 0 ON
1 1 Reserved

I want to test the condition to check if the device is ON or not.

Yep looks correct. Note that the bits are numbered from right to left... starting from bit 0.

1 Like

Yes, thanks for correcting me on the bit numbering scheme. It helped me.

I can't quite see how this is a question for Interfacing w/ Software on the Comouter. It seems a more general programming question and hence your topic has beem moved.

I am not able to receive 0X111 this message with the following command:
Since LED is not turning on, it indicates the condition if(mcp2515.readMessage(&canMsg)==0X111) is failing i.e. message is not received but I am confident that 0X111 is there in the CAN bus
#include<SPI.h>
#include<mcp2515.h>
#include<can.h>
struct can_frame canMsg;
#define CS 10;
int LED=3;
void setup()
{
pinMode(LED,OUTPUT);
while(!Serial);
Serial.begin(115200);

mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
void loop
{
if(mcp2515.readMessage(&canMsg)==0X111)
{
digitalWrite(LED,HIGH);
int bit5, bit6;
bit5=bitRead(canMsg.data[1],5);
bit6=bitRead(canMsg.data[1],6);
if(bit5==0 && bit6==1)
{
Serial.print("Module is ON");
}
else
{
Serial.print("Module status update failed");

     }

}
}

From the example code for that library... it looks like you are not interpreting the response from readMessage correctly. It returns an error response, and if ok you then need to look at canMsg.can_id, canMsg.can_dlc and canMsg.data[].

if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");
    }

    Serial.println();      
  }

I'm not a CAN guy, but I fail to see how you can get 0x111 in a byte - am I misinterpreting, or is the OP not quite on message? 0b111, sure. 0X111 (usually written 0x111) implies at least a 9-bit value.

makes sense. Let me give it a try and update you on how it goes.

so I modified my code but it is still not working.
void loop
{
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
{
if(canMsg.can_id == 0X111) /0X111 is the message id
{
do this;
}
}
}

but it does nothing.

Try just printing whatever you get (don't check can_id)... as per the example code I posted.

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