BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

PZEM-017 with Blynk

corrected, it’s the same type. I had 3 available and I replaced it (I though the board may be bad) all but still only show the zero readout.

As I’ve said, I think that these are designed for long range comms and they seem to be self-negotiating with regard to baud rate. I don’t see how that could be compatible with what you are tying to achieve.

I may be wrong, but don’t have either of your pieces of hardware available to do any testing if my own.
The boards seem to have Tx and Rx LEDs on them. Which seem to be on the RS485 side. Is there any activity on these?

Pete.

Yes, the board does have Tx and Rx LED on it but I don’t see any activity when it run.

Could it be because I have wrong connection?
ESP D5 --> RS485 TxD
ESP D6 --> RS485 RxD
ESP 5V --> RS485 VCC --> PZEM017 5V
ESP G --> RS485 GND --> PZEM017 GND
RS485 A --> PZEM A
RS485 B --> PZEM B

I have no idea, I’m not familiar with this adapter, but I doubt that it is suitable for this application.

Pete.

Found this Image For your adapter. Maybe it will help, maybe not.

To be honest I do not have much experience with this, but maybe try using the actual GPIO numbers instead of the “D” numbers.

SoftwareSerial pzem(D5,D6);  // (RX,TX) connect to TX,RX of PZEM for NodeMCU
SoftwareSerial pzem(14,12);  // (RX,TX) connect to TX,RX of PZEM for NodeMCU

Thanks Toro,

I have been using this same type of board for my other project like EPEVER Solar charge controller and it’s working fine.

There could be some code missing or wrong code which I can’t see or detect it as i’m “blind” now.

Can any of you look into the code to see if you can find anything wrong with it?

Sharing that piece of information, and the code you Re using, earlier in the discussion would have saved several of us a significant amount of time.

Pete.

Hi Pete,

I had used RS485 board in this project here

And I modified the the code on my PZEM-004 v3.0 here and try to make it work on PZEM-017

Unfortunately, the modification does not work on PZEM17 which is why i’m needing some help.

I think that starting with your EPEVER code base would be a better option, especially if it uses the same hardware that you are using now.

Pete.

Hi Pete and other expert,

I just found the website with the code for PZEM-017 and Arduino Mega board.
Since I don’t have the Arduino Mega so when I tried to applied that code to ESP8266 Mini D1 or ESP8266 NodeMCU, both of the board give me nothing on the Serial Monitor.

Here is the connection:

  • PZEM 5V --> 5V on RS485 & VV pin on ESP8266 NodeMCU

  • PZEM B --> B on RS485

  • PZEM A —> A on RS485

  • PZEM GND --> GND on RS485 & G pin on NodeMCU

  • NodeMCU TX —> DI on RS485

  • NodeMCU RX —> RO on RS485

  • NodeMCU D8 —> DE on RS485

  • NodeMCU 78 —> RE on RS485

Could anyone please check and let me know why it does not work on ESP8266?

Here is the link to the site: https://solarduino.com/pzem-017-dc-energy-meter-with-arduino/

And here is the code:

        /* 1- PZEM-017 DC Energy Meter */
        
        #include <ModbusMaster.h>                   // Load the (modified) library for modbus communication command codes. Kindly install at our website.
        #define MAX485_DE      8                    // Define DE Pin to Arduino pin. Connect DE Pin of Max485 converter module to Pin 2 (default) Arduino board
        #define MAX485_RE      7                    // Define RE Pin to Arduino pin. Connect RE Pin of Max485 converter module to Pin 3 (default) Arduino board
                                                    // These DE anr RE pins can be any other Digital Pins to be activated during transmission and reception process.
        static uint8_t pzemSlaveAddr = 0x01;        // Declare the address of device (meter) in term of 8 bits. You can change to 0x02 etc if you have more than 1 meter.
        static uint16_t NewshuntAddr = 0x0001;      // Declare your external shunt value. Default is 100A, replace to "0x0001" if using 50A shunt, 0x0002 is for 200A, 0x0003 is for 300A
                                                    // By default manufacturer may already set, however, to set manually kindly delete the "//" for line "// setShunt(0x01);" in void setup
        ModbusMaster node;                          /* activate modbus master codes*/  
        float PZEMVoltage =0;                       /* Declare value for DC voltage */
        float PZEMCurrent =0;                       /* Declare value for DC current*/
        float PZEMPower =0;                         /* Declare value for DC Power */
        float PZEMEnergy=0;                         /* Declare value for DC Energy */
        unsigned long startMillisPZEM;              /* start counting time for LCD Display */
        unsigned long currentMillisPZEM;            /* current counting time for LCD Display */
        const unsigned long periodPZEM = 1000;      // refresh every X seconds (in seconds) in LED Display. Default 1000 = 1 second 
        int page = 1;                               /* display different pages on LCD Display*/
        

        /* 2 - LCD Display  */

        #include<LiquidCrystal.h>                   /* Load the liquid Crystal Library (by default already built-it with arduino solftware)*/
        LiquidCrystal LCD(8,9,4,5,6,7);             /* Creating the LiquidCrystal object named LCD. The pin may be varies based on LCD module that you use*/
        unsigned long startMillisLCD;               /* start counting time for LCD Display */
        unsigned long currentMillisLCD;             /* current counting time for LCD Display */
        const unsigned long periodLCD = 1000;       /* refresh every X seconds (in seconds) in LED Display. Default 1000 = 1 second */
        int ResetEnergy = 0;                        /* reset energy function */
        unsigned long startMillisEnergy;            /* start counting time for LCD Display */
        unsigned long currentMillisEnergy;          /* current counting time for LCD Display */
        const unsigned long periodEnergy = 1000;    // refresh every X seconds (in seconds) in LED Display. Default 1000 = 1 second 


void setup() 
{
        /*0 General*/
        
        Serial.begin(9600,SERIAL_8N2);              /* To assign communication port to communicate with meter. with 2 stop bits (refer to manual)*/

        /* 1- PZEM-017 DC Energy Meter */
        
         setShunt(0x01);                          // Delete the "//" to set shunt rating (0x01) is the meter address by default
        // resetEnergy(0x01);                       // By delete the double slash symbol, the Energy value in the meter is reset. Can also be reset on the LCD Display      
        startMillisPZEM = millis();                 /* Start counting time for run code */
        node.begin(pzemSlaveAddr, Serial);          /* Define and start the Modbus RTU communication. Communication to specific slave address and which Serial port */
        pinMode(MAX485_RE, OUTPUT);                 /* Define RE Pin as Signal Output for RS485 converter. Output pin means Arduino command the pin signal to go high or low so that signal is received by the converter*/
        pinMode(MAX485_DE, OUTPUT);                 /* Define DE Pin as Signal Output for RS485 converter. Output pin means Arduino command the pin signal to go high or low so that signal is received by the converter*/
        digitalWrite(MAX485_RE, 0);                 /* Arduino create output signal for pin RE as LOW (no output)*/
        digitalWrite(MAX485_DE, 0);                 /* Arduino create output signal for pin DE as LOW (no output)*/
                                                    // both pins no output means the converter is in communication signal receiving mode
        node.preTransmission(preTransmission);      // Callbacks allow us to configure the RS485 transceiver correctly
        node.postTransmission(postTransmission);
        changeAddress(0XF8, 0x01);                  // By delete the double slash symbol, the meter address will be set as 0x01. 
                                                    // By default I allow this code to run every program startup. Will not have effect if you only have 1 meter
                           
        delay(1000);                                /* after everything done, wait for 1 second */

        /* 2 - LCD Display  */

        LCD.begin(16,2);                            /* Tell Arduino that our LCD has 16 columns and 2 rows*/
        LCD.setCursor(0,0);                         /* Set LCD to start with upper left corner of display*/  
        startMillisLCD = millis();                  /* Start counting time for display refresh time*/

}

void loop() 
{

        /* 0- General */

        /* 0.1- Button Function */
        
        int buttonRead;
        buttonRead = analogRead (0);                                                                      // Read analog pin A0. Pin A0 automatically assigned for LCD Display Button function (cannot be changed)

        /*Right button is pressed */
        if (buttonRead < 60) 
          {   
             LCD.setCursor(0,0); LCD.print (" PRESS <SELECT> "); 
             LCD.setCursor(0,1); LCD.print ("TO RESET ENERGY ");
          }       
     
        /* Up button is pressed */
        else if (buttonRead < 200) 
          {   
             LCD.setCursor(0,0); LCD.print (" PRESS <SELECT> "); 
             LCD.setCursor(0,1); LCD.print ("TO RESET ENERGY ");
          }          
                 
        /* Down button is pressed */
        else if (buttonRead < 400)
          {   
             LCD.setCursor(0,0); LCD.print (" PRESS <SELECT> "); 
             LCD.setCursor(0,1); LCD.print ("TO RESET ENERGY ");
          }           
     
        /* Left button is pressed */
        else if (buttonRead < 600)
          {   
            if(ResetEnergy ==0)
            {
              LCD.setCursor(0,0); LCD.print (" PRESS <SELECT> "); 
              LCD.setCursor(0,1); LCD.print ("TO RESET ENERGY ");
            }
            if(ResetEnergy ==1)                                                                           /* only to run reset energy if left button is pressed after select button*/
            {
              page = 2;
            }
          } 
     
        /* Select button is pressed */
        else if (buttonRead < 800)
          {   
              ResetEnergy = 1;                                                                            // to activate offset for power
              startMillisEnergy = millis();                                                               /* start counting time for pending response*/
          }
          
          /* After Select button is pressed */
          if(ResetEnergy ==1)
          {
            LCD.setCursor(0,0);                                                                           /* set display words starting at upper left corner*/
            LCD.print ("RESET ENERGY ?  ");
            LCD.setCursor(0,1);                                                                           /* set display words starting at lower left corner*/
            LCD.print ("PRESS < LEFT >  ");
            currentMillisEnergy = millis();
            if(( currentMillisEnergy - startMillisEnergy <= 5000) && (page==2))                           /* if within 5 seconds <left> button is pressed, do reset energy*/   
              {
                
                uint16_t u16CRC = 0xFFFF;                                                                         /* declare CRC check 16 bits*/
                static uint8_t resetCommand = 0x42;                                                               /* reset command code*/
                uint8_t slaveAddr =0X01;
                u16CRC = crc16_update(u16CRC, slaveAddr);
                u16CRC = crc16_update(u16CRC, resetCommand);
                preTransmission();                                                                                /* trigger transmission mode*/
                Serial.write(slaveAddr);                                                                         /* send device address in 8 bit*/
                Serial.write(resetCommand);                                                                      /* send reset command */
                Serial.write(lowByte(u16CRC));                                                                   /* send CRC check code low byte  (1st part) */
                Serial.write(highByte(u16CRC));                                                                  /* send CRC check code high byte (2nd part) */
                delay(10);
                postTransmission();                                                                               /* trigger reception mode*/
                delay(100);
                ResetEnergy=0;                                                                            /* reset command switch back to default*/
                page=1;                                                                                   /* go back to page 1 after reset*/
              }
            if(( currentMillisEnergy - startMillisEnergy > 5000) && (page!=2))                            /* if more than 5 seconds <Left> button does not pressed, go back to main page*/     
              {
                ResetEnergy=0;                                                                            /* reset command switch back to default*/
                page=1;                                                                                   /* go back to page 1 after reset*/
              }
          }

  
        /* 1- PZEM-017 DC Energy Meter */

        currentMillisPZEM = millis();                                                                     /* count time for program run every second (by default)*/
        if (currentMillisPZEM - startMillisPZEM >= periodPZEM)                                            /* for every x seconds, run the codes below*/
        {    
          uint8_t result;                                                                                 /* Declare variable "result" as 8 bits */   
          result = node.readInputRegisters(0x0000, 6);                                                    /* read the 9 registers (information) of the PZEM-014 / 016 starting 0x0000 (voltage information) kindly refer to manual)*/
          if (result == node.ku8MBSuccess)                                                                /* If there is a response */
            {
              uint32_t tempdouble = 0x00000000;                                                           /* Declare variable "tempdouble" as 32 bits with initial value is 0 */ 
              PZEMVoltage = node.getResponseBuffer(0x0000) / 100.0;                                       /* get the 16bit value for the voltage value, divide it by 100 (as per manual) */
                                                                                                          // 0x0000 to 0x0008 are the register address of the measurement value
              PZEMCurrent = node.getResponseBuffer(0x0001) / 100.0;                                       /* get the 16bit value for the current value, divide it by 100 (as per manual) */
              
              tempdouble =  (node.getResponseBuffer(0x0003) << 16) + node.getResponseBuffer(0x0002);      /* get the power value. Power value is consists of 2 parts (2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned 32bit */
              PZEMPower = tempdouble / 10.0;                                                              /* Divide the value by 10 to get actual power value (as per manual) */
              
              tempdouble =  (node.getResponseBuffer(0x0005) << 16) + node.getResponseBuffer(0x0004);      /* get the energy value. Energy value is consists of 2 parts (2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned 32bit */
              PZEMEnergy = tempdouble;                                                                    
              
              if (pzemSlaveAddr==2)                                                                       /* just for checking purpose to see whether can read modbus*/
                {
                }
            } 
              else
                {
                }
              startMillisPZEM = currentMillisPZEM ;                                                       /* Set the starting point again for next counting time */
        }


        /* 2 - LCD Display  */
        
        currentMillisLCD = millis();                                                                      /* Set counting time for LCD Display*/
        if (currentMillisLCD - startMillisLCD >= periodLCD)                                               /* for every x seconds, run the codes below*/  
          {
            if( page ==1)
            {
            LCD.setCursor(0,0);                                                                           /* Set cursor to first colum 0 and second row 1  */
            LCD.print(PZEMVoltage, 1);                                                                    /* Display Voltage on LCD Display with 1 decimal*/
            LCD.print("V         ");
            LCD.setCursor(9,0); 
            LCD.print(PZEMEnergy, 0);  
            LCD.print("Wh        ");
            LCD.setCursor(0,1);
            LCD.print(PZEMCurrent, 2);  
            LCD.print("A          ");
            LCD.setCursor(9,1); 
            LCD.print(PZEMPower, 1);
            LCD.print("W          ");
            startMillisLCD = currentMillisLCD ;                                                           /* Set the starting point again for next counting time */
            }
          }
          
}

void preTransmission()                                                                                    /* transmission program when triggered*/
{
  
        /* 1- PZEM-017 DC Energy Meter */
        
        digitalWrite(MAX485_RE, 1);                                                                       /* put RE Pin to high*/
        digitalWrite(MAX485_DE, 1);                                                                       /* put DE Pin to high*/
        delay(1);                                                                                         // When both RE and DE Pin are high, converter is allow to transmit communication
}

void postTransmission()                                                                                   /* Reception program when triggered*/
{
        
        /* 1- PZEM-017 DC Energy Meter */
        
        delay(3);                                                                                         // When both RE and DE Pin are low, converter is allow to receive communication
        digitalWrite(MAX485_RE, 0);                                                                       /* put RE Pin to low*/
        digitalWrite(MAX485_DE, 0);                                                                       /* put DE Pin to low*/
}



void setShunt(uint8_t slaveAddr)                                                                          //Change the slave address of a node
{

        /* 1- PZEM-017 DC Energy Meter */
        
        static uint8_t SlaveParameter = 0x06;                                                             /* Write command code to PZEM */
        static uint16_t registerAddress = 0x0003;                                                         /* change shunt register address command code */
        
        uint16_t u16CRC = 0xFFFF;                                                                         /* declare CRC check 16 bits*/
        u16CRC = crc16_update(u16CRC, slaveAddr);                                                         // Calculate the crc16 over the 6bytes to be send
        u16CRC = crc16_update(u16CRC, SlaveParameter);
        u16CRC = crc16_update(u16CRC, highByte(registerAddress));
        u16CRC = crc16_update(u16CRC, lowByte(registerAddress));
        u16CRC = crc16_update(u16CRC, highByte(NewshuntAddr));
        u16CRC = crc16_update(u16CRC, lowByte(NewshuntAddr));
      
        preTransmission();                                                                                 /* trigger transmission mode*/
      
        Serial.write(slaveAddr);                                                                       /* these whole process code sequence refer to manual*/
        Serial.write(SlaveParameter);
        Serial.write(highByte(registerAddress));
        Serial.write(lowByte(registerAddress));
        Serial.write(highByte(NewshuntAddr));
        Serial.write(lowByte(NewshuntAddr));
        Serial.write(lowByte(u16CRC));
        Serial.write(highByte(u16CRC));
        delay(10);
        postTransmission();                                                                                /* trigger reception mode*/
        delay(100);
        while (Serial.available())                                                                        /* while receiving signal from Serial3 from meter and converter */
          {   
          }
}

void changeAddress(uint8_t OldslaveAddr, uint8_t NewslaveAddr)                                            //Change the slave address of a node
{

        /* 1- PZEM-017 DC Energy Meter */
        
        static uint8_t SlaveParameter = 0x06;                                                             /* Write command code to PZEM */
        static uint16_t registerAddress = 0x0002;                                                         /* Modbus RTU device address command code */
        uint16_t u16CRC = 0xFFFF;                                                                         /* declare CRC check 16 bits*/
        u16CRC = crc16_update(u16CRC, OldslaveAddr);                                                      // Calculate the crc16 over the 6bytes to be send
        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));
      
        preTransmission();                                                                                 /* trigger transmission mode*/
      
        Serial.write(OldslaveAddr);                                                                       /* these whole process code sequence refer to manual*/
        Serial.write(SlaveParameter);
        Serial.write(highByte(registerAddress));
        Serial.write(lowByte(registerAddress));
        Serial.write(highByte(NewslaveAddr));
        Serial.write(lowByte(NewslaveAddr));
        Serial.write(lowByte(u16CRC));
        Serial.write(highByte(u16CRC));
        delay(10);
        postTransmission();                                                                                /* trigger reception mode*/
        delay(100);
        while (Serial.available())                                                                        /* while receiving signal from Serial3 from meter and converter */
          {   
          }
}

Pin D8 is not the same as GPIO8 and opin D7 is not the same as pin GPIO7
In fact, pins GPIO7 and 8 are reserved points on the NodeMCU and using then will normally cause the device to go into a constant reboot cycle.

That’s because there is no debug serial port defined. The serial port is being used for communication with the PZEM.

As you’ve probably already realised, this new code set is an awful starting point to use as a Blynk sketch.

I suggested before that the sketch you are using for your EPEVER solar controller would probably be a better starting point, but you seem to have ignored that suggestion.

Pete.

Hi Peter,

Per your suggestion, below it the code that get it from my EPEVER sketch with some modification on the address to match this PZEM-017

// CONNECT THE RS485 MODULE RX->RX of ESP8266, TX->TX.
// Disconnect when uploading code.
// Connect RS485 A -> PZEM A
// Connect RS485 B -> PZEM B
// Connect ESP 5V -> RS485 VCC -> PZEM 5V
// Connect ESP G -> RS485 GND -> PZEM GND
#include <ArduinoOTA.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
#include "SettingsOutdoorEpeverTracer.h"
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

int timerTask1, timerTask2, timerTask3, timerTask4;
float battChargeCurrent, bvoltage, ctemp, btemp, bremaining, lpower, lcurrent, pvvoltage, pvcurrent, pvpower;

uint8_t result;

char ssid[] = "SSID";                    //WiFi Credential
char pass[] = "xxxx";              //WiFi Password
char server[] = "192.168.x.x";         //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

//================Project Authorization code generate from Blynk App ============================
//Indoor Solar Monitor - Local Server
#define AUTH      "Blynk authorization code"

//==========================================
// this is to check if we can write since rs485 is half duplex 
bool rs485DataReceived = true;                            

ModbusMaster node;
SimpleTimer timer;

// tracer requires no handshaking
void preTransmission() {}                                 
void postTransmission() {}

// a list of the regisities to query in order
typedef void (*RegistryList[])();
RegistryList Registries = {
//  AddressRegistry_3005,
  AddressRegistry_0000,
 
};

// keep log of where we are
uint8_t currentRegistryNumber = 0; 
                     
// function to switch to next registry
void nextRegistryNumber() {                             
  currentRegistryNumber = (currentRegistryNumber + 1) % ARRAY_SIZE( Registries);
}

void setup()
{
Serial.begin(115200);
  node.begin(1, Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  WiFi.mode(WIFI_STA);
#if defined(USE_LOCAL_SERVER)
  WiFi.begin(ssid, pass);
  Blynk.config(AUTH, server, port);
#else
  Blynk.begin(AUTH, ssid, pass);
#endif
  while (Blynk.connect() == false) {}
  ArduinoOTA.setHostname(OTA_HOSTNAME);
  ArduinoOTA.begin();

  timerTask1 = timer.setInterval(1000, updateBlynk);
  timerTask2 = timer.setInterval(1000, doRegistryNumber);
  timerTask3 = timer.setInterval(1000, nextRegistryNumber);
}

// --------------------------------------------------------------------------------

void updateBlynk() {

  Blynk.virtualWrite(vPIN_BATT_CURRENT,             battCurrent);
  Blynk.virtualWrite(vPIN_PV_VOLTAGE,               pvvoltage);
  Blynk.virtualWrite(vPIN_PV_CURRENT,               pvcurrent);
  Blynk.virtualWrite(vPIN_PV_POWER,                 pvpower);
  Blynk.virtualWrite(vPIN_BATT_VOLTAGE,             bvoltage);
}

void doRegistryNumber() {
  Registries[currentRegistryNumber]();
}

// ============PROGRAM START ====================================

// === CONTROLLER BATT SETTING CURRENT ==========================
void AddressRegistry_0000() {
  result = node.readInputRegisters(0000, 1 );
  if (result == node.ku8MBSuccess)
  {
    battCurrent = node.getResponseBuffer(0) / 100.0f;
    if (debug == 1) {
      Serial.println();
      Serial.print("Rated Charging CURRENT to BAT: ");
      Serial.println(battCurrent);
    }
  } else {
    rs485DataReceived = false;
  }
}

// ==============================================================
/*void AddressRegistry_0000() {
  result = node.readInputRegisters(0x0000, 15);
  if (result == node.ku8MBSuccess)
  {    
    pvvoltage = (long)node.getResponseBuffer(0x00) / 100.0f;
    if (debug == 1) {
      Serial.println();
      Serial.print("PV Voltage: ");
      Serial.println(pvvoltage);
    }
    
    pvcurrent = (long)node.getResponseBuffer(0x01) / 100.0f;
    if (debug == 1) {
      Serial.print("PV Current: ");
      Serial.println(pvcurrent);
    }

    pvpower = ((long)node.getResponseBuffer(0x03) << 16 | node.getResponseBuffer(0x02)) / 100.0f;
    if (debug == 1) {
      Serial.print("PV Power: ");
      Serial.println(pvpower);
    }

    bvoltage = node.getResponseBuffer(0x04) / 100.0f;
    if (debug == 1) {
      Serial.print("Battery Voltage: ");
      Serial.println(bvoltage);
    }
  }
}
*/
 // ================================================
void loop()
{
  Blynk.run();
  ArduinoOTA.handle();
  timer.run();
}
// ========= END PROGRAM =============================

The compile completed without error but I get no reading on the Serial monitor

What did I do wrong?
Any idea?

The serial port is being used for communication with the PZEM, so can’t also be used to view serial messages - which is why your code does not contain any Serial.print or BLYNK_PRINT Serial commands - they would interfere with the communication with the PZEM.

Do you have access to an FTDI (USB to Serial) adapter?

Pete,

Hi Pete,

With the same code, it was working fine for EPEVER: when there is no signal to A or B on RS485 then there is NO reading or the same reading as above. Once I connect it to the EPEVER then the reading came up correctly.

To make sure the PZEM working as it should be, I connect it to USB Serial to the computer and run the manufacturer software, yes, I do get a reading on my PC. Therefore I know that the PZEM is working correctly as well as my setup.

So, when replace the address from original EPEVER code to align with PZEM then I get NO reading.

I don’t understand what this means.

If you do then I can show you a way to have both serial communication to the RS485 and serial debug monitor output at the same time with a NodeMCU/Wemos D1 Mini.

Pete.

Hi Pete,

Thank you for your response on the weekend.

1- With the same hardware (RS485 & ESP8266); when not connect to any device (either PZEM or EPEVER) then it give out zero reading as shown on previous message.

2- when the same hardware connect to EPEVER then I get the correct reading

3- But when the same hardware connect to PZEM then I have NO reading, same result as #1

Since ESP8266 has only 1 Tx & Rx therefore when doing the sketch upload, I have to disconnect the Rx

Yes, could you please show me “ a way to have both serial communication to the RS485 and serial debug monitor output at the same time with a NodeMCU/Wemos D1 Mini”

The NodeMCU/Wemos D1 Mini has one and a half serial ports.

The first serial port (technically Serial 0, but referred to in code as just Serial) is connected to pins GPIO1 and GPIO3, which are labelled as Tx and Rx on the board. This port is also connected to the microUSB connector via a TTL to USB chip which allows the serial data from the Tx pin to be viewed in the serial monitor.

The second serial port is Serial1 but this only has Tx capability and is connected to GPIO2, which is labelled as D4 on the board.
The fact that this half a serial port only has Tx capability is no problem, as that’s all we need for debugging.
To get the data from pin D4 into your PC you need a TTL to USB (FTDI) converter. Pin D4 should be connected to the Rx pin on the FTDI, and the GND pin of the NodeMCU should be connected to the GND pin of the FTDI. No other connections are necessary.
When you plug the FTDI into your PC, another COM port will be available and it is this COM port that you should use for your serial monitor. In the Arduino IDE, choosing Tools/Port and the new FTDI port then opening the serial monitor will work well, however, you may find it easier to use a separate serial monitor such as PuTTY, as it can make life a bit easier.

Thye Serial1 port needs to be initialised in your void setup with a suitable baud rate (74880 works best), like this:

  Serial1.begin(74880);

ALL debug messages must then be directed to Serial1. If you accidentally send any to Serial by mistake then this will corrupt the data being sent to your RS485 device.

This means using commands like:
#define BLYNK_PRINT Serial1

and
Serial1.println("debug data in here");

The easiest way to get around this is to upload via OTA, and because the Arduino IDE will complain when you then try to open a serial monitor, it’s easier to use a seperate program like PuTTY as I mentioned earlier.

Pete.

Hi Pete,
I’m getting loss now after spend all day today just try to understand your message but it does not go anywhere :frowning:

What board can I use for this connection?


or this?
image

The goal is to read the data from PZEM and display it on Blynk through NodeMCU/Mini D and one of the above board, why do I need the FTDI converter as I don’t want the data to display on the PC.

My mind is blind now, please explain little more detail. If you could, please have a quick draw then it would be great.

Best regards and always thanks a lot for your support.
Key

Up until now, you’ve told me that you only have this type of board:


and that it’s what you’ve been successfully using with your EPEVER solar controller.

Personally, I use this type of board:
image
to communicate with my EPEVER solar controller and it works well. However, don’t expect the same code to work with a different type of board. The lower board has to be put into receive or transmit mode by writing different values to the RE and DE pins.
I have no experience of the other type of board and as I said earlier it appears to be designed for use as an RS485 extender over serial communication lines, and I had doubts about it’s suitability for other tasks. You’ve told me that you are using this type of board successfully, so it must be suitable to a certain extent, but as I have no personal experience of this type of board I can’t comment any further.

You were clearly trying to view the data on your PC in post #25, and later said:

which I did, and I explained the logic behind this in great detail.
In my opinion, serial debugging is the simplest way to perform fault-finding and debugging operations when you are having issues like yours. Without it you are flying blind and are just guessing at what is happening in the background.

I’m going to step away from this topic, as my input clearly isn’t helping you to achieve your goal and I have projects of my own that I’m working on.
I’d suggest that you read through this topic from start to finish and attempt to clarify to other community members exactly which hardware and code you are using on your working EPEVER setup, and which hardware and code you are attempting to use on your PZEM device - and what results you are obtaining with each. This may allow other community members to step in and assist you.

Pete.