Fieldbus coupler parallel process

This documentation describes how a fieldbus coupler can be used to switch and process digital inputs and outputs as a parallel process to a horstFX program.

In this setup, a Python script is called via horstFX to handle communication with the fieldbus coupler. This Python script runs simultaneously with the horstFX script in the background.

In this example, the Wago 750-362 serves as the Modbus TCP fieldbus coupler. However, the example can be easily adapted to work with other Modbus TCP fieldbus couplers from different manufacturers.

1. installation of the packages

The control cabinet must be connected to the Internet to install the packages.

1.1 Installation / checking the installed Python version

Certain versions of Debian Linux are supplied with Python 3 pre-installed. This includes the version that is installed on our control cabinet.

The following commands can be executed via the console:

1. log in as root user:

su -l root

Please request the password directly from fruitcore.

 

2. System Update:

apt update

Avoid running the command "apt upgrade" in this setup.

3. Checking the installed Python version

python3 -V

1.2 Installation of pip

Pip can be installed via the console using the following commands:

apt install -y python3-pip
pip3 install --upgrade pip

1.3 Installation of pyModbusTCP

pip3 install pyModbusTCP

2. Creating the Python script
The Python script is used to communicate with the fieldbus coupler. It has a parallel process in which all 100ms inputs of the fieldbus coupler are read in. As soon as one of the inputs 1-4 receives the status "True", the corresponding output 1-4 is switched. If the status "False" is present at one of the inputs, the corresponding output is reset. Further information on the Modbus TCP read and write functions of the Python script can be found in the Python library documentation:

https://pymodbustcp.readthedocs.io/en/latest/index.html#

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
# modbus_thread
# start a thread for polling a set of registers, display result on console
# exit with ctrl+c
 
import sys
import time
from threading import Thread, Lock
from pyModbusTCP.client import ModbusClient
sys.path.insert(0, "..")
 
SERVER_HOST = '192.168.1.2'
SERVER_PORT = 502
 
# set global
regs = []
 
# init a thread lock
regs_lock = Lock()
 
c = ModbusClient(host=SERVER_HOST, port=SERVER_PORT, unit_id=1, auto_open=True, auto_close=False)
 
# previous state of lamps, so that ouputs were only set when the state changes
PrevStateLamp1 = False
PrevStateLamp2 = False
PrevStateLamp3 = False
PrevStateLamp4 = False
 
# modbus polling thread
def polling_thread():
    global regs
    #c = ModbusClient(host=SERVER_HOST, port=SERVER_PORT)
    # polling loop
    while True:
        # keep TCP open
        if not c.open():
            c.open()
        # do modbus reading on socket
        reg_list = c.read_discrete_inputs(0, 8)
        # if read is ok, store result in regs (with thread lock synchronization)
        if reg_list:
            with regs_lock:
                regs = list(reg_list)
        # 0.1s before next polling
        time.sleep(0.1)
 
# start polling thread
tp = Thread(target=polling_thread)
# set daemon: polling thread will exit if main thread exit
tp.daemon = True
tp.start()
 
# display loop (in main thread)
while True:
     
    # 0.1s before next loop run
    time.sleep(0.1)
     
    # print regs list (with thread lock synchronization)
    with regs_lock:
        #print(regs)
 
        # lamp 1
        if ( (regs[0] == True) and (PrevStateLamp1 == False) ):
            # turn on lamp 1
            if c.write_single_coil(0, 1):
                print("turn on lamp 1")
                PrevStateLamp1 = True
            else:
                print("write error turning on lamp 1")               
        if ( (regs[0] == False) and (PrevStateLamp1 == True) ):
            # turn off lamp 1
            if c.write_single_coil(0, 0):
                print("turn off lamp 1")
                PrevStateLamp1 = False
            else:
                print("write error turning off lamp 1")
 
        #lamp 2
        if ( (regs[1] == True) and (PrevStateLamp2 == False) ):
            # turn on lamp 2
            if c.write_single_coil(1, 1):
                print("turn on lamp 2")
                PrevStateLamp2 = True
            else:
                print("write error turning on lamp 2")            
        if ( (regs[1] == False) and (PrevStateLamp2 == True) ):
            # turn off lamp 2
            if c.write_single_coil(1, 0):
                print("turn off lamp 2")
                PrevStateLamp2 = False
            else:
                print("write error turning off lamp 2")
 
        #lamp 3
        if ( (regs[2] == True) and (PrevStateLamp3 == False) ):
            # turn on lamp 3
            if c.write_single_coil(2, 1):
                print("turn on lamp 3")
                PrevStateLamp3 = True
            else:
                print("write error turning on lamp 3")            
        if ( (regs[2] == False) and (PrevStateLamp3 == True) ):
            # turn off lamp 3
            if c.write_single_coil(2, 0):
                print("turn off lamp 3")
                PrevStateLamp3 = False
            else:
                print("write error turning off lamp 3")
 
        #lamp 4
        if ( (regs[3] == True) and (PrevStateLamp4 == False) ):
            # turn on lamp 4
            if c.write_single_coil(3, 1):
                print("turn on lamp 4")
                PrevStateLamp4 = True
            else:
                print("write error turning on lamp 4")            
        if ( (regs[3] == False) and (PrevStateLamp4 == True) ):
            # turn off lamp 4
            if c.write_single_coil(3, 0):
                print("turn off lamp 4")
                PrevStateLamp4 = False
            else:
                print("write error turning off lamp 4")

3. Automating Script Execution in horstFX

Learn how to automatically start the Python script in horstFX by following the steps outlined in the article "Executing External Python Scripts."

4. horstFX Sample Program

This sample program demonstrates how to call the Python script and make the robot move continuously between 2 waypoints. During this movement, inputs and outputs can be read or set using the fieldbus coupler in conjunction with the Python script.

If communication between the Python script and horstFX is required, they can interact with each other using TCP sockets.

Additionally, direct communication with the Modbus TCP fieldbus coupler can also be achieved through horstFX.

Download the sample program here:

Modbus Fieldbus Coupler Parallel Processes