Controlling Belimo Valves

From Open Source Controls Wiki
Jump to navigation Jump to search
Nrmodbusb.png

Belimo valves are one of the most recognised and widely used makes of valve in the HVAC industry.

The libraries on this page provide the tools to control and monitor valves
using the MQTT open controls protocol and Node-RED.


Documents

Modbus Registers

Note that the register number is one more than address.

Operation Registers

Belimo modbus1.png

Service Registers

Belimo modbus2.png

JSON Description

[
    {
        "register": "1",
        "reading": "dat.setpoint",
        "multiplier": "100",
        "datatype": "int16"
    },
    {
        "register": "2",
        "reading": "dat.overrideControl",
        "multiplier": "1",
        "datatype": "int16",
        "values": {
            "0": "none",
            "1": "open",
            "2": "close",
            "3": "min",
            "4": "mid",
            "5": "max"
        }
    },
    {
        "register": "3",
        "reading": "dat.command",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "4",
        "reading": "dat.actuatorType",
        "multiplier": "1",
        "datatype": "int16",
        "values": {
            "0": "Actuator Not Connected",
            "1": "Air / Water",
            "2": "VAV / EPIV",
            "3": "Fire",
            "4": "Energy Valve",
            "5": "6way EPIV"
        }
    },
    {
        "register": "5",
        "reading": "dat.relativePosition",
        "multiplier": "100",
        "datatype": "int16",
        "units": "%"
    },
    {
        "register": "6",
        "reading": "dat.absolutePosition",
        "multiplier": "1",
        "datatype": "int16",
        "units": "mm"
    },
    {
        "register": "6",
        "reading": "dat.sensorValue1",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "13",
        "reading": "dat.setpointAnalogue",
        "multiplier": "100",
        "datatype": "int16",
        "units": "%"
    },
    {
        "register": "100",
        "reading": "settings.busTermination",
        "multiplier": "1",
        "datatype": "int16",
        "values": {
            "0": "inactive",
            "1": "active"
        }
    },
    {
        "register": "101",
        "reading": "stat.seriesNumberPart1",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "102",
        "reading": "stat.seriesNumberPart2",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "103",
        "reading": "stat.seriesNumberPart3",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "104",
        "reading": "stat.firmwareVirsion",
        "multiplier": "1",
        "datatype": "int16"
    },
    {
        "register": "106",
        "reading": "settings.min",
        "multiplier": "100",
        "datatype": "int16",
        "units": "%"
    },
    {
        "register": "107",
        "reading": "settings.max",
        "multiplier": "100",
        "datatype": "int16",
        "units": "%"
    },
    {
        "register": "108",
        "reading": "settings.sensorType1",
        "multiplier": "1",
        "datatype": "int16",
        "values": {
            "0": "None",
            "1": "Active / Hybrid",
            "2": "Passive_1K",
            "3": "Passive_20K",
            "4": "Switch",
            "5": "PT1000_C",
            "6": "NI1000_C",
            "7": "NTC10K_C",
            "8": "PT1000_F",
            "9": "NI1000_F",
            "10": "NTC10K_F"
        }
    },
    {
        "register": "109",
        "reading": "settings.busFailPosition",
        "multiplier": "1",
        "datatype": "int16",
        "values": {
            "0": "None / Last setpoint",
            "1": "Fast close",
            "2": "Fast open",
            "3": "Mid position"
        }
    },
    {
        "register": "110",
        "reading": "settings.watchdogTimeout",
        "multiplier": "1",
        "datatype": "int16",
        "units": "s"
    }
]

Wiring

R24amod.png

Connecting via FTDI Cable

Ftdicable.jpg

A USB-FTDI RS485 cable can be used to connect to the actuator Modbus from a system with USB ports.

FTDI -> Actuator
Orange -> Grey [7]
Yellow -> Pink [6]
Black  -> Not Connected

Serial Settings

Belmodser.png

Example Commands

Read Modbus Setpoint

As an example, to read the Setpoint requires sending to the device (1 default) a FC3 read command (3) calling for register 1 (0 0), requesting a single value (0 1), ending with the CRC (Cyclic Redundancy Check).

In modbus the following characters would be sent to the valve over RS485 (shown in decimal and hex):

dec: [ 1, 3, 0, 0, 0, 1, 132, 10 ]  hex: [0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0a]

Read Analogue Setpoint

The analogue setpoint register (13) is different from the Modbus setpoint (1). Register 119 (Sepoint Selection) choses which is valid.

dec: [ 1, 3, 0, 12, 0, 1, 68, 9 ]

When reading the analogue setpoint, note that analogue values less than 2v will result in unreadable values (65030+). The valve will still be closed.

Set to Modbus Control

dec: [ 1, 6, 0, 118, 0, 1, 169, 208 ]

Set to Analogue Control

dec:  [ 1, 6, 0, 118, 0, 0, 104, 16 ]

Open Valve 100%

dec: [ 1, 6, 0, 0, 39, 16, 147, 246 ]

Close Valve

dec: [ 1, 6, 0, 0, 0, 0, 137, 202 ]

Simple Control

For very simple control or setup, Modbus messages can be directly injected to the serial connection as a buffer, including the CRC.

For example, to fully open the valve to 100% setpoint, the inject node would be setup as follows.

Injectbuffer.png

Injectbufferset.png


Import this example into Node-RED:

[{"id":"748c3615.f4aed8","type":"serial out","z":"9f18bf08.c2a65","name":"","serial":"b8be9e6d.b7861","x":2010,"y":200,"wires":[]},{"id":"973c444f7e178e38","type":"inject","z":"9f18bf08.c2a65","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[1,6,0,0,39,16,147,246]","payloadType":"bin","x":1850,"y":200,"wires":[["748c3615.f4aed8"]]},{"id":"b8be9e6d.b7861","type":"serial-port","serialport":"/dev/ttyAMA0","serialbaud":"38400","databits":"8","parity":"none","stopbits":"2","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"50","bin":"bin","out":"time","addchar":"","responsetimeout":"10000"}]

This method is rarely used as it requires one to generate CRC codes in advance.

CRC Calculation

A Cyclic Redundancy Check is a value at the end of a Modbus message that is calculated from the message and can be used to check that received message is uncorrupted.

The following function takes a buffer as an input. For example, in the Close Valve example above, the input is [ 1, 6, 0, 0, 0, 0 ] and the calculated crc value is [137, 202 ].

function crc16(buffer) {

    var crc = 0xFFFF;
    var odd;

    for (var i = 0; i < buffer.length; i++) {
        crc = crc ^ buffer[i];

        for (var j = 0; j < 8; j++) {
            odd = crc & 0x0001;
            crc = crc >> 1;
            if (odd) {
                crc = crc ^ 0xA001;
            }
        }
    }

    crc  = "0000" + crc.toString(16);
    crc = crc.substr(-4);

    return crc;
}

FC3 Read and FC6 Write Register Functions

The following function can be used to read values using FC3 command, and to write values using FC£ command, using pure JavaScript.

It takes an input msg as follows:

msg.payload = { fc:3, address:1, register:1, rlength:1 };   // Read FC3
msg.payload = { fc:6, address:1, register:1, rlength:1, targetv:5000 };   // Write FC6
var address = msg.payload.address || msg.address ||8;
var fc = msg.payload.fc || msg.fc || 3;
var register = msg.payload.register || msg.register || 1;
var rlength = msg.payload.rlength || msg.rlength || 1;
var targetv = msg.targetv; 
 
register = register - 1;  // offset 

var r1 = Math.floor(register / 256);
var r2 = register % 256;


if (fc == 3) {   // Read FC3
    
    var tosend = String.fromCharCode(devAddress) + String.fromCharCode(3);
    tosend += String.fromCharCode(r1) + String.fromCharCode(r2);
    tosend += String.fromCharCode(0) + String.fromCharCode(rlength);
    
    var crcString = crc16(Buffer.from(tosend, 'ascii'));
    tosend += String.fromCharCode(parseInt(crcString.substr(2,2),16)) + String.fromCharCode(parseInt(crcString.substr(0,2),16));    
    msg.payload  = Buffer.from(tosend, 'ascii');    
    
    return msg;


} else if (fc == 6 ) {     // Write FC6


    tosend = String.fromCharCode(address) + String.fromCharCode(6);    
    tosend += String.fromCharCode(r1) + String.fromCharCode(r2);
    
    targetv = parseInt(targetv);
    var hexStringValue  = "0000" + targetv.toString(16);
    hexStringValue = hexStringValue.substr(-4);        
    tosend += String.fromCharCode(parseInt(hexStringValue.substr(0,2),16)) + String.fromCharCode(parseInt(hexStringValue.substr(2,2),16));
        
    crcString = crc16(Buffer.from(tosend, 'ascii'));   
    tosend += String.fromCharCode(parseInt(crcString.substr(2,2),16)) + String.fromCharCode(parseInt(crcString.substr(0,2),16));          
    msg.payload  = Buffer.from(tosend, 'ascii');    
    
    return msg;


} else  { return null; }

Control Modes

Modbus register 119 is used to set the control mode: 0: Analog 1: Modbus (see example commands).

Modbus Control

The valve setpoint is controlled through register 1.

Analogue Control

The valve setpoint is controlled through the analogue input connection using a 2-10v signal.

Analogue Hybrid Mode

Refers to analogue control with Modbus connected for additional functions.