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

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

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

cutehmi.view.2 --extension="CuteHMI.Examples.Modbus.Basic.0"

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

First thing to notice are CuteHMI imports.

import CuteHMI.Modbus 2.0
import CuteHMI.Services 2.0

Example uses CuteHMI.Modbus.2 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