I am using a ESP8266/NodeMCU controller to monitor DC voltage and current of a battery via Modbus. It is being logged using Telegraph into an Influx database on a Raspberry Pi. The code is below. It works fantastic for weeks at a time. The only problem I have is when I need to reboot the raspberry Pi the connection is lost. To fix it all I have to do is reboot the NodeMCU which is a bit of a hassle to get to based on where I have it physically located.
Is there some code I can add that could reset the connection without me having to intervene?
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Import required libraries
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Ticker.h>
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
ModbusMaster node;
SoftwareSerial mySerial(D1, D2); // RX, TX
/*************************************************************
Modbus Definitions
*************************************************************/
#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];
int ModbusTCP_port = 502;
int voltage;
int current;
int power;
int energy;
WiFiServer MBServer(ModbusTCP_port);
Ticker MeterReadTimer;
// Replace with your network credentials
const char* ssid = "********";
const char* password = "***********";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Replaces placeholders with values
String processor(const String& var){
if(var == "VOLTAGE"){
return String(voltage);
}
else if (var == "CURRENT"){
return String(current);
}
else if (var == "POWER"){
return String(power);
}
else if (var == "ENERGY"){
return String(energy);
}
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
mySerial.begin(9600);
// Modbus slave ID 1
node.begin(1, mySerial);
MeterReadTimer.attach(1, getMeterReadings);
// Initialize SPIFFS
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
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");
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Route to load style.css file
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/style.css", "text/css");
});
server.on("/voltage", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(voltage).c_str());
});
server.on("/current", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(current).c_str());
});
server.on("/power", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(power).c_str());
});
server.on("/energy", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(energy).c_str());
});
// Start server
server.begin();
}
void getMeterReadings()
{
uint8_t result;
node.clearResponseBuffer();
result = node.readInputRegisters(0x00000,6);
if (result == node.ku8MBSuccess)
{
voltage = node.getResponseBuffer(0); //1LSB = 0.01V
current = node.getResponseBuffer(1); //1LSB = 0.01A
power = (node.getResponseBuffer(2)*256) + node.getResponseBuffer(3); //Merging two registers 1LSB = 0.1W
energy = (node.getResponseBuffer(4)*256) + node.getResponseBuffer(5); //Merging two registers 1LSB = 1Wh
}
if(result==node.ku8MBResponseTimedOut)
{
Serial.println("Inside Timeout block ");
}
if(result==node.ku8MBInvalidCRC)
{
Serial.println("Inside ku8MBInvalidCRC block ");
}
if(result==node.ku8MBInvalidFunction)
{
Serial.println("Inside ku8MBInvalidFunction block ");
}
if(result==node.ku8MBInvalidSlaveID)
{
Serial.println("Inside ku8MBInvalidFunction block ");
}
if(result==node.ku8MBSlaveDeviceFailure)
{
Serial.println("Inside ku8MBSlaveDeviceFailure block ");
}
if(result==node.ku8MBIllegalDataValue)
{
Serial.println("Inside ku8MBIllegalDataValue block ");
}
}
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
MBHoldingRegister[0] = voltage;
MBHoldingRegister[1] = current;
MBHoldingRegister[2] = power;
MBHoldingRegister[3] = energy;
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;
}
}
}