Modbus master/slave failed to read

Hi, I try to use modbus master/slave but it seem that it fail to read the modbus. There is only one time that it succeed to read the modbus.
this is my coding

#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>

////////////Blynk Virtual Pin Assignment
 
#define vPIN_VOLTAGE_1                V11
#define vPIN_CURRENT_USAGE_1          V12
#define vPIN_ACTIVE_POWER_1           V13
#define vPIN_ACTIVE_ENERGY_1          V14
#define vPIN_FREQUENCY_1              V15
#define vPIN_POWER_FACTOR_1           V16
#define vPIN_OVER_POWER_ALARM_1       V17

#define vPIN_VOLTAGE_2                V21
#define vPIN_CURRENT_USAGE_2          V22
#define vPIN_ACTIVE_POWER_2           V23
#define vPIN_ACTIVE_ENERGY_2          V24
#define vPIN_FREQUENCY_2              V25
#define vPIN_POWER_FACTOR_2           V26
#define vPIN_OVER_POWER_ALARM_2       V27

////////////Blynk Virtual Pin Assignment End


/////////SET PIN

#include <SoftwareSerial.h>  //  ( NODEMCU ESP8266 )
SoftwareSerial pzemSerial(D5, D6); // (RX,TX) NodeMCU connect to (TX,RX) of PZEM 

////////

static uint8_t pzemSlave1Addr = 0x01; 
static uint8_t pzemSlave2Addr = 0x02;

ModbusMaster node1;
ModbusMaster node2;

BlynkTimer timer;

double voltage_usage_1 = 0; 
double current_usage_1 = 0;
double active_power_1 = 0;
double active_energy_1 = 0;
double frequency_1 = 0;
double power_factor_1 = 0; 
double over_power_alarm_1 = 0;
 
double voltage_usage_2 = 0;
double current_usage_2 = 0;
double active_power_2 = 0;
double active_energy_2 = 0;
double frequency_2 = 0;
double power_factor_2 = 0; 
double over_power_alarm_2 = 0;

#define BLYNK_AUTH_TOKEN ""  //Enter your blynk auth token

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "";  //Enter your WIFi name
char pass[] = "";  //Enter your WIFI password

void setup() {
  Serial.begin(115200);
  WiFi.setSleepMode(WIFI_NONE_SLEEP);

  pzemSerial.begin(9600);

  //// start Modbus/RS-485 serial communication
  node1.begin(pzemSlave1Addr, pzemSerial);
  node2.begin(pzemSlave2Addr, pzemSerial);
   
  //changeAddress(0x01, 0x03);  //uncomment to set pzem address. You can press reset button on nodemcu if this function is not called

  //resetEnergy(0x01);

  Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);

  timer.setInterval(10000L, sendtoBlynk); // send values blynk server every 10 sec

  //delay(1000);

}

void sendtoBlynk() {
          
  Blynk.virtualWrite(vPIN_VOLTAGE_1,               voltage_usage_1);
  Blynk.virtualWrite(vPIN_CURRENT_USAGE_1,         current_usage_1);
  Blynk.virtualWrite(vPIN_ACTIVE_POWER_1,          active_power_1);
  Blynk.virtualWrite(vPIN_ACTIVE_ENERGY_1,         active_energy_1);
  Blynk.virtualWrite(vPIN_FREQUENCY_1,             frequency_1);
  Blynk.virtualWrite(vPIN_POWER_FACTOR_1,          power_factor_1);
  Blynk.virtualWrite(vPIN_OVER_POWER_ALARM_1,      over_power_alarm_1);

  Blynk.virtualWrite(vPIN_VOLTAGE_2,               voltage_usage_2);
  Blynk.virtualWrite(vPIN_CURRENT_USAGE_2,         current_usage_2);
  Blynk.virtualWrite(vPIN_ACTIVE_POWER_2,          active_power_2);
  Blynk.virtualWrite(vPIN_ACTIVE_ENERGY_2,         active_energy_2);
  Blynk.virtualWrite(vPIN_FREQUENCY_2,             frequency_2);
  Blynk.virtualWrite(vPIN_POWER_FACTOR_2,          power_factor_2);
  Blynk.virtualWrite(vPIN_OVER_POWER_ALARM_2,      over_power_alarm_2);  
}

void pzemdevice1()
{
  // PZEM Device 1 data fetching
  Serial.println("===================================================="); 
  Serial.println("Now checking Modbus 1");
  uint8_t result1;

  ESP.wdtDisable();     //disable watchdog during modbus read or else ESP crashes when no slave connected                                               
  result1 = node1.readInputRegisters(0x0000, 10);
  ESP.wdtEnable(1);    //enable watchdog during modbus read  
  
  if (result1 == node1.ku8MBSuccess)
  {
    voltage_usage_1      = (node1.getResponseBuffer(0x00) / 10.0f);
    current_usage_1      = (node1.getResponseBuffer(0x01) / 1000.000f);
    active_power_1       = (node1.getResponseBuffer(0x03) / 10.0f);
    active_energy_1      = (node1.getResponseBuffer(0x05) / 1000.0f);
    frequency_1          = (node1.getResponseBuffer(0x07) / 10.0f);
    power_factor_1       = (node1.getResponseBuffer(0x08) / 100.0f);
    over_power_alarm_1   = (node1.getResponseBuffer(0x09));

    Serial.println("Modbus 1 Data");
    Serial.print("VOLTAGE:           ");   Serial.println(voltage_usage_1);   // V
    Serial.print("CURRENT_USAGE:     ");   Serial.println(current_usage_1, 3);  //  A
    Serial.print("ACTIVE_POWER:      ");   Serial.println(active_power_1);   //  W
    Serial.print("ACTIVE_ENERGY:     ");   Serial.println(active_energy_1, 3);  // kWh
    Serial.print("FREQUENCY:         ");   Serial.println(frequency_1);    // Hz
    Serial.print("POWER_FACTOR:      ");   Serial.println(power_factor_1);
    Serial.print("OVER_POWER_ALARM:  ");   Serial.println(over_power_alarm_1, 0);
    Serial.println("====================================================");
  }

  else {
    Serial.println("Failed to read modbus 1");
   
  }
}

 void pzemdevice2()
 {
   
  // PZEM Device 2 data fetching
  Serial.println("===================================================="); 
  Serial.println("Now checking Modbus 2");
  uint8_t result2;
  
  ESP.wdtDisable();
  result2 = node2.readInputRegisters(0x0000, 10);
  ESP.wdtEnable(1);
  
  if (result2 == node2.ku8MBSuccess)
  {
    voltage_usage_2      = (node2.getResponseBuffer(0x00) / 10.0f);
    current_usage_2      = (node2.getResponseBuffer(0x01) / 1000.000f);
    active_power_2       = (node2.getResponseBuffer(0x03) / 10.0f);
    active_energy_2      = (node2.getResponseBuffer(0x05) / 1000.0f);
    frequency_2          = (node2.getResponseBuffer(0x07) / 10.0f);
    power_factor_2       = (node2.getResponseBuffer(0x08) / 100.0f);
    over_power_alarm_2   = (node2.getResponseBuffer(0x09));

    Serial.println("Modbus 2 Data");
    Serial.print("VOLTAGE:           ");   Serial.println(voltage_usage_2);   // V
    Serial.print("CURRENT_USAGE:     ");   Serial.println(current_usage_2, 3);  //  A
    Serial.print("ACTIVE_POWER:      ");   Serial.println(active_power_2);   //  W
    Serial.print("ACTIVE_ENERGY:     ");   Serial.println(active_energy_2, 3);  // kWh
    Serial.print("FREQUENCY:         ");   Serial.println(frequency_2);    // Hz
    Serial.print("POWER_FACTOR:      ");   Serial.println(power_factor_2);
    Serial.print("OVER_POWER_ALARM:  ");   Serial.println(over_power_alarm_2, 0);
    Serial.println("====================================================");

  }

  else {
    Serial.println("Failed to read modbus 2");
    //delay(6000);

  }
}

void resetEnergy(uint8_t slaveAddr) {
  //The command to reset the slave's energy is (total 4 bytes):
  //Slave address + 0x42 + CRC check high byte + CRC check low byte.
  uint16_t u16CRC = 0xFFFF;
  static uint8_t resetCommand = 0x42;
  u16CRC = crc16_update(u16CRC, slaveAddr);
  u16CRC = crc16_update(u16CRC, resetCommand);
  Serial.println("Resetting Energy");
  pzemSerial.write(slaveAddr);
  pzemSerial.write(resetCommand);
  pzemSerial.write(lowByte(u16CRC));
  pzemSerial.write(highByte(u16CRC));
  delay(1000);
}


//function to change/assign pzem address

void changeAddress(uint8_t OldslaveAddr, uint8_t NewslaveAddr)
{
  static uint8_t SlaveParameter = 0x06;
  static uint16_t registerAddress = 0x0002; // Register address to be changed
  uint16_t u16CRC = 0xFFFF;
  u16CRC = crc16_update(u16CRC, OldslaveAddr);
  u16CRC = crc16_update(u16CRC, SlaveParameter);
  u16CRC = crc16_update(u16CRC, highByte(registerAddress));
  u16CRC = crc16_update(u16CRC, lowByte(registerAddress));
  u16CRC = crc16_update(u16CRC, highByte(NewslaveAddr));
  u16CRC = crc16_update(u16CRC, lowByte(NewslaveAddr));

  Serial.println("Changing Slave Address");

  pzemSerial.write(OldslaveAddr);
  pzemSerial.write(SlaveParameter);
  pzemSerial.write(highByte(registerAddress));
  pzemSerial.write(lowByte(registerAddress));
  pzemSerial.write(highByte(NewslaveAddr));
  pzemSerial.write(lowByte(NewslaveAddr));
  pzemSerial.write(lowByte(u16CRC));
  pzemSerial.write(highByte(u16CRC));
  delay(1000);
}

void loop() {
  Blynk.run();
  timer.run();
  pzemdevice1();
  pzemdevice2();
  delay(1000);
}

I refer the coding from here "GitHub - pkarun/Blynk-PZEM-004T-v3.0-Multiple-device: Blynk ESP8266 (NodeMCU) Program to connect multiple PZEM 004T v3.0 Power Meter."

This is the result displayed on the serial monitor. Only that one time it gives value/

Please help me to understand why this happen and how can I solve it.

This is text output! Why do you post a picture of it?

Does that mean you don't get any values from the first slave device in the second run? You might see here why posting the serial output completely would have made sense because then we would see that in the output.

As you don't have pre-/post-transmission code I guess you don't use RS485 to connect to the slaves. May we ask for a wiring diagram of your setup?

Yes, for the second run I don't get any value.
I also didn't use RS485. I directly connect the wire to the nodeMCU. In the diagram, the line on PZEM to 3v3 means to 3v nodeMCU and GND to GND on nodeMCU. Does it necessary to use RS485? I still don't understand much about RS485 wiring and I thought just need it if want to use Ethernet. I was planning to only use WIFI.

Don't use that any further! You might destroy all connected devices by wiring it this way. I couldn't find any datasheet or the like for these devices (seems to be cheap Chinese stuff) but it says the serial interface is TTL which usually means 5V level. That alone may destroy your nodeMCU board.
The orange connection may work this way, at least for two, maybe three devices but don't expect it to work with more devices. The yellow connection produces short circuits. You must not use it this way. A UART TX line won't tri-state when not used, it's always HIGH when idling. If another board transfers data and pulls it to GND for that purpose you got a short circuit.

I actually just succeed using this modbus and get value from the PZEMs. The problem before is that I did not assign/change address of each my PZEMs. After I assign/change the address, it works. Currently I tried with 5 PZEMs with 1 DHT22. The connection of the PZEM is same as the diagram. I check the total current use for all the PZEMs and the DHT 22 is about 0.02A. Note that I'm not using the MCU in the diagram. I'm using nodeMCU, it is a chinese product which is cheaper alternative for arduino but it have similar functions and programed also programmed by arduino IDE

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.