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;
 }
 }

}

 

 

 

 

 

Add temperature sensor in Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor

KMtronic LAN DS18B20 WEB Temperature Monitor

 

Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor
Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor

 

Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor
Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor

 

Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor
Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor

 

 

Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor
Domoticz: KMtronic LAN DS18B20 WEB Temperature Monitor

 

 

LOG file

 

2018-04-02 14:13:12.546 (KMtronic DS18B20 Temperature Monitor) Temp (Boiler)
2018-04-02 14:13:12.547 (KMtronic DS18B20 Temperature Monitor) Temp (Office 1)
2018-04-02 14:13:12.548 (KMtronic DS18B20 Temperature Monitor) Temp (Office 2)
2018-04-02 14:13:12.549 (KMtronic DS18B20 Temperature Monitor) Temp (Store)

 

PHP receive script for KMTronic DS1820 LAN POST version module

 

Receive POST data using PHP

KMtronic LAN DS18B20 Temperature Monitor

 

 

LAN DS18B20 High-Precision 1-Wire Digital Temperature Monitor

 


 

PHP file:

<?php


$date = date('Ymd');
$time = date('H:i:s');
$hourtime = date('H:i');
$unixtime = time();

$file = "/var/www/html/data/".$date.".log";
$current = file_get_contents($file);

$current .= $date;
$current .= "-";
$current .= $time;
$current .= "\t";
$current .= $unixtime;
$current .= "\t";

$temp = $_POST['temperature'];

$temp2 = implode("",$_POST['temperature']);

$current .=  $temp2;
$current .= "\r\n";

// Write the contents back to the file
file_put_contents($file, $current);

// a:2:{s:9:"device_id";s:10:"B3D53A5348";s:11:"temperature";a:1:{s:18:"'2874EDD0040000F3'";s:5:"15.43";}}

?>

 


 

DATA file:
20161229-00:00:21    1482962421    22.75
20161229-00:00:56    1482962456    22.75
20161229-00:01:30    1482962490    22.75
20161229-00:02:04    1482962524    22.75
20161229-00:02:38    1482962558    22.75
20161229-00:03:12    1482962592    22.75
20161229-00:03:46    1482962626    22.75
20161229-00:04:20    1482962660    22.75
20161229-00:04:54    1482962694    22.75
20161229-00:05:28    1482962728    22.81
20161229-00:06:02    1482962762    22.81




 

 

 

Create a Crontab server side PHP script for uploading temperature to a MySQL database

 

KMtronic LAN DS18B20 WEB 1-Wire Digital Temperature Monitor
KMtronic LAN DS18B20 WEB 1-Wire Digital Temperature Monitor

 


 

Temperature Monitor STATUS XML data

http://XXX.XXX.XXX.XXX/status.xml
XXX.XXX.XXX.XXX is IP ADDRESS Temperature monitor

 


 

MySQL table

Create a Crontab server side PHP script for uploading temperature to a MySQL database
Create a Crontab server side PHP script for uploading temperature to a MySQL database
Create a Crontab server side PHP script for uploading temperature to a MySQL database
Create a Crontab server side PHP script for uploading temperature to a MySQL database

 


 

Cron is a system daemon used to execute desired tasks (in the background) at designated times. 

A crontab file is a simple text file containing a list of commands meant to be run at specified times. It is edited using the crontab command. The commands in the crontab file (and their run times) are checked by the cron daemon, which executes them in the system background.

Crontab PHP file:

<?php

$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "temperature_database";


// Loading the XML file
$xml = simplexml_load_file("http://XXX.XXX.XXX.XXX/status.xml");
// XXX.XXX.XXX.XXX is IP ADDRESS Temperature monitor

foreach($xml->children() as $sensor)
 {
  if ($sensor->id == "2874EDD0040000F3" )
  {
  $temp_value = $sensor->temp;
  }
 }
// "2874EDD0040000F3" is ID DS18B20 sensor

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
 die("Connection failed: " . $conn->connect_error);
}

$sql = "INSERT INTO km_temperature (temp_id, temp_value, temp_time )
VALUES ('2874EDD0040000F3', $temp_value , NOW())";
// "km_temperature" is TABLE name


if ($conn->query($sql) === TRUE) {
 echo "New record created successfully";
} else {
 echo "Error: " . $sql . "<br>" . $conn->error;
}

$conn->close();

?>