Tutorial 1: Boolean logic
In this tutorial you will:
- Use python to program a controller connected to buttons and lights.
- Test different logic combinations between the components in the station.
We will start by loading the tutorial system into the workspace, and navigating through the components in the tree and the scene to explore them.
This tutorial requires basic python knowlege.
Load the system
- Log into the Simumatik APP
- Open the workspace by connecting to a server
- Add the system called Python Tutorial 1: Boolean logic
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 the following 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 can easily abstract the end-user from all the complicated stuff required to connect the model with the programmable controller - don't worry about that.
To be able to follow this tutorial, make sure you have already done the Basic tutorials.
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.
Opening the component information panel will provide you with more information about the component itself and its public variables.
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.
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 neccessary 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 workspace menu button on the toolbar ('⁝') and open the Gateway tab.
If you are using the Gateway for the first time, the initial step is to download and install it.
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.
Check out the Gateway section of the Manual to learn more about how the Gateway works.
Test the system
It's time to start the 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: <client address>
The code in
example.py will pass the inputs directly to their corresponding outputs by using the
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
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
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.
The underscores simply means that we ignore the values we are not going to use. For example, if we didn't need the
S03 variable, we could replace it with an underscore.
[_, _, _, _, _, 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
This code utilizes ternary operators, to learn more look at these tips.
We can now set the outputs with the following method.
_controller.setMappedValue("outputs", [_, _, _, _, _, H03, H02, H01])
The mapping methods use the standard [MSB...LSB] order, which means that the most significant bits will be to the left.
Time to play!
Now you are ready to make a program for your 'Controller', run it, and test it against the model.
Let's try to make some different connections between the buttons and lights.
- When pressing the white button, turn on the red light. If the black button also is activated, instead turn on the green light.
- When the blue button is pressed, make the yellow light start blinking. Stop blinking when the blue button is pressed again.
- Make the lights repeatedly switch on/off after each other in a sequence from left to right.
To make the program wait before executing the next row, use the
time.sleep(s) function. Example:
time.sleep(0.5) makes the program wait for 0.5 seconds.