1

I need some help with Can4Python/SocketCAN with Raspberry Pi. Currently, I am using PiCAN2.

What I want to do is upon receiving a particular signal from transmitter, I would like to turn on/off LED (ON for signal value x and OFF for signal value y) connected to GPIO of Raspberry.

Currently, I am able to do basic operation like send CAN messages, Receive it, working on KCD files. I have written a code which sends CAN signals in some interval (Broadcast) on vcan0. My question is how to receive those signal continuously? I am only able to find from_kcd_files method which allows me to read signal from kcd files. I want to receive signals in real-time ie. signal coming on can0 or can1.

I am new to this field so I am little bit confused too.!! Any guidance or help would be appreciated. Thanks

oh.dae.su
  • 934
  • 1
  • 5
  • 12
Sailorman
  • 11
  • 1
  • 3

2 Answers2

1

Use the python-can module with pip3 install python-can, documentation is listed here https://python-can.readthedocs.io/en/stable/installation.html

First method is:

Use this module to test can Messages on the bus

import can

can_interface = 'can0'
bus = can.interface.Bus(can_interface, bustype='socketcan_native')
while True:
    message = bus.recv()

Second method is:

use the can-utils packages, Installation is explained here: https://elinux.org/Can-utils

make the candump executable and type in terminal:

./candump can0

you should see can Messages on the terminal

third method is:

you write your own socketcan Client with the python-can package. I prefer this method, because you can send, receive and filter CAN message depending on your Project.

Look at the socketcan_native.py and the socketcan_constants.py and the message.py which is located at: python_path/site-packages/can/Interfaces/socketcan_native.py

message.py there you can Change the Output of your can Messages

socketcan_constants.py in this file are the relevant constants to communicate over CAN-Socket

socketcan_native.py relevant method to create a socket Connection:

build_can_frame
dissect_can_frame
createSocket
bindSocket
capturePacket
recv
send
set_filters

But be careful, this are python relevant methods, if it is necessary for you, to have fully realtime connection to the bus, i think it´s better to develop the can modules in C/C++. There are a lot of examples on github, like the candump, which is programmed in c

bierschi
  • 340
  • 1
  • 2
  • 7
0

You can start a BufferedReader that calls a message everytime you receive a message. Or you adapt the BufferedReader class in a way that it filters for the message(s) you want.

Here is what I used to listen to specific messages:

class FilteredBufferedReader(can.BufferedReader):
    def __init__(self, filter):
        can.BufferedReader.__init__(self)
        self.buffer = queue.Queue(0)
        self.filter_list = filter

    def on_message_received(self, msg):
        if self.filter_list is None:  # no filtering
            self.buffer.put(msg, False)
        else:
            if msg.arbitration_id in self.filter_list:
                self.buffer.put(msg, False)

    def get_message_noblock(self):
        try:
            return self.buffer.get_nowait()
        except queue.Empty:
            return None

and the usage in code is like this:

fbr = FilteredBufferedReader([arbitration_ID])
notifier = can.Notifier(bus, [fbr])
msg = fbr.get_message_noblock()

Notifier is a class in can package. It starts a thread that listens for can messages. If a can message is received every Listener (in my case only one Listener, the FilteredBufferedReader) is informed about the message and the method 'on_message_received(self, msg)' is called with the received message. In my example I check, if the msg has a specified arbitration ID, and if so, I put the message into a buffer. With 'msg = fbr.get_message_noblock()' I can take a message out of the buffer for further use.

In your case I can also imagine that you process the message already in the on_message_received(...) method without needing a buffer and the get_message_noblock(...) method. You can stop the notifier thread with

notifier.running.clear()

if you want to stop the notifier thread.

Mario
  • 1