Longan-Labs / Arduino_CAN_BUS_MCP2515

Arduino CAN Bus library, MCP2515/MCP2551
https://www.longan-labs.cc/
MIT License
118 stars 371 forks source link

Problem with setting Filter and Mask during bus traffic #7

Open if2s opened 9 years ago

if2s commented 9 years ago

Hello, I have got still trouble with setting Filters and Masks when other Nodes are sending messages very fast: My Shield is using in industrial application and I do not have influence if other nodes are sending and with which frequency. So when there is a node sending messages (with IDs which should be blocked) when MCP is initializing, filtering does not work because I only can call init_Mask and init_Filt after CAN.begin is called. Maybe it is better if there is a possibility to set filters and masks before CAN.begin.

Example: A node is sending on ID 5 very, very fast all time.

When starting sketch I call CAN.begin and init_Mask and init_Filt to receive ID 522 only.

    if(CAN_OK == CAN.begin(CAN_500KBPS))                   // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init ok!");
        CAN.init_Mask(0, 0, 0x3FF);
        CAN.init_Mask(1, 0, 0x3FF);
        CAN.init_Filt(0, 0, 0x20A);
        CAN.init_Filt(1, 0, 0x20A);
        CAN.init_Filt(2, 0, 0x20A);
        CAN.init_Filt(3, 0, 0x20A);
        CAN.init_Filt(4, 0, 0x20A);
        CAN.init_Filt(5, 0, 0x20A);
        delay(100);
        Serial.println("masks and filters set!");
    }

The result: No message is filtered. All messages from all IDs arrive the buffer. MCP gets overflow.

_If there is no other Node sending data when resetting MCP, the filtering is working find and only ID 522 comes into buffer._

coryjfowler commented 9 years ago

I have built this up and I can replicate what you are experiencing. I have found that if I hold the reset button for a good five seconds while connected to a utilized bus, the filtering appears to behave as I would expect it to... I am not sure what the issue is, but I have been trying to work with Microchip about masks and filtering for a different but similar issue. In the mean time, I would also suggest that you use an 'if/then' statement to check the received ID against 0x20A in your sketch. Additionally, I previously told you to use 0x3FF for the mask, that was a mistake on my part and it should be 0x7FF but that has no burden on the above issue.

coryjfowler commented 9 years ago

I may have found a solution! I have a fork of this library on my github. I started a sub-development branch that allows the sketch to change the mode of the MCP2515. I modified a local copy of that library to initialize the MCP2515 while in 'loopback mode,' setup the masks and filters, and then I put it into 'normal mode.' Since trying this, I have not been able to recreate your problem. I will push my modifications to it in a moment...

if2s commented 9 years ago

Thank you. I can test your sub-development in a few days (my boards are at home and I am still on holiday), maybe on thursday or friday. I will report directly the results. Thank you for working on library.

if2s commented 9 years ago

At the moment, I am testing your sub-development. I had to modify some things like 'begin': CAN.begin(MCP_STD, CAN_500KBPS, MCP_16MHZ) and I changed the ID reading method according to your lib changes.

I have replaced the following three files: mcp_can.cpp, mcp_can.h and mcp_can_dfs.h

While building, there was an error with CAN_31K25BPS (not declared). I removed the case: CAN_31K25BPS in mcp_can.cpp and no further errors appeared.

The Problem: No IDs are filtered. Every ID comes in. At the moment, I do not know where to search the error.

In your master branch ID filtering works (if there is no big bus traffic).

coryjfowler commented 9 years ago

Did you also change the way the masks and filters are used? Standard IDs would be entered like 0x7FF0000 for the mask and 0x20A0000 for the filters. This change was to increase the functionality of the library. The MCP2515 can also filter the first two data bytes of standard ID messages.

I'm going to correct the CAN_31K25BPS error now, thanks for mentioning it.

psy460 commented 8 years ago

Hi, I'm using your fork, But I have same probleme to init mask.

I want to get 0x613 ID only, I tried this code, but i got return to previous mod failure, init mask failure :

` #include

include

long unsigned int rxId; unsigned char len = 0; unsigned char rxBuf[8];

MCP_CAN CAN0(10); // Set CS to pin 10

void setup() { Serial.begin(115200); if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.print("MCP2515 Init Okay!!\r\n"); else Serial.print("MCP2515 Init Failed!!\r\n"); pinMode(A5, INPUT); /I'm using TFT SCREEN which need pin 2, so i plugged pin 2 of canbus shield to A5 on my uno board /

CAN0.init_Mask(0,0,0x06FF0000); // Init first mask... CAN0.init_Filt(0,0,0x06120000); // Init first filter...

Serial.println("MCP2515 Library Mask & Filter Example..."); CAN0.setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted }

void loop() { if(!digitalRead(A5)) // If pin 2 is low, read receive buffer { CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s) Serial.print("ID: "); Serial.print(rxId, HEX); Serial.print(" Data: "); for(int i = 0; i<len; i++) // Print each byte of the data { if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero { Serial.print("0"); } Serial.print(rxBuf[i], HEX); Serial.print(" "); } Serial.println(); } }

/ END FILE / `

Could you tell me if I'm wrong or if it's doesn't work yet ?

coryjfowler commented 8 years ago

There was a bug in the library, re-download or correct the typo in mcp_can.cpp.

Also, there are five filters and two masks, by only setting one, you will receive ID 000 and potentially receive extended ID 00000000 as well. The mask should be 7FF otherwise that mask will receive IDs 612 and 712 since that bit isn't masked and thus ignored.

CAN0.init_Mask(0,0,0x07FF0000); // Init mask...
CAN0.init_Mask(1,0,0x07FF0000); // Init mask...
CAN0.init_Filt(0,0,0x06120000); // Init filter...
CAN0.init_Filt(1,0,0x06120000); // Init filter...
CAN0.init_Filt(2,0,0x06120000); // Init filter...
CAN0.init_Filt(3,0,0x06120000); // Init filter...
CAN0.init_Filt(4,0,0x06120000); // Init filter...
psy460 commented 8 years ago

thank you !! perfect.

I changed init line, giving MODE_CONFIG constant parameters, and replacing STDEXT by MODE_CONFIG in your library. I was able to set mask and filter before set normal mode, even if I have error while returning to previous mod :)

It's work fine ! https://www.youtube.com/watch?v=zJZtAQl4v20

lpcvoid commented 7 years ago

@psy460

Can you post the complete modified library?

Thanks mate.

coryjfowler commented 7 years ago

Use my fork of this CAN library... and set your masks and filters before the CAN.setMode(MCP_NORMAL) function in the setup function. If you need to change masks and filters while live, your routine will have to CAN.setMode(MCP_LOOPBACK), do changes and then CAN.setMode(MCP_NORMAL) or the filters and masks behave in undesirable ways.