AC voltage measuring using arduino

I am trying to measure AC voltage using arduino and a 3-0-3 step down transformer. After rectification , I am giving the input to ADC channel. and measuring by multiplying by a factor (230/1023), But the output I am getting is around 130v I think there is a mistake in the multiplication factor . Please help me

What is input voltage to transformer? What is output voltage from transformer? Measuring voltage after a rectifier would create an error, proportional to current drown by load. You better to measure AC.

Ac voltages are normally expressed as RMS equivalent volts unless otherwise specified. The conversation factor you will have to use in your program depends on the type of rectifier/filter you use, half wave, full wave bridge, full wave with center tapped transformer, etc. Basically the rectifier/filter will charge is some AC peak voltage value and the RMS factor will be some percentage of that value, .707 times that value is one classic value ratio.

So draw up your total wiring set-up and post your code and I'm pretty sure we can guide you to the proper conversion factor to use.

Lefty

Magician: What is input voltage to transformer? What is output voltage from transformer? Measuring voltage after a rectifier would create an error, proportional to current drown by load. You better to measure AC.

If the purpose is to just measure the normal equivalent AC primary line voltage and the only load is the arduino analog input pin then it can be done that way without significant error.

If the purpose is to just measure the normal equivalent AC primary line voltage and the only load is the arduino analog input pin then it can be done that way without significant error.

There would be voltage drop on bridge, even w/o load p-n junction drop is temperature dependent. The question how accurate measurements OP needs, and if lag-off is acceptable.

Magician:

If the purpose is to just measure the normal equivalent AC primary line voltage and the only load is the arduino analog input pin then it can be done that way without significant error.

There would be voltage drop on bridge, even w/o load p-n junction drop is temperature dependent. The question how accurate measurements OP needs, and if lag-off is acceptable.

Yes, but if the purpose is to just measure the nominal AC line voltage, then the diode loss can be just part of the conversion factor used, as the voltage drop is fairly constant and not changing with normal AC line voltage variation.

…and a 3-0-3 step down transformer.

Sorry, I don’t know what that is… What’s the output-voltage rating or the step-down ratio?

Do you have a multimeter to measure the actual secondary voltage?

Most transformers put-out their rated voltage at full load. A “12V 1A” transformer might actually put-out 12V when loaded to 1 Amp, but 18V with no load (or with a light load).

230VAC is the RMS voltage. You can look-up the math if you wish, but RMS is sort-of an average*. The peak value of a sine wave is about 1.4 times the RMS value (~plus and minus 320V peak). And of course, the minimum is zero. So with a rectifier, you should be getting “random” readings between zero and 320V (assuming everything is calibrated). Or, if you put a capacitor on the rectifier output to hold the peak, you should read 320V.

…measuring by multiplying by a factor (230/1023)

You should give yourself some “breathing room”… If 230V gives you 1023, then 250V is also going to give you 1023.

  • RMS is related to power, and you get the same power with 230VAC as you get with 230VDC. If you hook-up 230VDC to a light bulb, it will glow with the same brightness as with 230VAC.

Thanks for the support and sorry for forgetting to give the details I am using a 3-0-3 ,500 ma transformer with full wave rectifier. What I need is to measure the AC line voltage( Accuracy not so). Input is 230v/50Hz domestic line voltage.After the rectification I am using a10uF capacitor for filtering . About 230/1023. I think its a mistake. Since ADC is 10 bit , output voltage will be (analogout*(5/1024)). I am trying to change this. I tried with a load resistance 10K, but readings drops to 160v

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  int x,volt,y;
  x=analogRead(4);
  volt=x*(230/1023);
  Serial.println(x);
  
  delay(500);
   Serial.println(volt);
     delay(500);
}

About 230/1023.

If you know the the factor, then you are probably better off using the map(value, fromLow, fromHigh, toLow, toHigh) function to scale your reading, it will make your life easier.

So read in the analog value as X

Y= map(X, 0, 1023, 0, 230); //Adjust the 230 value based on real world comparison to actual measured // line voltage until they agree.

Print the Y value.

Lefty

I tried the map function , but value was very high. Also, there is a chance of change in limit, as the voltage may fluctuate between 200-230. So I cant use that function

RBR: I tried the map function , but value was very high. Also, there is a chance of change in limit, as the voltage may fluctuate between 200-230. So I cant use that function

The map function will track the changing input value and calculate the proper value every time you call it with a new value of X. You may have to adjust the 230 value if the conversion is too high, as I showed in the comment. Map is the proper tool to use and if not working for you then there is something else wrong going on.

Lefty

O’k, if I understand it right , your transformer is 230 / 3 - 0 - 3
But where is your bridge connected, to 3 - 0 pins or 3 - 3?
If to 3 - 3 , than after rectifier should be around 6 V x sqrt ( 2 ) - 1.4 = 7.2 V, what is too mach for arduino input .
For 3 - 0 pins, 3 V x sqrt(2) - 1.4 = 2.8 V should be fine.
Formula to calculate AC = (( x * 5.0 / 1024 ) + 1.4 ) * ( 230.0 / 3.0 ) / 1.414) ;

Magician: O'k, if I understand it right , your transformer is 230 / 3 - 0 - 3 But where is your bridge connected, to 3 - 0 pins or 3 - 3? If to 3 - 3 , than after rectifier should be around 6 V x sqrt ( 2 ) - 1.4 = 7.2 V, what is too mach for arduino input . For 3 - 0 pins, 3 V x sqrt(2) - 1.4 = 2.8 V should be fine. Formula to calculate AC = (( x * 5.0 / 1024 ) + 1.4 ) * ( 230.0 / 3.0 ) / 1.414) ;

I'm sure your math is correct, and the algorithm makes sense, but why bother with all the complexity and floating point? As long as the rectified/filtered DC voltage is less the +5vdc for the highest possible line voltage, why not use the much simpler map() function Y=map(x,0,1023,0,240) where 240 value is tweaked until Y indeed measures what a measurement of the line voltage actually is. The relationship is a straight linear one and the map function does that just fine using simple integer math.

Lefty

I am attaching my circuit here. I will try your calculations and reply you soon

PT.bmp (12.9 KB)

The relationship is a straight linear one and the map function does that just fine using simple integer math.

You are right, map would be easier, but at least bridges 1.4V (drop voltage) has to be included in map, otherwise error with 3 V transformer almost 30 %.

Y= map(X, 0, 1023, OFF-SET, 230); //Adjust the 230 value based on real world comparison to actual measured

Off- set could-be pre-calculated, approximately 230 x 1.4 / ( 3 * 1.414 )= 76 V, not very accurate , with 0.6 V per diode it's 65 V

Corrected: just noticed a drawings, there is only one diode, off-set about 230 x 0.7 / 3 x 1.414 = 38 V

@retrolefty

But my doubt is about the fluctuation in the voltage ranging between 200-230? How can I include this?

RBR: @retrolefty

But my doubt is about the fluctuation in the voltage ranging between 200-230? How can I include this?

I don't understand your doubts. If the line voltage varies then the analog input pin DC voltage will vary, tracking that change in line voltage, correct? And the map function will recalculate the value everytime you call it with the results of a new analogRead() command. You only have to validate the conversion factor value (the 230 value used in the map function in our examples so far) one time by comparing what the program prints out Vs what a meter reading of actual line volt is at the same time. Just adjust the 230 value in the map function until there is agreement and your program will succefully track changing AC line voltage just fine from then on.

That make sense?

Lefty

@Magician

Corrected: just noticed a drawings, there is only one diode, off-set about 230 x 0.7 / 3 x 1.414 = 38 V

Can you please explain it?

Let me get in this tread.

@RBR

I did a project to monitor AC voltage.

I check your circuit, it look OK, as long the V out is not over 5 V.

So, To figure this out, you need this :

  1. What is the voltage at that output of your circuit ? example : 3 V
  2. What is the AC main voltage in rms ? example : 122 V
  3. What is the A Vref voltage ? example : 5 V

So let calculate the ratio. 122 / 3 = 40.6666667

Let calculate a "step" value : 5 V / 1023 = 0.004887585 V

So Vin is the 3 V at the analog pin and 3 V is : 614 = value = analogRead( Vin );

Let do a code :

value = analogRead( Vin );
Vac = ( float (value) * ( 5.0 / 1023.0 ) ) * ( 122.0 / 3.0 ); 
Serial.print( Vac, 3);

Any question ?

Anyway.

Here my project code.

/*
   Size : 6810 Bytes
   
   Version 2.0
   
   AC Frequency and AVC Main monitor
   
   By Serge J Desjardins 
   aka techone / tech37
   
   Toronto, ON Canada
   
   Compile - Tested - Calibrated
*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);

byte sw_mode=3;
byte inpulse=2;
byte voltpin=1;

boolean what_mode;

const int number_of_samples = 50;
const float main_ratio = 40.63018242;

unsigned long duration_ton;
unsigned long average_ton;
unsigned long sample_the_pulse;
unsigned long duration_toff;
unsigned long average_toff;
unsigned long total_adc;

unsigned int sample_the_adc;
unsigned int average_adc;

float frequency;
float voltage;
float single_step;
float voltage_out;
float duty_cycle;

void setup()
{
  analogReference(DEFAULT);
  pinMode(inpulse, INPUT);
  pinMode(sw_mode, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Main:");
  lcd.setCursor(12,0);
  lcd.print("VAC");
  lcd.setCursor(0,1);
  lcd.print("F:");
  lcd.setCursor(7,1);
  lcd.print(" Hz D:");
  lcd.setCursor(15,1);
  lcd.print("%");
  single_step=4.92/1023.0;
  delay(5000);
  what_mode = digitalRead(sw_mode);
  delay(100);
  if ( what_mode == 0 )
  {
    Serial.print(" S ");
    Serial.print(main_ratio, 8);
    Serial.print(' ');
    Serial.print(single_step, 8);
    Serial.print(" E ");    
  }   
}


void loop()
{
  pulse_sampling();
     
  average_ton = ((duration_ton*10)/number_of_samples)/10;
  average_toff = ((duration_toff*10)/number_of_samples)/10;
  frequency = 1/(float(average_ton+average_toff)/1000000.0);
  duty_cycle = (float(average_ton)/float(average_ton+average_toff))*100.0;
  
  voltage_sampling();
  
  average_adc=((total_adc*10)/number_of_samples)/10;
  voltage_out=float(average_adc)*single_step;
  voltage=(float(average_adc)*single_step)*main_ratio;
  
  what_mode = digitalRead(sw_mode);
  delay(100);
  if ( what_mode == 0 ) 
  {
    send_data();
    display_the_data();
  }
  else
  {  
    display_the_data();
  }  
}

void pulse_sampling()
{
  duration_ton = 0;
  sample_the_pulse= 0;
  duration_toff=0;
    
  for (int i=0;i<number_of_samples;i++)
  {
    sample_the_pulse = pulseIn(inpulse, HIGH);
    duration_ton = sample_the_pulse+duration_ton;
    sample_the_pulse = pulseIn(inpulse, LOW);
    duration_toff = sample_the_pulse+duration_toff; 
  }
} 

void voltage_sampling()
{
  sample_the_adc=0;
  total_adc=0;
    
  for (int i=0;i<number_of_samples;i++)
  {
    sample_the_adc=analogRead(voltpin);
    total_adc=sample_the_adc+total_adc;
  }
}

void display_the_data()
{
  lcd.setCursor(5,0);
  lcd.print(voltage, 3); 
  lcd.setCursor(2,1);
  lcd.print(frequency, 3);
  lcd.setCursor(13,1);
  lcd.print(duty_cycle, 0);
} 

void send_data()
{
  Serial.print(" S ");  
  Serial.print(average_ton, DEC);
  Serial.print(' ');
  Serial.print(average_toff, DEC);
  Serial.print(' ');
  Serial.print(average_adc, DEC);
  Serial.print(" E ");  
}