Skip to content

Wago Programmable Logic Controllers

Wago PLCs

Wago PLCs (aka wagoboxes) are composed by:

  • an Ethernet communication module. The new ethernet communication module 750-8001 needs an extra entry main_module in the yml config file.
  • additional modules containing Input or Output channels for various signals:
    • Digital
    • Voltage
    • Current
    • Temperature
    • SSI encoder

The 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.

TL;DR

Configure the wago in BEACON:

name: wcid42a
plugin: bliss
description: ID42 wago nanoDCM
module: wago.wago
class: Wago
main_module: 750-8001  # only for the new ethernet communication module
tango:
  url: tango://id42/wcid42a/tg
modbustcp:
  url: wcid42a
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/wcid42a/tg with following resources:

Wago/wcid42a/DEVICE/Modbus: "id42/wcid42a/wcid42a-modbus"
id42/wcid42a/wcid42a-modbus->iphost: wcid42a
id42/wcid42a/wcid42a-modbus->Protocol: TCP
id42/wcid42a/wcid42a-modbus->TCPTimeout: 1000

Wago/wcid42a/DEVICE/Wago: "id42/wcid42a/tg"
id42/wcid42a/tg->beacon_name: wcid42a

Declare interlocks with the following resources:

interlocks:       
  - relay: relay011
    flags: inverted
    description: temperature wceudev01
    channels:
      - logical_name: ai011
        type: TC
        min: 0
        max: 5
  - relay: do012
    flags: inverted
    description: Analog input interlock
    channels:
      - logical_name: th012
        type: TC
        min: 20
        max: 30
  - relay: relay012
    flags: inverted
    description: monitor test
    channels:
      - logical_name: th011
        type: TC
        min: -201
        max: 850
        flags: MONITOR
        dac: dac1
        dac_scale: 2.2
        dac_offset: 30 

The MONITOR flag allows: val(dac1) = dac_scale*val(th11) + dac_offset Remark: dac mnemonic has to be dacxx like dac1.

Create a supervisor start-up script for the server:

[program:Wago_wcid42a]
command=bash -c "source /users/blissadm/conda/miniconda/bin/activate bliss && exec Wago wcid42a"
environment=TANGO_HOST="id42:20000",BEACON_HOST="id42:25000",ORBendPoint="giop:tcp:lid421:"
user=blissadm
startsecs=2
autostart=true
redirect_stderr=true
stdout_logfile=/var/log/%(program_name)s.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_capture_maxbytes=1MB

If a single counter is wanted in a session, use: ALIASES.add("tempCryo", wcid42atc1)

Communication with Wago PLCs

The communication is implemented through the standard Modbus/TCP protocol.

Modbus 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.

Configuration

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 informations

Connection to Wago can be done in two ways:

  • direct connection
  • through Tango Device Server

Note

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
Example:
modbustcp:
    url: wcid42a

Note

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
Example:
tango:
    url: tango://lid42ctrl1:20000/ID42/wcid42a/tg

Note

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 logical_names keyword.

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 logical_channel.

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,_
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 logical_channel 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, the type of board has to be declared then the logical names that will be used to access those channels can be mapped.

Some other examples:

  • Card type 750-476 is a 2 Channel +-10V Input, so 2 logical names, from which float values are expected, will be declared.

  • Card type 750-530 is an 8 Channel Digital Output -> 8 logical names that provide boolean data.

  • The last Card type shows how to behave in the case that there is nothing attached to a channel: an underscore can be used to map it.

The key counter_names has to be organized as a comma separated list of logical names. These names should be already defined in the preceding mapping.

The key 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
To this:
ignore_missing: True
mapping:
  - type: 750-530
    logical_names: p9,p10,p11,p12

Using _ underscore to map unused channels is a convention but is not ignoring them, simply mapping with the name _.

Simulation

We can simulate any Wago simply installing requirements-dev-conda and adding the following entry to the configuration:

simulate: True
This will launch a simulator on localhost (and a random port) ignoring other connection settings. This simulator can be used for basic testing, be aware that is initialized with random values and than it will keep the last value set.

The flag simulate: True musst be removed to connect to the real Hardware.

Basic usage from the shell

Normally only set and get methods will be needed.

BLISS [1]: w = config.get("transfocator_simulator")
BLISS [2]:
BLISS [2]:
BLISS [2]: wago_simulator = config.get("wago_simulator")
BLISS [3]: 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 [4]: wago_simulator.get("foh2ctrl")
  Out [4]: [1, 0, 1, 1]

BLISS [5]: wago_simulator.set("foh2ctrl",0,0,0,0)
BLISS [6]: wago_simulator.get("foh2ctrl")
  Out [6]: [0, 0, 0, 0]

BLISS [7]: wago_simulator.get("esTr1", "esTr2","o10v1")
  Out [7]: [78.8, -203.4, 44404]

BLISS [8]: wago_simulator.set("esTr1", 0)
!!! === RuntimeError: Cannot write: 'esTr1' is not an output === !!!