Skip to content

Easy measure of AC Voltage using Arduino and ZMPT101B

 



 

Need this with ESP8266 12E (NodeMcu)? Check: Measure any AC voltage (250VAC) with ZMPT101B and ESP8266 12E with Android App / Adafruit IO MQTT

Hello and welcome, before we start anything, I want to warn you about messing with domestic voltage, power line, wall power…. pay attention and be very careful it’s dangerous.

It’s this way if you need to measure AC current as well: Measure any AC current with ACS712 and Arduino + LCD / OLED

Watch the tutorial for further explanations.

So the project today is how to measure AC voltage up to 250V, in both 50Hz and 60Hz, using the ZMPT101B, that’s the name of the transformer only, but you’ll find it around with this name or “AC voltage sensor”.

Module.png
Voltage measuring sensor ZMPT101B

This module used with the right code, is far better for measures, than the other methods that uses a transformer + rectifier + voltage divider…., these kind of wirings can be dangerous if not done right, and also don’t give the right values all the time because it doesn’t make any difference if the signal is square or triangular, even though it does affect seriously the RMS, and the RMS is what we want to measure, and for this we should keep the same shape of the signal when adapting it for the Arduino, and here is when the module is handy.

 

Sineses.png

The module takes the signal we want to measure, here we have 220V domestic power, it has around 311V as its peak.

The module’s transformer brings it down to 2.5V peak.

Then the module’s amplifier adds a 2.5V offset to adapt it to the Arduino, since we can’t use have negative potential.

 

And here pay attention, some codes circulating around are used with this module but they only do a sampling of the signal and measure the peaks then do some multiplications, and it shows you the “RMS” of the signal, but those codes work only for perfect sinewave signal, if you’re measuring another shape of the signal it would be false. Unlike the one we are using which is True RMS.

Light dimmer.jpg
Home light dimmer



And for example here I used a light dimmer, which is based on a TRIAC and you know the “weird” shape of the signal that a TRIAC based circuit creates.

article-2014july-ics-answer-the-challenge-of-fig1

Here you can see, to measure the RMS you shouldn’t only measure the peaks and do the same calculations for the sinewave signal.

But you should do it the right way and it’s very difficult to code, that’s why I found a simple library as always to do the work for us 😀

But you should know how it’s done and it’s easy to find around.

 

For the measures I’m using an OLED display, you can check My previous tutorial, on how to use it with different examples.

OLED.jpg
OLED i2c display

 



Wiring:

Wiring.png
ZMPT101B wired with an Arduino UNO board and OLED i²c screen

This is the whole wiring, and as mentioned, I’m using an 128×32 OLED screen you can use it or no, the module is powered by 5v and delivers an analog signal on its output proportional to the input signal.

Setup:

adjust_pot.jpg
ZMPT101B adjusting potentiometer

The first thing you need to do, is calibrating the module by its potentiometer, you wire the module, plug the Arduino and upload this simple code, and don’t forget to place you measuring probes to the power socket (BE CAREFUL !!!) and you already know the voltage over.

 

Open the serial plotter of the Arduino IDE:

plot2
Module not outputting a sinewave like signal

 

plot1
On the bottom, the signal is good but it needs adjustment from top

 

You’ll see something like this in your serial plotter, it means you don’t acquire the whole signal, adjust the potentiometer until you have something that looks like a “sinewavish” thing. I know that’s not the AC sinewave signal.

plot3
Correct signal as it shows a sinewave envelope

 

When you have something like this you can add a delay to see a nice sinewave, here it’s because I’m measuring right after my light dimmer you’ll see a little peak before the signal peak if you measure the socket directly you won’t have this.

sinewaveee.png

Now your module is calibrated, the code calibrations will be based on it so try to not change it.



Libraries:

The library I’m using is Filters.h, it reduces the amount of work for you, Download here, or from Github. I don’t know if they are the same because I had it for 2 years.

Adafruit OLED display libraries:

Codes:

Code 1: Using Serial monitor only

 

Code 2:

Here’s the code I’ve used: Download here or check below. The code of course is used with the OLED display and the serial monitor, just remove the lines that you don’t need.

 

In this code you might have a problem understanding the intercept and slope values, I recommend you to check this tutorial’s video as I explained it further: Measure any AC current with ACS712 and Arduino + LCD / OLED

Tests:

Val_1.jpg
Our project compared to a True RMS multimeter

The values are sure not perfect and 100% accurate but as you see you need very precise calibrations to make it perfect, and don’t forget you’re using a 10$ or less module, and there it’s compared to a multimeter that uses TRMS, True RMS.



 

Val_2.jpg
RMS vs True RMS measuring, the right multimeter is not measuring at that moment

A non TRMS Multimeter will give you a false reading for a non Sinewave signal too, as you can see the cheap one (blue) compared to our project, it’s 40V difference which is not good. (NB: the other multimeter is not measuring at that moment, check the video for more).

That’s all folks.

Yassine View All

Automation and Electrical Engineer, Electronics amateur trying to share my little projects.

78 thoughts on “Easy measure of AC Voltage using Arduino and ZMPT101B Leave a comment

  1. Hi Sir
    How are you
    Sir i also want to run other perimeters what can i do
    When i was trying to remove while it says error while reading
    PLease help in it

    • Hi, I don’t know what you mean by “perimeters”, is it something in the code or materials??
      And if possible it’s better to contact me on facebook page

  2. Hi,

    I really like this project

    Can you tell me, from your code , where you got the values below ?
    float intercept = -0.04; // to be adjusted based on calibration testing
    float slope = 0.0405; // to be adjusted based on calibration testing
    current_Volts= current_Volts*(40.3231); //Further calibrations for the amplitude

    I have adjusted the Trim Pot as you suggested ..and the readings look good – . what is my next step to calibrating ?
    How do I get the the readings translated to the correct voltage.
    NOTE: My AC voltage is 240 Volts so I assume the values you have above are not correct for me ?
    How do I get the values I need ?

    thanks

    • Hi, did you ask me on hackster? because I had the same question toda, and I responded there.
      I’ll just copy it here:
      “Hi, to understand better you can check the “RunningStatistics.cpp” file from the library, you’ll find the mathematical functions, it takes the input which is an analog one, do some sampling then calculate the average square value and after the standard deviation…
      For the intercept and slope you can make the input as 0 and you should have 0 then take a known value and calibrate the slope
      For the “current_Volts= current_Volts*(40.3231)” actually I had this lying around for 2 years and first it was mean’t to measure “Current” so multiplied by (40.3231).
      About the multimeter, cheap multimeters measure all AC signals as sinewaves, if you want to use it to calibrate, measure AC sinewave signal from a socket or after a transformer, but since I used a Triac based light dimmer I had to use a TRMS multimeter to get the right value.”

      You can start by the values given above, as I said they are very sensitive, or you can put the Analog input to 0 and make slop=0 then adjust the intercept to get 0 as the result, then put the voltage to a known value, and the intercept to its new value and adjust the slope.
      For the last line to calibrate you can remove it, if you do this. Mein was based on an code I made before to measure current… so I had to readjust

  3. I am trying to get voltage reading on ESP32. I have used level shifting to protect damages from 5 voltage. I have connected ESP32 Pin 2 or Pin 15 with ZMPT101B via shifter. but there is always 4095 or 2189 reading even I connect or disconnect cable from module ZMPT101B OR 4 Channel Bi-Directional Logic Level Shifter.
    please advise what is wrong with this

    • Hi, sorry I didn’t tried it with an ESP32, but first the module should be powred by 5v, you should use an external source as the operating voltage of the ESP is around 3.3v I think, use the VCC and GND for power, then for the ESP32 use an Analog input and GND with the Signal and GND from the module, and make sure to use a proper level shifter, I think a voltage divider can do the work.

      When the module is powred (with 5v) it will send 2.5V (512) to the Arduino (when there’s no AC power to its input) and when you add an AC power source the voltage will be around 0-5V (0-1023) these values depend on the board ADC,for Arduino UNO it’s from 0-1023 10 bits). For the ESP32 I think it has a 12bits one so the values will be (0-4096) for (0-3.3V)

      The module could (I’m not sure) work with 3.3V, You can try to power it using 3.3V and GND from the ESP32, Measure with a multimeter the value should be around 1.6V, if this works it means you can wire it directly as the max voltage can never be higher than 3.3V

  4. Thank you for reply, Please advise further for module working as I am fear that module is faulty. How I check it as I do not have Arduino UNO with me. I have powered ZMPT101B module with 5v. and passed out via proper level shifter and then input it into pin15(analogread) of ESP32. but there is always 4096 value on it. voltage is almost 2.6v to 3.3 v on pin15. but there is no change in this value even I connect or disconnect AC power. when I pull out cable from shifter-To-ESP32(pin15), there is zero value on it.
    i was stuck in it.

    • First, please make sure everything is working fine:
      1) Power the ZMPT101B with (5V/GND), do not add AC voltage, measure the (Signal/Gnd) pins with a multimeter (DC Voltage), the voltage should be around 2.5V, because 2.5V is the offset.
      ==> if this works it means your module is working well

      2) Try this but this time use (3.3V/GND), no AC voltage -> measure -> it should be half 3.3 which is 1.65V.
      and can work with 3.3V and you can plug it directly to
      ==> if this works you can power the module directly from the ESP32 and use it without a level shifter

      3) If the (2) doesn’t work and (1) works well, try to use the level shifter, and make sure it’s working well, wire everything and check some test codes.

      The 4096 is the higher value of the Analog to Digital Converter and for it it means 3.3V, make sure it’s not higher (because it will keep the same value).

      The best way to test is only analogRead(signalpin) and use the Serial Plotter of the Arduino IDE, as I did

  5. 1. at 5v, measured the (Signal/Gnd) pins with a multimeter (DC Voltage) reading 2.53v
    2. at 3.3v, this time use (3.3V/GND), no AC voltage -> measured reading 1.65v
    1.2 both does not work, conenction and ground are ok. voltage level remain same(i.e 2.53 for 5v, 1.65v for 3.3v when AC voltage is connected. there is no change in behaviour of ZMPT101B voltage levels. I am not sure but it does not work as signal-out value remain same.

  6. So for (3.3V/Gnd) no AC -> 1.65 it’s good it means there’s the offset and the module is working.

    Do not use the level shifter, just the module directly with ESP32, POWERED with 3.3V/GND from the ESP and use an analog input.

    Test first with only this line “Serial.println(analogRead(A0));” add the necessary things like void setup, serial begin…., upload the code to the board and open the serial plotter in Arduino IDE, you’ll see values around 1.65V (2046) maybe.

    Add now an AC voltage and check the shape of the signal, turn the potentiometer unitl you have a shape like I found, you can add a delay after the serial print if you want.

  7. thank you for your conitnous support, I have applied 220v AC , but there is no change in value of Serial.println(analogRead(15)). it always display 4095. even I remove or apply AC voltage. shape signal is second thing, but first there should be change in analog value 1.65v and 3.3v . but it is same

    • No problem, do you use “Serial plotter” to see the shape of the signal?
      Also don’t forget that the module delivers a sinewave signal not a continuous one, if you just use the serial monitor to see the values it will show strange different values, and it would be difficult to measure them when AC is on.
      The better way as I said is to use the serial plotter !!!

  8. you are right , I used Serial Monitor and view plotter, code run perfectly with Ardnino Un R3 , but this code does not work with ESP32. but serial monitor help lot to tune ware form but is entirely different in upper corner and it seem to be remain straight , I have try my best to make it pure but upper corners remain same.
    i have used other site code which is same for arduino and ESP32. but with esp32 it does not reflect AC values in workable reading. it show abrupt changes in reading which is not good.
    i do not see people working on ESP32 much on internet
    https://www.youtube.com/redirect?event=video_description&v=nExAAbO-Lc4&redir_token=6gl2uh2TPcHiTf8scjdwowsvAud8MTU1NjU0NDU0MUAxNTU2NDU4MTQx&q=http%3A%2F%2Fsentroino.blogspot.com%2F2015%2F12%2Fmeasuring-ac-voltage-using-arduino.html%3Fm%3D1

    • You can add a delay like i did of 100ms or swipe through some values… Also try to use a different baude rate maybe, and you should use the potentiometer of the module to set its amplification otherwise the signle will not be readable… But I can’t give you concrete things as I didn’t use it with an ESP32

    • Ashraf, if it’s still actual project for you, I’ll reply.
      I’m doing exact the same thing and trying to make ZMPT101B work with ESP32. Haven’t calibrated it yet, but I can surely answer, why you’re getting 4095 ADC reading all the time. It’s because reference voltage (Vref) for ADC in ESP32 is 1.1 V. So your 1.65 V translate into 4095, because it’s out of range. You should use ADC channel attenuation. which can be 2.5, 6 or 11 dB. 11 dB reduces input signal to about 1/3.6, so 3.3/3.6 < 1.1 V and it should show you AC sine on graphs. Unfortunately I don't use Arduino IDE, I use ESP-IDF, so as for Arduino code, I can't tell you anything

      • Dear Alice, did you get the solution? This code is working fine in arduino but in ESP32 or Node MCU this code not runs. I can’t see a variation in analogRead except 4095. please help

    • Dear Ashraf, did you get the solution? I am also facing the same issue with the node mcu/ ESP32. analogRead is not showing any variation except 4095. this code wirking fine in arduino but it showing issue in EXP32 and node MCU.

      can you give me any solution?

    • You need 2 other variables for all:
      Sensor=0;
      Sensor=1;
      Sensor=2; for 3 inputs

      3 different currents volts,
      3 of these part:
      RunningStatistics inputStats;
      inputStats.setWindowSecs( windowLength );
      Sensor = analogRead(A0);
      inputStats.input(Sensor);

      each one has its name, and 3 of this part as well:

      current_Volts = intercept + slope * inputStats.sigma(); //Calibartions for offset and amplitude
      current_Volts= current_Volts*(40.3231);

      if you understand one you’ll be able to do the others

  9. Thank you Sir,
    it works

    /* This code works with ZMPT101B AC voltage sensor module
    * It permits you to measure any AC voltage up to 250V, BE CAREFUL !!!
    * The functions from Filters library permits you to calculate the True RMS of a signal
    * Refer to www.surtrTech.com or SurtrTech YouTube channel for more details
    */

    #include //Easy library to do the calculations

    float testFrequency = 50; // test signal frequency (Hz)
    float windowLength = 40.0/testFrequency; // how long to average the signal, for statistist

    int SensorR = 0; //Sensor analog input, here it's A0
    int SensorS = 1; //Sensor analog input, here it's A0
    int SensorT = 2; //Sensor analog input, here it's A0

    float intercept = -0.04; // to be adjusted based on calibration testing
    float slope = 0.0405; // to be adjusted based on calibration testing
    //float slope = 0.043; // to be adjusted based on calibration testing

    //float current_Volts; // Voltage
    float current_VoltsR; // Voltage
    float current_VoltsS; // Voltage
    float current_VoltsT; // Voltage

    unsigned long printPeriod = 1000; //Refresh rate
    unsigned long previousMillis = 0;

    void setup() {
    Serial.begin( 9600 ); // start the serial port
    }

    void loop() {

    RunningStatistics inputStatsR; //Easy life lines, actual calculation of the RMS requires a load of coding
    inputStatsR.setWindowSecs( windowLength );

    RunningStatistics inputStatsS; //Easy life lines, actual calculation of the RMS requires a load of coding
    inputStatsS.setWindowSecs( windowLength );

    RunningStatistics inputStatsT; //Easy life lines, actual calculation of the RMS requires a load of coding
    inputStatsT.setWindowSecs( windowLength );

    // inputStats.input(Sensor);

    while( true ) {
    SensorR = analogRead(A0); // read the analog in value:
    SensorS = analogRead(A1); // read the analog in value:
    SensorT = analogRead(A2); // read the analog in value:
    inputStatsR.input(SensorR); // log to Stats function
    inputStatsS.input(SensorS); // log to Stats function
    inputStatsT.input(SensorT); // log to Stats function

    if((unsigned long)(millis() - previousMillis) >= printPeriod) {
    previousMillis = millis(); // update time every second

    Serial.print( "\n" );

    current_VoltsR = intercept + slope * inputStatsR.sigma(); //Calibartions for offset and amplitude
    current_VoltsR = current_VoltsR*(40.3231); //Further calibrations for the amplitude
    current_VoltsS = intercept + slope * inputStatsS.sigma(); //Calibartions for offset and amplitude
    current_VoltsS = current_VoltsS*(40.3231); //Further calibrations for the amplitude
    current_VoltsT = intercept + slope * inputStatsT.sigma(); //Calibartions for offset and amplitude
    current_VoltsT = current_VoltsT*(40.3231); //Further calibrations for the amplitude

    //current_VoltsR= current_VoltsR*(42); //Further calibrations for the amplitude

    Serial.print( "\tVoltage (R): " );
    Serial.print( current_VoltsR ); //Calculation and Value display is done the rest is if you're using an OLED display

    Serial.print( "\tVoltage (S): " );
    Serial.print( current_VoltsS ); //Calculation and Value display is done the rest is if you're using an OLED display

    Serial.print( "\tVoltage (T): " );
    Serial.print( current_VoltsT ); //Calculation and Value display is done the rest is if you're using an OLED display

    }

    }

    }

    • I am someone from the old school VB background and am not too familar with the C syntax, also this is very first Arduino project, which I am doing it for my in-house purpose.

      I also have a very similar application, where I have to monitor AC voltages of 3 phases. So adapted Gerhard’s version in the following way. I am unable to get the voltages as required, any clue where I am wrong. I actually have other stuff to do in the main loop() so did this way to slightly organize the code, but this does not work, I get reading 1.02, 0.97, 1.10 etc

      I have mains voltage of 240V @ 50Hz

      Forgot to mention, I am using a Arduino Mega (clone) 2560, ZMPT101B, there are other things in the code but that has nothing to do with the AC voltage measuring thing, can put the full code if required.

      #include //Easy library to do the calculations, used for the AC voltage thing
      const float fFrequency = 50; //Test signal frequency (Hz)
      float windowLength = 40.0/fFrequency; // how long to average the signal, for statistics
      const float fAmplitudeMultiplier = 40.3231; // some constand required to multiply with voltage, this can be tweeked if required
      const int iRedPhaseSensorPin = 0; //Sensor analog input, pin A0
      const int iYellowPhaseSensorPin = 1; //Sensor analog input, pin A1
      const int iBluePhaseSensorPin = 2; //Sensor analog input, pin A2
      const float fIntercept = -0.04; // to be adjusted based on calibration testing
      const float fSlope = 0.0405; // to be adjusted based on calibration testing
      float fRedPhaseVoltage; // stores the voltage in the Red Phase
      float fYellowPhaseVoltage; // stores the voltage in the Yellow Phase
      float fBluePhaseVoltage; // stores the voltage in the Blue Phase

      void setup() {
      // put your setup code here, to run once:

      Serial.begin(9600);

      delay(5000); //wait for some time for the ethernet connection to be stable

      }

      void loop() {
      // put your main code here, to run repeatedly:

      //Determine the incoming AC voltage on each phase
      fRedPhaseVoltage = GetACVoltage(iRedPhaseSensorPin);
      fYellowPhaseVoltage = GetACVoltage(iYellowPhaseSensorPin);
      fBluePhaseVoltage = GetACVoltage(iBluePhaseSensorPin);

      Serial.print(“Voltages – R:”);
      Serial.print(fRedPhaseVoltage);
      Serial.print(” Y:”);
      Serial.print(fYellowPhaseVoltage);
      Serial.print(” B:”);
      Serial.println(fBluePhaseVoltage);
      delay(1000);

      }

      float GetACVoltage(int iPhasePin) {

      float fVoltage;
      int iSensor = 0;

      RunningStatistics inputStats; //Easy life lines, actual calculation of the RMS requires a load of coding
      inputStats.setWindowSecs(windowLength);

      iSensor = analogRead(iPhasePin); //read the value from the analog pin for the RedPhase
      Serial.print(“iPhasePin : “);
      Serial.println(iPhasePin);
      inputStats.input(iSensor); //log to Stats function
      fVoltage = fIntercept + fSlope * inputStats.sigma(); //Calibartions for offset and amplitude
      fVoltage = fVoltage * (fAmplitudeMultiplier); //Further calibrations for the amplitude

      return fVoltage;
      }

      • Hello, in the beginning you need the name of the library near the “#include” it’s “#include”
        On the measuring function the “Running statistics” entity and “setWindowSecs” function, they need to be in loop, then the calculation and calibration should be in a separate loop…. I tired to separate them to get be able to do other stuff but I didn’t succed for the moment… I will try to do it again, because the goal of this tutorial is just measuring.
        Note: I also got the same values when I tried to separate them like that
        For the intercept and slope, you should modify them depending on your calibration, first don’t forget to set the module potentiometer as I showed in the tutorial, just by observing the serial plotter until you get an acceptable shape.
        Another video will be up soon that uses the same method to calculate the alternating current.

    • I am someone from the old school VB background and am not too familar with the C syntax, also this is very first Arduino project, which I am doing it for my in-house purpose.

      I also have a very similar application, where I have to monitor AC voltages of 3 phases. So adapted Gerhard’s version in the following way. I am unable to get the voltages as required, any clue where I am wrong. I actually have other stuff to do in the main loop() so did this way to slightly organize the code, but this does not work, I get reading 1.02, 0.97, 1.10 etc

      I have mains voltage of 240V @ 50Hz

      Forgot to mention, using a Arduino Mega (clone) 2560, ZMPT101B, there are other things in the code but that has nothing to do with the AC voltage measuring thing, can put the full code if required.

      #include //Easy library to do the calculations, used for the AC voltage thing
      const float fFrequency = 50; //Test signal frequency (Hz)
      float windowLength = 40.0/fFrequency; // how long to average the signal, for statistics
      const float fAmplitudeMultiplier = 40.3231; // some constand required to multiply with voltage, this can be tweeked if required
      const int iRedPhaseSensorPin = 0; //Sensor analog input, pin A0
      const int iYellowPhaseSensorPin = 1; //Sensor analog input, pin A1
      const int iBluePhaseSensorPin = 2; //Sensor analog input, pin A2
      const float fIntercept = -0.04; // to be adjusted based on calibration testing
      const float fSlope = 0.0405; // to be adjusted based on calibration testing
      float fRedPhaseVoltage; // stores the voltage in the Red Phase
      float fYellowPhaseVoltage; // stores the voltage in the Yellow Phase
      float fBluePhaseVoltage; // stores the voltage in the Blue Phase

      void setup() {
      // put your setup code here, to run once:

      Serial.begin(9600);

      delay(5000); //wait for some time for the ethernet connection to be stable

      }

      void loop() {
      // put your main code here, to run repeatedly:

      //Determine the incoming AC voltage on each phase
      fRedPhaseVoltage = GetACVoltage(iRedPhaseSensorPin);
      fYellowPhaseVoltage = GetACVoltage(iYellowPhaseSensorPin);
      fBluePhaseVoltage = GetACVoltage(iBluePhaseSensorPin);

      Serial.print(“Voltages – R:”);
      Serial.print(fRedPhaseVoltage);
      Serial.print(” Y:”);
      Serial.print(fYellowPhaseVoltage);
      Serial.print(” B:”);
      Serial.println(fBluePhaseVoltage);
      delay(1000);

      }

      float GetACVoltage(int iPhasePin) {

      float fVoltage;
      int iSensor = 0;

      RunningStatistics inputStats; //Easy life lines, actual calculation of the RMS requires a load of coding
      inputStats.setWindowSecs(windowLength);

      iSensor = analogRead(iPhasePin); //read the value from the analog pin for the RedPhase
      Serial.print(“iPhasePin : “);
      Serial.println(iPhasePin);
      inputStats.input(iSensor); //log to Stats function
      fVoltage = fIntercept + fSlope * inputStats.sigma(); //Calibartions for offset and amplitude
      fVoltage = fVoltage * (fAmplitudeMultiplier); //Further calibrations for the amplitude

      return fVoltage;
      }

      • Thanks Yassine.
        Apologies for the double post.

        It was actually a copy paste error in my post, it is indeed
        #include //Easy library to do the calculations, used for the AC voltage thing

      • Hello, Well I tried some few stuffs and I managed to put the calculation part on a separate function that ou can call any time, this will let you do some other side stuffs.

        #include

        #define ZMPT101B A0

        float testFrequency = 50; // test signal frequency (Hz)
        float windowLength = 40.0/testFrequency; // how long to average the signal, for statistist

        int RawValue = 0;

        float intercept = 1.5; // to be adjusted based on calibration testing
        float slope = 1.26; // to be adjusted based on calibration testing
        float Volts_TRMS; // estimated actual current in amps
        float V=0;

        unsigned long printPeriod = 1000; // in milliseconds
        // Track time in milliseconds since last reading
        unsigned long previousMillis = 0;

        RunningStatistics inputStats;

        void setup() {
        Serial.begin( 9600 ); // start the serial port
        Serial.println(“Serial started”);
        inputStats.setWindowSecs( windowLength );
        }

        void loop() {

        V=ReadVoltage();
        Serial.println(V);

        }

        float ReadVoltage(){
        RawValue = analogRead(ZMPT101B); // read the analog in value:
        inputStats.input(RawValue); // log to Stats function

        if((unsigned long)(millis() – previousMillis) >= printPeriod) {
        previousMillis = millis(); // update time

        Volts_TRMS = inputStats.sigma()* slope + intercept;

        return Volts_TRMS;

        }
        }

        I modified the code a little bit because I’m about to make a little video concerning the “intercept” and “slope” values, now you can for example use this function if “modified more” to read each sensor separately and store the values on V1, V2 and V3 for example but it should take the sensor input as argument…. I don’t have 3 modules to test that for you neither the equipment to get proper 3 phase power from a single phase… Well overall it’s a start because I was stuck on how to drag out that calculation to do side stuff.

        Just be careful doing a lot of side stuffs can mess with your presicion

  10. Hello Yassine,
    I’m very happy with your project, but I still experience some difficulties calibrating the readings.
    If I understood you correctly, First I set the Slope=0, put no voltage to the module, and adjust intercept, so the value given in the serial monitor to be 0. After that i supply with known voltage and adjust Slope while I reach the known voltage.
    The problem is that when finished calibrating and supply a different voltage it gives back wrong readings.
    Am I doing something wrong?

    • The calibration of the slope and intercept can be pretty tricky, it’s best to start from the given values then modify them a little bit, otherwise put the AC voltage to 0, remove the slope and intercept completly,

      current_Volts = intercept + slope * inputStats.sigma(); —> “”current_Volts = inputStats.sigma();””

      First add the “intercept” until you get “current_volts=0” which means:

      “”current_Volts = inputStats.sigma() + intercept;””

      then put the AC voltage on a know value, then set the slope until you get the right value

      “”current_Volts = slope*inputStats.sigma() + intercept;””

  11. hello everyone 🙂
    how to draw zpt101b with fritzing ? anyone have a library for that module ? please help

  12. Great video tutorial with written explanation. Questions: 1- I’m using an ESP32 microcontroller with Home Assistant (ESPHome). Are you aware of anyone who has used the ZMPT101B module with Home Assistant? 2-Any Suggestions about incorporating the 2 libraries into Home assistant (Adafruit SSD1306 library, Adafruit GFX library)?

    Thanks again for your tutorial.

  13. Hello Yassine,
    I am looking to use ZMPT101B only to monitor if our street power is ON, and therefore do not need to show graphics of sine wave. The application is simply to monitor 1-phase 120v or 2-phase 240 volts coming into house.
    Nassau, Bahamas is having terrible power issues this summer, where BPL shuts off parts of the city for 3-4 hours, rotating limited power to homes.
    When BPL switches power back on, many homes get immediately hit with power “surges” that burn out electrics, fridges, radios, TV, etc.
    I noticed that homes with private generators avoid these surges, as their switching system on generator waits 30-60 seconds after the power comes back on, before switching back over to BPL’s grid.
    As we don’t have a generator, I’m developing a “latching relay” (Panasonic 50A and 90A relays) system that can wait 30-60 seconds before allowing power into our home.
    Therefore, I need an Arduino (Particle.io) program that can monitor BPL’s grid, switching OFF my home’s power internally, when power is lost (will use UPS to power Arduino), then watching (with ZMPT) until BLP’s power comes back on — to then switch the entire house back ON again to BPL’s grid.
    Any thoughts of how to do this with ZMPT ?

    • Hello yes you can add the ZMPT101B Right after your main breaker or before the device you want to protect, just don’t forget that it’s max voltage is 250V, and you can use a simple code for examlpe to measure peak to peak, but if your goal is just to know whether there’s voltage or not, you can use an optocoupler but always check the Max rating…
      For the latching relay you can just buy one too, for the 60s delay use an Arduino board if you want

      • Thanks for your advice. I’m testing on a Particle.io Argon board, as this will send out messages via the Particle.io API, so I can get alerts when power is cut. Particle can also send short “heartbeat” messages, with data on voltage, stats, etc. What I like most is you can send a command back to the Particle board from an app on your phone, web site, etc. This could be used to shut off house circuits, or do a manual switch-on via your phone…
        We’ll have L1+N for lights, appliances and small devices, plus L1+L2+N for a cistern pump and A/C compressor. The 240V is quite important, even though I don’t expect a pump to suffer from a power surge, as compared to small electronics, TV, etc.
        I found this GitHub:
        https://github.com/Abdurraziq/ZMPT101B-arduino
        If I get this working, I’ll post a .ino file back to you.

  14. Hi,

    I need to use this on a NodeMCU, but it looks like I have a wrong. Filters.h library, as it resets the microcontroller.
    Do you have any suggestion?
    Thanks

    Fabio

  15. Nevermind, I hit the problem.
    ESP-12 (and ESP8266) has the watchdog(WDT) turned on by default. If the watchdog timer isn’t periodically reset then it will automatically reset your ESP8266. The watchdog is reset every time loop() runs or you call delay() or yield() but if you have blocking code like the above ( when you check milliseconds) then the watchdog may time out. I have just replaced the miliseconds check with a delay(1000).

    Fabio

  16. hi, I’m about to do the project that using ZMPT101b,, but, first of all I need to draw the sketch in fritzing apps.
    I was looking for the ZMPT101b parts library in (.fzpz) format on internet, but haven’t find any result.
    so, could you share that ZMPT101b parts library in .fzpz format please?

  17. Hi, i tested it exactly as your code and it works pefectly, but now i want to run it inside a bigger project and i get a lot of noise (same hardware, more complex arduino code). i suspect is because i do other work in the main arduino loop besides calling this functions.

    i added a “delay(3)” inside the loop to simulate other work and got the same problem.

    Do you have an idea of what could it be?

    • Did you remove that “while(true)”? Because you should remove it if you’re using the code in another project.
      And of course it would be affected if you’re running a big code beside it, and those are the limits of the Arduino unfortunately, all I can do is to recommend you to measure the voltage for few seconds (Try and find what’s suits you)… then execute the other code

  18. hi. thank you for your great article.
    btw i need zmpt101b fritzing part and i have search but i didn’t find the part.
    may i beg your zmpt101b fritzing parts?
    i really thanks if you help me out

  19. Hi. thanks for your great article.
    btw i really need zmpt101b fritzing part for my coursework and i see yours.
    may i beg your zmpt101b fritzing parts?
    i am very grateful if you want to give me your zmpt101b fritzing parts!

  20. Hello, your project is very good, thanks! Can you help me in the project? I need to add that when I exceed 15 VAC, I will trigger an output of 5 V on the arduino. Could you tell me what I should add in the code? Thank you!

  21. Hello guys ,
    I have doubts about Arduino program. In my projetc I will work with Arduino Uno , Display LCD 1206 and sensor ZMPT101B.
    In My team we are building a Eletric generator . But I want use the arduino project to do the measuring circuit from the electric generator. Please give a example to do the eletronic conection and programming to show the voltage in the displays .
    Thanks in advanced,
    Mr. Gilmar
    My programming is below , But the Ac Voltage measure is not right. Can Somebody help me?

    #include
    LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

    //varias globais
    float volts=0;

    void setup()
    {
    lcd.clear();
    lcd.begin(16, 2);

    }

    void loop() {
    volts=analogRead(0)*(5.0/1023.0);

    Serial.println(volts);
    lcd.setCursor(0,0);
    lcd.print(“Voltimetro”);
    lcd.setCursor(5,1);
    lcd.print(volts);

    delay(2222);
    }

  22. When i print directly on serial monitor it give accurate volt but when i am using TM1637 Library and module to print the voltage it give us unstable voltage, i fund the reason is some delay on TM1637 library, Now what can i do for stable value with TM1637 and Filter library for stable value and sigma value, please help

  23. Hi sir, thank you for this wonderful project. I’m using this code for voltage measurement in energy meter. Since there is while (true) in the code, loop is getting stuck here and current, power, energy etc measurement is not happening. Do you have any work around for this issue? Thanks in advance

  24. How to fix this erros
    AC_Voltage_Measuring:52:3: error: ‘RunningStatistics’ was not declared in this scope
    RunningStatistics inputStats; //Easy life lines, actual calculation of the RMS requires a load of coding
    ^~~~~~~~~~~~~~~~~
    AC_Voltage_Measuring:53:3: error: ‘inputStats’ was not declared in this scope
    inputStats.setWindowSecs( windowLength );
    exit status 1
    ‘RunningStatistics’ was not declared in this scope

  25. Hello Surtrtech,
    How did you calculate the calibration values? Because I am getting almost double the voltage (the code shows more than 440 V for 220 V, thank you.

  26. Hi sir can you help me how can I combine acs712 and zmpt101b in one code with filters library to measuring voltage and current in the same time

    • Hello, I’ll try to do in the future… but for the moment you can try it yourself: Try making the same thing for both Voltage and Current, use the same method but different variables, and then alternate between them.

  27. Hi Yassine. First, Thx for this very informative post! It helped us enormously in our project. Do you know if it is also possible to display the Frequency as well as the voltage using Filters.h library ? or maybe you would recommend some other way to do it instead?
    We are using the ZMPT101B.
    Thank you again for the good work, Keep it UP!

  28. Hi Yassine.
    I’m combining the ACS712 and the ZMPT101B in one code at the same time. It worked, but when i add a delay the measurement become off, do you know why? I add a delay because im sending the measurement into a web database.
    Thank you in advance.

  29. How do I code for two sensors? I have tried, but data appears in both sensors even if I have only one connected to the 220 power source.

  30. Hi, i’m beginner for high voltage thing, can anyone tell me using this ZMPT101B sensor. can we measure 400AC voltage and voltage Frequency ?

  31. Hi,
    I am having trouble finding a GOOD reliable ZMPT101B module. Can you direct me to a place where I can get GOOD TESTED modules? Thank you very much.

Leave a Reply to RisnandaCancel reply

Discover more from SURTR TECHNOLOGY

Subscribe now to keep reading and get access to the full archive.

Continue reading