Skip to content
JamesNewton edited this page Jun 4, 2020 · 17 revisions

There are two ways to connect to a ModBus device: Serial and TCP. In either case, the protocol needs to be processed via an NPM Module which can be integrated into the DDE Job Engine and which has been added to DDE for the PC as of version 3.5.7 (Note: This is a BETA version).

Module

If your job engine doesn't already have it, you will need to install support for ModBus protocol into Dexter. We have tested the modbus-serial NPM package. Despite the name, modbus-serial supports both serial and TCP connections.

You can do this directly if Dexter is connected to the internet by SSHing into Dexter and then:

cd /root/Documents/dde
npm install modbus-serial

Note: The install will take a while.

If your Dexter is NOT directly connected to your PC and does not have ModBus installed, you can try to install it locally, and then copy the files over into the node_modules folder and trigger the make in the node_modules/modbus-serial/node_modules/@serialport/bindings/build folder. This is not well documented. Hopefully you can get an updated image with the ModBus support pre-installed, or connect your Dexter to the internet for this process.

Once the module is installed, you can use it via node.js. Examples are found here:
https://github.com/yaacov/node-modbus-serial/tree/master/examples

Job Engine Support

To access the new module from DDE jobs, until support is built in, we need to update the core files SSHing into Dexter and then:

cd /root/Documents/dde
nano core/index.js

Scroll down to the global. section near the end and add the line:
var ModbusRTU = require("modbus-serial") after the last var line above the global section, then below the other globals, add:
global.ModbusRTU = ModbusRTU

After this change, any of the methods allowed by the library should be available in a DDE job via the ModbusRTU object.

ModBus TCP

To access network modbus devices (other than you own PC), your Dexter will need to be connected to the network.

//var ModbusRTU = require("modbus-serial") //for node.js, not needed in DDE
var client = new ModbusRTU();
var plc = "192.168.1.24"; //change to the address of the remote device.

// open connection to remote device
client.connectTCP(plc, { port: 8502 })
    .then(setClient)
    .then(function() {
        console.log("Connected"); })
    .catch(function(e) {
        console.log(e.message); });

function setClient() {
    // set the client's unit id
    client.setID(1); //change to the correct unit id
    // set a timeout for requests default is null (no timeout)
    client.setTimeout(1000);
    // run program
    run();
}

function run() {
    // write to coil
    client.writeCoil(5, true)
        .then(function(d) {
            console.log("Write true to coil 5", d); })
        .catch(function(e) {
            console.log(e.message); })
        .then(writeRegisters);
}

function writeRegisters() {
    // write 3 registers statrting at register 101
    // negative values (< 0) have to add 65535 for Modbus registers
    client.writeRegisters(101, [10, 9, 8, -20 + 65535, -10 + 65535])
        .then(function(d) {
            console.log("Write 10, 9, 8, -20, -10 to registers 101 to 105", d); })
        .catch(function(e) {
            console.log(e.message); })
        .then(close);
}

function close() {
    client.close();
}

A more extensive example is available.

A good tool for this is QModMaster which can simulate a ModBus master and allow you to send test messages.

When working with ModBusTCP, it would be best for Dexter to be listening for a message all the time, and to start a job if a new message is recieved. This ability will be integrated into the onboard node web server in time. See Issue 34 for progress.

ModBus Serial

Of course, accessing a serial modbus device requires a serial adapter, either one with built in RS485 support 1, or standard serial unit 1, 2, 3 with a TTL to RS485 adapter 1. USB adapters based on the CP2102 or CP2104 are known to work with Dexter.

See Dexter-Serial-Peripherals for installation, testing and troubleshooting of serial adapters in general.

This example job connects to a serial adapter at /dev/ttyUSB0 and once the connection is established, it turns on the relay coil, reads the switch input and then turns off the relay. It uses a device address of 0 which seems to work with the standard cheap chinese modbus devices^.

const serial_path = "/dev/ttyUSB0"
const client_id = 0;
const coil_no = 0;

// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();

// open connection to a serial port, then callback write
client.connectRTUBuffered(serial_path, { baudRate: 9600 }, write);

//connection open, set client address and write
function write() {
    client.setID(client_id);

    // write the value to the coil
    client.writeCoil(coil_no, 1)
        .then(read) //promise to read
    console.log("write done");
    return
    }

function read() {
    // read the register
    client.readHoldingRegisters(0,1)
        .then(function(data){
                console.log(data)
                client.writeCoil(coil_no, 0)
                    .then(finish)
                });
    }

function finish() {
        client.close()
        console.log("finished")
        }

Clone this wiki locally