CuteHMI - Basic Modbus Example (CuteHMI.Examples.Modbus.Basic.2)
Basic Modbus Example

Baisc Modbus example. Example demonstrates basic usage of QML components provided by CuteHMI.Modbus.3 extension.

To run the example use cutehmi.view.4 tool.

cutehmi.view.4 CuteHMI.Examples.Modbus.Basic.0

Let's make a quick tour over View.qml file.

First thing to notice are CuteHMI imports.

import CuteHMI.Modbus 3.0
import CuteHMI.Services 2.0

Example uses CuteHMI.Modbus.3 and CuteHMI.Services.2 extensions.

Next thing to notice is a configuration of a Modbus server. The server is given an IP address, a port and a slave address.

TCPServer {
id: server
host: "127.0.0.1"
port: 50002
slaveAddress: 1
}

Similarly we configure Modbus client.

TCPClient {
id: client
host: "127.0.0.1"
port: 50002
slaveAddress: 1
}

We want our server to be managed by CuteHMI.Services.ServiceManager, so that we don't need to worry about its connection status. This is simply done by embedding it inside CuteHMI.Services.Service component.

Service {
id: serverService
name: "TCP Server"
TCPServer {
id: server
host: "127.0.0.1"
port: 50002
slaveAddress: 1
}
}

Similarly we want the client to be turned into a service. Outside a service client would not perform polling, handle connection errors and so on.

Service {
id: clientService
name: "TCP Client"
TCPClient {
id: client
host: "127.0.0.1"
port: 50002
slaveAddress: 1
}
}

As the client and the server are configured we can move on to establishing some interaction between them. Let's create a button that will tell the client to send a request to turn on a coil.

Button {
text: "Client set coil"
onClicked: client.requestWriteCoil(10, true)
}

Once the button is clicked it will send a request to write coil value at address 10. This may look suspicious on a localhost, but the whole communication is done over TCP/IP protocol. Now let's reset coil value to off on the server side.

Button {
text: "Server reset coil"
onClicked: server.requestWriteCoil(10, false)
}

Now let's introduce CuteHMI.Modbus.CoilController. Controllers typically are a better mean of control as they allow for property binding.

CoilController {
id: coilController
device: client
address: 10
onValueChanged: coilSwitch.checked = value
}

We assign a device using id of of the client. We also set up the same address as used by buttons. We use onValueChanged signal handler to update value of a corresponding switch once the value in the controller changes. The switch itself updates the value of a controller once the user changes its value.

onCheckedChanged: coilController.value = checked

Value of the coil can be binded to other properties as it is done with active property of status indicator.

active: coilController.value

The same procedure is repeated for a holding register, of course using different set of controls - adequate to holding register 16 bit integer capacity.

Button {
text: "Client set holding register"
onClicked: client.requestWriteHoldingRegister(10, 2020)
}
Button {
text: "Server reset holding register"
onClicked: server.requestWriteHoldingRegister(10, 0)
}
SpinBox {
id: holdingRegisterSpinBox
from: 0
to: 10000
value: holdingRegisterController.value
onValueChanged: holdingRegisterController.value = value
HoldingRegisterController {
id: holdingRegisterController
device: client
address: 10
onValueChanged: holdingRegisterSpinBox.value = value
}
}
Label {
text: holdingRegisterController.value
}

Last, but not least. We start the services by calling CuteHMI.Services.ServiceManager.start() slot.

Component.onCompleted: ServiceManager.start()
CuteHMI::Modbus
CuteHMI
CuteHMI::Services