Last active
October 12, 2023 13:23
-
-
Save Lauszus/bd322b17b77c96f240fc to your computer and use it in GitHub Desktop.
Simple script for calculating filter and mask for CAN bus communication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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