PZEM-004T library for UNO R4 (works on R3/Nano/Mega too)

Hey folks,

I just published a library for the PZEM-004T V4.0 energy monitor. The main reason I made this is because none of the existing libraries work with the new UNO R4 boards - they all use Serial1 differently and most just crash.

What it does: Reads voltage, current, power, energy, frequency, and power factor from PZEM-004T using Modbus RTU. Also lets you reset the energy counter and change the device address if needed.

Why it might be useful:

  • Actually works on UNO R4 (Minima and WiFi versions)

  • Also works on R3, Nano, Mega with the same code

  • Library auto-detects which board you're using

  • Includes proper error handling with specific error codes

  • Has a batch read function that's way faster than reading parameters individually

Installation: Library Manager -> search "PZEM004Tv40_R4"

Or grab it from GitHub: https://github.com/bharanidharanrangaraj/PZEM004Tv40_R4

Basic example (For UNO R4 series):

#include <PZEM004Tv40_R4.h>

PZEM004Tv40_R4 pzem(&Serial1);  // R4 uses Serial1

void setup() {
  Serial.begin(115200);
  pzem.begin();
}

void loop() {
  if (pzem.readAll()) {
    Serial.print("Voltage: ");
    Serial.print(pzem.getVoltage());
    Serial.println(" V");
    
    Serial.print("Power: ");
    Serial.print(pzem.getPower());
    Serial.println(" W");
  }
  delay(1000);
}

For R3/Nano, you'd use SoftwareSerial instead - there's an example in the library that shows both.

It includes Basic reading example, Individual parameter reading

I've been using this for a couple months now in my home energy monitoring setup and it's been solid. Tested on R4 WiFi, R4 Minima, regular R3 and Nano Series.

If you find bugs or have suggestions, open an issue on GitHub or let me know here. Pull requests welcome if you want to add features.

Thanks and Regards
Bharani Dharan Rangaraj

1 Like

Thanks for sharing, appreciated!

At first sight I see no bugs, just two performance tips:

multiplication is faster than division

_current = iRaw / 1000.0;

==>

_current = iRaw * 1e-3;

delay

More important is to investigate how to remove the calls to delay() as these are blocking.
Async calls might help.