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 guys, 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”.
This module used with the right code, is far better for measures, than the other methodes that uses transformer + rectifier + voltage divider…., these kind of things 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 si 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.
The module takes the signal we want to measure, here a 220V domestic power, it has around 311V as its peak.
The module transformer brings it back to 2.5V peak.
Then it adds a 2.5V offset to adapt it to the Arduino.
And here pay attention, some codes around are used with this module, they only do a sampling of the signal and measure the peaks then a little multiplication,and it can show you the “RMS” of this signal, but those codes work only for perfect sinewave signal, if you’re measuring another shape of the signal it would be false.
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 makes.
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.
Wiring:
This is the whole wiring, and as mentionned I’m using an 128×32 OLED screen you can use it or no, the module is powred by 5v and delivers an analog signal.
Setup:
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.
1 2 3 4 5 6 7 8 |
void setup() { Serial.begin(9600); } void loop() { Serial.println(analogRead(A0)); } |
Open the serial plotter of the Arduino IDE:
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.
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.
1 2 3 4 5 6 7 8 9 |
void setup() { Serial.begin(9600); } void loop() { Serial.println(analogRead(A0)); delay(100); } |
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
Code:
Here’s the code I’ve used: Download here
Tests:
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.
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, I hope you like it, be careful and if you have any probel feel free to contact me, don’t forget to support the channel by a subscribe.
Categories
Yassine View All
Automation and Electrical Engineer, Electronics amateur trying to share my little projects.
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
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
Hi my problem is that it deos not work ESP32
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
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
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.
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.
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 !!!
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?
Hello Sir,
i like this project.
I want to check all 3 line with 3 ZMPT101B’s.
How can i change out ino ?
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
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
}
}
}
Thank you a lot for sharing it here with us
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
No problem, If you have problem with calibration, you can check my latest tutorial about current sensor ACS712 I use the same method.
https://surtrtech.com/2019/12/11/measure-any-ac-current-with-acs712-and-arduino-lcd-oled/
(check the video or read a code, third code or LCD/OLED code)
But for the other thing (doing other stuffs beside measuring) I’ll start working on it as soon as possible and if I succeded, a little video will be up with calibration summary too.
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
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;””
hello everyone 🙂
how to draw zpt101b with fritzing ? anyone have a library for that module ? please help
That was just a png image, for the library I just used that “Filters” one
can i have your library zmpt101 in fritzing? I am not found it
I don’t have it that was just a png image
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.
Hello, I’m sorry, I’m not familiar with the ESPHome, I think you could use the Adafruit SSD1306 library:
https://esphome.io/components/display/ssd1306.html
The only thing I can mention, is to pay attention to the values, I operate the module with 5V, ESP32 has 3.3V, so try to adapt the values.
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.
Thanks, good luck
hello, has anyone tried this on 60Hz frequency to measure 220-240V?
Hello, in the code there’s “testFrequency = 50” that’s for the frequency you can change it to 60
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
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
I got that kind of problems before, yield function solves it.
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?
Hello sorry that’s not a fritzing part, it’s just a .PNG that I integrated to fritzing.
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
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
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!
It was just a png
https://drive.google.com/drive/u/0/folders/1QWjyMn-uxsei6WB1oH7e40QBTEZVho1_
Just a PNG not a full functionnal fritzing part.
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!
Hi, after the functions that display the readings you can add what you want in a “if” statement https://www.arduino.cc/reference/en/language/structure/control-structure/if/
if(condition)
digitalwrite(pinx,HIGH)
and don’t forget to declare the pin and its mode
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);
}
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
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
Hello, yes you can remove that while(true) loop, move the “RunningStatistics inputStats;” to global declarations, “inputStats.setWindowSecs( windowLength );” can be set at “setup”, you can keep other calculations in the loop… please check those articles to find some examples:
https://surtrtech.com/2020/04/08/measure-any-ac-voltage-250vac-with-zmpt101b-and-esp8266-12e-with-android-app-adafruit-io-mqtt/
https://surtrtech.com/2019/12/11/measure-any-ac-current-with-acs712-and-arduino-lcd-oled/
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
That’s a library problem.
please help how to fix library problem
It needs to be installed, search on how to do it.
HI DEAR
I want measure both current with(ac712)+ voltage with (zpmt) .
How do I use the Sigma function for both?
Hello you can declare other variables, or you can use the same method for both just change the pin, like selecting the sensor A pin or sensor B pin, and it will switch between them.
Can u right code for that please thanx
Hi
How can we measure both voltage and current using Filters.h
Best regards
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.
Hello Surtrtech,
How did you calculate the calibration values? Because I am getting like 440V instead of 220V, thank you.
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.
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!
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.
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.
Hi, i’m beginner for high voltage thing, can anyone tell me using this ZMPT101B sensor. can we measure 400AC voltage and voltage Frequency ?
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.