Controller inputs and outputs¶
The controller carries twenty inputs and outputs, on top of the six of the tool connector
documented in Tool inputs and outputs. The IOs of the controller are prefixed with c,
and the robot user manual documents their wiring on the connector: pin assignment, wire
colors, ground and supply.
Labels |
What they are |
|---|---|
|
Digital inputs, read only. |
|
Digital outputs. |
|
Analog inputs, read only, in volts. |
|
Analog outputs, in volts. |
Reading and writing¶
get_all() returns the inputs and outputs of the
controller and of the tool at once, keyed by label:
1 from pyniryo_nate import Nate
2 from pyniryo_nate.models import IOLabel
3
4 nate = Nate(hostname="10.10.10.10", login=("user", "secret"))
5
6 states = nate.io.get_all()
7 print(states.digital_inputs[IOLabel.CDI3].value)
8
9 nate.io.set_digital_output(IOLabel.CDO1, True)
Outputs that must change together are written in one call, so that the robot never passes through an intermediate combination:
1 from pyniryo_nate.models import DigitalIO, IOLabel
2
3 nate.io.update_states([
4 DigitalIO(id=IOLabel.CDO1, value=True),
5 DigitalIO(id=IOLabel.CDO2, value=False),
6 ])
Analog outputs¶
cao1 and cao2 are driven in volts by
set_analog_output(). The tool connector carries no
analog output, so these two are the only ones a program can write.
1 nate.io.set_analog_output(IOLabel.CAO1, 4.5)
The range of a channel belongs to the robot, which refuses a write outside it with
ClientError. The message of the exception names the
channel, the value that was sent and the range the robot serves:
1 from pyniryo_nate.exceptions import ClientError
2
3 try:
4 nate.io.set_analog_output(IOLabel.CAO1, 42.0)
5 except ClientError as error:
6 print(error)
Warning
Reading an analog input gives back what is measured, out of range values included. The robot checks what a program writes, not what the world does to its inputs.
Waiting on an input¶
wait_for_digital_io() blocks until an input holds a
value. A program waiting on a sensor, a button or a handshake from a machine needs nothing
more:
1 nate.io.wait_for_digital_io(IOLabel.CDI1, True, timeout=30)
The current state is read once the subscription is in place, so an input that already
holds the value returns at once rather than waiting for a change that will not come, and a
change happening meanwhile is not missed. A label the robot serves no digital IO under is
refused instead of waited on. Without a timeout the call waits forever; with one it raises
TimeoutError.
on_digital_io() and
on_analog_io() report a single IO as it changes,
without polling and without blocking:
1 unsubscribe = nate.io.on_digital_io(IOLabel.CDI1, lambda io: print(io.value))
2
3 # later, to stop receiving the changes
4 unsubscribe()
Labels this client does not know¶
IOLabel holds the labels that existed when this version
was released. A robot may serve more. Those are reported with their raw label, and the
rest of the answer is served as usual:
1 states = nate.io.get_all()
2
3 print(states.digital_inputs['cdi9'].value)
4 nate.io.set_digital_output('cdo9', True)
An unknown label is sent as it is and the robot decides, so a program keeps working
against hardware released after the client that drives it. A label the robot does not
serve is refused with ClientError.
When the robot serves no IO¶
A read and a write both raise ServerError with a status
code of 503 while the chain that carries the inputs and outputs is not running. A robot
that is not ready is told apart from a robot that has no input and no output, which an
empty answer would hide.
1 from pyniryo_nate.exceptions import ServerError
2
3 try:
4 states = nate.io.get_all()
5 except ServerError as error:
6 if error.status_code == 503:
7 print(f"the robot is not serving its IOs yet: {error.reason}")
8 else:
9 raise