Help filtering CAN data please!

Thanks to this sub I'm able to now read CAN data from my car. I'm using an Arduino Uno and an MCP2515 shield.

The data I'm getting is a stream of everything. What I'm trying to do now is filter that data. Here's a sample of my data as seen in Arduino's serial monitor:

09:42:25.202 -> ID: 156, Data: 80 0 0 0 0 0 0 17
09:42:25.240 -> ID: 156, Data: 80 0 0 0 0 0 0 17
09:42:25.273 -> ID: 156, Data: 80 0 0 0 0 0 0 17
09:42:25.307 -> ID: 284, Data: 881 3 0 8 0 0 0 0

I've been using Cory Fowlers Arduino code and samples: GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library

I've been using this code to try and filer data: MCP_CAN_lib/Standard_MaskFilter.ino at master · coryjfowler/MCP_CAN_lib · GitHub

There's some preamble in that code that explains how to filter, but I frankly don't get it. I've tried a few things and everything I've done has resulted in everything being filtered.

So In the sample code above, how would I go about filtering all data from "156"? (or some other ID)
Ultimately I'd like to be able to filter out a list of IDs so I can use process of elimination to detect some devices on my CAN network.

I've been reading as much as I can find, stuff like this:

I apparently am missing something really basic... It's just not clicking with me. If someone can explain this in plan english I'd really really appreciate it!

It's not feasible to answer general questions like this, because the scope of errors that you may have made, is much too large. Please post an attempt that you think should have worked, even better if you can tie it to some specific advice in the "preamble" you mentioned. Then we can look and see where the problem is. Probably, after that, it will become clearer why the other attempts failed.

Ericschimel:
If someone can explain this in plan english I'd really really appreciate it!

Setting the filter on the MCP2515 can be mind boggling! :slight_smile:
hopefully this breif explanation and set of examples will help you get a better image of how it should be done:

1. The Rx Mask is nothing more than a bit level switch to enable or disable the filter bits.
Assuming an 11 bit Id, if, for example, the Mask is set to a value of 0b00000000111 (0x0007) then only set bits (ie bits 0,1 & 2) of the filter bits will be used to filter the received Id against.

2. The Rx filter is used to check the received CAN Id against.
If a match is detected on the active filter bits, then the received CAN message is placed in the Rx buffer, else the CAN message is discarded.

Examples (assuming 11 bit Id)
Eg 1/
Mask Value: 0b11111111111 (0x03FF) (all filter bits enabled)
Filter Value: 0b11111111111 (0x03FF)
The Rx buffer will only receive CAN frames with an Id of 0x03FF

Eg 2/
Mask Value: 0b11111111111 (0x03FF) (all filter bits enabled)
Filter Value: 0b11111111110 (0x03FE)
The Rx buffer will only receive CAN frames with an Id of 0x03FE

Eg 3/
Mask Value: 0b11111111110 (0x03FE)
Filter Value: 0b11111111111 (0x03FF)
The Rx buffer will receive CAN frames with an Id of 0x03FE or 0x03FF as bit 0 of the filter bit is disabled.

Eg 4/
Mask Value: 0b11111111110 (0x03FE)
Filter Value: 0b11111111110 (0x03FE)
The Rx buffer will receive CAN frames with an Id of 0x03FE or 0x03FF as bit 0 of the filter bit is disabled.

Eg 5/
Mask Value: 0b11111111111 (0x03FF) (all filter bits enabled)
Filter Value: 0b11111111000 (0x03F8)
The Rx buffer will only receive CAN frames with an Id of 0x03F8

Eg 6/
Mask Value: 0b11111111000 (0x03F8)
Filter Value: 0b11111111000 (0x03F8)
The Rx buffer will receive CAN frames with an Id of 0x03F8,0x03F9,0x03FA,0x03FB,0x03FC,0x03FD,0x03FE,0x03FF as bit 0,1 & 2 of the filter bits are disabled.

Eg 7/
Mask Value: 0b11111111111 (0x03FF) (all filter bits enabled)
Filter Value: 0b00000000000 (0x0000)
The Rx buffer will only receive CAN frames with an Id of 0x000

Eg 8/
Mask Value: 0b11111111111 (0x03FF) (all filter bits enabled)
Filter Value: 0b00000000001 (0x0001)
The Rx buffer will only receive CAN frames with an Id of 0x001

Eg 9/
Mask Value: 0b11111111000 (0x03F8)
Filter Value: 0b00000000000 (0x0000)
The Rx buffer will receive CAN frames with an Id of 0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007 as bit 0,1 & 2 of the filter bits are disabled.

Eg 10/
Mask Value: 0b00000000111 (0x0007)
Filter Value: 0b00000000000 (0x0000)
The Rx buffer will receive CAN frames that end either 0,1,2,3,4,5,6,7 (0x121 = accepted, 0x0128 = discarded)

what I found out, that you have to set the second mask also, otherwise the (unset) second filter will let through every message.

    CAN.init_Mask(0, 0, myMask);                // Init first mask
    CAN.init_Filt(0, 0, myFilter);              // Init first filter
    //  CAN.init_Filt(1, 0, myFilter);              // Init second filter... not needed if only one filter 
    CAN.init_Mask(1, 0, myMask);                // Init second mask - must be set, otherwise first mask isn't working

to filter 157 you could just enable the full bitmask saying: "Check each bit" and define the filter to 157:

myMask = 0b11111111111;
myFilter = 0b00010011101; // 157

Ok, I think this is starting to gel a bit for me, let me repeat back some stuff to see if I understand it right:

The "mask" is "covering" part of the message that's coming.. It's essentially instructing the filter as to where to look in the ID. If it were phone numbers the mask could be saying "Hey look at only the are codes on this number" or you could set the mask to "look at only the last four digits of the phone number". Right? Assuming I understand that right, then you get to the filter:

Using my phone number example still, the mask would be set to only look at area codes and the filter could be set to pull out a specific area code. If there's a match to that area code that phone number is put in the buffer?

My goal is just to filter out by IDs to start with, I don't want to get super granular yet and filter out the data after the IDs, so Sherzaad and noiasca I should be able to do this:

myMask = 0b11111111111; << This says look at every bit in the message
myFilter = 0b00010011101; // 157 <<This says grab, and filter out ID of 157. Correct?

If I'm correct there could I do something like this:

; This filters out the RPM (this is a made up example)
myMask = 0b11111111111;
myFilter = 0b00010011101; // 157

; This filters out the Throttle Position (this is a made up example)
myMask = 0b11111111111;
myFilter = 0b01110011001; // 159

; This filters out the Temperature (this is a made up example)
myMask = 0b11111111111;
myFilter = 0b00110111110; // 162

If I could list these all in a row like this I could one-at-a-time eliminate messages as I see them. It'd be tedious but I think it would work..

Assuming I'm correct in all of this, how to I convert a 3 digit ID to something like 0b010001110101?

Unless you have a speed problem, I'm not clear why you need the filters. Your existing code already gets the ID, it should be simple to use an if statement to check for the one(s) you want. If there are a lot of them, put them in an array and use a for loop.

Assuming I'm correct in all of this, how to I convert a 3 digit ID to something like 0b010001110101?

either do it manually or start a calculator in programmers mode ^^
It just turn out that when you are dealing with binary filters, it comes handy if you write your id's also in binary.

wildbill:
Unless you have a speed problem, I'm not clear why you need the filters. Your existing code already gets the ID, it should be simple to use an if statement to check for the one(s) you want. If there are a lot of them, put them in an array and use a for loop.

I do have a speed problem.. The CAN bus on the car I'm trying to sniff fills up screen after screen so fast in the serial monitor window I can't keep up. The idea is to filter out as much stuff as I can when the car is "idle" so then I can track down things like power windows, climate controls, etc and visually see the changes live in the terminal window without the "regular" stuff getting in the way.

I'm going to have to look up how to do a for loop. I'm a bit of a novice at this stuff...

noiasca:
either do it manually or start a calculator in programmers mode ^^
It just turn out that when you are dealing with binary filters, it comes handy if you write your id's also in binary.

I tried googling a couple of programming calculators and to be honest, I have no idea how to make them work.. So doing it manually is out of the question until I learn something. Do you have a recommendation for a programming calculator?

The stock calculator that ships with Microsoft Windows has a programming mode.

exactly. I'm just using START --> calc