Measure AC Voltage with Arduino doesn't work?

I want to measure AC Voltage (230) I wan't to do it in way that I find here (Measuring AC Voltage with an AC to AC power adapter — OpenEnergyMonitor 0.0.1 documentation)

I have made few changes to this circuit diagram:

  • I use AC/AC Adapter with output 21V RMS
  • for R1 I use 4k7
  • for R2 I use 100k (like on circuit diagram)
  • for R3 and R4 I use 470k
  • for C1 I use 3.3uF
    also I plan use it with 3.3 powered Arduino (not 5V like on circuit diagram)

I connect all together and for testing do not connect Arduino at this moment but I conncect 3.3V supply to point on circuit diagram described as "Arduino GND" and "Arduino 5V d.c." also I power AC Mains and now I test Voltage with my multimeter:

  • on Adapter output in AC range I have value 21V
  • between "Arduino GND" and "Arduino 5V d.c." I have 3.3V (DC range)
  • between "Arduino GND" and "Arduino Input" I have 1.61V in DC range or 0.9V when I switch multimeter to AC range, when I disconnect AC Mains supply then in DC range I still have 1.61V but in AC range I have 0V

Is this ok?
(I will check all connection in my circuit and all is like on circuit diagram)

between "Arduino GND" and "Arduino Input" I have 1.61V in DC range or 0.9V when I switch multimeter to AC range, when I disconnect AC Mains supply then in DC range I still have 1.61V but in AC range I have 0V

Is this ok?

Well, what is 3.3V/2 ?

Since you are measuring 1.61V at the midpoint I would guess that either your 3.3V really only 3.22V or
your resistors are out of tolerance.
What is the voltage (exactly) that you are calling 3.3V ?

Using 5% or 10% resistors? Still all seems to work fine. 4k7 / (100k + 4k7) * 21V = 0.94V, so the ac
values seem reasonable. 0.9V rms is about 2.6V peak-to-peak so that's nicely within the 0..3.3V range

raschemmel:
Well, what is 3.3V/2 ?

Since you are measuring 1.61V at the midpoint I would guess that either your 3.3V really only 3.22V or
your resistors are out of tolerance.
What is the voltage (exactly) that you are calling 3.3V ?

I use 5% resistors. 3.3V is exactly 3.31V

MarkT:
Using 5% or 10% resistors? Still all seems to work fine. 4k7 / (100k + 4k7) * 21V = 0.94V, so the ac
values seem reasonable. 0.9V rms is about 2.6V peak-to-peak so that's nicely within the 0..3.3V range

Then is it safe to connect to Arduino?

I think that using multimeter I should measure between "Arduino GND" and "Arduino input" around 0,94V at DC range not AC. I'am wrong? If I now connect it to Arduino then it do not blowup my Arduino because of AC?

Just add a 10k resistor inline with the Arduino pin, robust extra protection at minimal cost.

It's works... probably, reading voltage using this code:

void loop() {
Serial.println(ads.readADC_SingleEnded(2) * 0.000125);
}

I'm reading without any delay it's probably around 10ms between reads.
I got values like this:

0,55
2,67
0,77
2,26
1,33
1,61
2
1
2,51
0,61
2,72
0,6
2,54
0,97
2,01
1,61
1,33
2,16
0,85
2,61
0,56
2,71
0,67
2,39
1,16
2
1,6
1,32
2,23
0,81
2,63
0,55
2,69
0,7
2,34
1,21
1,71
1,89
1,07
2,33
0,71
2,68
0,54
2,65
0,78
2,22
1,32
1,59
2
0,96
2,4
0,66

It's probably right, but how to get RMS value from this "variable" values?
On page which I give link earlier is library for that but because I use external ADC (ADS1115) I can't use this library

XnIcRaM:
I'm reading without any delay it's probably around 10ms between reads.

Can't do that. Printing also takes time.
You need to sample the AC wave as fast as possible for a certain amount of time,
while only storing the min and max peak values during that time.
Then calculate the difference betwean them (peak/peak value).

The average Arduino A/D is many times faster for that than an ADS1115.
Leo..

You start your post saying you want to follow the example given ,
which is this:

peak_voltage_output = R1 / (R1 + R2) x peak_voltage_input =
10k / (10k + 100k) x 12.7V = 1.15V

I'm not sure how the values posted relate to the example you gave, in view of the fact that
you have not posted any code or calculations. What are we supposed to do with what you
posted ?

raschemmel:
You start your post saying you want to follow the example given ,
which is this:

I'm not sure how the values posted relate to the example you gave, in view of the fact that
you have not posted any code or calculations. What are we supposed to do with what you
posted ?

Why ppl with many thousands posts don't read my first post?

example which I want to follow is for Arduino 5V and AC/AC power adapter 11.2V RMS if you read cearfully my first post you can see that I have AC/AC Adapter with 21V RMS output and Arduino 3.3V instead of 5V then I change few elements in given example to fit circuit to what I have.

If you don't want help or don't know how to help me then I'm asking you: do not write in my topic, don't waste your time

If you don't want help or don't know how to help me then I'm asking you: do not write in my topic, don't waste your time

Would think this is a little overdramatic. Folks here sincerely try to help, sometimes they get it right on, sometimes they misunderstand the question and sometimes they are exasperated by some other incident in their lives. IMHO the kinder approach is always best :slight_smile:

i read your OP.
I don't see any code posted relevant to the example you gave.

What is your question ?

It's works... probably, reading voltage using this code:

I don't see any code, so what exactly is working ?

Please post your code.

If you don't want help or don't know how to help me then I'm asking you: do not write in my topic, don't waste your time

Help you how ?
You have to ask a question for someone to help you.

So what is your question ?

Also you have to post your code. Where is it ?

The printout is exactly what the code does.
Print a single snapshot of a forever changing wave every ~10ms.
About two readings per wave at random points in time.

Take the lowest reading of that list and subtract it from the highest reading.
Then you have the value to calculate peak/peak value.

Read post#6 again.
Leo..

On a 3.3volt supply, PGA gain ofcourse has to be set to 2x if you want max single-ended resolution (15-bit).
Then the resistors must be calculated for 2.048volt peak/peak.
Leo..

Wawa:
Take the lowest reading of that list and subtract it from the highest reading.
Then you have the value to calculate peak/peak value.

Now I do it like that:

void loop() {
unsigned long ts = millis();
float V;
float minV = 4;
float maxV = 0;

for (long i = 0; i <= 100; i++){
V = ads.readADC_SingleEnded(2) * 0.000125;
if (V > maxV){
maxV = V;
}else if (V < minV){
minV = V;
}
}
Serial.println((maxV - minV)* 110);
}

Have stable and sensitive output but need try it at differents place and phase's

Wawa:
Read post#6 again.

will check how it works on build in ADC (but not today) I use ads1115 because theoretically it's more accurate however, I did not think it was slower. Now I know that and will check it

Wawa:
On a 3.3volt supply, PGA gain ofcourse has to be set to 2x if you want max single-ended resolution (15-bit).
Then the resistors must be calculated for 2.048volt peak/peak.

now I use gain 1x and I try to calculate if 2x isn't too much but not now :slight_smile: I need go to sleep (is late here)

XnIcRaM:
It's works... probably, reading voltage using this code:
I'm reading without any delay it's probably around 10ms between reads.
I got values like this:

It's probably right, but how to get RMS value from this "variable" values?

If you know that RMS stands for root-mean-square, you should be able to figure
out that you calculate the mean of the squares of the samples, then take the
square root.

In particular you need to remove the DC offset first, ie:

  1. calculate the mean
  2. subtract the mean for every sample <<< correction: from every sample
  3. square every sample
  4. calculate the mean value of these squares
  5. take the square-root of this value.

XnIcRaM:
will check how it works on build in ADC (but not today) I use ads1115 because theoretically it's more accurate however, I did not think it was slower. Now I know that and will check it

Read the specs, do your homework.

The ADS1115 is accurate and has good resolution, it's dirt cheap, but also slow: maximum sampling rate is just 860 sps. It's 12-bit sister the ADS1015 can do better at 3,300 sps.

In contrast, a 16 MHz Arduino can do some 9,600 sps in default configuration and that can be boosted quite a bit (at loss of resolution).

wvmarle:
...maximum sampling rate is just 860 sps.

Yes, but only of your code is set from default to that speed.
And you use an interrupt on the alert/ready pin.

Who knows. OP only has posted snippets.
Leo..

wvmarle:
Read the specs, do your homework.

The ADS1115 is accurate and has good resolution, it's dirt cheap, but also slow: maximum sampling rate is just 860 sps. It's 12-bit sister the ADS1015 can do better at 3,300 sps.

In contrast, a 16 MHz Arduino can do some 9,600 sps in default configuration and that can be boosted quite a bit (at loss of resolution).

How fast I should read to get correct values for measure AC voltage 50Hz? Now I read voltage 125 times per second it's 125Hz, it isn't enought for 50Hz AC?

Depends on what you're actually trying to measure.

To get a more or less accurate representation of the actual waveform I'd want to be at least at 10x higher frequency (500 sps), for a smooth waveform you'd have to look at 100x (so 5k sps).

If you just want to know the peak voltage, I'd be looking at a circuit containing a rectifier, smoothing cap and voltage divider (RC of the cap & voltage divider at about 10x the period, so RC of 10 ms for 50 Hz as it gets doubled in frequency by the rectifier).

If you want to measure the actual frequency, a zero crossing or peak detection circuit.

void loop() {
 unsigned long ts = millis();
 float V;
 float minV = 4;
 float maxV = 0;

 for (long i = 0; i <= 100; i++){
  V = ads.readADC_SingleEnded(2) * 0.000125;
  if (V > maxV){
    maxV = V;
  }else if (V < minV){
    minV = V;
  }
 }
  Serial.println((maxV - minV)* 110);
}

For starters, your declarations should not be in the main loop, and for seconds, you should put your
samples in an array inside a loop with nothing else in the loop so you get the fastest sampling speed,
and for thirds, you can use loops later to process the collected data.

Look up how to initialize an empty array
Look up how to append an array in a loop
Look up how to find min and max values in a loop
and last but not least , reread this:

If you know that RMS stands for root-mean-square, you should be able to figure
out that you calculate the mean of the squares of the samples, then take the
square root.

In particular you need to remove the DC offset first, ie:

  1. calculate the mean
  2. subtract the mean for every sample <<< correction: from every sample
  3. square every sample
  4. calculate the mean value of these squares
  5. take the square-root of this value.

also, there are plenty of examples on the web of how to do fast analog reads with an arduino.
What should be obvious is that you should not be doing anything else in between reads because
it reduces your sampling time.

Here's a freebee:
analogReadFast Library