PZEM-004T v3.0 with WEMOS D1 not reading on Serial monitor


I just received my PZEM-004T version 3 and WEMOS D1 Mini

Here is my connection:

  • Wemos 5V to PZEM 5V
  • Wemos G to PZEM GND
  • Wemos Rx to PZEM Tx
  • Wemos Tx to PZEM Rx

Connect Wemos USB port to laptop. Open PZEMDISPLAY.INO in Aduino and load library .

Modify PZEMDISPLAY line 4 to “PZEM004T pzem(13,15)”

The COM port for Wemos is COM5

Here is the error message that I received when upload (with Rx-Tx and Tx-Rx are connected)

Here is the error message that I received when upload (with Wemos Rx disconnected)

B[quote=“key, post:1, topic:38130”]

  • Wemos Rx to PZEM Tx
  • Wemos Tx to PZEM Rx

Connect Wemos USB port to laptop

The Tx and Rx pins on the D1 Mini are the same pins that are connected to the Wemos USB port.

You’ve already identified that you need to use SoftwareSerial to provide another serial port, and defined this as using GPIO 13 and 15 (which are labelled D7 and D8 on the Wemos).
These are the pins that your PZEM should be connected to, not Tx/Rx.

The sketch isn’t uploading because the serial communication between your PC and the Wemos is being affected by the fact that the PZEM is also connected to the pins that are being used to upload the sketch.

From your screenshot it appears that you’re missing a command to begin your SoftwareSerial UART at the desired baud rate.

When you get it working and try to add-in Blynk code then it won’t work, because your void loop isn’t Blynk friendly.
At that point you should read this:

Or you could check-out @Costas’s off the shelf solution which also uses Blynk:


Hi Pete,

Thank you for your response.

  • When connect PZEM Tx to Wemos D7 and PZEM Rx to Wemos D8 ==> I can’t upload the sketch.
  • When connect PZEM to Wemos Tx and Rx ==> Then yes, I can upload the sketch ==> The Serial Monitor only show 0.00V and nothing else. Even when I applied the AC power to the PZEM, still nothing show up :frowning:

I do have the file name “SoftwareSerial.h” file in the libraries. Do I have to modify anything on for this file to works?

Please let me know what I need to do to upload the sketch using D7 & D8 on PZEM?

FYI, once I get the data show up on Serial Monitor then I will look into the code to work with Blynk.

I believed the ESPmonitor is no longer work or support by the owner. I did tried to download the app but can’t create the account or login. I think I read it some where, the owner said he no longer host/support the app.

Why don’t you try to disconnect the PZEM, upload the code then reconnect the PZEM to D7 and D8?

Digging a bit deeper, it looks like the library you’re using should handle the SoftwareSerial declaration and setup itself in the background, so the SoftwareSerial library probably doesnt need to be included, although its difficult to say without knowing exactly which library you’re using.

There is a known bug with the recent versions of the ESP core which affects SoftwareSerial…

Even if your PZEM library doesn’t require the SoftwareSerial.h library to be included, it’s probably using the library in the background so could be affected by this issue.

There’s also an issue with voltages on the latest version of the PZEM whne using it with an ESP. See this topic:

It would also help if you posted actual code and copy/pasted compiler error messages rather than screenshots. If you do this, ensure that you surround your code and compiler messages with triple backticks so that it displays correctly. Triple backticks look like this:

Having said that, this isn’t a Blynk related problem at this point, as you’re not using Blynk in your sketch, so this probably isn’t the best forum to be asking these questions.


У меня тоже была эта проблема. Для WEMOS D1 mini нет рабочих библиотек (только для ESP без физического UART типа ESP-01 или ESP-12) и согласование уровней тоже не поможет с PZEM v3!!! V3 и V1 это абсолютно РАЗНЫЕ вещи. Помогла TASMOTA из темы

Настройки описаны пользователем MIGAS77 как для PZEM-016 но для PZEM-04 v.3 работает !!! А дальше по MQTT и на Blynk .
Возможно кто-то и вытащит из TASMOTA или еще как-то, в отдельную библиотеку для PZEM-04 v3 рабочий код. Дело времени !

I was able to upload the sketch to Wemos successful.
The problems I got now is voltage only show up as 0.00V in serial monitor.

How do I fix it so the actual voltage, watt … can show up in the serial monitor?

Here is the sketch:

#include <SoftwareSerial.h> // Arduino IDE <1.6.6
#include <PZEM004T.h>

PZEM004T pzem(13,15);  // (RX,TX) connect to TX,RX of PZEM
IPAddress ip(192,168,1,88);

void setup() {

void loop() {
  float v = pzem.voltage(ip);
  if (v < 0.0) v = 0.0;
  Serial.print(v);Serial.print("V; ");

  float i = pzem.current(ip);
  if(i >= 0.0){ Serial.print(i);Serial.print("A; "); }
  float p = pzem.power(ip);
  if(p >= 0.0){ Serial.print(p);Serial.print("W; "); }
  float e = pzem.energy(ip);
  if(e >= 0.0){ Serial.print(e);Serial.print("Wh; "); }


//  delay(1000);

And here is the PZEM004T.cpp

#include "PZEM004T.h"

#define PZEM_VOLTAGE (uint8_t)0xB0
#define RESP_VOLTAGE (uint8_t)0xA0

#define PZEM_CURRENT (uint8_t)0xB1
#define RESP_CURRENT (uint8_t)0xA1

#define PZEM_POWER   (uint8_t)0xB2
#define RESP_POWER   (uint8_t)0xA2

#define PZEM_ENERGY  (uint8_t)0xB3
#define RESP_ENERGY  (uint8_t)0xA3

#define PZEM_SET_ADDRESS (uint8_t)0xB4
#define RESP_SET_ADDRESS (uint8_t)0xA4

#define PZEM_POWER_ALARM (uint8_t)0xB5
#define RESP_POWER_ALARM (uint8_t)0xA5

#define RESPONSE_SIZE sizeof(PZEMCommand)

#define PZEM_BAUD_RATE 9600

#ifdef PZEM004_SOFTSERIAL    
PZEM004T::PZEM004T(uint8_t receivePin, uint8_t transmitPin)
    SoftwareSerial *port = new SoftwareSerial(receivePin, transmitPin);
    this->serial = port;
    this->_isSoft = true;

PZEM004T::PZEM004T(HardwareSerial *port)
    this->serial = port;
    this->_isSoft = false;

        delete this->serial;

void PZEM004T::setReadTimeout(unsigned long msec)
    _readTimeOut = msec;

float PZEM004T::voltage(const IPAddress &addr)
    uint8_t data[RESPONSE_DATA_SIZE];

    send(addr, PZEM_VOLTAGE);
    if(!recieve(RESP_VOLTAGE, data))
        return PZEM_ERROR_VALUE;

    return (data[0] << 8) + data[1] + (data[2] / 10.0);

float PZEM004T::current(const IPAddress &addr)
    uint8_t data[RESPONSE_DATA_SIZE];

    send(addr, PZEM_CURRENT);
    if(!recieve(RESP_CURRENT, data))
        return PZEM_ERROR_VALUE;

    return (data[0] << 8) + data[1] + (data[2] / 100.0);

float PZEM004T::power(const IPAddress &addr)
    uint8_t data[RESPONSE_DATA_SIZE];

    send(addr, PZEM_POWER);
    if(!recieve(RESP_POWER, data))
        return PZEM_ERROR_VALUE;

    return (data[0] << 8) + data[1];

float PZEM004T::energy(const IPAddress &addr)
    uint8_t data[RESPONSE_DATA_SIZE];

    send(addr, PZEM_ENERGY);
    if(!recieve(RESP_ENERGY, data))
        return PZEM_ERROR_VALUE;

    return ((uint32_t)data[0] << 16) + ((uint16_t)data[1] << 8) + data[2];

bool PZEM004T::setAddress(const IPAddress &newAddr)
    send(newAddr, PZEM_SET_ADDRESS);
    return recieve(RESP_SET_ADDRESS);

bool PZEM004T::setPowerAlarm(const IPAddress &addr, uint8_t threshold)
    send(addr, PZEM_POWER_ALARM, threshold);
    return recieve(RESP_POWER_ALARM);

void PZEM004T::send(const IPAddress &addr, uint8_t cmd, uint8_t data)
    PZEMCommand pzem;

    pzem.command = cmd;
    for(int i=0; i<sizeof(pzem.addr); i++)
        pzem.addr[i] = addr[i];
    pzem.data = data;

    uint8_t *bytes = (uint8_t*)&pzem;
    pzem.crc = crc(bytes, sizeof(pzem) - 1);


    serial->write(bytes, sizeof(pzem));

bool PZEM004T::recieve(uint8_t resp, uint8_t *data)
    uint8_t buffer[RESPONSE_SIZE];

#ifdef PZEM004_SOFTSERIAL    
        ((SoftwareSerial *)serial)->listen();

    unsigned long startTime = millis();
    uint8_t len = 0;
    while((len < RESPONSE_SIZE) && (millis() - startTime < _readTimeOut))
        if(serial->available() > 0)
            uint8_t c = (uint8_t)serial->read();
            if(!c && !len)
                continue; // skip 0 at startup
            buffer[len++] = c;
        yield();	// do background netw tasks while blocked for IO (prevents ESP watchdog trigger)

    if(len != RESPONSE_SIZE)
        return false;

    if(buffer[6] != crc(buffer, len - 1))
        return false;

    if(buffer[0] != resp)
        return false;

        for(int i=0; i<RESPONSE_DATA_SIZE; i++)
            data[i] = buffer[1 + i];

    return true;

uint8_t PZEM004T::crc(uint8_t *data, uint8_t sz)
    uint16_t crc = 0;
    for(uint8_t i=0; i<sz; i++)
        crc += *data++;
    return (uint8_t)(crc & 0xFF);

And here is the code for PZEM004T.h

#ifndef PZEM004T_H
#define PZEM004T_H

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#include "WProgram.h"

// #define PZEM004_NO_SWSERIAL

#if (not defined(PZEM004_NO_SWSERIAL)) && (defined(__AVR__) || defined(ESP8266))

#if defined(PZEM004_SOFTSERIAL)
#include <SoftwareSerial.h>

#include <IPAddress.h>

#define PZEM_ERROR_VALUE -1.0

struct PZEMCommand {
    uint8_t command;
    uint8_t addr[4];
    uint8_t data;
    uint8_t crc;

class PZEM004T
    PZEM004T(uint8_t receivePin, uint8_t transmitPin);
    PZEM004T(HardwareSerial *port);

    void setReadTimeout(unsigned long msec);
    unsigned long readTimeout() {return _readTimeOut;}

    float voltage(const IPAddress &addr);
    float current(const IPAddress &addr);
    float power(const IPAddress &addr);
    float energy(const IPAddress &addr);

    bool setAddress(const IPAddress &newAddr);
    bool setPowerAlarm(const IPAddress &addr, uint8_t threshold);

    Stream *serial;

    bool _isSoft;
    unsigned long _readTimeOut = PZEM_DEFAULT_READ_TIMEOUT;

    void send(const IPAddress &addr, uint8_t cmd, uint8_t data = 0);
    bool recieve(uint8_t resp, uint8_t *data = 0);

    uint8_t crc(uint8_t *data, uint8_t sz);

#endif // PZEM004T_H

And here is the code for SoftwareSerial.h:

#include <SoftwareSerial.h>
// software serial #1: RX = digital pin 10, TX = digital pin 11
SoftwareSerial portOne(10, 11);

// software serial #2: RX = digital pin 8, TX = digital pin 9
// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega
SoftwareSerial portTwo(8, 9);

void setup() {
  // Open serial communications and wait for port to open:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only

  // Start each software serial port

void loop() {
  // By default, the last intialized port is listening.
  // when you want to listen on a port, explicitly select it:
  Serial.println("Data from port one:");
  // while there is data coming in, read it
  // and send to the hardware serial port:
  while (portOne.available() > 0) {
    char inByte = portOne.read();

  // blank line to separate data from the two ports:

  // Now listen on the second port
  // while there is data coming in, read it
  // and send to the hardware serial port:
  Serial.println("Data from port two:");
  while (portTwo.available() > 0) {
    char inByte = portTwo.read();

  // blank line to separate data from the two ports:

Software serial is being included by your PZEM library, so you don’t need to include it yourself.

Presumably you have one conductor of a 240v appliance going through the coil and the appliance is turned on?

Do you have an FTDI USB to serial converter available?


I’m in US, yes, there is 120V go through the PZEM and the appliance is ON.

Yes, I do have RS485 to USB converter, what do you want me to do with this?

I was referring to a TTL serial to USB adaptor like this:

If you have one then you can connect the PZEM direct to your PC and
monitor the output directly on the PC to see what’s happening.


Повторю еще раз. В связке WEMOS d1 mini и PZEM-04 — V.3— НЕ БУДЕТ работать Сериал монитор!!! И танцы с SoftwareSerial или другими не помогут !!! (см.Google - доказано и не раз). Только через WEB интерфейс. Именно эта плата не подходит для этого !

Hi SVS2007m,

When looking at the video (in Korea language) from your post on the other topic, I do see the data show up on Serial Monitor.

How do I fix this so data can show up on Serial Monitor? or
How to access it through Web Interface?

Were you able to make it work with your PZEM on Auduino? if yes, please help and share your works, please.

Там на видео к сожалению для PZEM-04 —V.1—
У меня эта связка заработала только c прошивкой TASMOTA . (Ардуино у меня нет).С настройками от MIGAS 77 (см. выше). Дело на 30 мин с кофе


Could you please share the steps on what you did and some screenshot, please.

Как ставить TASMOTA куча роликов на YOUTUBE.Да и здесь эта тема тоже была.
У Ze_Pico куча проектов с TASMOTA. Лучше чем у него мне рассказать не получится.

I have pzem-004t v3.0 and nodemcu esp8266
Can you give me a code to connect with Bynk, thank you

I done , ok
Share code and library: https://drive.google.com/folderview?id=16xXaT6tC1U2AIx4BRYihrBVOkV2ecmnL