Simple read/write on Modbus¶
Prerequisites¶
Modbus connector
A Modbus device or a virtualized Modbus device like
oitc/modbus-server:1.1.2
Checkout branches
git checkout origin/osp-modbus-configuration .
For the virtual device
docker container run -p 5020:5020 --name=modbus-test oitc/modbus-server:1.1.2
Description¶
Note
The complete example can be checkout with git checkout origin/example-modbus_simple_read_write_example
.
In this tutorial you will learn how to :
Register a Modbus slave
Read/write Modbus values from the slave
This illustration demonstrates the establishment of a loop involving a Modbus coil (boolean) located at address 0. The Modbus module will continuously perform read and write operations with a 1-second interval. With each iteration, the value will be inverted.
Steps¶
1. Register a Modbus slave¶
The first step is to create a “slave” file in which we define how to connect to the slave. Replace the IP by the IP of the Modbus device. We are using a read frequency of 1 second for our test. This means the input from the Modbus will be updated every second.
Content : root/plc/slave-1/slave.modbus
{
"host": "10.0.2.15:5020",
"moduleId": "modules.modbus.modbus-1",
"readPeriod": {
"value": 1,
"unit": "SECONDS"
}
}
2. Create a coil input¶
Content : root/input-coil/value.ospp
{
"name": "input-coil",
"description": "input-coil",
"type": "BOOLEAN"
}
We introduce an entity called owner.modbus
. This file serves the purpose of indicating our intention to interpret address 0 as a coil for reading. The slave ID field serves as the connection identifier to the corresponding slave device.
Content : root/input-coil/owner.modbus
{
"address": 0,
"endianness": "BIG",
"modbusType": "COIL",
"slaveId": "root.plc.slave-1",
"valueType": "BOOLEAN"
}
1. Create an output file to write value on the modbus device¶
The output.modbus
file describes how we want to write to the Modbus device, but does nothing if nobody interacts with it.
Content : root/output-coil/output.modbus
{
"address": 0,
"endianness": "BIG",
"modbusType": "COIL",
"slaveId": "root.plc.slave-1",
"valueType": "BOOLEAN"
}
4. Call the output from an event.¶
To create a state inversion, this test adds some simple logic to read the value from address 0 then call the output with the inverted value using the expression capabilities.
Content : root/input-coil/callback.ospp
{
"linkedOutputs": [
{
"outputId": "root.output-coil",
"transform": "not(value)"
}
]
}
1. Push the configuration and check the result¶
git add .
git commit -m "Add simple modbus test"
git push
Check the value of the device :
docker container logs -f modbus-test
Logs must show :
The connexion from `osp-modbus` :
2023-08-14 14:10:48,922 MainThread DEBUG sync :347 Started thread to serve client at ('172.17.0.1', 51850)
2023-08-14 14:10:48,922 Thread-1 DEBUG sync :46 Client Connected [172.17.0.1:51850]
A write request between 0 and 1 on the coil address (each second) :
2023-08-14 14:11:23,922 Thread-1 DEBUG sync :229 send: [ReadBitResponse(1)]- b'003d0000000401010100'
2023-08-14 14:11:23,922 Thread-1 DEBUG sync :199 Handling data: 0x0 0x3e 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0xff 0x0
2023-08-14 14:11:23,923 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x3e 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0xff 0x0
2023-08-14 14:11:23,923 Thread-1 DEBUG factory :137 Factory Request[WriteSingleCoilRequest: 5]
2023-08-14 14:11:23,923 Thread-1 DEBUG context :63 validate: fc-[5] address-1: count-1
2023-08-14 14:11:23,923 Thread-1 DEBUG context :90 setValues[5] 1:1
2023-08-14 14:11:23,923 Thread-1 DEBUG context :77 getValues fc-[5] address-1: count-1
2023-08-14 14:11:23,923 Thread-1 DEBUG sync :229 send: [WriteCoilResponse(0) => 1]- b'003e0000000601050000ff00'
2023-08-14 14:11:24,921 Thread-1 DEBUG sync :199 Handling data: 0x0 0x3f 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x0 0x0 0x1
2023-08-14 14:11:24,922 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x3f 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x0 0x0 0x1
2023-08-14 14:11:24,922 Thread-1 DEBUG factory :137 Factory Request[ReadCoilsRequest: 1]
2023-08-14 14:11:24,922 Thread-1 DEBUG context :63 validate: fc-[1] address-1: count-1
2023-08-14 14:11:24,922 Thread-1 DEBUG context :77 getValues fc-[1] address-1: count-1
2023-08-14 14:11:24,922 Thread-1 DEBUG sync :229 send: [ReadBitResponse(1)]- b'003f0000000401010101'
2023-08-14 14:11:24,923 Thread-1 DEBUG sync :199 Handling data: 0x0 0x40 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0x0 0x0
2023-08-14 14:11:24,923 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x40 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0x0 0x0
2023-08-14 14:11:24,923 Thread-1 DEBUG factory :137 Factory Request[WriteSingleCoilRequest: 5]
2023-08-14 14:11:24,923 Thread-1 DEBUG context :63 validate: fc-[5] address-1: count-1
2023-08-14 14:11:24,923 Thread-1 DEBUG context :90 setValues[5] 1:1
2023-08-14 14:11:24,923 Thread-1 DEBUG context :77 getValues fc-[5] address-1: count-1
2023-08-14 14:11:24,924 Thread-1 DEBUG sync :229 send: [WriteCoilResponse(0) => 0]- b'004000000006010500000000'