# 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

  Parameters

    - module_type (`ModuleType`) – The type of the add-on module.

    - sw_version (`canlib.VersionNumber`) – The software version in the add-on module.

    - 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: `IoPin`

  property hysteresis

    The hysteresis in Volt for analog input pin

  property lp_filter_order

    The low-pass filter order for analog input pin

  property value

    Voltage level on the Analog input pin

## AnalogOut

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

  Bases: `IoPin`

  property 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 (`Channel`) – The channel where the discovery of I/O pins should take place.

  Variables

    - io_pins (list(`IoPin`)) – All discovered I/O pins.

    - modules (list(`AddonModule`)) – All included add-on-modules.

    - 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 `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

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

  Changed in version 1.9: `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: `IoPin`

  property high_low_filter

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

  property low_high_filter

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

  property value

    Value on digital input pin (0 or 1)

## DigitalOut

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

  Bases: `IoPin`

  property value

    Value on digital output pin (0 or 1)

## DigitalValue

class canlib.canlib.iopin.DigitalValue(value)

  Enum used digital values

  HIGH = 1
  LOW = 0

## Direction

class canlib.canlib.iopin.Direction(value)

  Enum used for values in `Info`

  IN = 4

    Input

  OUT = 8

    Output

## Info

class canlib.canlib.iopin.Info(value)

  Enum used internally in `IoPin` for calls to `kvIoPinGetInfo` and `kvIoPinSetInfo`

  AI_HYSTERESIS = 11

    The hysteresis in volt.

    The hysteresis in volt for an analog input pin, i.e. the amount the input have to change before the sampled value is updated.

    0.0 - 10.0, default 0.3

  AI_LP_FILTER_ORDER = 10

    The low-pass filter order for an analog input pin.

    0 - 16, default 3 (sample time is 1 ms)

  DIRECTION = 2

    One of `Direction`

  DI_HIGH_LOW_FILTER = 9

    Time when a digital input pin goes from LOW to HIGH.

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

    Range: 0 - 65000, Default 5000 us

  DI_LOW_HIGH_FILTER = 8

    Time when a digital input pin goes from HIGH to LOW.

    Filter time in micro seconds when a digital input pin goes from HIGH to LOW. Range: 0 - 65000, Default 5000 us

  FW_VERSION = 16

    Software version number of the submodule the pin belongs to. Read-only.

  MODULE_NUMBER = 14

    The module number the pin belongs to. The number starts from 0. Read-only.

  MODULE_TYPE = 1

    One of `ModuleType`

  NUMBER_OF_BITS = 5

    Resolution in number of bits. Read-only.

  PIN_TYPE = 4

    One of `PinType`

  RANGE_MAX = 7

    A float that contains the upper range limit in volts. Read-only.

  RANGE_MIN = 6

    A float that contains the lower range limit in volts. Read-only.

  SERIAL_NUMBER = 15

    Serial number of the submodule the pin belongs to. Read-only.

## IoPin

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

  Base class of I/O ports

  property direction

    Pin direction (Read-only)

    Type

      `Direction`

  property fw_version

    Firmware version in module (Read-only)

    Type

      VersionNumber

  property hysteresis

    Base class does not implement hysteresis attribute

  property lp_filter_order

    Base class does not implement lp_filter_order attribute

  property module_type

    Type of module (Read-only)

    Type

      `ModuleType`

  property number_of_bits

    Resolution in number of bits (Read-only)

    Type

      int

  property pin_type

    Type of pin (Read-only)

    Type

      `PinType`

  property range_max

    Upper range limit in volts (Read-only)

    Type

      float

  property range_min

    Lower range limit in volts (Read-only)

    Type

      float

  property serial

    Module serial number (Read-only)

    Type

      int

  property value

    Base class does not implement value attribute

## ModuleType

class canlib.canlib.iopin.ModuleType(value)

  Enum used for return values in `kvIoPinGetInfo`

  ANALOG = 2

    Analog Add-on (4 inputs, 4 outputs).

  DIGITAL = 1

    Digital Add-on (16 inputs, 16 outputs).

  INTERNAL = 4

    Internal Digital module (1 input, 1 output).

  RELAY = 3

    Relay Add-on (8 inputs, 8 outputs).

## PinType

class canlib.canlib.iopin.PinType(value)

  Enum used for values in `Info`

  ANALOG = 2
  DIGITAL = 1
  RELAY = 3

## Relay

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

  Bases: `IoPin`

  property value

    Value on relay, `0` for off, `1` for on