Use the ACS712 to monitor my house energy use?

Thanks Robert,
In fact, this is what I have at the moment - an SCT-013-030 clamped on the main cable (actually x3 since it’s 3-phase setup).
However, with this setup I’m not really confident about accuracy - e.g. when my oven starts (it’s 1-phase) I see a current reading increase in 2 phases… so I though doing it with ACS712 would be more stable.
In that case, what I can do is place an ACS712 after some circuit breakers (most of them are 16 or 10A). Hopefully the board can survive it…:wink:

Having said that, I’m also struggling with Volt reading. I want use the ZMPT101B with ESP32 Devkit DOIT and emonlib library but I can’t get it to work - the reading are completely unstable (even after calibration of the device, setting analogReadResolution(10), etc.)

I read somewhere that ESP32 is pretty crappy when it comes to reading ADC signal so I thinking if I could go with an external MCP3008 or even ADS1115 converters for a more stable output (btw - on an old Arduino - this works qutie well without any issues).

Is there any example with ZMPT101B voltage sensor working with ESP32? I have already spent 2 days on the net looking for such an example :frowning: so I’m wondering if it has sense at all…

Is yours a 4-wire system or 3-wire (not counting the protective earth conductor, do you have L1, L2, L3 & N or only L1, L2 & L3)?

I have L1, L2, L3 & N

Yep. Seems like a device for a single outlet < 16A rather than whole house monitoring.

I had very nice mains voltage readings using a ZMPT101B and opamp recently, it’s a component worth looking at.

@Padmocho maybe worth looking at this?

And your voltage is 230 V L-N?

Your value of 6.9 kW is wrong because the 30 A represents the peak (or d.c.) maximum current, the rms value that is the normal and assumed measure of alternating current will be about 21 A or less, depending on the exact shape of the current waveform. So a little more than 4.8 kW.

Is your oven actually connected across 2 phases, or even 3? That could explain why you see current on two phases.

If you’re confident with the Arduino, why don’t you use 3 × ZMPT101 modules to measure the three phase voltages, and three SCT-013-030 c.t’s to measure the phase currents? You’d need to make up the c.t. interface circuit (see the ‘Learn’ section) but the ZMPT module would connect directly to the ADC input of the Arduino.

The ADS 1115 isn’t a good choice - at a maximum of 860 samples per second, that’s only 17 samples per mains cycle shared between the voltage and current inputs, so about 8 sample pairs. The emonTx (the same processor as the Arduino Uno) with emonLib can do 55 sample pairs per mains cycle.

The MCP3008 would be a better choice, but another user is struggling to get that working with a Raspberry Pi (DIY Current Monitor on Raspberry Pi. My power calculation isn't accurate. Help please?)

I’m not familiar with the ESP32, so I can’t really help. The link to the schematic of the DOIT is 404, so there’s no useful information available to me. The only suggestion I have is, have you calculated the sample rate, and (if you’re using calcIrms( )) the correct number of samples to average over? Because if it’s doing 200 k or 2 M samples per second, you need to average over an absolute minimum of one fiftieth of that (i.e. 40 k or 400 k samples).

Thanks for Your help! I am now having a bit more time so I can come back to this topic. Let me summarize my issues a little:

  1. I’m using ESP32 which has a pretty crappy ADC (non linear, poor reading etc.) → therefore I decided to “upgrade” it with the ADS1115
  2. From the Arduino serial plotter I am now getting a relatively good looking sign-wave for the current. This was not possible using the ESP32’s internal ADC’s.
  3. So, current setup is: ESP32 + ZMPT101B + ADS1115 (to be honest I don’t fully understand Robert’s explanation about max number of samples :frowning: )
  4. I’m forgetting the current readings (ACS712) completely - just concentrating on Voltage at the moment.

The issue is - how do I get the AC Voltage reading from the ADS1115 channel (which is a sign wave)?
I wanted to use the emonlib function:
emon1.voltage(pin,calibration,1.7) - but I don’t know how to provide the “pin” information here…

My concern here also is I’m migrating a bit from the original topic - I wouldn’t like to “brake” any forum norms…


As I wrote above

That number - 860 samples per second- came from the data sheet. If you are using the ADS1115 only to measure voltage, that still means that you can have a maximum of 17 samples per mains cycle - and that is if you allow the processor to do the maths while the ADS1115 is working. If it has to wait for a result, work on the maths and then ask the ADS1115 to take another reading, the sample rate will be even slower.

It also means that if you are going to calculate real power, you can only make use of 17 (or less) samples per cycle of current readings - because you must use them in pairs. Now here’s the unpleasant part: if your current waveform not a nice clean sine wave (and it probably will not be if you have switched-mode power supplies), then your current readings will not include all the harmonics, and they will be wrong.

There is no emonLib method to calculate only the rms voltage, and you can’t use emonLib directly. There is calcVI( ) which calculates everything, and that’s what you need to use.
EnergyMonitor::voltage( ) and EnergyMonitor::current ( ) only set things up for calcVI( ).

You can’t simply call emonLib because it reads from a pin. You will need to write your own function, one that’s almost exactly the same as calcVI( ), to get the output from the ADS1115 and whatever you later use for the current measurements. That value for voltage will come in as serial data from the ADS1115, and then you substitute that number in calcVI( ) where it reads the input pin of the Atmel '328P:
(That appears twice - once in a loop while it waits for the zero crossing, and once in the main loop to calculate power etc. Note that as you are only reading 17 samples per cycle or less, you will need to open up the band where it detects ‘zero’ - as it stands, it is the mid-scale ±5%. It will need to be much wider than that, at least about ±20% to guarantee catching a sample on the first half-cycle).

If the title doesn’t seem appropriate, it can very easily be changed. It would be a mistake I think to start a new topic now. (If only because instead of scrolling up to remind myself what’s happened with your project, I’d need to find this old thread first and then refresh my memory.)

OK, so today I have been trying to focus only on getting the VAC measurement.

  • I have used a modified version of the Emonlib library which allowed me to substitute the analog ping with the ADS1115 function… - that didn’t work
    So, I’m now trying to “simply” calculate the effective Voltage based on analog reads… I also read on the ADS1115 datasheet that if I switch to 12-bit version (Adafruit_ADS1015 ads;) I get more sample rates(?)

So, in my current setup I am using ZMPT101B to measure 230V AC current and then attaching its output to A0 on ADS1115.
I’m reading the value with:
adc0 = ads.readADC_SingleEnded(0);
and then printing it with:
Serial.println(adc0 * multiplier /1000);

  • where “multiplier” is 0.1875F representing 0.1875mV per 1 bit

After some calibration, this gives me a nice sine-wave between voltages of around: 0.71-3.78V with 2.55V being steady when the AC voltage is OFF.

here’s my full code:
#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
//Adafruit_ADS1015 ads;     /* Use thi for the 12-bit version */
const float multiplier = 0.1875F;
int16_t adc0=0;

void setup() {

void loop() {
adc0 = ads.readADC_SingleEnded(0);
Serial.print("Vout: ");Serial.println(adc0 * multiplier /1000);

How can I proceed further?

  • should I try and “copy” the calcVI( ) function - I’m worried this will be too hard to understand for me
  • is there any available examples elsewhere how I can find the effective Voltage doing my own calculations? - here the issue is I found a lot of examples for Arduino where the analog range is 0-1024 and I don’t really see how other parameters are chosen

I have used different chips (NodeMCU, Arduino Uno, Wemos D1 mini, ESP32, NodeMCU) - and in each case I’m hitting a wall of some kind:

  • either not enough analog pins (e.g. Wemos)
  • either poor quality of the ADC (ESP32)

I’m almost at the point of giving up all together on it :frowning: as I’m surprised how difficult it is to use popular components like ESP32 + ZMPT101B + SCT-013-30A + ADS1115 / MCP3008 to get a home energy setup going…
I really expected there would be tons of ready-made examples :frowning: Really feeling down…

You mean you’re measuring the 230 V a.c. voltage?

The problem I think is, those are indeed popular components, but they are not fully suitable for the task. Measuring mains quantities is quite complicated and specialised - there are i.c’s dedicated to the task, but using them safely at home is quite difficult as they are intended to go in professional equipment that the user won’t go inside and touch possibly fatal voltages.

Have you thought about using one of the more powerful Arduinos - if the Arduino Uno (which uses the same processor as the emonTx and emonPi) is not good enough for what you want?

Why will it be too hard to understand? The basic idea is very simple - it is complicated only because it is counting mains cycles and doing three separate calculations all at the same time.
Here are the three basic steps:

  1. Wait for the voltage to cross the a.c. zero.
  2. Run a loop adding up the V² from each reading, and every time it crosses zero, add to the count of cycles.
  3. When you have the required number of cycles, calculate the rms value and add the calibration.

In the real calcVI( ), step 2 also does the same for current, it corrects for phase errors between the two transformers, and it adds up V × I to give you real power.


Try this function. Put it in a loop and print the value it returns. It doesn’t do everything that calcVI( ) does, and there’s no guarantee it will work, but there is a good chance that it might. If it does, you’ll have a good understanding of the basic working of Step 2 of calcVI( ).
Make Number_of_Samples a large number - about 850 at a guess. That should give you an answer roughly every second.

double offsetV = ADC_COUNTS>>1;  // Start with the offset = half-scale
double filteredV;          //Filtered_ is the raw analog value minus the DC offset
double sumV = 0;
double VCAL = 0.1875F;  // This number is probably wrong - you need to find the correct value.

double calcVrms(unsigned int Number_of_Samples)
  for (unsigned int n = 0; n < Number_of_Samples; n++)
    sampleV = ads.readADC_SingleEnded(0);
    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset, 
	  //  then subtract this - signal is now centered on 0 counts.
    offsetV += (sampleV-offsetV)/1024;
	  filteredV = sampleV - offsetV;

    // Root-mean-square method voltage
    // 1) sum squared voltage values

    sumV += filteredV * filteredV;
  Vrms = VCAL * sqrt(sumV / Number_of_Samples); 

  //Reset accumulators
  sumV = 0;
  return Vrms;

If it works, look very hard at emonLib and see what I’ve done. Do you recognise any of it?

Near the top, I put a comment “This number is probably wrong - you need to find the correct value”.
That is because I have not worked out the calibration that you need. You know that 1 count represents 0.1875 mV, but this does not take your ZMPT101B into account to give the true mains voltage, which is what you really want. The value for VCAL will probably be about 50 (working from the numbers you quoted).

If it doesn’t, you can debug it. :wink: But don’t despair, I’ve helped people climb out of bigger holes than this. I won’t give up on you.

1 Like

Thanks Robert, You’re adding hope :slight_smile:
I will work on Your code and provide feedback how it goes. In the mean time to answer Your questions:

  • Yes, I’m (trying) to measure 230V a.c.
  • I mentioned the parts I’m using but You’re suggesting that they are “not suitable for the task” - what would be a better list of hardware? (note the final goal is measuring 3x phase energy for the house)
  • I tried You code and with some modification is producing outcome… which isn’t sensible at all (note I’ve used ESP32 for it) giving values between 400 and 2100…

So, I’ll try to analyze the full code and come back…

I have told you what I see as the limitations several times.

Robin Emley ( uses the Atmel ATMega 328P in his 3-phase energy diverter, and I think if you copy his design - which is proven to work - you will have what you require. Depending on how you want to display the power, you could use a serial output or the 433 MHz radio.

If the number varies significantly, then the likeliest reason is you are not averaging over enough samples of the mains wave. To measure one cycle accurately, you must exactly fit the samples into one cycle. If you measure less or more than exactly one cycle, you will have an error. If you don’t know how many samples fit into one cycle, then you do not know where to start.

This is what you wrote earlier:

I calculated the values for that. If you are going to use the ESP32, then I am not surprised it does not work. I can only help you if you do what you say you are going to do. If you do differently, you cannot expect that what I suggest will work.

So, you can either go back to the ADS1115, or measure the sample rate you get with the ESP32, then adjust the number of samples you average over to cover an exact whole number of mains cycles.

I’m trying to figure out 2 points:

  1. The mentioned sample rates for the ADS1115
  2. Your comment about fitting samples into a cycle

Ad.1 In code I tested the following:

void loop()
adc0 = ads.readADC_SingleEnded(0);
for (int i = 0; i < 10000; i++)

In the serial monitor, I’m looking at the output with timestamp and see:

19:00:32.013 → 7688

19:00:33.002 → 9622

So, for around 1 second I’m getting (9622-7688) => 1,934 readings… how does that fit into the ADS1115 datasheet sample rate of 860 Samples/Second?

Now, when You say:

To measure one cycle accurately, you must exactly fit the samples into one cycle.

In Poland the AC is delivered with 50Hz (50 cycles / sec). So, using 860 samples / second => this would give me around 17.2 samples for 1 cycle… Am I thinking about it correctly?

Also, when I mentioned I am using ZMPT101B with ADS1115 - and that I’m using ESP32 as the board - I didn’t mean I’m measuring anything with ESP32… I’m just using it as the “brains”…

What are you trying to do there? As I read that piece of code, it measures 1 sample, then prints the numbers 0 - 9999. I cannot see how that tells you anything useful, because it is timing the print as well as the analog read. I think that shows that 1 analog read plus a lot of print statements takes 989 ms.

I don’t think so. I don’t see how that piece of code can tell you that.

You need something like:

void loop()
  Serial.println("Start 1");

  for (int i = 0; i < 100; i++)
    adc0 = ads.readADC_SingleEnded(0);
  Serial.println("End 1");
  Serial.println("Start 2");

  for (int i = 0; i < 10100; i++)
    adc0 = ads.readADC_SingleEnded(0);
  Serial.println("End 2");


and note the 4 times for the prints. The time for 10000 samples is then [times of] (End2 - Start2) - (End1 - Start1).

Yes - it’s the same in the UK (where I am), except we’re not synchronised to the European grid, as we’re connected by d.c. links.

Ah, understood. When you wrote

I thought you meant that you were using the ADC in the ESP32.

Hi Pavel,

You may want to take a look at this:

Bottom line: using an ADS1115 is an excercise in futility. The ADC sample rate is too slow.
The thread at the link above explains why. It’s a quick read. There are only 8 posts in total.

Hey, I am working on something similar, and I need help with my smart meter project. From a circuit breaker, I plan to connect the ZMPT101B voltage sensor and the ACS712 30A current sensors to an MCP3008 ADC, which would send readings to my Raspberry Pi 3. I also have an 8 channel SSR relay module to help switch off and on appliances in this office. Firstly, the largest load is an air conditioner and also, I really want to know if my project is viable with those sensors and the ADC?
Secondly, do I need any other electrical components to make this work?
Thirdly, can anyone put me through with the work?

Welcome @bolade_jr to the OEM forum.

I’m afraid trying to measure power and using the ZMPT101B module is doomed to be a failure. I’ve written several times about this - but the ZMPT101 current transformer on its own using the circuit on the data sheet is fine.

The performance of the MCP3008 appears to be adequate in terms of the maximum sample rate.

Of course - The application notes from the manufacturer usually give ‘typical’ circuits, which you should be able to copy and use.

I don’t understand what you are asking there. We can only offer advice, based on what you’ve told us. We can’t design the project for you.

The sole purpose of the voltage sensor is to measure voltage and the current sensor to measure current, while I plan on using the Raspberry Pi to calculate the power. Still, I would appreciate it if you could explain more why the ZMPT101B voltage sensor would be doomed to fail. Also, do you have any other recommendation of the electrical component that could read 240v ac or perform a better function on what I intend to build


Did you search for my posts about the ZMPT101B module? In fact, do you understand how to measure power?

Remember, we only know what you write about your project.

I’m not sure how to measure power, I presumed I could code that on the Pi

Look at the ‘Learn’ section. Although the examples use the ATMega328P or Arduino Uno, the principles and the maths are the same whichever processor you use.