pythonraspberry-pican-buspython-can

PiCan Filtering


So I am pretty new to can bus stuff but i need a way to "select" certain bits(46-30) of the 64 bit Data part of the can frame. Here is what i have so far.

import os
import time
import can

mcFilters = [
    {"can_id": 0x08850225, "can_mask": 0x1FFFFFFF, "extended": True},
    {"can_id": 0x08850245, "can_mask": 0x1FFFFFFF, "extended": True},
    {"can_id": 0x08850265, "can_mask": 0x1FFFFFFF, "extended": True},
    {"can_id": 0x08850285, "can_mask": 0x1FFFFFFF, "extended": True},
]


def setup_can_interface():
    print("\n\rCAN Data Parser")
    print("Bring up CAN0....")
    # Bring down the interface if it's already up
    os.system("sudo /sbin/ip link set can0 down")
    # Bring up the interface with the correct settings
    os.system("sudo /sbin/ip link set can0 up type can bitrate 250000")
    time.sleep(0.1)
    print("Ready")


def shutdown_can_interface():
    os.system("sudo /sbin/ip link set can0 down")
    print("\n\rCAN interface shut down")


def initialize_bus():
    try:
        bus = can.interface.Bus(
            channel="can0", bustype="socketcan", can_filters=mcFilters
        )  # Correct interface type
        print("Initialized bus & Filter")
        return bus
    except OSError:
        print("Cannot find PiCAN board.")
        exit()


def parse_can_message(message):
    # Function to parse CAN message data
    parsed_data = {
        "timestamp": message.timestamp,
        "arbitration_id": message.arbitration_id,
        "dlc": message.dlc,
        "data": message.data,
    }

    # Example: Print data in hex format
    data_str = " ".join(f"{byte:02x}" for byte in message.data)
    parsed_data["data_str"] = data_str

    return parsed_data


def main():
    setup_can_interface()
    print("The setup_can_interface done")
    bus = initialize_bus()
    print("Bus varible is set")

    try:
        print("In the try")
        while True:
            message = bus.recv()  # Wait until a message is received.
            parsed_message = parse_can_message(message)

            print(f"Timestamp: {parsed_message['timestamp']:.6f}")
            print(f"ID: {parsed_message['arbitration_id']:x}")
            print(f"DLC: {parsed_message['dlc']}")
            print(f"Data: {parsed_message['data_str']}")
            print("-" * 30)

    except KeyboardInterrupt:
        shutdown_can_interface()
        print("\n\rKeyboard interrupt")


if __name__ == "__main__":
    main()

Right now it will just filter out certain can Id's and print what ever it contains. I am using the python-can library . If you need more info please let me know

I know it had to something with bit manipulation and the can mask but other then that i am stuck. Any help will be most grateful


Solution

  • I need help figuring out how to select certain bits from the 8 bytes of data. Is that what the 'can_mask' does or is that for the whole can frame?

    According to the documentation:

    A filter matches, when <received_can_id> & can_mask == can_id & can_mask. If extended is set as well, it only matches messages where <received_is_extended> == extended. Else it matches every messages based only on the arbitration ID and mask.

    So it looks like can_mask is only applied to the can id. If you want to extract certain bits from the data, you'll need to use Python's bitwise operators to mask and shift things as necessary.