Using a CAN message in an if statement - cannot get it to work

Morning All,

This is my first post, so please forgive me if I overlook a detail or not follow the guideline 100%, but I will do my best!

I have the following problem. I use a MCP2515 and MCP2551 with an Arduino Nano Every. What I am trying to achieve is to read a CAN message (that part is working). If bit X of Byte Y is 0, then make it 1 and send it back on the bus. Once this is working I will implement more of these if statements against CAN message in my code.

I can read the message, know what bit X of byte Y is, but the if statement seems to always be true, regardless if bit x=0 or bit x=1.

I have tried to incorporate the CAN message directly in my if statement, and also writing the bit X of byte Y to a variable and use the variable in my if statement, but that didn’t work either.

I have attached the CAN library I am using.

Here is my code;

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

struct can_frame canMsg;

MCP2515 mcp2515(10);

void setup() {
  Serial.begin(115200);                                                                 // Open Serial Monitor for debugging
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_125KBPS, MCP_8MHZ);                                            // 125 KBPS CAN speed with 8Mhz Oscillator     

  mcp2515.setConfigMode();
  mcp2515.setFilterMask(MCP2515::MASK0, false, 0x7FF);
  mcp2515.setFilter(MCP2515::RXF0, false, 0x412);                                       // Filter out only CAN Message ID 0x412
  mcp2515.setFilter(MCP2515::RXF1, false, 0x412);
  mcp2515.setFilterMask(MCP2515::MASK1, false, 0x7FF);
  mcp2515.setFilter(MCP2515::RXF2, false, 0x412);
  mcp2515.setFilter(MCP2515::RXF3, false, 0x412);
  mcp2515.setFilter(MCP2515::RXF4, false, 0x412);
  mcp2515.setFilter(MCP2515::RXF5, false, 0x412);
  mcp2515.setNormalMode();
    
  Serial.println("------- CAN Read ----------");                                        // Print header on the serial monitor
  Serial.println("ID  DLC   DATA");
}

void loop() {
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.print(canMsg.can_id, HEX); // print ID                                       // Print CAN ID to Serial Monitor
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC                                     // Print DLC to Serial Monitor
    Serial.print(" ");

    Serial.print(canMsg.data[5], HEX);                                                  // Print byte 5 to Serial Monitor
    Serial.print(" ");
    Serial.println(canMsg.data[5]>>3 & 1);                                              // Print Byte 5, bit 3 to Serial Monitor
    
      if ((canMsg.data[5]>>3 & 1) == 0)                                                 // If Byte 5, bit 3 is low, do;
      {
      
      canMsg.data[5] |= 0x10;                                                           // Write Byte 5, bit 3 high
      Serial.println();
      Serial.print("New Value: ");    
      Serial.println(canMsg.data[5], HEX);                                              // Write new message to Serial Monitor

      mcp2515.sendMessage(&canMsg);                                                     // Send new value on the CAN bus
      
      Serial.println("Message sent!");                                                  // Confirm new value is written to CAN bus on Serial Monitor
  
      }

    Serial.println();      
  }
}

Does anyone have any idea? Your help is appreciated!

Thanks so much!

arduino-mcp2515-master.zip (249 KB)

What do you see when you print the value that you are testing ?

Be aware that data[5] is actually the sixth byte in the array

BTW, it would be simpler to use bitRead() to determine the state of a bit rather than masking and shifting

Hello UKHeliBob,

Thanks for your reply. I am aware of the offset in byte, or that the counts starts at 0. But thanks for the reminder, that is an easy thing to overlook.

I am sending a 0 on the bus, Serial.println(canMsg.data[5]>>3 & 1); reads 0. It reads 1 when I send 1, so that part seems to work.

Ok, I have to learn about bitRead(), no experience with it. If you have a quick pointer on how I would use that, I would appreciate that!

Thanks!

Suppose that you want the value of bit 3 of the sixth element of the array

byte bitValue = bitRead(array[5], 3);

You can also change the value of a bit using bitWrite() function

Ok, I will try that out! Thanks for that.

Any idea why the if statement if not working?

Any idea why the if statement if not working?

You did not clarify whether the value that you are testing has the expected value

I am using Canalyzer and a VN1610 to send the message. In the message I am sending, I am sure byte 5 bit 3 = 1.
The serial monitor prints 1, so I am reading the correct value. When I change byte 5 bit 3 to 0, the serial monitor prints 0 as well.

The problem is, that even while I am sending 1, the serial monitor prints 1, the code still progresses through the if statement.

So I am sending the value I want, read the same value on the serial monitor, but the if statement fails. I hope that is more clear.

Thanks for your help.

I am sorry to ask obvious questions, but are you counting the bits from the correct end off the byte ? Try printing what you receive in binary but note that leading zeroes will not be printed

I can try that later, that is a good suggestion.

I am pretty confident I am looking at the right bit, because I can toggle the bit in Canalyzer and see the bit toggle on the serial monitor as well. Also, I did a HEX comparison of the entire byte between what Canalyzer is sending and the serial monitor is reading, and that is the same as well.