Modbus Driver
Modbus is a data communications protocol originally published by Modicon (now Schneider Electric) in 1979 for use with its programmable logic controllers (PLCs). Modbus has become a de facto standard communication protocol and is now a commonly available means of connecting industrial electronic devices.
Modbus is popular in industrial environments because it is openly published and royalty-free. It was developed for industrial applications, is relatively easy to deploy and maintain compared to other standards, and places few restrictions on the format of the data to be transmitted.
Requirements
Since Modbus is a client/server (formerly master/slave) protocol, the client node must routinely poll each field device and look for changes in the data.
The Core Services of the Edge Compute Platform need to have been installed.
- ase-modbus-driver
These services can be deployed by adding the "App - ECP Modbus Driver" application from the Marketplace to your own space (see "Edge Ops > Studio > Marketplace").
Objective
The goal is to create a "Modbus device driver" to communicate with modbus server devices to control and gather telemetry. Only Modbus TCP/IP version is considered for implementation.
Details
- Coil (Read-write, 1 bit)
- Discrete input (Read-only, 1 bit)
- Input register (Read-only, 16 bits)
- Holding register (Read-write, 16 bits)
Each type has its own address space (0-0xFFFF). Server can have coil and input register with the same address. User should know available objects and their meaning for specific server. More complex data types (float, int32) can be built on top of registers and it is next level responsibility to handle/display it properly.
Thing Description
{ "@type": [ "swx:MBSlave" ], "id": "/things/mb_slave1", "title": "Modbus server #1", "properties": { "ip": { "title": "IP address", "description": "Device (slave) IP address", "type": "string", "readOnly": false }, "port": { "title": "Port", "description": "Device (listening) port", "type": "integer", "minimum": 1, "maximum": 65525, "readOnly": false }, "slaveid": { "title": "Slave Id", "description": "Id of slave device (may be omitted for TCP)", "type": "integer", "minimum": 1, "maximum": 65535, "readOnly": false }, "pollperiod": { "title": "Poll Period", "description": "Data will be retrieved every <pollperiod> seconds, 0 - disabled", "type": "integer", "minimum": 0, "maximum": 7200, "readOnly": false }, "input-status,1": { "title": "Input Conatct", "description": "Binary input (addr=1)", "type": "integer", "minimum": 0, "maximum": 1, "readOnly": true }, "coil,1": { "title": "Output Coil", "description": "Binary output (addr=1)", "type": "integer", "minimum": 0, "maximum": 1, "readOnly": false }, "input-register,33": { "title": "Input Register", "description": "Input register (addr=33)", "type": "integer", "minimum": 0, "maximum": 65535, "readOnly": true }, "holding-register,44": { "title": "Output register", "description": "Output register (addr=44)", "type": "integer", "minimum": 0, "maximum": 65535, "readOnly": false } }, "actions": { "readvalue": { "title": "Read Value", "description": "Reads input/output coil/register value at address <address>", "input": { "@type": "ValueAddress", "type": "object", "properties": { "address": { "type": "integer", "minimum": 0, "maximum": 65535 }, "type": { "type": "string" } } } } } }
Important properties that define modbus server are: ip, port - IP address and port of modbus server. slaveid can be used if server requires it (mostly ignored in case of modbus TCP/IP).
pollinterval allows periodically poll data for each data object (global property, not per data object). If value is 0 - polling is disabled, the only way to get the value is readvalue action.
The rest of the properties represent modbus objects available on the server.
Property name looks like <type>,<address>, (for example "coil,123" ).
- input-status - discrete input
- coil - output coil
- input-register
- holding-register
- address - any from 0-65535 range
Since data can be only acquired by polling, readvalue action is implemented for reading. Example of parameters (type, address limitations are the same as for property name):
{ "readvalue": { "input": { "type": "coil", "address": 1 } } }
Extended Functionality of the Modbus Driver
Standard Modbus uses IEC 61131 addressing where only 16-bit registers are used. Installers can choose to use the 16-bit addresses to store 1-bit ("bool") and 32-bit ("real") variables as described below.
In case a single bit of a 16-bit register is used like a "bool" variable; these are stored in one of the 16 bit areas of the 16-bit "word memory" address.
In case two 16-bit registers are combined into a 32-bit "real" variable; these are stored in two consecutive 16-bit "word memory" addresses which are combined using "little endian" ordering.
For these two cases, new "types" have been introduced:
- bit-register - which is used in property names with the bit area appended, for example "bit-register,141,10"
- real-register – which is used in property names with the first address only, the second one is assumed consecutive, for example "real-register,240"