Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program

 

Heatmiser EDGE ModBus Thermostat
Heatmiser EDGE ModBus Thermostat

 

Protocol:
EDGE SERIES MODBUS COMMUNICATION PROTOCOL V1.8

Communication protocol:
1. UART Baud Rate: 9600
2. UART Parity: None
3. Communications ID Rang:0-32 ,255

Heatmiser EDGE
The Heatmiser EDGE is 230v powered Thermostat that is compatible with the Heatmiser wireless air sensor and wireless door/window switch. The wireless air sensor function is perfect for those looking to measure the temperature in another location and for those with larger open plan properties, multiple air sensors can be used to create an average temperature.

The Heatmiser EDGE can be set to work as a non programmable, 5/2 day, 7 day or 24 hour programmable thermostat.

230V Powered
Wireless Air Sensor Function
Modbus Network Function

 

Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter
Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter

 

Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter
Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter

 

Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter
Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter

 

Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter
Testing Heatmiser EDGE ModBus Thermostat with ModbusMAT freeware program and KMtronic USB<>RS485 adapter

 

ModbusMAT freeware ModBus program

 

ESP8266: Reading Voltage from SDM120 Modbus Power Energy Meter

 

http://en.trialcommand.com/blog/esp8266-slave-modbus-tcpip-no-libraries/

 

 

/*
 * More Tutorials: 
 * Website http://trialcommand.com
 * In English: http://en.trialcommand.com
 * En Español: http://en.trialcommand.com 
 */
#include <ESP8266WiFi.h>

const char* ssid = "KMTRONIC";
const char* password = "12345678";

// RS485 Control pin
const int RS485_control = D0;

// Receive buffer
long Buffer[9];

int VoltageReadCommand[] ={0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xCB};

int ModbusTCP_port = 502;

//////// Required for Modbus TCP / IP /// Requerido para Modbus TCP/IP /////////
#define maxInputRegister 20
#define maxHoldingRegister 20

#define MB_FC_NONE 0
#define MB_FC_READ_REGISTERS 3 //implemented
#define MB_FC_WRITE_REGISTER 6 //implemented
#define MB_FC_WRITE_MULTIPLE_REGISTERS 16 //implemented
//
// MODBUS Error Codes
//
#define MB_EC_NONE 0
#define MB_EC_ILLEGAL_FUNCTION 1
#define MB_EC_ILLEGAL_DATA_ADDRESS 2
#define MB_EC_ILLEGAL_DATA_VALUE 3
#define MB_EC_SLAVE_DEVICE_FAILURE 4
//
// MODBUS MBAP offsets
//
#define MB_TCP_TID 0
#define MB_TCP_PID 2
#define MB_TCP_LEN 4
#define MB_TCP_UID 6
#define MB_TCP_FUNC 7
#define MB_TCP_REGISTER_START 8
#define MB_TCP_REGISTER_NUMBER 10

byte ByteArray[260];
unsigned int MBHoldingRegister[maxHoldingRegister];

//////////////////////////////////////////////////////////////////////////

WiFiServer MBServer(ModbusTCP_port);

void setup() {

pinMode(14, OUTPUT);

// Set RS485 Control pin to OUTPUT
 pinMode(RS485_control, OUTPUT); 
 
 // Set pin to send data HIGH
 digitalWrite(RS485_control, HIGH);
 
 Serial.begin(2400);
 delay(100) ;
 WiFi.begin(ssid, password);
 delay(100) ;
 Serial.println(".");
 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
 }
 MBServer.begin();
 Serial.println("Connected ");
 Serial.print("ESP8266 Slave Modbus TCP/IP ");
 Serial.print(WiFi.localIP());
 Serial.print(":");
 Serial.println(String(ModbusTCP_port));
 Serial.println("Modbus TCP/IP Online");
 
}


void loop() {

// Check if a client has connected // Modbus TCP/IP
 WiFiClient client = MBServer.available();
 if (!client) {
 return;
 }


 boolean flagClientConnected = 0;
 byte byteFN = MB_FC_NONE;
 int Start;
 int WordDataLength;
 int ByteDataLength;
 int MessageLength;
 
 // Modbus TCP/IP
 while (client.connected()) {
 
 if(client.available())
 {
 flagClientConnected = 1;
 int i = 0;
 while(client.available())
 {
 ByteArray[i] = client.read();
 i++;
 }

client.flush();

///// code here --- codigo aqui

///////// Holding Register [0] A [9] = 10 Holding Registers Escritura
 ///////// Holding Register [0] A [9] = 10 Holding Registers Writing
 
 // Set pin to HIGH > Transmit mode
 digitalWrite(RS485_control, HIGH); 
 
 // Send command to ModBus Meter
 for (int i=0; i < 8; i++) Serial.write(VoltageReadCommand[ i ]);
 delay(50);

// Set pin to LOW > Receive mode
 digitalWrite(RS485_control, LOW);
 
 // Waiting for receive reply
 while ( Serial.available()<9); 
 
 // Read reply in Buffer[];
 for (int i=0; i < 9; i++) Buffer[i] = Serial.read();

// Print voltage data received
 Serial.println();
 Serial.print(Buffer[3], HEX); Serial.print(" ");
 Serial.print(Buffer[4], HEX); Serial.print(" ");
 Serial.print(Buffer[5], HEX); Serial.print(" ");
 Serial.print(Buffer[6], HEX); Serial.print(" "); 
 Serial.println();

// Convert to Float
 float x;
 ((byte*)&x)[3]= Buffer[3];
 ((byte*)&x)[2]= Buffer[4];
 ((byte*)&x)[1]= Buffer[5];
 ((byte*)&x)[0]= Buffer[6];
 
 // Convert to Float
 Serial.print(x,2);
 Serial.println(" Volts");

MBHoldingRegister[0] = word(Buffer[3],Buffer[4]);
 MBHoldingRegister[1] = word(Buffer[5],Buffer[6]);
 MBHoldingRegister[4] = random(0,12);
 MBHoldingRegister[5] = random(0,12);
 MBHoldingRegister[6] = random(0,12);
 MBHoldingRegister[7] = random(0,12);
 MBHoldingRegister[8] = random(0,12);
 MBHoldingRegister[9] = random(0,12);


 ///////// Holding Register [10] A [19] = 10 Holding Registers Lectura
 ///// Holding Register [10] A [19] = 10 Holding Registers Reading
 
 int Temporal[10];
 
 Temporal[0] = MBHoldingRegister[10];
 Temporal[1] = MBHoldingRegister[11];
 Temporal[2] = MBHoldingRegister[12];
 Temporal[3] = MBHoldingRegister[13];
 Temporal[4] = MBHoldingRegister[14];
 Temporal[5] = MBHoldingRegister[15];
 Temporal[6] = MBHoldingRegister[16];
 Temporal[7] = MBHoldingRegister[17];
 Temporal[8] = MBHoldingRegister[18];
 Temporal[9] = MBHoldingRegister[19];

/// Enable Output 14
 digitalWrite(14, MBHoldingRegister[14] );


 //// debug

for (int i = 0; i < 10; i++) {

Serial.print("[");
 Serial.print(i);
 Serial.print("] ");
 Serial.print(Temporal[i]);
 
 }
 Serial.println("");


//// end code - fin 


//// rutine Modbus TCP
 byteFN = ByteArray[MB_TCP_FUNC];
 Start = word(ByteArray[MB_TCP_REGISTER_START],ByteArray[MB_TCP_REGISTER_START+1]);
 WordDataLength = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
 }
 
 // Handle request

switch(byteFN) {
 case MB_FC_NONE:
 break;
 
 case MB_FC_READ_REGISTERS: // 03 Read Holding Registers
 ByteDataLength = WordDataLength * 2;
 ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
 ByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
 for(int i = 0; i < WordDataLength; i++)
 {
 ByteArray[ 9 + i * 2] = highByte(MBHoldingRegister[Start + i]);
 ByteArray[10 + i * 2] = lowByte(MBHoldingRegister[Start + i]);
 }
 MessageLength = ByteDataLength + 9;
 client.write((const uint8_t *)ByteArray,MessageLength);
 
 byteFN = MB_FC_NONE;
 
 break;
 
 
 case MB_FC_WRITE_REGISTER: // 06 Write Holding Register
 MBHoldingRegister[Start] = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
 ByteArray[5] = 6; //Number of bytes after this one.
 MessageLength = 12;
 client.write((const uint8_t *)ByteArray,MessageLength);
 byteFN = MB_FC_NONE;
 break;
 
 case MB_FC_WRITE_MULTIPLE_REGISTERS: //16 Write Holding Registers
 ByteDataLength = WordDataLength * 2;
 ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
 for(int i = 0; i < WordDataLength; i++)
 {
 MBHoldingRegister[Start + i] = word(ByteArray[ 13 + i * 2],ByteArray[14 + i * 2]);
 }
 MessageLength = 12;
 client.write((const uint8_t *)ByteArray,MessageLength); 
 byteFN = MB_FC_NONE;
 
 break;
 }
 }

}

 

 

 

 

 

Reading Voltage from SDM120 Modbus Power Energy Meter using KMtronic TCP<>RS485 bridge via PHP

 

Reading Voltage from SDM120 Modbus Power Energy Meter using TCP<>RS485 bridge via PHP.

Bridge IP : 192.168.1.199

Bridge PORT : 9761

SDM120 Energy Meter Speed: 2400/8/N/1

 

Reading Voltage from SDM120 Modbus Power Energy Meter via TCP<>RS485 bridge via PHP
Reading Voltage from SDM120 Modbus Power Energy Meter via TCP<>RS485 bridge via PHP

 

Reading Voltage from SDM120 Modbus Power Energy Meter via TCP<>RS485 bridge via PHP
Reading Voltage from SDM120 Modbus Power Energy Meter via TCP<>RS485 bridge via PHP

 

PHP file

<?php

function hexTo32Float($strHex) {
 $v = ($strHex);
 $x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
 $exp = ($v >> 23 & 0xFF) - 127;
 return $x * pow(2, $exp - 23);
}

 
$msg = chr(0x01).chr(0x04).chr(0x00).chr(0x00).chr(0x00).chr(0x02).chr(0x71).chr(0xCB);
$len = strlen($msg); 

 
error_reporting(E_ALL);

echo "<h2>TCP/IP Connection</h2>\n";

/* Get the port for the WWW service. */
$service_port = 9761;

/* Get the IP address for the target host. */
$address = gethostbyname('192.168.1.199');

/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
 echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
} else {
 echo "OK.\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
 echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
} else {
 echo "OK.\n";
}


$out = '';

echo "Sending HTTP HEAD request...";
echo socket_sendto($socket, $msg, $len, 0, '192.168.1.199', 9761);
echo "OK.\n";

echo "Reading response:\n\n";
sleep(1);
$out = socket_read($socket, 9761);
 
 $hexstr = unpack('H*', $out);
 $data = array_shift($hexstr);
 $voltage1 = hexdec(substr($data, -6, 2));
 $voltage2 = hexdec(substr($data, -8, 2));
 $voltage3 = hexdec(substr($data, -10, 2));
 $voltage4 = hexdec(substr($data, -12, 2));

$voltage = ((256*256*256*$voltage4) + (256*256*$voltage3) + (256*$voltage2) + $voltage1);

$voltage = round(hexTo32Float($voltage),2);
 echo $voltage . "V";
 echo "\r\n";


echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";

?>

 

Result

kmtronic@ubuntu-sever2:~$ php /var/www/html/for-test/tcp-send-hex.php
<h2>TCP/IP Connection</h2>
OK.
Attempting to connect to '192.168.1.199' on port '9761'...OK.
Sending HTTP HEAD request...8OK.
Reading response:

229.7V
Closing socket...OK.

kmtronic@ubuntu-sever2:~$

 


Din rail meter

“I use this to monitor my solar array. I bought this one specifically because of the bidirectional monitoring and size. Small display but easily readable. Probably does more than I’ll ever use.”  by Doctorxerox