# I/O pin

Experimental support for accessing IO-pins on sub modules of the Kvaser DIN Rail SE 400S and variants that was added to CANlib v5.26.

New in version 1.8.

## AddonModule

class `canlib.canlib.iopin.``AddonModule`(module_type, fw_version=None, serial=None, first_pin_index=None)

  Contains information about one add-on module

  Variables: | module_type (`iopin.ModuleType`) – The type of the add-on module. sw_version (`canlib.Version`) – The software version in the add-on module. iopin.serial (int) – The serial number of the add-on module. first_index (int) – The index of the add-on modules first pin.

  New in version 1.9.

  `issubset`(spec)

    Check if current attributes are fulfilling attributes in spec

    Any attribute in spec that is set to None is automatically considered fulfilled.

    The `fw_version` attribute is considered fulfilled when `self.fw_version >= spec.fw_version`.

    This can be used to check if a specific module fulfills a manually created specification:

        >>> module_spec = [iopin.AddonModule(module_type=iopin.ModuleType.DIGITAL)]
        ... config = iopin.Configuration(channel)
        >>> config.modules
        [AddonModule(module_type=<ModuleType.DIGITAL: 1>, fw_version=VersionNumber(major=2, minor=5, release=None, build=None), serial=2342), first_pin_index=0]
        >>> config.issubset(module_spec)
        True

        >>> module_spec = [iopin.AddonModule(
                module_type=iopin.ModuleType.DIGITAL,
                fw_version=VersionNumber(major=3, minor=1),
                serial=2342)]

        >>> config.issubset(module_spec)
        False

        >>> module_spec = [
            iopin.AddonModule(module_type=iopin.ModuleType.ANALOG),
            iopin.AddonModule(module_type=iopin.ModuleType.DIGITAL,
                              fw_version=VersionNumber(major=3, minor=1),
                              serial=2342)]

        >>> config.issubset(module_spec)
        False

## AnalogIn

class `canlib.canlib.iopin.``AnalogIn`(channel, pin)

  Bases: `canlib.canlib.iopin.IoPin`

  `hysteresis`

    The hysteresis in Volt for analog input pin

  `lp_filter_order`

    The low-pass filter order for analog input pin

  `value`

    Voltage level on the Analog input pin

## AnalogOut

class `canlib.canlib.iopin.``AnalogOut`(channel, pin)

  Bases: `canlib.canlib.iopin.IoPin`

  `value`

    Voltage level on the Analog output pin

## Configuration

class `canlib.canlib.iopin.``Configuration`(channel)

  Contains I/O pins and the `canlib.Channel` to find them on

  Creating this object may take some time depending on the number of I/O pins availably on the given `canlib.Channel`.

  Parameters: | channel (‘canlib.Channel’) – The channel where the discovery of I/O pins should take place.
  Variables: | io_pins (list(`iopin.IoPin`)) – All discovered I/O pins. pin_names (list(str)) – List of label I/O pin names. (dict(str (pin_index) – int)): Dictionary with I/O pin label name as key, and pin index as value.

  To create an `iopin.Configuration` you need to supply the `canlib.Channel`, which is were we look for I/O pins:

      >>> from canlib.canlib import iopin
      ... from canlib import canlib, Device, EAN
      ... device = Device.find(ean=EAN('01059-8'), serial=225)
      ... channel = canlib.openChannel(device.channel_number(), canlib.Open.EXCLUSIVE)
      ... config = iopin.Configuration(channel)

  Now we can investigate a specific pin by index:

      >>> config.pin(index=80)
      Pin 80: <PinType.ANALOG: 2> <Direction.OUT: 8> bits=12 range=0.0-10.0 (<ModuleType.ANALOG: 2>)

  It is also possible to find the label name from the index and vice verse for a pin, as well as access the pin using the label name:

      >>> config.name(80)
      '4:AO1'

      >>> config.index('4:AO1')
      80

      >>> config.pin(name='4:AO1')
      Pin 80: <PinType.ANALOG: 2> <Direction.OUT: 8> bits=12 range=0.0-10.0 (<ModuleType.ANALOG: 2>)

  Note

  A configuration needs to be confirmed using `iopin.Configuration.confirm` (which calls `canlib.channel.io_confirm_config`) before accessing pin values:

      >>> config.pin(name='4:AO1').value = 4
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "...\canlib\canlib\iopin.py", line 271, in value
        File "...\canlib\canlib\dll.py", line 94, in _error_check
          raise can_error(result)
      canlib.canlib.exceptions.IoPinConfigurationNotConfirmed: I/O pin configuration is not confirmed (-45)
      I/O pin configuration is not confirmed (-45)

      >>> config.confirm()

      >>> config.pin(name='4:AO1').value = 4

  An `iopin.Configuration` may be compared with an expected ordered list of `iopin.AddonModule` before confirming using `iopin.AddonModule.issubset`

  Changed in version 1.9: `iopin.Configuration.modules` is now an attribute, containing an ordered list of `AddonModule` objects.

  `confirm`()

    Confirm current configuration

    Convenience function that calls `Channel.io_confirm_config`.

  `index`(name)

    Return index for pin with the given label name

  `issubset`(spec)

    Check if attributes of modules in self is fulfilled by given spec

    This is a convenience method that calls `AddonModule.issubset` on all modules given by `self.modules` which can be used to check if the current configuration fulfills a manually created specification:

        >>> config = iopin.Configuration(channel)
        >>> config_spec = [iopin.AddonModule(module_type=iopin.ModuleType.ANALOG),
                           iopin.AddonModule(module_type=iopin.ModuleType.DIGITAL,
                                             fw_version=VersionNumber(major=3, minor=1),
                                             serial=2342)]

        >>> config.issubset(config_spec)
        False

    New in version 1.9.

  `name`(index)

    Return label name for pin with given index

  `pin`(index=None, name=None)

    Return `IoPin` object using index or name

    Either `index` or `name` must be given, if both are given, the name will be used.

    Parameters: | index (int) – I/O pin index name (str) – I/O pin name

## DigitalIn

class `canlib.canlib.iopin.``DigitalIn`(channel, pin)

  Bases: `canlib.canlib.iopin.IoPin`

  `high_low_filter`

    Filter time in micro seconds when a digital pin goes from HIGH to LOW

  `low_high_filter`

    Filter time in micro seconds when a digital pin goes from LOW to HIGH

  `value`

    Value on digital input pin (0 or 1)

## DigitalOut

class `canlib.canlib.iopin.``DigitalOut`(channel, pin)

  Bases: `canlib.canlib.iopin.IoPin`

  `value`

    Value on digital output pin (0 or 1)

## DigitalValue

class `canlib.canlib.iopin.``DigitalValue`

  Enum used digital values

  `HIGH` = 1
  `LOW` = 0

## Direction

class `canlib.canlib.iopin.``Direction`

  Enum used for return values in `kvIoPinGetInfo`

  `IN` = 4
  `OUT` = 8

## Info

class `canlib.canlib.iopin.``Info`

  Enum used for calls to `kvIoPinGetInfo` and `kvIoPinSetInfo`

  `AI_HYSTERESIS` = 11
  `AI_LP_FILTER_ORDER` = 10
  `DIRECTION` = 2
  `DI_HIGH_LOW_FILTER` = 9
  `DI_LOW_HIGH_FILTER` = 8
  `FW_VERSION` = 16
  `MODULE_NUMBER` = 14
  `MODULE_TYPE` = 1
  `NUMBER_OF_BITS` = 5
  `PIN_TYPE` = 4
  `RANGE_MAX` = 7
  `RANGE_MIN` = 6
  `SERIAL_NUMBER` = 15

## IoPin

class `canlib.canlib.iopin.``IoPin`(channel, pin)

  Base class of I/O ports

  `direction`

    Pin direction (Read-only)

    Type: | `Direction`

  `fw_version`

    Firmware version in module (Read-only)

    Type: | VersionNumber

  `hysteresis`

    Base class does not implement hysteresis attribute

  `lp_filter_order`

    Base class does not implement lp_filter_order attribute

  `module_type`

    Type of module (Read-only)

    Type: | `ModuleType`

  `number_of_bits`

    Resolution in number of bits (Read-only)

    Type: | int

  `pin_type`

    Type of pin (Read-only)

    Type: | `PinType`

  `range_max`

    Upper range limit in volts (Read-only)

    Type: | float

  `range_min`

    Lower range limit in volts (Read-only)

    Type: | float

  `serial`

    Module serial number (Read-only)

    Type: | int

  `value`

    Base class does not implement value attribute

## ModuleType

class `canlib.canlib.iopin.``ModuleType`

  Enum used for return values in `kvIoPinGetInfo`

  `ANALOG` = 2
  `DIGITAL` = 1
  `INTERNAL` = 4
  `RELAY` = 3

## PinType

class `canlib.canlib.iopin.``PinType`

  Enum used for return values in `kvIoPinGetInfo`

  `ANALOG` = 2
  `DIGITAL` = 1
  `RELAY` = 3

## Relay

class `canlib.canlib.iopin.``Relay`(channel, pin)

  Bases: `canlib.canlib.iopin.IoPin`

  `value`

    on)

    Type: | Value on relay (0
    Type: | off, 1