I have been trying to construct a smart energy meter that can observe readings of 220v household. For now i am working on voltmeter. I have been following the circuit I attached. Transformer step down 220V to 6V. Zener diode is of 5V. The output from the circuit( 5v max) is fed to arduino Mega 2560 A0 pin. * I am powering arduino using a USB cable * Arduino takes this voltage as input from pin A0 in form of analog values between 0 to 1023. 0 being 0 volt and 1023 being 5v.So any ranenter image description heredom analog value corresponds to X=(5/1023)*Y where Y is obtained analog value. X is then multiplied by a value obtained by hit and try method (165 in my case) to reach the exact reading of voltage in line observed via multimeter. Now the problem is that, everything works fine when i calibrate it, but after some time when i switch circuit on the value is inaccurate by margin, and i have to calibrate it again and again every time I turn circuit on after some time.If i switch circuit on soon after switching it off, it gives almost accurate value. I guess this issue is due to the capacitor, but i don't know anything about it or how to solve it I have constructed the same circuit more than 5 times, soldering it 3 times and 2 times on bread board and i am sure there is no problem with my implementation, verified it many times. this is my code:

float V; // Voltage samples
float V0;

void setup() {

void loop() {
  for(int i=0; i<=20000; i++){
    V = V + analogRead(A0); 
  V = V / 20000;
  V = round(V);

  float V0 = V * (5.0 / 1023.0);
  I0 = I0 * 165; // has to be callibrated again and again each time circuit is switched on after a while

  Serial.print("Voltage = ");
  Serial.println(" -------------- ");

this is the link i am following http://engineerexperiences.com/3-phase-smart-energy-meter-using-arduino.html

Any help would be appreciated, Thanks!

  • you monitor the household or only some appliance or device?
    – Juraj
    Commented May 24, 2018 at 11:57
  • thank you for asking Mr. Edgar Bonet, my aim is to monitor electrical consumption of a household.
    – Ali Kashan
    Commented May 24, 2018 at 12:46

2 Answers 2


With that circuit you can expect a roughly 10% variance in the output voltage depending on the exact moment at which you sample the voltage.

The basic circuit you have, and the waveforms generated, are like this:

enter image description here

That green waveform is the one you are reading. As you can see, exactly where you sample defines what the result will be.

Since you're trying to average over an undefined period (20,000 samples of how long per sample exactly?) you're not going to get a particularly well defined output.

You should change your sampling strategy to perform multiple samples over a well defined period to find the maximum value. That is the value you should then use in your calculations.

Ideally, you want to repeatedly sample for at least one entire waveform cycle. At 50Hz that's a period of 20ms (17ms for 60Hz).

For example:

uint16_t maxval = 0;
uint32_t ts = millis();
while (millis() - ts < 20) {
    uint16_t val = analogRead(0);
    if (val > maxval) {
       maxval = val;

// Use "maxval" in your calculations. 

With this strategy, because you're looking for the peak value, you don't care about the impact that the capacitor has on the circuit (except that it will remain artificially high for a period if the voltage drops), so you could actually simplify the circuit and remove that capacitor completely.

  • he uses average of 20000 A0 readings
    – Juraj
    Commented May 24, 2018 at 11:12
  • Yeah, now the post is formatted I see that. That's not really ideal though, since you're dependent on a) how fast the ADC reads, and b) how fast the capacitor discharges. By finding the max over at least 1 wave period you don't care about either of those.
    – Majenko
    Commented May 24, 2018 at 11:14
  • Re-worded it to fit that existing method a little more.
    – Majenko
    Commented May 24, 2018 at 11:17
  • Honorable Majenko, first of all thank you for sparing some time and communicating amazing knowledge to me. Earlier i was using this approach for (int i=0; i<=39; i++){ adc_int[i] = analogRead(A0); } int max = adc_int[0]; for(int i=0; i<=39; i++){ if(max < adc_int[i]) max = adc_int[i]; } and i used this peak value in my calculations the results were unpredictable after time as i explained in my question, anyway I will follow what you have instructed and get back to you soon after implementing your teachings
    – Ali Kashan
    Commented May 24, 2018 at 13:04

I just wanted to add some points to what Majenko already said.

You are making a measurement device, so you need a precise reference. So why are you using the 5V reference?

Your 5V in your circuit is assumed to be stable. But is it? Maybe some time you are using the PC to power it, then you attach a lot of loads to the USB ports, then you use a wall USB power supply. Every time the 5V can change (see here for instance). A variation in the supply of +/-5% will be translated in a +/- 12V for a 240V input (I don't know if this is above or below your expected accuracy).

The solution is to use the internal reference, which is an internal peripheral used explicitely for measuring analog sources.

In your case (Arduino MEGA 2560) you have a 1.1V or a 2.56V internal references. Your transformer is a 240->6V transformer, which means the value you should read after it is around 8.5V (6Vrms has a peak of 6*1.415 = 8.5V). After the voltage divider, this becomes 1.53 V. Consequently you can use the 2.56V reference in this case. To do so write, in your setup function, analogReference(INTERNAL2V56);. Then your readings will be relative to 2.56V rather than 5.0V (so float V0 = V * 2.56 / 1023.0;).

(Note: the way to implement this was taken from the arduino reference manual; I never implemented it, so it may require tweaking)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.