Sending periodically doesn't work even though single messages can be send

Issue #58 closed
Sebastian Kienitz created an issue

Hi,

I wonder why I cant use the cyclic send function even though I can send single messages. I have two physical devices connected to each other to proof if its working.

In the following code "send_one()" works perfectly, but "send_cyclic()" doesnt:

from __future__ import print_function

import can
import time
can.rc['interface'] = 'socketcan_ctypes'
can.rc['channel'] = 'can0'

from can.interfaces.interface import *


def send_one():
    bus = can.interface.Bus(channel='can0' , bustype='socketcan_ctypes')
    msg = can.Message(arbitration_id=0xc0ffee,
                      data=[0, 25, 0, 1, 3, 1, 4, 1],
                      extended_id=False)
    try:
        bus.send(msg)
        print("Message sent on {}".format(bus.channel_info))
    except can.CanError:
        print("Message NOT sent")


def send_cyclic():
    bus = can.interface.Bus(channel='can0' , bustype='socketcan_ctypes')
    msg = can.Message(arbitration_id=0xc0ffee,
                      data=[0, 25, 0, 1, 3, 1, 4, 1],
                      extended_id=False)
    try:
        can.send_periodic('can0', msg, 0.020)
        print("Message sent periodically on  {}".format(bus.channel_info))
    except can.CanError:
        print("Message NOT sent")

if __name__ == "__main__":
    send_one()
    send_cyclic()
    time.sleep(10)

Comments (7)

  1. Brian Thorne repo owner

    It looks like you're doing everything correct. Can you post the error/logging messages you get?

    Might help to add logging.basicConfig(level=logging.DEBUG) to increase the verbosity.

    The reason cyclic sending is not always guaranteed to work even when simple sending works is because we utilise the linux kernel's BCM interface. https://python-can.readthedocs.io/en/latest/bcm.html

  2. Sebastian Kienitz reporter

    If I execute can_test.py on the 1st device:

    python3 -m can_test
    
    from __future__ import print_function
    
    
    import logging
    logging.basicConfig(level=logging.DEBUG)
    import can
    import time
    can.rc['interface'] = 'socketcan_ctypes'
    can.rc['channel'] = 'can0'
    
    from can.interfaces.interface import *
    
    
    def send_one():
        bus = can.interface.Bus(channel='can0' , bustype='socketcan_ctypes')
        msg = can.Message(arbitration_id=0xc0ffee,
                          data=[0, 25, 0, 1, 3, 1, 4, 1],
                          extended_id=False)
        try:
            bus.send(msg)
            print("Message sent on {}".format(bus.channel_info))
        except can.CanError:
            print("Message NOT sent")
    
    
    def send_cyclic():
        bus = can.interface.Bus(channel='can0' , bustype='socketcan_ctypes')
        msg = can.Message(arbitration_id=0xc0ffee,
                          data=[0, 25, 0, 1, 3, 1, 4, 1],
                          extended_id=False)
        try:
            can.send_periodic('can0', msg, 0.020)
            print("Message sent periodically on  {}".format(bus.channel_info))
        except can.CanError:
            print("Message NOT sent")
    
    if __name__ == "__main__":
        send_one()
        send_cyclic()
        time.sleep(10)
    

    The 2nd device only see`s the message send via "send_one()":

    ^Croot@raspberrypi:/home/pi/Documents# candump can0
      can0  7EE   [8]  00 19 00 01 03 01 04 01
    

    The Log on the 1st Device:

    DEBUG:can:Loading python-can
    DEBUG:can.bcm:Loading base broadcast manager functionality
    INFO:can.socketcan.ctypes:Loading socketcan ctypes backend
    DEBUG:can.socketcan.ctypes:Loading libc with ctypes...
    DEBUG:can.socketcan.ctypes:Result of createSocket was 4
    DEBUG:can.socketcan.ctypes:Binding socket with id 4 to channel can0
    DEBUG:can.socketcan.ctypes:calling ioctl SIOCGIFINDEX
    INFO:can.socketcan.ctypes:ifr.ifr_ifindex: 4
    DEBUG:can.socketcan.ctypes:bind returned: 0
    DEBUG:can.socketcan.ctypes:Packing a can frame
    DEBUG:can.socketcan.ctypes:Data: bytearray(b'\x00\x19\x00\x01\x03\x01\x04\x01')
    DEBUG:can.socketcan.ctypes:Type: <class 'bytearray'>
    DEBUG:can.socketcan.ctypes:sizeof frame: 16
    Message sent on ctypes socketcan channel
    DEBUG:can.socketcan.ctypes:Result of createSocket was 5
    DEBUG:can.socketcan.ctypes:Binding socket with id 5 to channel can0
    DEBUG:can.socketcan.ctypes:calling ioctl SIOCGIFINDEX
    INFO:can.socketcan.ctypes:ifr.ifr_ifindex: 4
    DEBUG:can.socketcan.ctypes:bind returned: 0
    {'interface': 'socketcan_ctypes', 'channel': 'can0'}
    DEBUG:can.socketcan.ctypes:Creating bcm socket on channel 'can0'
    DEBUG:can.socketcan.ctypes:Created bcm socket (un-connected fd=6)
    DEBUG:can.socketcan.ctypes:Connecting socket with id 6 to channel can0
    DEBUG:can.socketcan.ctypes:calling ioctl SIOCGIFINDEX
    INFO:can.socketcan.ctypes:ifr.ifr_ifindex: 4
    DEBUG:can.socketcan.ctypes:connect returned: 0
    DEBUG:can.socketcan.ctypes:Connected bcm socket
    DEBUG:can.socketcan.ctypes:Packing a can frame
    DEBUG:can.socketcan.ctypes:Data: bytearray(b'\x00\x19\x00\x01\x03\x01\x04\x01')
    DEBUG:can.socketcan.ctypes:Type: <class 'bytearray'>
    DEBUG:can.socketcan.ctypes:sizeof frame: 16
    INFO:can.socketcan.ctypes:Sending BCM TX_SETUP command
    DEBUG:root:Error sending frame :-/
    DEBUG:root:Error sending frame to stop cyclic message:-/
    
  3. Sebastian Kienitz reporter

    socket can native gives me that:

    DEBUG:can:Loading python-can
    DEBUG:can.bcm:Loading base broadcast manager functionality
    DEBUG:can.socketcan.native:Loading native socket can implementation
    INFO:can.socketcan.native:Created a socket
    DEBUG:can.socketcan.native:Binding socket to channel=can0
    DEBUG:can.socketcan.native:Bound socket.
    {'interface': 'socketcan_native', 'channel': 'can0'}
    INFO:can.socketcan.native:Sending BCM command
    Traceback (most recent call last):
      File "/usr/lib/python3.4/runpy.py", line 170, in _run_module_as_main
        "__main__", mod_spec)
      File "/usr/lib/python3.4/runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "/home/pi/can_test.py", line 39, in <module>
        send_cyclic()
      File "/home/pi/can_test.py", line 32, in send_cyclic
        can.send_periodic('can0', msg, 0.020)
      File "/usr/local/lib/python3.4/dist-packages/python_can-1.4.3-py3.4.egg/can/broadcastmanager.py", line 75, in send_periodic
        return can.interface.CyclicSendTask(channel, message, period)
      File "/usr/local/lib/python3.4/dist-packages/python_can-1.4.3-py3.4.egg/can/interfaces/interface.py", line 84, in __new__
        return cls(channel, *args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/python_can-1.4.3-py3.4.egg/can/interfaces/socketcan_native.py", line 135, in __init__
        self._tx_setup(message)
      File "/usr/local/lib/python3.4/dist-packages/python_can-1.4.3-py3.4.egg/can/interfaces/socketcan_native.py", line 143, in _tx_setup
        self.bcm_socket.send(header + frame)
    OSError: [Errno 22] Invalid argument
    
  4. Sebastian Kienitz reporter

    The sending device is:

    Linux raspberrypi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux

  5. Brian Thorne repo owner

    One minor point - you don't need to create a bus when using cyclic sending as ultimately we connect to a different type of socket. Just tested on my machine though and it doesn't do any harm.

    Would you be able to set up a virtual can device and run python3 -m examples.cyclic from the python-can source directory.

    Also it might be worth logging the header + frame that is being sent to your bcm socket.

  6. Log in to comment