Code Monkey home page Code Monkey logo

pzem-004t-v30's Introduction

PZEM-004T v3.0

GitHub issues GitHub license PlatformIO Build Buy me a Beer

LINKS & REFs

Arduino library for Peacefair PZEM-004T-10A and PZEM-004T-100A v3.0 Energy monitor using the ModBUS interface.

The Version 3.0 PZEM is an upgraded version of the older PZEM-004T for which you can find the library Here

Main features

  • Measures Voltage, Current, Power, Energy, Power Factor and Frequency (New in Version 3.0)
  • 247 unique programmable slave addresses
    • Enables multiple slaves to use the same Serial interface PZEM MultiDevice Demo (May need to use external transistors to drive multiple devices on one bus due to GPIO current limitations)
  • Internal Energy counter up to 9999.99kWh

Common issues: READ FIRST BEFORE OPENING NEW ISSUE!

  • Make sure the PZEM device is connected to the 230V AC power! The 5V pin only powers the optocouplers, not the actual chip.
  • Make sure the 5V and GND are BOTH connected! They are essential for the optocouplers!
  • If you are getting NaNs and only the TX LED is blinking, try swapping the RX/TX wires.
  • Make sure you are using the correct custom address (change with PZEMChangeAddress) or you are using the default address PZEM_DEFAULT_ADDR = 0xF8 (only works for 1 device on ModBus)
  • If you want to use multiple devices on the same ModBus, please set a custom address for each and use PZEMMultiDevice
  • If the current is much higher than you would expect (eg. 0.5A for a 60W device), don't panic, welcome to the world of AC! You are probably dealing with a device with bad powerfactor <1. In such cases the classic P=V*I does not apply. You can read more about this here: Power Factor
  • Please be safe, AC is dangerous! If you don't know what you are doing, you can die! You are responsible for your own safety.

Other features

  • Over power alarm
  • Energy counter reset
  • CRC16 checksum
  • Better, but not perfect mains isolation

The module

PZEM-004T v3.0 Image

This module is an upgraded version of the PZEM-004T with frequency and power factor measurement features, available at the usual places. It communicates using a TTL interface over a Modbus-RTU like communication protocol but is incompatible with the older @olehs library found here: https://github.com/olehs/PZEM004T. I would like to thank @olehs for the great library which inspired me to write this one.

Manufacturer (optimistic) specifications

Function Measuring range Resolution Accuracy TODO: Realistic specifications
Voltage 80~260V 0.1V 0.5%
Current 0~10A or 0~100A* 0.01A or 0.02A* 0.5%
Active power 0~2.3kW or 0~23kW* 0.1W 0.5%
Active energy 0~9999.99kWh 1Wh 0.5%
Frequency 45~65Hz 0.1Hz 0.5%
Power factor 0.00~1.00 0.01 1%

* Using the external current transformer instead of the built in shunt

Compatibility

MCU Hardware Serial Software Serial Not Tested Examples Notes
ATmega168 X HardwareSerial SoftwareSerial
ATmega328 (Arduino Uno) (:white_check_mark:) ✔️ HardwareSerial SoftwareSerial HW Serial conflicts with Debug output. It can be used however without having any Serial Console output
ATmega2560 (Arduino Mega) ✔️ ✔️ HardwareSerial SoftwareSerial
ESP8266 (:white_check_mark:) ✔️ SoftwareSerial HW Serial conflicts with Debug output Serial
ESP32 ✔️ HardwareSerial SW Serial not really needed as ESP32 has 3 HW serials with configurable pins
STM32 BluePill X

Examples

Hardware Serial

This example uses Hardware Serial2 in order to interface with the PZEM module. Note that not all MCUs feature multiple Serial ports. It won't for example work on the Arduino Uno.

#include <PZEM004Tv30.h>

/* Hardware Serial2 is only available on certain boards.
 * For example the Arduino MEGA 2560
*/
#if defined(ESP32)
PZEM004Tv30 pzem(Serial2, 16, 17);
#else
PZEM004Tv30 pzem(Serial2);
#endif

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

    // Uncomment in order to reset the internal energy counter
    // pzem.resetEnergy();
}

void loop() {
        
    Serial.print("Custom Address:");
    Serial.println(pzem.readAddress(), HEX);

    // Read the data from the sensor
    float voltage = pzem.voltage();
    float current = pzem.current();
    float power = pzem.power();
    float energy = pzem.energy();
    float frequency = pzem.frequency();
    float pf = pzem.pf();

    // Check if the data is valid
    if(isnan(voltage)){
        Serial.println("Error reading voltage");
    } else if (isnan(current)) {
        Serial.println("Error reading current");
    } else if (isnan(power)) {
        Serial.println("Error reading power");
    } else if (isnan(energy)) {
        Serial.println("Error reading energy");
    } else if (isnan(frequency)) {
        Serial.println("Error reading frequency");
    } else if (isnan(pf)) {
        Serial.println("Error reading power factor");
    } else {

        // Print the values to the Serial console
        Serial.print("Voltage: ");      Serial.print(voltage);      Serial.println("V");
        Serial.print("Current: ");      Serial.print(current);      Serial.println("A");
        Serial.print("Power: ");        Serial.print(power);        Serial.println("W");
        Serial.print("Energy: ");       Serial.print(energy,3);     Serial.println("kWh");
        Serial.print("Frequency: ");    Serial.print(frequency, 1); Serial.println("Hz");
        Serial.print("PF: ");           Serial.println(pf);

    }

    Serial.println();
    delay(2000);
}

Output:

Custom Address:10
Voltage: 229.60V
Current: 0.10A
Power: 4.50W
Energy: 7.368kWh
Frequency: 50.0Hz
PF: 0.19

Software Serial

Using the <SoftwareSerial.h> library...

#include <PZEM004Tv30.h>
#include <SoftwareSerial.h>

/* Use software serial for the PZEM
 * Pin 11 Rx (Connects to the Tx pin on the PZEM)
 * Pin 12 Tx (Connects to the Rx pin on the PZEM)
*/

SoftwareSerial pzemSWSerial(11, 12);
PZEM004Tv30 pzem;

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

void loop() {
         
    Serial.print("Custom Address:");
    Serial.println(pzem.readAddress(), HEX);

    // Read the data from the sensor
    float voltage = pzem.voltage();
    float current = pzem.current();
    float power = pzem.power();
    float energy = pzem.energy();
    float frequency = pzem.frequency();
    float pf = pzem.pf();

    // Check if the data is valid
    if(isnan(voltage)){
        Serial.println("Error reading voltage");
    } else if (isnan(current)) {
        Serial.println("Error reading current");
    } else if (isnan(power)) {
        Serial.println("Error reading power");
    } else if (isnan(energy)) {
        Serial.println("Error reading energy");
    } else if (isnan(frequency)) {
        Serial.println("Error reading frequency");
    } else if (isnan(pf)) {
        Serial.println("Error reading power factor");
    } else {

        // Print the values to the Serial console
        Serial.print("Voltage: ");      Serial.print(voltage);      Serial.println("V");
        Serial.print("Current: ");      Serial.print(current);      Serial.println("A");
        Serial.print("Power: ");        Serial.print(power);        Serial.println("W");
        Serial.print("Energy: ");       Serial.print(energy,3);     Serial.println("kWh");
        Serial.print("Frequency: ");    Serial.print(frequency, 1); Serial.println("Hz");
        Serial.print("PF: ");           Serial.println(pf);

    }

    Serial.println();
    delay(2000);
}

Output:

Custom Address:11
Voltage: 229.60V
Current: 0.10A
Power: 4.50W
Energy: 7.368kWh
Frequency: 50.0Hz
PF: 0.19

Links

Check LINKS & REFs page for additional DOC's and related links

Contributing

Many thanks to all the other contributors that add new features, find bugs and generally keep this project afloa.


Thank you to @olehs for inspiring this library.

pzem-004t-v30's People

Contributors

bembenk18 avatar fxeio avatar kaconk17 avatar kozfelipe avatar mandulaj avatar ste94pz avatar vortigont avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pzem-004t-v30's Issues

problems with wemos d1 and PZEM-004T

My connections:

  • Wemos D5 to PZEM Tx
  • Wemos D6 to PZEM Rx
  • Wemos 5V to PZEM 5V
  • Wemos GND to PZEM GND
    After running a few minutes the system will crush. Error messages:

Exception 0: Illegal instruction

PC: 0x402021e4: circular_queue ::push(unsigned int&&) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/10.1.0/bits/atomic_base.h line 420
EXCVADDR: 0x00000000

Decoding stack results
0x4010079c: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 166
0x40100e2c: check_poison_block(umm_block*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/umm_malloc/umm_poison.c line 95
0x40100cd1: umm_free_core(void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/umm_malloc/umm_malloc.cpp line 351
0x401006d8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 137
0x401006d8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 137
0x401006d8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 137
0x401006d8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 137
0x40204768: loop_task(ETSEvent*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_features.h line 92
0x4020dee4: sys_timeout_LWIP2 at core/timeouts.c line 304
0x4020df57: tcpip_tcp_timer at core/timeouts.c line 153
0x40204784: loop_task(ETSEvent*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 208
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x4020d6b2: glue2esp_linkoutput at glue-esp/lwip-esp.c line 241
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401003b0: SoftwareSerial::rxBitISR(SoftwareSerial*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/10.1.0/bits/unique_ptr.h line 420
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401007b8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 174
0x4010079c: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 166
0x401003b0: SoftwareSerial::rxBitISR(SoftwareSerial*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/10.1.0/bits/unique_ptr.h line 420
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x401006d8: interrupt_handler(void*, void*) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring_digital.cpp line 137
0x40100569: millis() at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring.cpp line 193
0x4010054c: millis() at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring.cpp line 175
0x402021dc: std::_Function_handler >::_M_invoke(const std::_Any_data &, unsigned int &&) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/libraries/SoftwareSerial/src/SoftwareSerial.cpp line 423
0x40201ca8: circular_queue ::for_each(Delegate const&) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/10.1.0/bits/atomic_base.h line 122
0x401001ce: SoftwareSerial::writePeriod(unsigned int, unsigned int, bool) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/libraries/SoftwareSerial/src/SoftwareSerial.cpp line 263
0x40201f88: SoftwareSerial::rxBits() at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/10.1.0/bits/std_function.h line 303
0x401004fc: ets_post(uint8, ETSSignal, ETSParam) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 177
0x402021d0: std::_Function_handler >::_M_invoke(const std::_Any_data &, unsigned int &&) at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/libraries/SoftwareSerial/src/SoftwareSerial.cpp line 423
0x4020483b: __yield() at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_features.h line 92
0x402015fa: PZEM004Tv30::recieve(unsigned char*, unsigned short) at /home/willieyu/Arduino/libraries/PZEM-004T-v30-master/PZEM004Tv30.cpp line 469
0x402016aa: PZEM004Tv30::sendCmd8(unsigned char, unsigned short, unsigned short, bool, unsigned short) at /home/willieyu/Arduino/libraries/PZEM-004T-v30-master/PZEM004Tv30.cpp line 246
0x40201752: PZEM004Tv30::updateValues() at /home/willieyu/Arduino/libraries/PZEM-004T-v30-master/PZEM004Tv30.cpp line 377
0x402018dd: PZEM004Tv30::voltage() at /home/willieyu/Arduino/libraries/PZEM-004T-v30-master/PZEM004Tv30.cpp line 130
0x40201077: getPzem() at /home/willieyu/Arduino/PZEMSoftwareSerial/PZEMSoftwareSerial.ino line 119
0x40201374: loop() at /home/willieyu/Arduino/PZEMSoftwareSerial/PZEMSoftwareSerial.ino line 78
0x40204928: loop_wrapper() at /home/willieyu/arduino/arduino-1.8.13/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line

197

Sketch:

#include <PZEM004Tv30.h>
#include <ESP8266WiFi.h>

/* Use software serial for the PZEM

  • Pin 11 Rx (Connects to the Tx pin on the PZEM)
  • Pin 12 Tx (Connects to the Rx pin on the PZEM)
    */
    PZEM004Tv30 pzem(D5, D6);

#ifndef APSSID
#define APSSID ""
#define APPSK "
"
#endif

const char* ssid = APSSID;
const char* password = APPSK;

const char* host = "192.168.0.103";
const int port = 3000;

int i = 0;

WiFiClient client;

void prinScanResult(int networksFound)
{
Serial.printf("%d network(s) found\n", networksFound);
for (int i = 0; i < networksFound; i++)
{
Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i + 1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : "");
}
}

void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("trying to connected WIFI...");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// Use WiFiClient class to create TCP connections
if (!client.connected()) {
Serial.println("connected to server");
if (!client.connect(host, port)) {
Serial.println("connection failed");
delay(5000);
return;
}
Serial.println("connected sucess ");
}

}

void loop() {

if (!client.connected()) {
  Serial.println("reconnected to server");
  if (!client.connect(host, port)) {
    Serial.println("reconnection failed");
    delay(5000);
    return;
  }
  Serial.println("reconnected sucess");
}

getPzem(); 

     // This will send a string to the server
Serial.println("sending data to server");
if (client.connected()) {
  client.print("{name:'test'}");
}

// delay(2000);
// wait for data to be available
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
if((WiFi.status() != WL_CONNECTED)){
Serial.println(">>> WiFi disconnected!");
}else{
Serial.println(">>> WiFi connected!");
}
delay(60000);
return;
}
}

  // Read all the lines of the reply from server and print them to Serial
  Serial.println("receiving from remote server");
  // not testing 'client.connected()' since we do not need to send data here
  while (client.available()) {
    char ch = static_cast<char>(client.read());
    Serial.print(ch);
  }

   Serial.println();


Serial.println();
delay(2000);

}

void getPzem(){

// String result = "";
// result += "[";
float voltage = pzem.voltage();
if( !isnan(voltage) ){
Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V");
// result += "{name:'voltage', value:"+String(voltage)+", unit:'V'},";
} else {
Serial.println("Error reading voltage");
}

float current = pzem.current();
if( !isnan(current) ){
    Serial.print("Current: "); Serial.print(current); Serial.println("A");

// result += "{name:'current', value:"+String(current)+", unit:'A'},";
} else {
Serial.println("Error reading current");
}

float power = pzem.power();
if( !isnan(power) ){
    Serial.print("Power: "); Serial.print(power); Serial.println("W");

// result += "{name:'power', value:"+String(power)+", unit:'W'},";
} else {
Serial.println("Error reading power");
}

float energy = pzem.energy();
if( !isnan(energy) ){
    Serial.print("Energy: "); Serial.print(energy,3); Serial.println("kWh");

// result += "{name:'energy', value:"+String(energy)+", unit:'kWh'},";
} else {
Serial.println("Error reading energy");
}

float frequency = pzem.frequency();
if( !isnan(frequency) ){
    Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz");

// result += "{name:'frequency', value:"+String(frequency)+", unit:'Hz'},";
} else {
Serial.println("Error reading frequency");
}

float pf = pzem.pf();
if( !isnan(pf) ){
    Serial.print("PF: "); Serial.println(pf);

// result += "{name:'pf', value:"+String(pf)+", unit:''},";
} else {
Serial.println("Error reading power factor");
}

// result += "]";
// return result;
}`

not an issue, nor a pull request as it's a change the API, but got a working samd21 and pzem.

Hi,

So as I have wrote in that long title after some hours I got a working SAMD21 with pzem-004t-v30 using Uart/Sercom.
First thank @mandulaj for your work :-D
ie: I got inspiration from the TinyGSM library and a post on stackoverflow, and the knx from thelsing, and many bug report :-D

Instead of using traditional hardwareSerial or softwareserial, as neither work well with new microcontroller like the samd21/51 (DUE, Feather M0, sparkfun SAMD21 ....), I have used the Stream class with reference instead of pointer...

in the .ino file:

PZEM004Tv30 pzem(Serial1, PZEM_DEFAULT_ADDR);
Setup call add:
Serial1.begin(9600);

In .h

Change :
PZEM004Tv30(HardwareSerial* port, uint8_t addr=PZEM_DEFAULT_ADDR);
to
PZEM004Tv30(HardwareSerial& serialPZEM, uint8_t addr=PZEM_DEFAULT_ADDR);

And
Stream* _serial; // Serial interface
to
Stream& _serial; // Serial interface

And in .cpp
comment:
//extern HardwareSerial Serial;

Replace:

PZEM004Tv30::PZEM004Tv30(HardwareSerial* port, uint8_t addr) {

port->begin(PZEM_BAUD_RATE);
this->_serial = port;
this->_isSoft = false;
init(addr);
}

with:
PZEM004Tv30::PZEM004Tv30(HardwareSerial& serialPZEM, uint8_t addr) :
_serial(serialPZEM)
{
this->_serial = serialPZEM;
init(addr);
}

Remove: // Need to find cleaner way that completely removing :-D

if(_isSoft)
delete this->_serial;

And line around line 244
change _serial->write(sendBuffer, 8); to _serial.write(sendBuffer, 8);

same for 431/432 change the => with .
same for 463-466

This solution could remove many DEFINE and condition in the .h and .cpp and just need something like:
for softwareSerial:
SoftwareSerial SerialPZEM(2, 3);

HardwareSerial \ Uart and sercom should be the same.
ie for an another sercom on a samd21
Uart Serial2(&sercom1, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX); //TX D10, RX D12
The "extern HardwareSerial serial" could be define here....?!?!

@mandulaj : what do you think about changing a little bit the API? to be more future proof and use direct Stream class ?

Pzem reads 2-way?

Other electronic meters often distinguish the current direction.
Is there any way pzem can distinguish the current direction?
Because I want to have kWh import and kWh export
please help!

Compatibility with Arduino nano 33 IoT

I was trying to connect PZEM004 to Arduino nano 33 IoT board, and this library is using SofwareSerial.h,
I tried to dig deeper, and Nano 33 IoT does not use SoftwareSerial anymore, so I'm not sure how to make
PZEM004 compatible with Nano 33 IoT board, could not find anything in the internet about this issue.
Maybe someone has an idea how to solve this?

This is from arduino official site:

Serial ports on the Arduino NANO 33 IoT

The USB connector of the board is directly connected to the USB host pins of the SAMD21. This routing enables you to use the Arduino NANO 33 IoT as a client USB peripheral (acting as a mouse or a keyboard connected to the computer) or as a USB host device so that devices like a mouse, keyboard, or an Android phone can be connected to the Arduino NANO 33 IoT. This port can also be used as a virtual serial port using the Serial object in the Arduino programming language. The RX0 and TX1 pins are a second serial port available as Serial1

So I've tried to simply write the code like this:

#include <PZEM004Tv30.h>

PZEM004Tv30 pzem(Serial1);

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

  Serial.print("Reset Energy");
  pzem.resetEnergy();


  Serial.print("Set address to 0x42");
  pzem.setAddress(0x42);
}

void loop() {
  float volt = pzem.voltage();
  float cur = pzem.current();
  float powe = pzem.power();
  float ener = pzem.energy();
  float freq = pzem.frequency();
  float pf = pzem.pf();
  

  Serial.print(volt);
  Serial.print(" ");
  Serial.print(cur);
  Serial.print(" ");
  Serial.print(powe);
  Serial.print(" ");
  Serial.print(ener,3);
  Serial.print(" ");
  Serial.print(freq);
  Serial.print(" ");
  Serial.println(pf);

  delay(1000);
}

But getting error output in aruino IDE:

error: no matching function for call to 'PZEM004Tv30::PZEM004Tv30(Uart&)'

PZEM004Tv30 pzem(Serial1);

Documents\Arduino\libraries\PZEM-004T-v30/PZEM004Tv30.h:65:5: note: candidate: PZEM004Tv30::PZEM004Tv30(arduino::HardwareSerial*, uint8_t)

PZEM004Tv30(HardwareSerial* port, uint8_t addr=PZEM_DEFAULT_ADDR);

^~~~~~~~~~~

Documents\Arduino\libraries\PZEM-004T-v30/PZEM004Tv30.h:59:7: note: candidate: constexpr PZEM004Tv30::PZEM004Tv30(const PZEM004Tv30&)

class PZEM004Tv30

^~~~~~~~~~~

exit status 1
no matching function for call to 'PZEM004Tv30::PZEM004Tv30(Uart&)'

Add calibration function to the library

The chip supports this.
This seems to be in the documentation. It would be great.

The format of the master command for calibrating a slave (6 bytes in total):

0xF8 + 0x41 + 0x37 + 0x21 + CRC check high byte + CRC check low byte.

Correct answer: 0xF8 + 0x41 + 0x37 + 0x21 + CRC check high byte + CRC check low byte.

Error response: 0xF8 + 0xC1 + anomalous code + CRC check high byte + CRC check low byte.

It should be noted that the calibration takes from 3 to 4 seconds, after the master sends a command, if the calibration is successful, it takes 3-4 seconds to get a response from the slave.

Measuring speed

Hello,

dont know if its an issue but is there some limitation to measuring only once a second? And if so is there a way to make the process faster. It looks like the measuring is happening faster but data get "updated" only once a second. What should i do if i want to measure faster?

I apologize, english is not my first language and Thank you all for your answers.

Refresh rate

Hi,
First i would like to thank you for the work done on library.
do you know how to speed up the refresh rate of measurements?
i did some testing with a n Arduino Mega and a 2x16 display to find out that the rate is around 1 sec or more.
it did not matther if i disable serial print statements.

do you have an idea?

Regards, Alrik

How to enable multiple slave in an same Serial Interface ?

Hi, I'd like do understand how can I use more than one PZEM using the same Serial Interface as described in README. I've tested some ways but none worked.
PS: I'm starting to use Github these days, sorry if it isn't the correct space. Thanks!

Hardserial on bluepill doesn't work

Hi everyone!

I just got the pzem v3 module and found this library (I use hardserial examples, because like in pzem v2 to use bluepill, we can only use hardserial libraries). I use Bluepill as MCU, and use serial 1 on PA9 & PA10 pins, but Sketch can't be uploaded and error messages like this appear:

Arduino: 1.8.5 (Windows 10), Board: "Generic STM32F103C series, STM32F103C8 (20k RAM. 64k Flash), STLink, 72Mhz (Normal), Smallest (default)"
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 32: 23: error: conflicting declaration 'HardwareSerial Serial'
 extern Hardware Serial Serial;
                       ^
In file included from C: \ Users \ Windows 10 \ Documents \ Arduino \ hardware \ Arduino_STM32-master \ STM32F1 \ cores \ maple / wirish.h: 71: 0,
                 from C: \ Users \ Windows 10 \ Documents \ Arduino \ hardware \ Arduino_STM32-master \ STM32F1 \ cores \ maple / Arduino.h: 30,
                 from C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.h: 19,
                 from C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 1:
C: \ Users \ Windows 10 \ Documents \ Arduino \ hardware \ Arduino_STM32-master \ STM32F1 \ cores \ maple / usb_serial.h: 96: 22: error: 'Serial' has a previous declaration as 'USBSerial Serial'
     extern USB Serial Serial;
                      ^
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: In constructor 'PZEM004Tv30 :: PZEM004Tv30 (uint8_t, uint8_t, uint8_t)':
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 62: 5: error: 'Software Serial' was not declared in this scope
     Software Serial * port = new Software Serial (receivePin, transmitPin);
     ^
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 62: 21: error: 'port' was not declared in this scope
     Software Serial * port = new Software Serial (receivePin, transmitPin);
                     ^
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 62: 32: error: expected type-specifier before 'SoftwareSerial'
     Software Serial * port = new Software Serial (receivePin, transmitPin);
                                ^
C: \ Users \ Windows 10 \ Documents \ Arduino \ libraries \ PZEM-004T-v30-master \ PZEM004Tv30.cpp: 62: 32: error: expected ';' before 'Software Serial'
exit status 1
Error compiling for Generic STM32F103C series board.

how is the solution to solve this problem?
I'm not good at programming for now

by the way, thank you for making this library for the v3 pzem module, hopefully it will get better in the future
Thank you!

Use programmable slave addresses

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
To monitor my solar panels, I need 5 PZEM as slaves. With the old library from [@olehs] it war possible. Why I can set the slaveAdress, if I can't use it?

Describe alternatives you've considered
I can use 5 Arduinos with SD-Card for ever Panel. Or I use the old PZEM004T. With this I have implemented three phase monitoring.
Additional context
Add any other context or screenshots about the feature request here.

Direction of energy

Hello all, in PZEM-004Tv3.0 version, how do we can see the direction of energy? In the older version the IC have a output that indicate the direction of energy ... like this article [https://github.com/apreb/eNode ].... it's possible in the new V3.0 version?

Wemos D1 Mini / Software Serial compile error

Hello,

First, thanks U for this library ! 👍

I want to use her with a "Wemos D1 Mini" board. When i compile the exemple program named "PZEMSoftwareSerial" i have the following error code :
C:\Users\ADN\Documents\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:456:42: error: 'class SoftwareSerial' has no member named 'listen'.

I have been looking for a solution on internet for several days but without success...

For additionnal information, this program work very well on a "Arduino Uno" board.

Thanks U in advance

Add debugging capability to the library

Wee need a way to easily set the debug level of the library in order to print out useful statistics for debugging purposes.

For start I imagine a simple debug macro setting a verbosity level which allows to print information to the debug console when receiving or sending commands to the PZEM module:

// For setting debug level verbosity
#define PZEM004TV30_DEBUG 0

// For configuring custom serial debug interface
#define PZEM004TV30_DEBUG_SERIAL Serial

The debug code should be conditioned by the DEBUG verbosity level and only compiled if required.

Reduce RAM usage by storing crcTable in PROGMEM

Hi, thanks for the module!

You could reduce the RAM usage of the module by declaring crcTable as:
static PROGMEM const uint16_t crcTable[]

In this case reading from the crcTable should be updated to:
crc ^= (uint16_t)pgm_read_word(&crcTable[nTemp]);

Configure Current probe

At the moment, the library assumes the 100A current probe. There should be a way to set the current probe version to the 10A version.

Test the actual capabilities of the PZEM module

Though amazing, the manufacturer's specifications are sometimes slightly too optimistic. As was the case in this issue #47, the true Energy accumulation gets imprecise after about 60kWh.

It would be great to test the true specifications of the units with verified instruments so that we can get a better understanding of the real expectations we can have from the modules.

  • Voltage range and accuracy
  • Current range and accuracy
  • PF range and accuracy
  • Frequency range and accuracy
  • Energy range and accuracy
  • Power range and accuracy

I have an oscilloscope capable of doing the measurements, but in case anyone has professional instruments, it would be great to get more precise measurements.

Multiple PZEMS

Hello friends, tell me how to fix the library to read in a loop.
I don't like the case option.
PZEM004Tv30 pzem1 (D1, D2);
PZEM004Tv30 pzem2 (D3, D4);
PZEM004Tv30 pzem3 (D5, D6);

v [0] = pzem1.voltage ();
c [0] = pzem1.current ();
p [0] = pzem1.power ();
e [0] = pzem1.energy ();
f [0] = pzem1.frequency ();

v [1] = pzem2.voltage ();
c [1] = pzem2.current ();
p [1] = pzem2.power ();
e [1] = pzem2.energy ();
f [1] = pzem2.frequency ();

v [2] = pzem3.voltage ();
c [2] = pzem3.current ();
p [2] = pzem3.power ();
e [2] = pzem3.energy ();
f [2] = pzem3.frequency ();

Is it possible to somehow bring to the form:
for (size_t i = 0; i < 3; i++){
v [i] = pzem[i].voltage ();
c [i] = pzem[i].current ();
p [i] = pzem[i].power ();
e [i] = pzem[i].energy ();
f [i] = pzem[i].frequency ();
}

Need example code (Arduino) to 'set' and 'read' getPowerAlarm(); and setPowerAlarm(uint16_t watts);

Hello
I can't seem to get the 'getPowerAlarm()' function to output a usable response. Does the returned value (boolean) in this case represent that the power alarm is 'triggered'? Or does it only signify that a value has been added to the 'setPowerAlarm' register?
If you could point me in the direction of an example of working code for the 'get and set' Power alarm functions, it would be very much appreciated.

**forgot to mention that I am using a Chinese Arduino nano clone, all other functions work perfectly for my application so the only issue seems to be the configuration of the power alarm.

Thanks in advance.
mjd

Cannot use the library on Platformio

I've tried to import it to the project and complied with platformio core there's an error that seems to come out from SoftwareSerial library. Does anyone have any solution

Screen Shot

here is the error log:
`Processing megaatmega2560 (platform: atmelavr; board: megaatmega2560; framework: arduino)

Verbose mode can be enabled via -v, --verbose option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/megaatmega2560.html
PLATFORM: Atmel AVR 1.15.0 > Arduino Mega or Mega 2560 ATmega2560 (Mega 2560)
HARDWARE: ATMEGA2560 16MHz, 8KB RAM, 248KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.1.1
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 15 compatible libraries
Scanning dependencies...
Dependency Graph
|-- 1.0.0
| |-- 6.6.4
Building in release mode
Compiling .pio/build/megaatmega2560/src/main.cpp.o
Compiling .pio/build/megaatmega2560/lib2c4/EspSoftwareSerial_ID168/SoftwareSerial.cpp.o
Compiling .pio/build/megaatmega2560/libad6/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp.o
Archiving .pio/build/megaatmega2560/libFrameworkArduinoVariant.a
Compiling .pio/build/megaatmega2560/FrameworkArduino/CDC.cpp.o
Indexing .pio/build/megaatmega2560/libFrameworkArduinoVariant.a
Compiling .pio/build/megaatmega2560/FrameworkArduino/HardwareSerial.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/HardwareSerial0.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/HardwareSerial1.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/HardwareSerial2.cpp.o
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:27:0,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp:1:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:19: error: 'Delegate' has not been declared
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:27: error: expected ',' or '...' before '<' token
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:31: error: 'Delegate' has not been declared
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:39: error: expected ',' or '...' before '<' token
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:27:0,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30,
from src/main.cpp:2:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:19: error: 'Delegate' has not been declared
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:27: error: expected ',' or '...' before '<' token
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:31: error: 'Delegate' has not been declared
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:39: error: expected ',' or '...' before '<' token
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:27:0,
from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:23:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:19: error: 'Delegate' has not been declared
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:27: error: expected ',' or '...' before '<' token
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:31: error: 'Delegate' has not been declared
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:222:39: error: expected ',' or '...' before '<' token
bool for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: variable or field 'for_each' declared void
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:55: error: expected primary-expression before 'void'
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:76: error: expected primary-expression before '>' token
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:78: error: 'fun' was not declared in this scope
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue' is not a static data member of 'class circular_queue<T, ForEachArg>'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: variable or field 'for_each' declared void
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:55: error: expected primary-expression before 'void'
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:76: error: expected primary-expression before '>' token
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:78: error: 'fun' was not declared in this scope
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue' is not a static data member of 'class circular_queue<T, ForEachArg>'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: template definition of non-template 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue'
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:67: error: expected primary-expression before 'bool'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:87: error: expected primary-expression before '>' token
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:89: error: 'fun' was not declared in this scope
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: template definition of non-template 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue'
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:67: error: expected primary-expression before 'bool'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:87: error: expected primary-expression before '>' token
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:89: error: 'fun' was not declared in this scope
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp:1:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:20: error: 'Delegate' has not been declared
void onReceive(Delegate<void(int available), void*> handler);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:28: error: expected ',' or '...' before '<' token
void onReceive(Delegate<void(int available), void*> handler);
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp:1:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:252:5: error: 'Delegate' does not name a type
Delegate<void(int available), void*> receiveHandler;
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp:1:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:162:12: error: 'size_t SoftwareSerial::readBytes(uint8_t*, size_t)' marked 'override', but does not override
size_t readBytes(uint8_t* buffer, size_t size) override;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:165:12: error: 'size_t SoftwareSerial::readBytes(char*, size_t)' marked 'override', but does not override
size_t readBytes(char* buffer, size_t size) override {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: variable or field 'for_each' declared void
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:46: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:55: error: expected primary-expression before 'void'
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:76: error: expected primary-expression before '>' token
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:357:78: error: 'fun' was not declared in this scope
void circular_queue<T, ForEachArg>::for_each(Delegate<void(T&&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue' is not a static data member of 'class circular_queue<T, ForEachArg>'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: template definition of non-template 'bool circular_queue<T, ForEachArg>::for_each_rev_requeue'
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:58: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:67: error: expected primary-expression before 'bool'
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:87: error: expected primary-expression before '>' token
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:376:89: error: 'fun' was not declared in this scope
bool circular_queue<T, ForEachArg>::for_each_rev_requeue(Delegate<bool(T&), ForEachArg> fun)
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from src/main.cpp:2:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:20: error: 'Delegate' has not been declared
void onReceive(Delegate<void(int available), void*> handler);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:28: error: expected ',' or '...' before '<' token
void onReceive(Delegate<void(int available), void*> handler);
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:23:0:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:20: error: 'Delegate' has not been declared
void onReceive(Delegate<void(int available), void*> handler);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:193:28: error: expected ',' or '...' before '<' token
void onReceive(Delegate<void(int available), void*> handler);
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:23:0:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:252:5: error: 'Delegate' does not name a type
Delegate<void(int available), void*> receiveHandler;
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:23:0:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:162:12: error: 'size_t SoftwareSerial::readBytes(uint8_t*, size_t)' marked 'override', but does not override
size_t readBytes(uint8_t* buffer, size_t size) override;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:165:12: error: 'size_t SoftwareSerial::readBytes(char*, size_t)' marked 'override', but does not override
size_t readBytes(char* buffer, size_t size) override {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::begin(uint32_t, SoftwareSerialConfig, int8_t, int8_t, bool, int, int)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:71:20: error: 'ESP' was not declared in this scope
m_bitCycles = (ESP.getCpuFreqMHz() * 1000000UL + baud / 2) / baud;
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from src/main.cpp:2:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:252:5: error: 'Delegate' does not name a type
Delegate<void(int available), void*> receiveHandler;
^
In file included from /Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.h:30:0,
from src/main.cpp:2:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:162:12: error: 'size_t SoftwareSerial::readBytes(uint8_t*, size_t)' marked 'override', but does not override
size_t readBytes(uint8_t* buffer, size_t size) override;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:165:12: error: 'size_t SoftwareSerial::readBytes(char*, size_t)' marked 'override', but does not override
size_t readBytes(char* buffer, size_t size) override {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:84:40: error: no match for 'operator||' (operand types are 'bool' and 'std::unique_ptr<circular_queue >')
if (m_buffer && (!m_parityMode || m_parityBuffer) && m_isrBuffer) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:84:40: note: candidate: operator||(bool, bool)
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:84:40: note: no known conversion for argument 2 from 'std::unique_ptr<circular_queue >' to 'bool'
/Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp: In destructor 'PZEM004Tv30::~PZEM004Tv30()':
/Users/wit03/.platformio/lib/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp:94:22: warning: deleting object of abstract class type 'Stream' which has non-virtual destructor will cause undefined behaviour [-Wdelete-non-virtual-dtor]
delete this->_serial;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::end()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:108:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_buffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_buffer) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:112:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_isrBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_isrBuffer) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'uint32_t SoftwareSerial::baudRate()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:118:12: error: 'ESP' was not declared in this scope
return ESP.getCpuFreqMHz() * 1000000UL / m_bitCycles;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::enableRx(bool)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:156:31: error: 'ESP' was not declared in this scope
m_isrLastCycle = (ESP.getCycleCount() | 1) ^ m_invert;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:158:125: error: 'attachInterruptArg' was not declared in this scope
attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast<void ()(void)>(rxBitISR), this, CHANGE);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:160:150: error: 'attachInterruptArg' was not declared in this scope
attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast<void ()(void)>(rxBitSyncISR), this, m_invert ? RISING : FALLING);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'virtual int SoftwareSerial::read()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:176:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_parityBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_parityBuffer)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'size_t SoftwareSerial::read(uint8_t*, size_t)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:192:33: error: 'class circular_queue' has no member named 'pop_n'
if (0 == (avail = m_buffer->pop_n(buffer, size))) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:194:27: error: 'class circular_queue' has no member named 'pop_n'
avail = m_buffer->pop_n(buffer, size);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:197:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_parityBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_parityBuffer) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:201:25: error: 'class circular_queue' has no member named 'pop_n'
m_parityBuffer->pop_n(nullptr, parityBits / 8);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'virtual int SoftwareSerial::available()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:223:33: error: 'optimistic_yield' was not declared in this scope
optimistic_yield(10000UL);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::preciseDelay(bool)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:232:51: error: 'xt_wsr_ps' was not declared in this scope
if (!m_intTxEnabled) { xt_wsr_ps(m_savedPS); }
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:233:24: error: 'ESP' was not declared in this scope
auto expired = ESP.getCycleCount() - m_periodStart;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:239:98: error: 'optimistic_yield' was not declared in this scope
while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) { optimistic_yield(10000); }
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:241:54: error: 'xt_rsil' was not declared in this scope
if (!m_intTxEnabled) { m_savedPS = xt_rsil(15); }
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:245:17: error: 'ESP' was not declared in this scope
while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) {}
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:248:21: error: 'ESP' was not declared in this scope
m_periodStart = ESP.getCycleCount();
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'size_t SoftwareSerial::write(const uint8_t*, size_t, SoftwareSerialParity)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:293:31: error: 'xt_rsil' was not declared in this scope
m_savedPS = xt_rsil(15);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:298:21: error: 'ESP' was not declared in this scope
m_periodStart = ESP.getCycleCount();
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:359:28: error: 'xt_wsr_ps' was not declared in this scope
xt_wsr_ps(m_savedPS);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'virtual void SoftwareSerial::flush()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:370:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_parityBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_parityBuffer)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'virtual int SoftwareSerial::peek()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:390:9: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_parityBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_parityBuffer) m_lastReadParity = m_parityBuffer->peek() & m_parityOutPos;
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::rxBits()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:402:23: error: 'class std::atomic' has no member named 'exchange'
if (m_isrOverflow.exchange(false)) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:412:13: error: 'ESP' was not declared in this scope
if (ESP.getCycleCount() - m_isrLastCycle > detectionCycles) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:419:81: error: no matching function for call to 'circular_queue::for_each(SoftwareSerial::rxBits()::<lambda(const uint32_t&)>)'
m_isrBuffer->for_each([this](const uint32_t& isrCycle) { rxBits(isrCycle); });
^
In file included from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.h:27:0,
from /Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:23:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:10: note: candidate: void circular_queue<T, ForEachArg>::for_each(int) [with T = long unsigned int; ForEachArg = void]
void for_each(Delegate<void(T&&), ForEachArg> fun);
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/circular_queue/circular_queue.h:210:10: note: no known conversion for argument 1 from 'SoftwareSerial::rxBits()::<lambda(const uint32_t&)>' to 'int'
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::rxBits(const uint32_t&)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:472:25: error: could not convert '((SoftwareSerial*)this)->SoftwareSerial::m_parityBuffer' from 'std::unique_ptr<circular_queue >' to 'bool'
if (m_parityBuffer)
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In static member function 'static void SoftwareSerial::rxBitISR(SoftwareSerial*)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:500:25: error: 'ESP' was not declared in this scope
uint32_t curCycle = ESP.getCycleCount();
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In static member function 'static void SoftwareSerial::rxBitSyncISR(SoftwareSerial*)':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:509:22: error: 'ESP' was not declared in this scope
uint32_t start = ESP.getCycleCount();
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: At global scope:
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:531:32: error: variable or field 'onReceive' declared void
void SoftwareSerial::onReceive(Delegate<void(int available), void*> handler) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:531:32: error: 'Delegate' was not declared in this scope
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:531:41: error: expected primary-expression before 'void'
void SoftwareSerial::onReceive(Delegate<void(int available), void*> handler) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:531:62: error: expected primary-expression before 'void'
void SoftwareSerial::onReceive(Delegate<void(int available), void*> handler) {
^
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp: In member function 'void SoftwareSerial::perform_work()':
/Users/wit03/.platformio/lib/EspSoftwareSerial_ID168/src/SoftwareSerial.cpp:538:9: error: 'receiveHandler' was not declared in this scope
if (receiveHandler) {
^
*** [.pio/build/megaatmega2560/src/main.cpp.o] Error 1
*** [.pio/build/megaatmega2560/libad6/PZEM-004T-v30_ID6551/PZEM004Tv30.cpp.o] Error 1
*** [.pio/build/megaatmega2560/lib2c4/EspSoftwareSerial_ID168/SoftwareSerial.cpp.o] Error 1
================================= [FAILED] Took 1.33 seconds =================================`

Issue with multiple pzems - solved

Hi there,
i worked on a project to monitor multiple breakers using this library + wemos d1 mini, but came into some issues. First it was powering them via internal voltage regulator which was solved by using max 6 pzem on one gpio pair, so only 6 pzems having load at the same time. Other issue was memory limit, with more than 16 devices i get into system crash - heap was full. This was solved by great help of a guy @mzero on adafruit discord channel. You need to modify

PZEM004Tv30.h
####################################
#if defined(PZEM004_SOFTSERIAL)
PZEM004Tv30(uint8_t receivePin, uint8_t transmitPin, uint8_t addr=PZEM_DEFAULT_ADDR);
PZEM004Tv30(SoftwareSerial &port, uint8_t addr=PZEM_DEFAULT_ADDR);
#endif
####################################

PZEM004T.cpp
####################################
#if defined(PZEM004_SOFTSERIAL)
PZEM004Tv30::PZEM004Tv30(uint8_t receivePin, uint8_t transmitPin, uint8_t addr)
{
SoftwareSerial *port = new SoftwareSerial(receivePin, transmitPin);
port->begin(PZEM_BAUD_RATE);
this->_serial = port;
this->_isSoft = true;
init(addr);
}
PZEM004Tv30::PZEM004Tv30(SoftwareSerial &port, uint8_t addr)
{
port.begin(PZEM_BAUD_RATE);
this->_serial = &port;
this->_isSoft = false;
init(addr);
}
####################################

then you can use this example:
####################################
SoftwareSerial serial56(D5, D6);
SoftwareSerial serial34(D3, D4);
SoftwareSerial serial12(D1, D2);

PZEM004Tv30 pzem1(serial56, 0x01);
PZEM004Tv30 pzem2(serial56, 0x02);
PZEM004Tv30 pzem3(serial34, 0x03);
PZEM004Tv30 pzem4(serial34, 0x04);
PZEM004Tv30 pzem5(serial12, 0x05);
PZEM004Tv30 pzem6(serial12, 0x06);
PZEM004Tv30 pzem7(serial56, 0x07);
PZEM004Tv30 pzem8(serial56, 0x08);
PZEM004Tv30 pzem9(serial34, 0x09);
PZEM004Tv30 pzem10(serial34, 0x0a);
PZEM004Tv30 pzem11(serial12, 0x0b);
PZEM004Tv30 pzem12(serial12, 0x0c);
PZEM004Tv30 pzem13(serial56, 0x0d);
PZEM004Tv30 pzem14(serial56, 0x0e);
PZEM004Tv30 pzem15(serial34, 0x0f);
PZEM004Tv30 pzem16(serial34, 0x10);
PZEM004Tv30 pzem17(serial12, 0x11);
PZEM004Tv30 pzem18(serial12, 0x12);
####################################

and memory stays low because heap isnt being used at all because nothing is being dynamically allocated. Once again, big thanx to mzero.

ESP32Support

I'm not able to use this in an ESP32 System, can you please check it and make the necessary changes or provide with an example of use specifically for an ESP32 Device. Thanks.

PZEM-004T v3.0 Power and Energy meter" To save data to SD CARD

"PZEM-004T v3.0 Power and Energy meter" is used very well.

But there is one thing that is not good.

It wants to store the data value in SD CARD.
SD CARD stores data by SPI communication.

It works well if only one SD card is connected to Arduino.
Or "PZEM-004T v3.0 Power and Energy meter".

The problem is that if both are connected, it will not work properly.
Is there any way?

===============================code ==============================

// SD card attached MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 10
#include <PZEM004Tv30.h>
PZEM004Tv30 pzem(7, 8);
#include <SD.h>
const int chipSelect = 10;
String inputString;
boolean stringComplete = false;
boolean doFlag = false;
boolean closeFlag = false;
boolean recFlag = false;
long idx = 0;
File myFile;

void setup() {

pinMode(SS, OUTPUT);
Serial.begin(57600);
// see if the card is present and can be initialized:

if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present"); // don't do anything more:
while (1) ;
}
Serial.println("I'm Ready");
}

void loop() {

while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();

if (inChar != '\r' && inChar != '\n') {
  inputString += inChar;
  stringComplete = true;
} else {
  if (stringComplete) {
    Serial.println(inputString);

    if (inputString.equals("on")) {
      // Serial.println("on_ok");
      doFlag = true;
    } else if (inputString.equals("off")) {
      //  Serial.println("off_ok");
      doFlag = false;
      closeFlag = true;
    }
    inputString = "";
    stringComplete = false;
  }
}

}

if (doFlag) {

if ( recFlag == false) {
  Serial.println("card initialized.");
  char filename[] = "LOGGER00.TXT";
  for (uint8_t i = 0; i < 1000; i++) {
    filename[6] = i / 10 + '0';
    filename[7] = i % 10 + '0';
    if (! SD.exists(filename)) {
      Serial.println(filename);
      myFile = SD.open(filename, FILE_WRITE);  // only open a new file if it doesn't exist
      break;  // leave the loop!
    }
  }
  if (myFile) {
    recFlag = true;
  }
  if (! myFile) {
    Serial.println("couldnt create file");
  }
}

    float voltage = pzem.voltage();

    if (voltage != NAN) {
      Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V");
    } else {
      Serial.println("Error reading voltage");
    }

Serial.println(voltage);
myFile.println(voltage);
myFile.flush();
delay(2000);

} else if (closeFlag) {
Serial.println("gps recording stop");
recFlag = false;
doFlag = false;
closeFlag = false;
myFile.flush();
myFile.close();
}
}

compile errors with MKR 1010

hi, i've been using the library very well on an arduino uno, but today i decided to compile it for an arduino MKR1010, without sucess.
is this board compatible? i tried to use both hardware and software serial.
the errors are the following:

`In file included from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/delay.h:23:0,
from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/Arduino.h:81,
from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.h:41,
from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:23:
C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\variants\mkrwifi1010/variant.h:222:37:

error: conflicting declaration 'HardwareSerial SerialUSB'
#define Serial SerialUSB

                                 ^

C:\Users\\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:54:23: note: in expansion of macro 'Serial'
extern HardwareSerial Serial;
^~~~~~
In file included from C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/Arduino.h:139:0,
from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.h:41,
from C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:23:
C:\Users\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.8.8\cores\arduino/USB/CDC.h:158:16: note: previous declaration as 'Serial_ SerialUSB'
extern Serial_ SerialUSB;
^~~~~~~~~
C:\Users\\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp: In destructor 'PZEM004Tv30::~PZEM004Tv30()':
C:\Users\MEOCloud\Arduino\libraries\PZEM-004T-v30-master\PZEM004Tv30.cpp:119:22: warning: deleting object of abstract class type 'Stream' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]
delete this->_serial;
^~~~~~~
exit status 1
Erro ao compilar para a placa Arduino MKR WiFi 1010.
`

pzem.setAddress() function doesn't work?

Firstly, thank you very much for creating this library. It works great! Recently, I tried the ChangeAddress example with Arduino Mega and Particle's Argon board but couldn't change the address. It prints out 248 always. If I initialize the meter with say PZEM004Tv30 pzem(10, 11, 0x07);, it does work and getAddress() gives me the same.

Anything I'm doing wrong?

Read 2 pzem04 with wemos d1 with 2 serial

Good morning,

I have a problem with wemos d1 and 2 pzem04T

When wemos d1 turns on it does not read the pzem04,
I must first connect 1 pzem and after the other pzem, then it starts to read them

the code is attached

thank you very much

`//

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <PZEM004Tv30.h>

//PZEM004Tv30 pzem(&Serial3);
PZEM004Tv30 pzem (D5, D6);
PZEM004Tv30 pzem2 (D7, D8);

const char* ssid = "+++++++";
const char* password = "++++++++";
const char* mqtt_server = "192.168.1.1";
long previousMillis = 0;
long interval = 60000;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

const char* inTopic = "home/enel";
const char* outTopic = "home/enel";
const char* outTopic_enel_gen_v = "home/enel/generale/v";
const char* outTopic_enel_gen_a = "home/enel/generale/a";
const char* outTopic_enel_gen_w = "home/enel/generale/w";
const char* outTopic_enel_gen_kwh = "home/enel/generale/kwh";
const char* outTopic_enel_gen_hz = "home/enel/generale/hz";
const char* outTopic_enel_gen_pf = "home/enel/generale/pf";
const char* outTopic_enel_ap_v = "home/enel/appartamento/v";
const char* outTopic_enel_ap_a = "home/enel/appartamento/a";
const char* outTopic_enel_ap_w = "home/enel/appartamento/w";
const char* outTopic_enel_ap_kwh = "home/enel/appartamento/kwh";
const char* outTopic_enel_ap_hz = "home/enel/appartamento/hz";
const char* outTopic_enel_ap_pf = "home/enel/appartamento/pf";
const char* outIP = "home/enel/ip";

void setup_wifi() {

delay(5);
WiFi.begin(ssid);

while (WiFi.status() != WL_CONNECTED) {
for(int i = 0; i<500; i++){
delay(1);
}
Serial.print(".");
}
}

void callback(char* topic, byte* payload, unsigned int length) {
if ((char)payload[0] == '1') {
pzem.resetEnergy();
pzem2.resetEnergy();

}
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("Enel")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish(outTopic, "enel booted");
client.subscribe(inTopic);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
for(int i = 0; i<5000; i++){
delay(1);
}
}
}
}

void send_ip(){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
client.publish(outIP, WiFi.localIP().toString().c_str());
}
}

void read_enel_gen(){

float volt = pzem.voltage();
Serial.print("Voltage: ");
Serial.print(volt);
Serial.println("V");

float cur = pzem.current();
Serial.print("Current: ");
Serial.print(cur);
Serial.println("A");

float powe = pzem.power();
Serial.print("Power: ");
Serial.print(powe);
Serial.println("W");

float ener = pzem.energy();
Serial.print("Energy: ");
Serial.print(ener,3);
Serial.println("kWh");

float freq = pzem.frequency();
Serial.print("Frequency: ");
Serial.print(freq);
Serial.println("Hz");

float pf = pzem.pf();
Serial.print("PF: ");
Serial.println(pf);

char buffer[10];
dtostrf(volt,2,2, buffer);
client.publish(outTopic_enel_gen_v,buffer);
dtostrf(cur,2,2, buffer);
client.publish(outTopic_enel_gen_a,buffer);
dtostrf(powe,2,2, buffer);
client.publish(outTopic_enel_gen_w,buffer);
dtostrf(ener,2,2, buffer);
client.publish(outTopic_enel_gen_kwh,buffer);
dtostrf(freq,2,2, buffer);
client.publish(outTopic_enel_gen_hz,buffer);
dtostrf(pf,2,2, buffer);
client.publish(outTopic_enel_gen_pf,buffer);

}

void read_enel_ap(){

float volt = pzem2.voltage();
Serial.print("Voltage2: ");
Serial.print(volt);
Serial.println("V");

float cur = pzem2.current();
Serial.print("Current: ");
Serial.print(cur);
Serial.println("A");

float powe = pzem2.power();
Serial.print("Power: ");
Serial.print(powe);
Serial.println("W");

float ener = pzem2.energy();
Serial.print("Energy: ");
Serial.print(ener,3);
Serial.println("kWh");

float freq = pzem2.frequency();
Serial.print("Frequency: ");
Serial.print(freq);
Serial.println("Hz");

float pf = pzem2.pf();
Serial.print("PF: ");
Serial.println(pf);

char buffer[10];
dtostrf(volt,2,2, buffer);
client.publish(outTopic_enel_ap_v,buffer);
dtostrf(cur,2,2, buffer);
client.publish(outTopic_enel_ap_a,buffer);
dtostrf(powe,2,2, buffer);
client.publish(outTopic_enel_ap_w,buffer);
dtostrf(ener,2,2, buffer);
client.publish(outTopic_enel_ap_kwh,buffer);
dtostrf(freq,2,2, buffer);
client.publish(outTopic_enel_ap_hz,buffer);
dtostrf(pf,2,2, buffer);
client.publish(outTopic_enel_ap_pf,buffer);

}

void setup() {

Serial.begin(115200);
setup_wifi(); // Connect to wifi
client.setServer(mqtt_server, 1883);
// client.setCallback(callback);

Serial.print("Reset Energy");
// pzem.resetEnergy();
// pzem2.resetEnergy();

// Serial.print("Set address to 0x42");
// pzem.setAddress(0x42);

// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname("enel");
// START OTA
ArduinoOTA.onStart( {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}

// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);

});
ArduinoOTA.onEnd( {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
//END OTA
}

void loop() {
if (!client.connected()) {
reconnect();
}
ArduinoOTA.handle();
client.loop();
read_enel_gen();
delay(2000);
read_enel_ap();
delay(2000);
send_ip();
}`

Arduino 32U4 problem

Hello,
sorry for disturbing you.
Is it possible that there is a problem when using 32U4 processors?

I compile the Soft Serial example with the target Arduino Nano, everything is perfect.
If I now switch to 32U4 based Arduino boards like Leonardo or Micro, then I get the following error:


C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino/USBAPI.h:154:16: note: previous declaration as 'Serial_ Serial'

extern Serial_ Serial;

^~~~~~

exit status 1

A similar behavior could be observed if I use the HW Serial example.

Thanks for your support.

Multiple pzem

Hi, can we put multiple pzem in to 1 uart serial? any recommendation method? thank you

Reading Multiple PZEM-004t in one SoftwareSerial

Screen Shot 2020-01-24 at 4 02 10 PM

I follow the same initialization, as you said. But it only returns the last PZEM connected.

here's my code.
'#include <PZEM004Tv30.h>

/* Use software serial for the PZEM
Pin 11 Rx (Connects to the Tx pin on the PZEM)
Pin 12 Tx (Connects to the Rx pin on the PZEM)
*/
PZEM004Tv30 pzem1(D5, D6, 0x01);
PZEM004Tv30 pzem2(D5, D6, 0x02);
PZEM004Tv30 pzem3(D5, D6, 0x03);
void setup() {
Serial.begin(115200);
}

void loop() {
float voltage1 = pzem1.voltage();
if( !isnan(voltage1) ){
Serial.print("voltage1: "); Serial.print(voltage1); Serial.println("V");
} else {
Serial.println("Error reading voltage");
}

float current1 = pzem1.current();
if( !isnan(current1) ){
    Serial.print("Current1: "); Serial.print(current1); Serial.println("A");
} else {
    Serial.println("Error reading current");
}

float power1 = pzem1.power();
if( !isnan(power1) ){
    Serial.print("Power: "); Serial.print(power1); Serial.println("W");
} else {
    Serial.println("Error reading power");
}

float energy1 = pzem1.energy();
if( !isnan(energy1) ){
    Serial.print("Energy1: "); Serial.print(energy1,3); Serial.println("kWh");
} else {
    Serial.println("Error reading energy");
}

float frequency1 = pzem1.frequency();
if( !isnan(frequency1) ){
    Serial.print("Frequency1: "); Serial.print(frequency1, 1); Serial.println("Hz");
} else {
    Serial.println("Error reading frequency");
}

float pf1 = pzem1.pf();
if( !isnan(pf1) ){
    Serial.print("PF1: "); Serial.println(pf1);
} else {
    Serial.println("Error reading power factor");
}

float voltage2 = pzem2.voltage();
if( !isnan(voltage2) ){
Serial.print("voltage2: "); Serial.print(voltage2); Serial.println("V");
} else {
Serial.println("Error reading voltage");
}

float current2 = pzem2.current();
if( !isnan(current2) ){
    Serial.print("Current2: "); Serial.print(current2); Serial.println("A");
} else {
    Serial.println("Error reading current");
}

float power2 = pzem2.power();
if( !isnan(power2) ){
    Serial.print("Power: "); Serial.print(power2); Serial.println("W");
} else {
    Serial.println("Error reading power");
}

float energy2 = pzem2.energy();
if( !isnan(energy2) ){
    Serial.print("Energy2: "); Serial.print(energy2,3); Serial.println("kWh");
} else {
    Serial.println("Error reading energy");
}

float frequency2 = pzem2.frequency();
if( !isnan(frequency2) ){
    Serial.print("Frequency2: "); Serial.print(frequency2, 2); Serial.println("Hz");
} else {
    Serial.println("Error reading frequency");
}

float pf2 = pzem2.pf();
if( !isnan(pf2) ){
    Serial.print("PF2: "); Serial.println(pf2);
} else {
    Serial.println("Error reading power factor");
}

 float voltage3 = pzem3.voltage();
if( !isnan(voltage3) ){
    Serial.print("voltage3: "); Serial.print(voltage3); Serial.println("V");
} else {
    Serial.println("Error reading voltage");
}

float current3 = pzem3.current();
if( !isnan(current3) ){
    Serial.print("Current3: "); Serial.print(current3); Serial.println("A");
} else {
    Serial.println("Error reading current");
}

float power3 = pzem3.power();
if( !isnan(power3) ){
    Serial.print("Power: "); Serial.print(power3); Serial.println("W");
} else {
    Serial.println("Error reading power");
}

float energy3 = pzem3.energy();
if( !isnan(energy3) ){
    Serial.print("Energy3: "); Serial.print(energy3,3); Serial.println("kWh");
} else {
    Serial.println("Error reading energy");
}

float frequency3 = pzem3.frequency();
if( !isnan(frequency3) ){
    Serial.print("Frequency3: "); Serial.print(frequency3, 3); Serial.println("Hz");
} else {
    Serial.println("Error reading frequency");
}

float pf3 = pzem3.pf();
if( !isnan(pf3) ){
    Serial.print("PF3: "); Serial.println(pf3);
} else {
    Serial.println("Error reading power factor");
}

}`

Create Wiki for the PZEM-004T v3.0

The information about this module exists, but it is sparsely distributed on the internet. It would be useful to collect all the available information in one place that could act as a reference for further development.

The Wiki feature of Github could be used for that. Would be great to include the datasheet info, perform some actual measurements. However this is a long term endeavor. Anyone willing to invest their time would be welcome to take over.

always getting error reading message with default example

Hi I am using an Arduino Uno and tried to connect the PZEM-004-v30 RX -->D11 and TX --> D12.
when I compiled and uploaded the default example I gets always the following message in the serial monitor.
Error reading voltage
Error reading current
Error reading power
Error reading energy
Error reading frequency
Error reading power factor

code which i have used:
#include <PZEM004Tv30.h>

/* Use software serial for the PZEM

  • Pin 11 Rx (Connects to the Tx pin on the PZEM)
  • Pin 12 Tx (Connects to the Rx pin on the PZEM)
    */
    PZEM004Tv30 pzem(11, 12);

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

void loop() {
float voltage = pzem.voltage();
if( !isnan(voltage) ){
Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V");
} else {
Serial.println("Error reading voltage");
}

float current = pzem.current();
if( !isnan(current) ){
    Serial.print("Current: "); Serial.print(current); Serial.println("A");
} else {
    Serial.println("Error reading current");
}

float power = pzem.power();
if( !isnan(power) ){
    Serial.print("Power: "); Serial.print(power); Serial.println("W");
} else {
    Serial.println("Error reading power");
}

float energy = pzem.energy();
if( !isnan(energy) ){
    Serial.print("Energy: "); Serial.print(energy,3); Serial.println("kWh");
} else {
    Serial.println("Error reading energy");
}

float frequency = pzem.frequency();
if( !isnan(frequency) ){
    Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz");
} else {
    Serial.println("Error reading frequency");
}

float pf = pzem.pf();
if( !isnan(pf) ){
    Serial.print("PF: "); Serial.println(pf);
} else {
    Serial.println("Error reading power factor");
}

Serial.println();
delay(2000);

}

any Idea what I am doing wrong?

[Arduino Uno] PZEMSoftwareSerial example

Hey guys

Im running PZEMSoftwareSerial example in my arduino uno using 115200 serial baud rate.

Heres my serial output every 2s:

Error reading voltage
Error reading current
Error reading power
Error reading energy
Error reading frequency
Error reading power factor

Error reading voltage
Error reading current
Error reading power
Error reading energy
Error reading frequency
Error reading power factor

I got my D11 and D12 setup according to example although I got only RX blinking at arduino side and TX blinking at PZEM side.

How can I diagnose this?

Compatibility problem with Arduino Due

Hi,
I was able to test your library on an Arduino Mega. It works very well and thank you for your update. Unfortunately, only the Arduino Due is able to run my home automation programs and I have a compatibility problem when I wear it on this platform.

Thanks in advance,
cordially

Rewrite the example code to be more readable

At the moment, the example code is written in a very verbose way that does not look very appealing. We should aim for examples that are around 20 lines of compact, elegant code.

Most of the code centers around error handling. Perhaps, this should be somehow compressed and made more readable.

Compatibility with Nodemcu ESP32 board?

I have used the library to work with Arduino UNO and it works fine.
With my Nodemcu-32S board, I am not able to get anything on the serial monitor when I run "PZEMHardSerial" example with "&Serial" instead of "&Serial3".
Is your library compatible with Nodemcu-32S module?
If not, is there a way to make it compatible?

Thanks.

Add ESP32 Support

Please add ESP32 support.

I changed line #25 in PZEM004Tv30.h file to:

#if (not defined(PZEM004_NO_SWSERIAL)) && (defined(__AVR__) || defined(ESP8266)) || defined(ESP32)
which makes it works with hardwareserial e.g. serial2

But softwareserial still makes problems and didn't work with the EspSoftwareSerial.

Software Serial WemosD1Mini

I use WeMos D1 Mini and use 2 Pzem which I connect to pin D5-D8 and some other sensors on pin D0-D3
when starting boot must disconnect the pzem from the pin, otherwise the system will not work

HardSerial connect issue

Hey there, first of all thanx for the great work you doing. I am using 4x pzem 004t v3 on d1 mini via softserial for months without issue. I want to attach more devices but run our of usable gpio ports. I was trying to run hardserial, connected multiple pzem to one rx/rx but no success. Whatever i do i always get nan, and the leds on pzem not blink. Even the changeaddress from examples i watsnt able to use i had to use windows tool downloaded from inovatorsguru.com website and so change the address. Please tell me what i doing wrong i am desperate. thank you very much

Library

Thanks a lot for your library. It works really well.
What does not work is the usage of "NAN" in the SoftwareSerial example. I replaced it with "isnan" and then it works really well so far. I created a 3-phase circuit with an esp8266 with 3 SoftwareSerial interfaces and mqtt readout. Thanks a lot for your work.

Problem with integrating your lib example

Hey, i'am using a ESP32 and coding in Visual Studio Code.

I copied your example SoftwareSerial but getting a compiling errors

no instance of constructor "PZEM004Tv30::PZEM004Tv30" matches the argument list -- argument types are: (int, int)

and

invalid conversion from 'int' to 'HardwareSerial*' [-fpermissive]

It's happend at the line PZEM004Tv30 pzem(11, 12);

/* Use software serial for the PZEM

  • Pin 11 Rx (Connects to the Tx pin on the PZEM)
  • Pin 12 Tx (Connects to the Rx pin on the PZEM)
    */
    PZEM004Tv30 pzem(11, 12); <======================

and giving the next statement;

D:_Dev_MyLib\PZEM-004T-v30/PZEM004Tv30.h:65:5: note: initializing argument 1 of 'PZEM004Tv30::PZEM004Tv30(HardwareSerial*, uint8_t)'
PZEM004Tv30(HardwareSerial* port, uint8_t addr=PZEM_DEFAULT_ADDR);

Can't use SoftwareSerial example

Hi, you should rename SoftwareSerial.ino to PZEMSoftwareSerail.ino, otherwise it won't be shown in the Arduino IDE examples list.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.