Wireless Peacefair PZEM-004T Energy Monitor on Audrino Web Server



  • I am a noob interested in a Peacefair PZEM-004T Energy Monitor but I can't find any good builds yet.

    The mypowermeter-v1-0 project seems to have died and I would really like to see some documentation on this Russian Power Meter. WiFi enabled Peacefair PZEM-004T EnergyMonitorWiFi enabled Peacefair PZEM-004T EnergyMonitor.

    There are also safety issues with the PZEM-004T module and I would like to connect multiple modules with a wifi link to an Audrino as a web server.

    Has anyone found anything along these lines?



  • This post is deleted!

  • MySensors Evangelist

    I received my unit today. Let's see if we can make the baby talk MySensors.

    0_1516470233698_WhatsApp Image 2018-01-20 at 18.36.11.jpeg



  • Was anyone able to get this working with MySensor?



  • @jaykumar Yes,
    i built it a couple of years ago, but it's operative for about three months.
    I used :
    arduino mini pro 3.3v/8Mhz powered by a 3.7v 14500 Li-Ion battery
    NRF24L01
    PZEM-004T (modified to work at 3.3v)

    It's a simple watt/energy meter that sends data to the controller(domoticz) every 40 secs, the PZEM-004T does most of the work.



  • @zampedro Can you share the code and a picture of wiring?



  • @Karolis-Kirna Just a bit late but here it is.
    arduino+nrf24l01+pzem_2.jpg pzem-004t_2a.jpgarduino mini 3.3v 8Mhz+NRF24L01.jpg meter_panel.jpg meter_log1.jpg
    The code:

    /*
     * Send Watt and Kwh to gateway
     * using PZEM-004t
     * 26/8/2020  cambiato linea 45, 21-23
     */
    
    /*++++++++++++++  Global Settings   +++++++++++++++++*/
    #define SN "PZEM Monitor"
    #define SV "0.4"
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 9
    #define MY_PARENT_NODE_ID 11 // from domoticz log
    #define MY_PARENT_NODE_IS_STATIC
    /*+++++++++++++  Local Settings  ++++++++++++++++++++*/
    #define SEND_ONLY_IF_CHANGED  
    //#define MY_DEBUG
    //#define DEBUG 
    //#define TEST // Aggiunge codice di test da levare
    
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 9600
    #endif
    
    #include <debugpaolo.h>
    
    #include <SPI.h>
    #include <MySensors.h>  
    //#include <SoftwareSerial.h> // Arduino IDE <1.6.6
    #include <PZEM004T.h>
    
    #define RX_PIN 4  
    #define TX_PIN 5 
    PZEM004T pzem(RX_PIN,TX_PIN);  // RX pin,TX pin
    IPAddress ip(192,168,1,1);
    
    #define CHILD_WATT_ID 0  
    #define VOLTAGE_ID  1
    
    unsigned long lastSend=0;
    unsigned long SEND_FREQUENCY = 40000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
    
    MyMessage wattMsg(CHILD_WATT_ID,V_WATT);
    MyMessage kWhMsg(CHILD_WATT_ID,V_KWH);
    //MyMessage kwhSaveMsg(CHILD_WATT_ID,V_VAR1);
    //MyMessage varMsg(CHILD_WATT_ID,V_VAR); // chi lo sa non va in domoticz
    
    double oldKwh=0.0;
    double oldwh=0.0;
    float oldwatt=0.0;
    #ifdef TEST
      double whtest=0.0;
    #endif
    
    #ifdef SEND_ONLY_IF_CHANGED
      int kwh_counter;
      #define KWH_COUNTER_MAX 33 //dopo 23 volte(15 min) invia comunque
    #endif
    
    MyMessage msgVoltage(VOLTAGE_ID, V_VOLTAGE);
    float lastv=0;
    #define V_COUNTER_MAX 70
    int v_counter=0;
    
    int BATTERY_SENSE_PIN = A3;  // select the input pin for the battery sense point
    int oldBatteryPcnt = 0;
    
    #define MAX_BATTERY_CHECK    56  // 56*40 sec = 56 min circa
    int battery_check;
    
    
    #define VREF 1.106
    #define RBATT  5.73305  // ((1578+333.4)/333.4)?
    #define VFACTOR  RBATT*VREF/1023 //
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ++++++++++++++++   SETUP    +++++++++++++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    void setup() {
    //  begin(incomingMessage);
      analogReference(INTERNAL);
      pzem.setAddress(ip);
      battery_check = MAX_BATTERY_CHECK;
    }
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ++++++++++++++++++   Presentation  ++++++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
      present(CHILD_WATT_ID, S_POWER);
      present(VOLTAGE_ID, S_MULTIMETER);
    }
    
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++   Loop  +++++++++++++++++++++++++++
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    void loop() {
    
    /* +++++++++++++++++++++++++++++++++++++++++++
       ++++    PZEM          section     +++++++++
       +++++++++++++++++++++++++++++++++++++++++++*/  
      float v = pzem.voltage(ip);
      if (v < 0.5) { 
        delay(500);
        // check v twice
        v = pzem.voltage(ip);
        if (v < 0.5 ) v = 0.0;
      }
      DEBUG_PRINT(v);DEBUG_PRINT("V; ");
    #ifdef DEBUG  
      float i = pzem.current(ip);
      if(i >= 0.0){ DEBUG_PRINT(i);DEBUG_PRINT("A; "); }
      float VA=v*i;
      if(VA >= 0.0){ DEBUG_PRINT(VA);DEBUG_PRINTLN("VA; "); }
    #endif  
    /* ---------------------------
     *------- Sezione potenza ----
      ----------------------------*/
      float watt = pzem.power(ip);
      #ifdef TEST
        watt=kwh_counter*2;
      #endif  
      DEBUG_PRINT(watt);DEBUG_PRINT("W ");DEBUG_PRINT(VA);DEBUG_PRINTLN("VA ");
      if (watt <=0 ) {
        DEBUG_PRINT(watt);DEBUG_PRINTLN("W. Sensore NC o assenza rete! ");
        if ( oldwatt>0) {
           watt =0;
           send(wattMsg.set(watt,1));  // Send watt value to gw 
           oldwatt=0.0;
        }
      } 
      else {
       if ( oldwatt==0.0) {
        send(wattMsg.set(watt,1));  // Send watt value to gw 
        DEBUG_PRINT(watt);DEBUG_PRINTLN("Rete ritornata! ");
        oldwatt = watt;
       }
       else {
        DEBUG_PRINT(watt);DEBUG_PRINTLN("W; ");
        float diffwatt=abs(watt-oldwatt);
        if ( diffwatt >= 49.9 ) { // watt in aumento di 50watt
            DEBUG_PRINT("Differenza ");DEBUG_PRINT(diffwatt);DEBUG_PRINTLN("W; ");
            oldwatt = watt;
            send(wattMsg.set(watt,1));  // Send watt value to gw 
        }
        else {
          float perc = 100.0*diffwatt/oldwatt; // oldwatt o watt?
          DEBUG_PRINT("Perc ");DEBUG_PRINT(perc);DEBUG_PRINTLN("% ");
          if ( perc >= 49.9 ) { // variazione del 50%
            DEBUG_PRINT("Percentuale Diff ");DEBUG_PRINT(perc);DEBUG_PRINTLN("%; ");
            oldwatt = watt;
            send(wattMsg.set(watt,1));  // Send watt value to gw 
    //        send(varMsg.set(watt,1));  // non va in domoticz
          }
          else {
            if ( (perc >= 15.0) && (diffwatt>=8) ) {
              DEBUG_PRINT("Diff ");DEBUG_PRINT(diffwatt);
              DEBUG_PRINT("Perc ");DEBUG_PRINT(perc);DEBUG_PRINTLN("%; ");
              oldwatt = watt;
              send(wattMsg.set(watt,1));  // Send watt value to gw 
            }
          }
        }
       }
      }
      
      //send(wattMsg.set(watt,1));  // Send watt value to gw 
    /* ---------------------------
     *------- Sezione energia ----
      ---------------------------*/
      float wh = pzem.energy(ip);
      #ifdef TEST
        whtest+=10.0;
        wh=whtest;
      #endif
      if(wh >= 0.0){ DEBUG_PRINT(wh);DEBUG_PRINT("Wh; "); }
      else wh = 0.0;
      DEBUG_PRINTLN();
      
    #ifdef SEND_ONLY_IF_CHANGED 
      if ( (kwh_counter==0) ||(abs(wh-oldwh) > 187) ) { // 100 wh
    #else    
      if ( wh > 0.0 ) { 
    #endif    
          double kwh = (double)wh/(double)1000.0;
          send(kWhMsg.set(kwh, 3));  // Send kwh value to gw 
          oldwh=wh;
          #ifdef SEND_ONLY_IF_CHANGED 
          kwh_counter=0;
          #endif      
      }
    #ifdef SEND_ONLY_IF_CHANGED 
      DEBUG_PRINT("kwh_counter=");
      kwh_counter++;
      DEBUG_PRINT(kwh_counter);DEBUG_PRINT(" ");
      if (kwh_counter == KWH_COUNTER_MAX ) kwh_counter = 0;
      DEBUG_PRINTLN();
    #endif    
    
    /* +++++++++++++++++++++++++++++++++++++++++++
       ++++    Battery check section     +++++++++
       +++++++++++++++++++++++++++++++++++++++++++*/
      if ( battery_check == MAX_BATTERY_CHECK) {
        analogRead(BATTERY_SENSE_PIN); // needed for accuracy
        int sensorValue = analogRead(BATTERY_SENSE_PIN);
        DEBUG_PRINT("A0 Value = ");DEBUG_PRINTLN(sensorValue);
        float batteryV  = sensorValue * VFACTOR;
        // 100% 4.0v 0% 3.3v
        int batteryPcnt = ( batteryV - 3.3) / (4.0 - 3.3) * 100;
        batteryPcnt = (batteryPcnt > 100) ? 100 : batteryPcnt;
        batteryPcnt = (batteryPcnt < 0) ? 0 : batteryPcnt;
        DEBUG_PRINT("Battery Voltage: ");DEBUG_PRINT(batteryV);DEBUG_PRINTLN(" V");
        DEBUG_PRINT("Battery Percent: ");DEBUG_PRINT(batteryPcnt);DEBUG_PRINTLN(" %");
        //if (oldBatteryPcnt != batteryPcnt) {
         sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
        //}
        battery_check=0;
      } else {
         battery_check++;
         DEBUG_PRINT("Check = ");
         DEBUG_PRINTLN(battery_check);
        }
    /* +++++++++++++++++++++++++++++++++++++++++++
       ++++    230 Voltage   section     +++++++++
       +++++++++++++++++++++++++++++++++++++++++++*/  
    #ifdef SEND_ONLY_IF_CHANGED 
      float diffv= abs(v-lastv);
      if ( ((v_counter == 0) || ( diffv > 3.50))  ) {
        DEBUG_PRINT("v diff: ");DEBUG_PRINT(diffv);DEBUG_PRINTLN("V ");
        if ( diffv > 3.50 ) v_counter = 0;
        else v_counter++;
        DEBUG_PRINT("v_counter : ");DEBUG_PRINTLN(v_counter);
    #endif
        send(msgVoltage.set(v, 1));
        lastv = v;
    #ifdef SEND_ONLY_IF_CHANGED 
      } else {
        v_counter++;
        if (v_counter >= V_COUNTER_MAX ) v_counter = 0;
        DEBUG_PRINT("v_counter : ");DEBUG_PRINTLN(v_counter);
      }
    #endif
      sleep(SEND_FREQUENCY);
      delay(500); // ???
    }
    
    
    
    
    

Log in to reply
 

Suggested Topics

  • 8
  • 2
  • 3
  • 1
  • 1
  • 5

0
Online

11.4k
Users

11.1k
Topics

112.7k
Posts