Better AC sensing circuit for ADC conversion

MrAl

Joined Jun 17, 2014
13,716
Thank you.

Do you want me to use this idea into the code that I posted ?
Hi,

Well I've found that regular rectification and analog filtering combined with digital filtering works very well, and it's pretty simple.
In the last step, you calibrate the digital part to get good accuracy.
 

Thread Starter

Hasan2019

Joined Sep 5, 2019
199
Hi,

Well I've found that regular rectification and analog filtering combined with digital filtering works very well, and it's pretty simple.
In the last step, you calibrate the digital part to get good accuracy.
In which platform you are working on. Is it python, c or what ? Any harm you think to post your code here ?
 

MrAl

Joined Jun 17, 2014
13,716
In which platform you are working on. Is it python, c or what ? Any harm you think to post your code here ?
Hi,

Well I've used both asm and C and C++. In asm you have to work with individual instructions, in C you can work it like a simple math expression.
The one I gave previously was:
Vavg=(Vavg*(N-1)+Vsample)/N

You can use that or the one given by MrChips after that.

If you need it as fast as possible then you would use all integers, but if not you can use floating point. If you like you can also used fixed point.
I used all integers on some apps, floating point on others, and when the AMD fake 8 cores came out I switched to fixed point for image processing.

That filter above is a first order filter but it works pretty darn good with large N. The larger you go up in the value of N, the smoother your DC voltage becomes and more stable. The tradeoff is it takes more time during startup to get a good first reading, and takes more time to get a good average after a step change. Step changes don't always matter too much though it depends on what you are doing.
 

Thread Starter

Hasan2019

Joined Sep 5, 2019
199
Hi,

Well I've used both asm and C and C++. In asm you have to work with individual instructions, in C you can work it like a simple math expression.
The one I gave previously was:
Vavg=(Vavg*(N-1)+Vsample)/N

You can use that or the one given by MrChips after that.

If you need it as fast as possible then you would use all integers, but if not you can use floating point. If you like you can also used fixed point.
I used all integers on some apps, floating point on others, and when the AMD fake 8 cores came out I switched to fixed point for image processing.

That filter above is a first order filter but it works pretty darn good with large N. The larger you go up in the value of N, the smoother your DC voltage becomes and more stable. The tradeoff is it takes more time during startup to get a good first reading, and takes more time to get a good average after a step change. Step changes don't always matter too much though it depends on what you are doing.

I am posting a basic one here, take a look

C:
// Moving average parameters
const int N = 10;          // Number of samples for averaging
float Vavg = 0.0;          // Running average
int sensorPin = A0;        // Analog input pin

void setup() {
  Serial.begin(9600);
}

void loop() {
  // Read raw ADC value (0–1023)
  int raw = analogRead(sensorPin);

  // Convert to voltage (0–5V)
  float Vsample = raw * (5.0 / 1023.0);

  // Apply your formula
  Vavg = (Vavg * (N - 1) + Vsample) / N;

  // Print results
  Serial.print("Sample: ");
  Serial.print(Vsample, 3);
  Serial.print(" V   |   Avg: ");
  Serial.print(Vavg, 3);
  Serial.println(" V");

  delay(100);
}
 

drjohsmith

Joined Dec 13, 2021
1,614
No. It is preferable to stay on the same thread on the same topic, no matter how long is the thread.
sorry @MrChips
you seem to miss understand my post.
I did not suggesting that the OP starts a new thread, which itvseems your thinking Imsaid,
its just that the OP have been around a few options over the past 206 posts, so was sugesting that they took a moment, and wrote what they have decided , and there current direction of travel,
that way we optimise the help we can give.,
 

Thread Starter

Hasan2019

Joined Sep 5, 2019
199
sorry @MrChips
you seem to miss understand my post.
I did not suggesting that the OP starts a new thread, which itvseems your thinking Imsaid,
its just that the OP have been around a few options over the past 206 posts, so was sugesting that they took a moment, and wrote what they have decided , and there current direction of travel,
that way we optimise the help we can give.,
@MrChips kindly follow post #200, 203 and 204. The code I added to #169, should modified with sampling technique?
 

MrChips

Joined Oct 2, 2009
34,863
From what I can surmise, I think the TS is trying to build a voltage regulator for an AC generator.
I would simply use a step-down transformer, a single rectifier diode and a smoothing capacitor. There is no need to measure RMS.
 

MrChips

Joined Oct 2, 2009
34,863
This is the formula that was given:
Vavg=(Vavg*(N-1)+Vsample)/N

The following method does the same thing. It is faster to compute and does not require floating point arithmetic if you choose N carefully and use shift operations, whether you program in ASM or C.

sum = sum + (Vsample - Vavg)
Vavg = sum / N
 

Thread Starter

Hasan2019

Joined Sep 5, 2019
199
measuring voltage accurately is certainly nice but... in this application i don't think it makes any difference (True RMS, average, peak...). all that matters is reading that changes proportionally with mains voltage. more over, low values are not important - if the voltage drops from 220 to 5V or 15V, or 60V, it makes no difference - all of them are too low. and that means that puny 0.6V drop due to diode makes no significant difference.

so idea in the very first post to measure peak voltage can work but ... it could (and should) use transformer for isolation.
in fact it should be good enough even without dedicated transformer. one could use same transformer that powers Arduino and relays. the key is measuring DC bus voltage before regulator(s). after all load is constant - most of the time. the only change is at the moment you are switching to another relay and - it is always just one relay that needs to be on (so constant load).

i did a little test:
View attachment 362130

as you can see voltages at nodes marked ADC0 and ADC1 track changes in V1 voltage.

at first it was voltage divider R2/R3 with smoothing cap C2. D5 was added to clamp voltage to safe value to analog input does not get harmed. R4 and C3 are added for extra filtering.
View attachment 362131

and the above graphs are after i introduced a bit of disturbance (I1 to simulate some change in load).
zoomed in it is something like this:
View attachment 362132

schematics could look something like this:
View attachment 362133
the red lines are for high current. TR1 should produce high enough voltage for relays even when mains voltage is down. due to large swing in unregulated voltage across C2, 12V regulator should be switching type and the simplest option here is to use ready made unit.

@panic mode, I just wanted to play around a similar circuit with Arduino Nano, I used 4 relays, set my tabs for 190, 200. 210, 230VAC, when I run the simulation I can see the voltage divider in R1 and R2 is nearly 4.75V, if I make R2 is 344k then it becomes 4.8V not 5V! The voltage after bridge diode is 19.5V in my case, should I change BR1?
Hasan_idea.PNG

In my code, I wrote

C:
void loop() {
 
  int acval = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = acval* (5.00 / 1023.0);
  Serial.print("AC analog VALUE ");
  Serial.print(acval);
  Serial.println(voltage);
  delay(100);

But, the output shows error message as it was indented to do at


C:
  else if (acval >= 580)
  {
    Serial.println("Voltage is  more than 230V  .Warning!! ");
    lcd.print(" OUTPUT OFF ");
    digitalWrite(relay1, 1); //            tapper 1
    digitalWrite(relay2, 1); //            tapper 2
    digitalWrite(relay3, 1); //170 >>192.4  tapper3
    digitalWrite(relay4, 1); //            tapper 4
    //digitalWrite(relay5, 1); //            tapper 5
    }

Its kind of wired because, input voltage is not more than 230V ! Somewhere I am doing wrong.
 

Thread Starter

Hasan2019

Joined Sep 5, 2019
199
I hope that you are not trying to show me how to calculate values for a voltage divider circuit.
Do you understand why 1 MΩ is not appropriate for this circuit?
No I wouldn't teach you anything. It does not matter how many zeros you are putting but ratio should maintain. Are you talking about high resistive power loss or something else ?
 

MrChips

Joined Oct 2, 2009
34,863
No I wouldn't teach you anything. It does not matter how many zeros you are putting but ratio should maintain. Are you talking about high resistive power loss or something else ?
Yes. It does matter how many zeros you put on the resistor value.
Yes. It matters how much load you are putting on the voltage divider.
Yes. Determine how much current you are drawing from the voltage divider. Then you will discover that the voltage output is not what the voltage divider was calculated to be.
No. It has nothing to do with "high resistive power loss" which is something you just made up.
 

panic mode

Joined Oct 10, 2011
5,013
when I run the simulation I can see the voltage divider in R1 and R2 is nearly 4.75V, if I make R2 is 344k then it becomes 4.8V not 5V! The voltage after bridge diode is 19.5V in my case, should I change BR1?
Its kind of wired because, input voltage is not more than 230V ! Somewhere I am doing wrong.
you need to select ratio that works for you.
if you are getting 19.5VDC when AC side is ok, ask yourself what is it going to be when AC size is at maximum that you are expecting to see.

suppose you expect 270V and right now is 230V, then rectified DC will be

19.5VDC * (270VAC/230VAC) = 22.9VDC

then your voltage divider need to be chosen so that you get less than 5V from it. keeping R1 as 1Meg and using R2 as 220k will give you decent ratio.

Vadc_max=Vdc_max*R2/(R1+R2)
Vadc_max=22.9VDC * 220k/(220k+1000k)=4.13V
 

panic mode

Joined Oct 10, 2011
5,013
same goes for minimum voltage... so using also 50V change,
Vac_min = 220-50V=170VAC
Vdc_min=Vdc*Vac_min/Vac=19.5VDC * (170VAC/230VAC) = 14.4VDC

so for mains voltage in range 170*270VAC, voltage after bridge rectifier is expected to be approximately 14.4...22.9VDC.
this is reasonable to derive 12VDC.

and the voltage for ADC will be
Vadc_min=Vdc_max*R2/(R1+R2)
Vadc_min=14.4VDC * 220k/(220k+1000k)=2.59V
so for mains voltage in range 170VAC-270VAC, your ADC would see 2.59VDC .. 4.13VDC. Which looks reasonable.

btw, you chose lower value filter caps, for some reason placed as D5 a Schottky diode instead of Zener. that is not going to help protect ADC. if you want to use that diode for protection it should be wired like this:
1768767188854.png

however, Schottky diodes have large leakage current and that would affect voltage reading that you are trying to measure.
 

panic mode

Joined Oct 10, 2011
5,013
also your code is not scaling voltage correctly. you are converting ADC reading into DC volts but really, you should be scaled to display AC voltage. and the slope will not necessarily go through origin. so better calibration would be to use two points (or more).
 
Top