Wago Programmable Logic Controllers¶
Wago PLCs (aka wagoboxes) are composed by:
- an Ethernet communication module
- additional modules containing Input or Output channels for various signals:
- SSI encoder
Wago class accesses these values by reading or writing specific
modbus registers. The user is allowed to map these input/output channels with
string names through the yaml config file as described after.
name: wcid42g plugin: bliss description: ID42 wago nanoDCM module: wago.wago class: Wago tango: url: tango://ID42/wcid42g/tg modbustcp: url: wcid42g mapping: - type: 750-478 logical_names: ai1, ai2 - type: 750-461 logical_names: pt1, pt2 - type: 750-469 logical_names: tc1, tc2 counter_names: ai1, ai2, pt1, pt2, tc1, tc2
- Declare a tango device id42/wcid42g/tg
- Create a supervisor statrtup script for the server
- If a single counter is wanted in a session, use:
Communication with Wago PLCs¶
The communication is implemented through the standard Modbus/TCP protocol.
The standard Modbus serial protocol defines mainly:
- 4 memory areas on the device that can be accessed writing, reading or both
- how to construct and send requests to the device and how to interpret responses
What the protocol does not define are information contained in those specific memory areas as this is device dependent.
In order to obtain this information, it is necessary to consult the documentation provided by the producer.
The Modbus/TCP protocol is built on top of the Modbus serial protocol as it encapsulates Modbus messages through a TCP/IP socket usually on standard port 502.
The configuration is a matter of defining the following:
- Provide connection informations
- Map PLC input/output plugged modules
- Assign some meaningful logical names to input/output
- Define counters
- Define counters gains
- If interlocks are present, provide the configuration
Connection to Wago can be done in two ways:
- direct connection
- through Tango Device Server
To use a wago trough a Tango device server requires to configure it and allows to use Tango tools (Jive, AtkPanel, HDB++) to monitor signals.
The connection can be direct with the following configuration:
modbustcp: url: host:port
modbustcp: url: wcid42a
If not specified, the default Modbus port 502 is taken.
Or the connection can be done via Tango Device Server using its Fully Qualified Domain Name (FQDN).
tango: url: tango://host:port/domain/family/member
tango: url: tango://lid42ctrl1:20000/ID42/wcid42a/tg
host:port can be omitted if the global variable
TANGO_HOST is defined.
Mapping PLC input/output plugged modules¶
Here is given a basic example of yaml configuration:
name: wcid31l plugin: bliss description: ID31 EH I/O Station module: wago.wago class: Wago modbustcp: url: wcid31l
Basic information have the purpose to identify the device, the kind of device and the host address to allow communications.
As the PLC can be composed following user needs we have to specify what modules are
attached to the Main CPU, this is done using the
type keyword. Than we want to
give a name to single input/output and this is done using the
If the input/output module has, for example, 4 inputs, we can’t give more than 4 logical_names,
but we can use the same name twice or more to logically group them. In this case we can still
distinguish them later accessing to the
Let’s take this example:
name: wcid31l plugin: bliss description: ID31 EH I/O Station module: wago.wago class: Wago modbustcp: url:wcid31l mapping: - type: 750-476 logical_names: pot1vol, pot1cur - type: 750-530 logical_names: p9,p10,p11,p12,p13,pso,wcdm2c7,wcdm2c8 - type: 750-478 logical_names: pot1out, adc8 - type: 750-478 logical_names: pot2out, adc10 - type: 750-562 logical_names: dac5, dac6 - type: 750-562-UP logical_names: pot1in, dac8 - type: 750-469 logical_names: th_mask, _ - type: 750-516 logical_names: i0_g,i0_g,i0_g,_ - type: 750-467 logical_names: i0,_ - type: 750-436 logical_names: o1, o2, o3, o4, o5 ignore_missing: True counter_names: pot1vol, pot1cur, pot2vol, pot2cur, i0 counter_gain_names: i0_g
We can see that
i0_g is used three times and so we are mapping three
input/output with the same
logical_name and they will have a
with a progressive number starting from zero. So the first
i0_g will have
logical_channel 0, the second will have 1 and so on.
First, you have to declare the type of board and then you can map the logical names that will be used to access those channels.
Some other examples:
Card type 750-476 is a 2 Channel +-10V Input, so you will declare 2 logical names from which you will expect float values.
Card type 750-530 is an 8 Channel Digital Output, so you will declare 8 logical names and you will expect and use boolean data.
The last Card type shows how to behave in the case that there is nothing attached to the channel: you can just map with an underscore.
counter_names have to be organized as a comma separated list of
logical names. These names should be already defined in the preceding mapping.
counter_gain_names associates a counter with gains when the hardware
requires it (e.g.novelec electrometer with 3 different gains).
Ignore not mapped channels¶
The additional key
ignore_missing is used to avoid exception if a channel is
not mapped on
logical_names. Be aware that we can avoid defining last channels
on the module, but we can’t skip.
For example we can go from this:
mapping: - type: 750-530 logical_names: p9,p10,p11,p12,p13,pso,wcdm2c7,wcdm2c8
ignore_missing: True mapping: - type: 750-530 logical_names: p9,p10,p11,p12
_ underscore to map unused channels is a convention but is not ignoring
them, simply mapping with the name
We can simulate any Wago simply installing requirements-dev-conda and adding the following entry to the configuration:
simulate: Trueif you want to connect to the real Hardware!
Basic usage from the shell¶
Normally you would simply need
BLISS : w = config.get("transfocator_simulator") BLISS : BLISS : BLISS : wago_simulator = config.get("wago_simulator") BLISS : wago_simulator logical logical module module device channel type description ---------------- --------- -------- -------------------------------------- foh2ctrl 0 750-504 4 Channel Digital Output foh2ctrl 1 750-504 4 Channel Digital Output foh2ctrl 2 750-504 4 Channel Digital Output foh2ctrl 3 750-504 4 Channel Digital Output foh2pos 0 750-408 4 Channel Digital Input foh2pos 1 750-408 4 Channel Digital Input foh2pos 2 750-408 4 Channel Digital Input foh2pos 3 750-408 4 Channel Digital Input sain2 0 750-408 4 Channel Digital Input sain4 0 750-408 4 Channel Digital Input sain6 0 750-408 4 Channel Digital Input sain8 0 750-408 4 Channel Digital Input pres 0 750-408 4 Channel Digital Input esTf1 0 750-469 2 Channel Ktype Thermocouple Input esTf2 0 750-469 2 Channel Ktype Thermocouple Input esTf3 0 750-469 2 Channel Ktype Thermocouple Input esTf4 0 750-469 2 Channel Ktype Thermocouple Input esTr1 0 750-469 2 Channel Ktype Thermocouple Input esTr2 0 750-469 2 Channel Ktype Thermocouple Input esTr3 0 750-469 2 Channel Ktype Thermocouple Input esTr4 0 750-469 2 Channel Ktype Thermocouple Input intlckf1 0 750-517 2 Changeover Relay Output intlckf2 0 750-517 2 Changeover Relay Output encoder1 0 750-630 24 bit SSI encoder special_out_1 0 750-508 2 Channel Digital Output special_out_2 0 750-508 2 Channel Digital Output o10v1 0 750-554 2 Channel 4/20mA Output o10v2 0 750-554 2 Channel 4/20mA Output double_out 0 750-517 2 Changeover Relay Output double_out 1 750-517 2 Changeover Relay Output OK: Given mapping does match Wago attached modules. BLISS : wago_simulator.get("foh2ctrl") Out : [1, 0, 1, 1] BLISS : wago_simulator.set("foh2ctrl",0,0,0,0) BLISS : wago_simulator.get("foh2ctrl") Out : [0, 0, 0, 0] BLISS : wago_simulator.get("esTr1", "esTr2","o10v1") Out : [78.8, -203.4, 44404] BLISS : wago_simulator.set("esTr1", 0) !!! === RuntimeError: Cannot write: 'esTr1' is not an output === !!!