python-can
python-can copied to clipboard
pcan interface does not use hardware filtering
Hi,
I think it would be great if the pcan driver also supports HW-Filtering. As I found out in the PCAN Basic API Documentation that should be possible.
cheers mathias
If I remember correctly, you specify a range instead of ID and mask, so it won't be portable. That being said, it is not an problem to add interface specific settings if needed.
We could also apply a first rough level of filtering on the HW layer, but let recv_internal()
return False
as the second parameter, which causes the Bus class to apply the finer grained filters on top of that. I dunno whether that's worth the effort though, but it could be more efficient.
Okay i understand.
@mgiaco Do you want to implement that? Do you need help?
@felixdivo I can try it but I am very busy these days so it will take some time.
If I remember correctly, you specify a range instead of ID and mask, so it won't be portable. That being said, it is not an problem to add interface specific settings if needed.
That's technically correct when you use the FilterMessages
method provided by the PCAN-Basic API. But this is actually only a "convenience" function where they try to calculate an ID+mask given a range of IDs to actually set in hardware [^1] . This can be read on the last page (Appendix D) of their parameter documentation PDF.
[^1]: See chapter 6.4.15 in the datasheet of the actual hardware CAN controller chip inside PCAN devices.
But it's also possible to manually set ID+Filter through the parameter PCAN_ACCEPTANCE_FILTER_11BIT
and PCAN_ACCEPTANCE_FILTER_29BIT
. This is documented in page 66 of above linked PDF (and also in their API documentation chm
file you can download from their website):
This parameter allows the configuration of complex filter patterns, and it is intended for users with extended CAN knowledge. Note that the calculation of mask and code patterns is not a trivial matter. For most applications the use of the function CAN_FilterMessages for setting message reception ranges is more adequate. A simple example on code and mask calculation can be seen in the Appendix D
I tried setting a filter with self.m_objPCANBasic.SetValue(self.m_PcanHandle, PCAN_ACCEPTANCE_FILTER_11BIT, 0x00000XXX00000YYY)
(where XXX
denote the ID to match and YYY
denote the mask). And it "kind of" works but I still got unwanted messages through which still requires the software filter to be active. I might test this more extensively why it is the case.
You can also read out the current mask + filter value set in hardware with GetValue
and the same parameter:
result, value = self.m_objPCANBasic.GetValue(self.m_PcanHandle, PCAN_ACCEPTANCE_FILTER_11BIT)
hex_str = format(value, 'x').zfill(8 * 2)
print(f"Acceptance filter: id={hex_str[0:8]} mask={hex_str[8:16]})
With this method, you can also check what id+mask combination FilterMessages
actually sets behind the scenes.
And even though some unwanted messages coming through, on a busy bus this filter already dramatically improves performance because of many messages not needed to be parsed by the python software "fallback" filter. In my usecase, there was often a delay of 5+ seconds for one message to appear in the application after its reception because of all the other messages on the bus spamming the software filter.