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:
- Wait for the voltage to cross the a.c. zero.
- Run a loop adding up the V² from each reading, and every time it crosses zero, add to the count of cycles.
- 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.
Now - COURAGE
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);
sumV = 0;
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. But don’t despair, I’ve helped people climb out of bigger holes than this. I won’t give up on you.