Skip to content

Instantly share code, notes, and snippets.

@Lauszus
Last active October 12, 2023 13:23
Show Gist options
  • Save Lauszus/bd322b17b77c96f240fc to your computer and use it in GitHub Desktop.
Save Lauszus/bd322b17b77c96f240fc to your computer and use it in GitHub Desktop.
Simple script for calculating filter and mask for CAN bus communication
#!/usr/bin/python
#
# Copyright (C) 2018 Kristian Lauszus, Candela. All rights reserved.
#
# Contact information
# -------------------
# Kristian Lauszus
# Web : http://www.lauszus.com
# e-mail : lauszus@gmail.com
import operator
from functools import reduce
def can_bus_filter_mask(can_bus_ids, quiet=True, verbose=False):
if verbose:
print('[{}]'.format(', '.join([hex(x).upper() for x in can_bus_ids])))
# Calculate CAN Bus filter and mask
can_bus_filter = reduce(operator.and_, can_bus_ids) # Simply bitwise AND all IDs together
can_bus_mask = reduce(operator.or_, can_bus_ids) ^ can_bus_filter # Get bits that are not constant among the IDs
# We can use all bits except these ones for the mask, so simply flip bits according to current format
if reduce(operator.or_, can_bus_ids) > 0x7FF: # Check if using extended format
can_bus_mask ^= 0x1FFFFFFF # Extended format = 29 bits
else:
can_bus_mask ^= 0x7FF # Base format = 11 bits
# Just to make sure that it is calculated correctly
for can_bus_id in can_bus_ids:
assert can_bus_id & can_bus_mask == can_bus_filter, 'Error: 0x{:03X}'.format(can_bus_id)
if not quiet:
print('Filter: 0x{:03X}'.format(can_bus_filter))
print('Mask: 0x{:03X}'.format(can_bus_mask))
if not quiet:
if can_bus_filter <= 0x7FF:
can_bus_received_id_count = 0
for can_bus_id in range(0, 0x7FF + 1):
if can_bus_id & can_bus_mask == can_bus_filter:
can_bus_received_id_count += 1
if verbose:
print('ID: 0x{:03X} will be received'.format(can_bus_id))
print('{} ID\'s will be received\n'.format(can_bus_received_id_count))
else: # It takes too long to loop through all extended IDs
for can_bus_id in can_bus_ids:
if can_bus_id & can_bus_mask != can_bus_filter:
print ('ID: 0x{:03X} will NOT be received'.format(can_bus_id))
return can_bus_filter, can_bus_mask
# noinspection PyPep8Naming
def main():
# See: http://www.cse.dmu.ac.uk/~eg/tele/CanbusIDandMask.html
# ids = range(0, 0x1FFFFFFF + 1) # Extended format example
# ids = range(0, 0x7FF + 1) # Base format example
inverter_id = 0x01
INVERTER_INFO = 0x12C, 0x136, 0x140, 0x14A, 0x154
ids = [x + inverter_id for x in INVERTER_INFO]
can_bus_filter_mask(ids, False)
node_ids = [inverter_id] # Set all the node ID's here
CANOPEN_EMCY, CANOPEN_HEARTBEAT = 0x080, 0x700
ids = [msg + node for node in node_ids for msg in [CANOPEN_EMCY, CANOPEN_HEARTBEAT]]
can_bus_filter_mask(ids, False)
bms_error_ids = [list(range(0x100, 0x100 + 8)), # General frames
list(range(0x200, 0x200 + 8)) + [0x200 + 256]] # Error last seen
for ids in bms_error_ids:
can_bus_filter_mask(ids, False, True)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment