diff --git a/can/interfaces/usb2can/usb2canInterface.py b/can/interfaces/usb2can/usb2canInterface.py index 504b61c7b..cfe00ec82 100644 --- a/can/interfaces/usb2can/usb2canInterface.py +++ b/can/interfaces/usb2can/usb2canInterface.py @@ -4,9 +4,16 @@ import logging from ctypes import byref -from typing import Optional - -from can import BusABC, Message, CanInitializationError, CanOperationError +from typing import Optional, Union + +from can import ( + BusABC, + Message, + CanInitializationError, + CanOperationError, + BitTiming, + BitTimingFd, +) from .usb2canabstractionlayer import Usb2CanAbstractionLayer, CanalMsg, CanalError from .usb2canabstractionlayer import ( IS_ERROR_FRAME, @@ -14,6 +21,7 @@ IS_ID_TYPE, ) from .serial_selector import find_serial_devices +from ...util import check_or_adjust_timing_clock # Set up logging log = logging.getLogger("can.usb2can") @@ -75,6 +83,13 @@ class Usb2canBus(BusABC): Bitrate of channel in bit/s. Values will be limited to a maximum of 1000 Kb/s. Default is 500 Kbs + :param timing: + Optional :class:`~can.BitTiming` instance to use for custom bit timing setting. + If this argument is set then it overrides the bitrate argument. The + `f_clock` value of the timing instance must be set to 32_000_000 (32MHz) + for standard CAN. + CAN FD and the :class:`~can.BitTimingFd` class are not supported. + :param flags: Flags to directly pass to open function of the usb2can abstraction layer. @@ -96,6 +111,7 @@ def __init__( flags: int = 0x00000008, *_, bitrate: int = 500000, + timing: Optional[Union[BitTiming, BitTimingFd]] = None, serial: Optional[str] = None, **kwargs, ): @@ -112,12 +128,26 @@ def __init__( raise CanInitializationError("could not automatically find any device") device_id = devices[0] - # convert to kb/s and cap: max rate is 1000 kb/s - baudrate = min(int(bitrate // 1000), 1000) - self.channel_info = f"USB2CAN device {device_id}" - connector = f"{device_id}; {baudrate}" + if isinstance(timing, BitTiming): + timing = check_or_adjust_timing_clock(timing, valid_clocks=[32_000_000]) + connector = ( + f"{device_id};" + "0;" + f"{timing.tseg1};" + f"{timing.tseg2};" + f"{timing.sjw};" + f"{timing.brp}" + ) + elif isinstance(timing, BitTimingFd): + raise NotImplementedError( + f"CAN FD is not supported by {self.__class__.__name__}." + ) + else: + # convert to kb/s and cap: max rate is 1000 kb/s + baudrate = min(int(bitrate // 1000), 1000) + connector = f"{device_id};{baudrate}" self.handle = self.can.open(connector, flags) super().__init__(channel=channel, **kwargs)