As you can see, the sketch in my previous post is not very efficient, as it needs to repeat several blocks of code with slight changes.
With a little help from my son, who suggested using an array of modbusmaster instances (we weren’t sure it was going to work, but it did!), I rewrote the code which is now shorter, with a more “elegant” approach to using several sensors, very easy to “escalate” in case more sensors are added.
I also simplified Key’s code (the base for this one, which had some remains of former experiments, vars, and libraries that weren’t needed) and also eliminated the need for “settingsPZEM.h”.
// #include <ArduinoOTA.h> //not used
#include <BlynkSimpleEsp8266.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
SoftwareSerial pzem(D5,D6); // (RX,TX) connect to TX,RX of PZEM for NodeMCU
//SoftwareSerial pzem(D7,D8); // (RX,TX) connect to TX,RX of PZEM
#include <ModbusMaster.h>
// instantiate ModbusMaster objects
ModbusMaster node[3];
BlynkTimer timer;
//WiFi data
char ssid[] = "*********"; //WiFi Credential
char pass[] = "**********"; //WiFi Password
// Server data
char server[] = "192.168.1.XXX"; //Blynk local server IP address
int port = 8080; //Blynk local port
#define USE_LOCAL_SERVER //Use local Blynk Server - comment-out if use Blynk hosted cloud service
#define AUTH "******************************" //PZEM-004v3 Auth code for 192.168.1.XXX:9443 (gmail)
// #define OTA_HOSTNAME "PZEM-004v3" // Brought from settingsPZEM.h, not needed
// Vars for reading PZEM's output
float U_PR[3], I_PR[3], P_PR[3], E_PR[3], F_PR[3], PF_PR[3]; bool AL_PR[3];
uint8_t result;
void setup(){
// Flash LED on start
pinMode(LED_BUILTIN, OUTPUT);
for (int i = 0; i < 6 ; i++){
Serial.println("LED on");
digitalWrite(LED_BUILTIN, LOW);
delay(200);
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("LED off");
delay(200);
}
// End LED flash
//Initialize serial ports and Modbus nodes
Serial.begin(74880); Serial.println("Start serial");
pzem.begin(9600); Serial.println("Start PZEM serial");
node[0].begin(1, pzem); Serial.println("Start PZEM 1"); // 1 = ID MODBUS, pzem = soft serial port previously defined
node[1].begin(2, pzem); Serial.println("Start PZEM 2"); // 2 = ID MODBUS
node[2].begin(3, pzem); Serial.println("Start PZEM 3"); // 3 = ID MODBUS
//Wifi and server connect
WiFi.mode(WIFI_STA);
#if defined(USE_LOCAL_SERVER)
Serial.println("Connecting to WiFi");
WiFi.begin(ssid, pass);
Serial.println("Connecting local Blync server");
Blynk.config(AUTH, server, port);
#else
Serial.println("Connecting to WiFi and Blynk");
Blynk.begin(AUTH, ssid, pass);
#endif
while (Blynk.connect() == false) {}
Serial.println("Connected!");
// ArduinoOTA.setHostname(OTA_HOSTNAME);
// ArduinoOTA.begin();
// timerTask1 = timer.setInterval(1000, updateBlynk);
} //end Setup
void updateBlynk() { // Write values to Blynk's virtual pins
for (int i=0; i<3; i++){
//Write to Blynk virtual pins
Blynk.virtualWrite(7*i, U_PR[i]); // Write voltage to V0, V7, V14
Blynk.virtualWrite(7*i+1, I_PR[i]); // Write current to V1, V8, V15
Blynk.virtualWrite(7*i+2, P_PR[i]); // Write active power to V2, V9, V16
Blynk.virtualWrite(7*i+3, E_PR[i]); // Write active energy to V3, V10, V17
Blynk.virtualWrite(7*i+4, F_PR[i]); // Write frequency to V4, V11, V18
Blynk.virtualWrite(7*i+5, PF_PR[i]); // Write power factor to V5, V12, V19
Blynk.virtualWrite(7*i+6, AL_PR[i]); // Write alarm status to V6, V13, V20
}
} //End updateBlynk()
void loop(){
Serial.println("Starting loop");
Blynk.run();
//ArduinoOTA.handle();
for (int i=0; i<3; i++){
result = node[i].readInputRegisters(0x0000, 10); // leer 10 registros comenzando en el 0
if (result == node[i].ku8MBSuccess) {
U_PR[i] = (node[i].getResponseBuffer(0x00)/10.0f);
I_PR[i] = ((node[i].getResponseBuffer(0x01) + (node[i].getResponseBuffer(0x02)*65532))/1000.000f);
P_PR[i] = ((node[i].getResponseBuffer(0x03) + (node[i].getResponseBuffer(0x04)*65532))/10.0f);
E_PR[i] = ((node[i].getResponseBuffer(0x05) + (node[i].getResponseBuffer(0x06)*65532))/1000.0f);
F_PR[i] = (node[i].getResponseBuffer(0x07)/10.0f);
PF_PR[i] = (node[i].getResponseBuffer(0x08)/100.0f);
AL_PR[i] = (node[i].getResponseBuffer(0x09));
Serial.print("Node "); Serial.print(i+1); Serial.println(" OK LED on");
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Voltage "); Serial.print(U_PR[i]); Serial.println(" V"); // V
Serial.print("Current "); Serial.print(I_PR[i],3); Serial.println(" A"); // A
Serial.print("Active power "); Serial.print(P_PR[i]); Serial.println(" W"); // W
Serial.print("Energy "); Serial.print(E_PR[i],3); Serial.println(" kWh");// kWh
Serial.print("Frequency "); Serial.print(F_PR[i]); Serial.println(" Hz"); // Hz
Serial.print("Power factor "); Serial.print(PF_PR[i]); Serial.println(); // FP
Serial.print("Alarm "); Serial.print(AL_PR[i]); Serial.println(); // Alarm
delay(200);
Serial.print("Node "); Serial.print(i+1); Serial.println(" LED off");
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("====================================================");
}
else{
U_PR[i] = 0;
I_PR[i] = 0;
P_PR[i] = 0;
// E_PR[i] = 0; //If PZEM cannot be read (lost of power), last energy would be better aproximation than zero
F_PR[i] = 0;
PF_PR[i] = 0;
AL_PR[i] = 0;
Serial.print("Node "); Serial.print(i+1); Serial.println(" ERROR");
Serial.println("====================================================");
}
delay(200);
}
updateBlynk();
}