Python: API Reference#

Reference for the synergy_logic package. See Quick Start: Python for a tutorial introduction.

import synergy_logic

Base#

The backplane. Constructing one signs on every module and builds the object tree.

synergy_logic.Base(*, zero_indexing=False, cs_pin=..., ack_pin=..., spi=..., en_pin=...)

All parameters are keyword-only and every one has a default that is correct for SLM-RP4 hardware. In practice you write Base().

Parameter

Default

Purpose

zero_indexing

False

Number slots and channels from 0 instead of 1

cs_pin

board.D27

Chip select

ack_pin

board.D25

Acknowledge

spi

SPI(6, 0)

The /dev/spidev6.0 bus

en_pin

board.D17

Base enable

Indexing#

base[1]        # IO_Module for slot 1

Methods#

init() : Re-run sign-on. Called automatically by the constructor.

deinit() : Release the base controller.

print_modules() : Print each slot and its module name.

rollCall(module_names) : Compare a list of expected module names against those that signed on. Raises ValueError reporting each mismatch, the module expected and its position in the list. Call this at startup in any program that assumes a particular rail.

The exception text reads ... in slot 0 but the number is the zero-based index into the list you passed, not a slot number. A mismatch on the module in slot 1 is reported as slot 0.

base.rollCall(["SLM-DCI-16NP", "SLM-DCO-15P", "SLM-AI-8-V"])

Properties#

is_active : True if the base controller is initialised and responding.

Watchdog#

config_watchdog(milliseconds, mode="TOGGLE") : Set the timeout. mode is "TOGGLE" (reset the controller and recover) or "HOLD" (hold in reset until 24 V is cycled).

start_watchdog() / stop_watchdog() : Start and stop the timer.

pet_watchdog() : Reset the timer manually. Any bus read or write does this implicitly.

C-style API#

An alternative to the object model, matching the form of the C++ library.

base.writeDiscrete(data, slot, channel=None)
base.readDiscrete(slot, channel=None)
base.writeAnalog(data, slot, channel)
base.readAnalog(slot, channel)
base.readTemperature(slot, channel)
base.readStatus(slot)

Passing channel=None to the discrete calls operates on every channel of the slot at once, as a bitmap.


IO_Module#

One module in one slot. Obtained from base[slot].

Indexing#

module[2]           # IO_Channel for channel 2
module[1:]          # every channel, as a list

Combo modules, which carry both inputs and outputs, raise ValueError on both forms — a slice is as ambiguous as a single index. Use module.inputs[n] and module.outputs[n], which accept an index or a slice:

combo.outputs[1]    # one channel
combo.inputs[1:]    # every input channel

Value properties#

Property

Read

Write

Notes

values

✓

✓

List of every channel’s value. Not valid on combo modules.

reals

✓

✓

Same, in engineering units.

input_values

✓

Combo-safe

output_values

✓

✓

Combo-safe

input_reals

✓

Combo-safe

output_reals

✓

✓

Combo-safe

module.values = [1, 0, 1, 0, 1, 0, 1, 0]
module.reals  = [5.0, 2.5, 0.0, 10.0]

Bitmapped access#

do_bitmapped(states) : Write every discrete output from one integer. 0xAA sets every even channel.

di_bitmapped() : Read every discrete input as one integer.

status_bitmapped() : Read the module’s status bytes as one integer.

These are a single bus transaction, so they are markedly faster than looping over channels.

Status properties#

Property

Meaning

missing24

Field supply absent

not_ready

Module still initialising

over_range(channel=None)

Input above range

under_range(channel=None)

Input below range

burnout(channel=None)

Open circuit

Omit channel to test whether any channel on the module reports the condition.

Configuration#

configure_module(config_data) : Send a configuration block. Factory defaults are applied automatically at sign-on; this overrides them.

module.configure_module((0x40, 0x03))   # channels 1-4 only

Block layouts and field values: Module Configuration Blocks.

Other#

print_state() : Print every channel’s current reading.

Broken on combo modules. It prints the slot header, then raises AttributeError: 'NoneType' object has no attribute 'channel'. Read input_values and output_values instead.


IO_Channel#

A single channel. Obtained from module[channel].

Properties#

value : The channel’s value, read or written.

  • Discrete: True / False

  • Analog: raw counts at the module’s native resolution, 0-8191 for a 13-bit input and 0-4095 for a 12-bit output.

real : The value in engineering units, such as volts, milliamps or degrees. Writing converts to the nearest available count.

channel.value = True
counts = channel.value

channel.real = 5.0
volts = channel.real

Scale against the module’s own resolution

Counts are reported at the resolution of the module, not at a fixed width. Module Catalog lists the resolution of every module.

Status properties#

over_range, under_range and burnout, per channel, read-only.


slm_rp4_helpers#

A small companion package for the SLM-RP4’s own peripherals.

from slm_rp4_helpers import read_switch_state

read_switch_state() : Read the front-panel toggle switch (GPIO 13). Returns 0 or 1.

See Onboard Peripherals.


Exceptions#

ValueError : Raised by rollCall() on a mismatch, and by values, reals or plain indexing on a combo module.

TypeError : Raised by rollCall() if not given a list or tuple of strings.

The library does not raise on a bus timeout. A failed transfer generally appears as a stale or zero reading, so validate values that matter rather than relying on an exception.