Scripting boolean logic in Python

Content

Load the system

  • Log into the Simumatik APP

  • Open the workspace by connecting to a server

  • Add the system called Scripting boolean logic in Python

Components with third-party integration

Usually, automated system models include one or several special components, which can be connected to external devices, like PLCs or Robot controllers. The connection with third-party tools or devices is done through component drivers and the Gateway.

This and future tutorials will make use of a component (Python API Controller) which uses the UDP protocol to interact with a python program running on the local or a remote computer. This compact ‘Controller’ model has been created by the Simumatik team to provide an example of such a device.

Simumatik OEP provides the tools to build components that abstracts all the complicated stuff required to connect the model with the programmable controller – so you don’t have to worry about that.

Python API Controller

This component has 8 electric input ports and 8 electric output ports that can be connected to other components as we have done in previous tutorials. The user just needs to decide a name for an input and output variable that will map all these signals to the python program. The variable names can be adjusted in the public variable panel. We will come back to this later.

System description

The system includes one assembly with an electric box, a 24V DC power supply, a Controller, three buttons, and three lights.

Let’s download the diagrams and take a look at the configuration of the system.

The ‘PS01’ power supply is feeding the ‘Controller’ and the three buttons with the output ‘dc_p’. If you select the ‘PS01’ component and inspect the port selector, you will see them.

On the other hand, the ‘PS01’ ground output ‘dc_n’ is connected to the ‘Controller’ ‘x2’ input and the lights.

The rest of the connections are done to or from the ‘Controller’ inputs and outputs.

IO List

If you check the system assets again, you will see that there is another document called ‘IO List’. If you download it you will see this table.

The ‘IO List’ shows how the ‘Controller’ variables ‘input’ and ‘output’ are mapped to different ports, and also shows the port connections. Since the ‘Controller’ has 8 input ports and 8 output ports, these variables have a size of a BYTE (8 bits), so each input and output port corresponds to a specific bit of each variable.

If we follow the IO List, we can see that the ‘in_0’ input port is mapped to the bit 0 of the variable ‘inputs’, ‘in_1’ to the bit 1, and so on… The same happens with the output ports, ‘out_0’ port is mapped to the bit 0 of the ‘outputs’ variable, ‘out_1’ to bit 1,…

This means that if the ‘in_0’ input electric port of the ‘Controller’ goes high (24V) the bit 0 on the ‘Controller’ variable ‘inputs’ will be TRUE, and if it goes low (0V) it will be FALSE. On the other hand, if the ‘outputs’ variable bit 0 is TRUE on the ‘Controller’, the ‘out_0’ port will be powered with 24V, and 0V if it is FALSE. So basically, we can handle all the ‘Controller’ IO ports using just two variables.

Run the example program

Simumatik offers a python library to have an easy way of communicating with the Python API Controller. The Controller class includes the methods necessary for handling the variables. Start by downloading the python files, they can be found in our GitHub repository. An easy way of doing this is by cloning the repository.

We will begin by running the example code to make sure everything is working correctly. Run the file example.py. This will start listening for the controller. You should get the following message:

Controller UDP server listening: 0.0.0.0: 8400

This means that our control program is up and running. Now it’s time to go back into the Simumatik APP.

Activate the Gateway

The connection to third-party software or hardware controllers is done using the Gateway. The Gateway allows components loaded on the server to communicate with third-party software or hardware on your machine or network.

Click on the ‘Cog’ button on the workspace menu toolbar and open the Gateway tab.

If the Gateway is properly installed it will display the version and the status ‘STANDBY’. Click on the switch and if everything is working as expected, it should become green and the status ‘connected’ should be displayed, as seen below.

The connection with the Gateway is now done, and as soon as the emulation is started, the gateway will be available for the components that require it, so they can communicate with third-party software or hardware devices.

Test the system

While running the example.py program, start the Simumatik emulation. A connection should be established between the control program and the ‘Control’ component. When this happens, the following message will be displayed in the Python terminal:

New connection established:

The code in example.py will pass the inputs directly to their corresponding outputs by using the getValue() and setValue() methods. Try pressing the buttons, if everything is working correctly the indicators should light up.

IO Mapping to the Python program

Let’s take a look at how we can map the input and output bits to variables. The code discussed in this chapter can be found in the example_mapping.py file.

In practice, the way to connect the ‘Controller’ component to the Python program is by declaring the IO variables with the same name as in the component and mapping the ports according to the model, following the IO List or the connections. Let’s take a look at the example code. The following code will create an instance of the Controller and declare the variables.

_controller = UDP_Controller()
_controller.addVariable("inputs", "byte", 0)
_controller.addVariable("outputs", "byte", 0)
_controller.start()

It’s good practice to initialize all the relevant outputs, the following code will give the outputs a default value of False.

H01 = H02 = H03 = False

The Controller has built-in methods for adding, getting and setting variables. The following code will receive the inputs variable and map it to variables with the same names as we have given the components in the Simumatik app, this will make things easy to follow.

[_, _, _, _, _, S03, S02, S01] = _controller.getMappedValue("inputs")

Now that we’ve got variables describing the state of all inputs, it’s time to modify the output variables.

H01 = S01
H02 = not S03 and S02
H03 = S03 or S02

We can now set the outputs with the following method.

_controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])

Writing a program example

Now you are ready to make a program for your Controller component in your workspace. After you have tried the sample program that is already written in the example_mapping.py file, you can modify it and write a new python program, to show an example of what you can do. 

Let’s first remove the following code from your example_mapping.py program:

				
					H01 = S01 
H02 = not S03 and S02 
H03 = S03 or S02
				
			

Then we add an if-statement (2) where we removed the code above, the if-statement will look if the white button has been pressed:

				
					[_, _, _, _, _, S03, S02, S01] = _controller.getMappedValue("inputs") 
if S01:

_controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01]) 
time.sleep(1e-5)
				
			

If the white button is pressed, all lights should flash three times. For this we can use a for-loop (2) that runs three times in the if-statement:

				
					if S01:
     for x in range(3):
				
			

In order to make the lights flash, we need to set the relevant outputs to true and false with some time interval between:

				
					if S01:
     for x in range(3):
         H01 = H02 = H03 = True
         _controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])
         time.sleep(1)
         
         H01 = H02 = H03 = False
         _controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])
         time.sleep(1)
				
			

As a final touch, let’s add a line of code outside of the if-statement that turns on the yellow light as long as we press down the blue button.

				
					if S01:
     for x in range(3):
         H01 = H02 = H03 = True
         _controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])
         time.sleep(1)
         
         H01 = H02 = H03 = False
         _controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])
         time.sleep(1)

H02 = S02
				
			

And we are done! Now you can try out your new code and see if it works as intended. You might notice that the blue button will not work while the for-loop runs.