How to make a high voltage (500V+ !!!) AC voltmeter

Published by MKDas on

In our previous articles, we learned how to make an AC voltmeter and how to measure high voltage AC voltage. In this article, we will learn how to make a high voltage AC voltmeter. Yes, you can measure 500V+ or higher easily with this circuitry.

Disclaimer: Electricity is always dangerous. Skill required to work with electricity. Do work with your own risk. Author will not be responsible for any misuse or harmful act. This website contents is also copyright protected. Anything copied and directly posted in your website and claiming it as yours is prohibited and nonsensical. Author published all the articles as opensource to help you making your project and learning purpose only. Learn and make one for yourself. If need any help feel free to ask the author. Author will be helpful to you. Thanks.

Before you read further, I’ll request to read the other articles

  1. How to make an AC voltmeter
  2. How to measure high voltage AC

Different ways to measure high voltage AC:

There are different ways to measure high voltage AC. A transformer is the most common device in this case. But when we need to consider the size and weight, we have to find other ways to do the job.

An Op-Amp can be used in this case. Op-Amps are cheap and small in size and weight is also negligible comparing with transformer. A circuit like this is very very helpful for this purpose:

High voltage measurement using Op-Amp

Voltmeter circuit diagram:

Circuit diagram

Coding:

/*******************************************************************************
* Program for "High voltage AC voltmeter"                                      *
* Program written by_ Engr. Mithun K. Das                                      *
* MCU:PIC16F73; X-Tal:8MHz; mikroC pro for PIC v7.6.0                          *
* Date:05-05-2020                                                              *
*******************************************************************************/
char segment_array[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//cmmon cathode_non dot

sbit digit0 at RC0_bit;
sbit digit1 at RC1_bit;
sbit digit2 at RC2_bit;
sbit digit3 at RC3_bit;

char digits[5];
void display_7segment(int number)
{
   digits[3]=number/1000u;
   digits[2]=(number/100u)%10u;
   digits[1]=(number/10u)%10u;
   digits[0]=(number/1u)%10u;
}

void InitTimer0()
{
  OPTION_REG     = 0x85;
  TMR0           = 100;
  INTCON         = 0xA0;
}

int position=0;
void Interrupt() iv 0x0004 ics ICS_AUTO
{
  if (TMR0IF_bit)
  {
    TMR0IF_bit   = 0;
    TMR0         = 100;

    digit0 = 1;
    digit1 = 1;
    digit2 = 1;
    digit3 = 1;
    if(position>3)position=0;

    if(position==1)PORTB = segment_array[digits[position]]+128; //dot point
    else PORTB = segment_array[digits[position]];

    if(position==3)
    {
        digit0 = 0;
        digit1 = 1;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==2)
    {
        digit0 = 1;
        digit1 = 0;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==1)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 0;
        digit3 = 1;
    }
    else if(position==0)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 1;
        digit3 = 0;
    }
    position++;
  }
}



void Get_AC_Voltage(void);
unsigned int max_point=0,mm=0,k=0,temp=0,adc_rd0=0,ac_voltage;
void main()
{
 TRISA=0xFF;//all input
 TRISB=0x00;//all output
 TRISC=0x00;//all output
 PORTB=0x00;
 PORTC=0x00;//clear ports
 ADCON1=0x00;//all analog in
 InitTimer0();//5ms timer
 while(1)
 {

    Get_AC_Voltage(void);
    display_7segment(ac_voltage);

 }
}

void Get_AC_Voltage(void)
{
      int mm;
      max_point = 0;//clear all data
      adc_rd0 = 0;//clear data
      for(mm=0;mm<10;mm++)
      {
          for(k=0;k<500;k++)
          {
               ADCON0 = 0b00000001;//AN0 selected
              if(temp = ADC_Read(0),temp>max_point)
              {
                  max_point = temp;
              }
          }
          max_point = abs(ceil((long)(max_point-128)));
          adc_rd0+= max_point*41.8;
      }
      adc_rd0/=10;

      ac_voltage = adc_rd0;
}

Code explanation:

char segment_array[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//cmmon cathode_non dot

sbit digit0 at RC0_bit;
sbit digit1 at RC1_bit;
sbit digit2 at RC2_bit;
sbit digit3 at RC3_bit;

In this part, we took an array for different digits of 7-Segment. And later on, set our MCU’s pins for different digits of the 4×1 7-Segment so that we can call the digit directly later.

char digits[5];
void display_7segment(int number)
{
   digits[3]=number/1000u;
   digits[2]=(number/100u)%10u;
   digits[1]=(number/10u)%10u;
   digits[0]=(number/1u)%10u;
}

In this part, display_7segment is just taking each digit of a number and saves in array digits[]. This will be called in ISR later.

void Interrupt() iv 0x0004 ics ICS_AUTO
{
  if (TMR0IF_bit)
  {
    TMR0IF_bit   = 0;
    TMR0         = 100;

    digit0 = 1;
    digit1 = 1;
    digit2 = 1;
    digit3 = 1;
    if(position>3)position=0;

    if(position==1)PORTB = segment_array[digits[position]]+128; //dot point
    else PORTB = segment_array[digits[position]];

    if(position==3)
    {
        digit0 = 0;
        digit1 = 1;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==2)
    {
        digit0 = 1;
        digit1 = 0;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==1)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 0;
        digit3 = 1;
    }
    else if(position==0)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 1;
        digit3 = 0;
    }
    position++;
  }
}

In this ISR, we just displaying our multiplexed 7-segment with the help of timer interrupt. Timer0 is used in this case here. A dot point is positioned too here.

void Get_AC_Voltage(void)
{
      int mm;      
      max_point = 0;//clear all data
      adc_rd0 = 0;//clear data
      for(mm=0;mm<10;mm++)
      {
          for(k=0;k<500;k++)
          {
               ADCON0 = 0b00000001;
              if(temp = ADC_Read(0),temp>max_point)
              {
                  max_point = temp;
              }
          }
          max_point = abs(ceil((long)(max_point-128)));// subtract 2.5V
          adc_rd0+= max_point*41.8; //after calculation,calibration factor. 
      }
      adc_rd0/=10;

      ac_voltage = adc_rd0;
}

And finally in the AC voltage measurement section, we used the same peak finding method with the average result like our AC voltmeter’s code. Only one thing is changed here is the calibration factor. Also note that, as the output of Op-Amp circuitry is 2.5V at no input voltage so we have to subtract 2.5V from our calculation.

Test result:

Here is the test result of our high voltage AC voltmeter:

Test result

As you can see our voltmeter is displaying almost exact voltage it is supplied from the POT-VR. A small error in result is not so bad at all. Although this error can be eliminated in professional design by tuning the circuit and code.

This way, we can measure 500V+(!!!) even more if the resistors are selected properly. Remember, electricity is always dangerous. Work carefully with your own risk!!!

A non-polar 0.01uF capacitor can be used just at the input terminals of our Op-Amp to reduce noise. Note that, this may reduce the response time but it will filter most of the noises. R-C filter also can be added after output which will make the output more noise free.

Anyway, I hope you enjoyed the article and will be able to make a voltmeter for yourself which can measure high voltage. If you need any help, feel free to ask. Thank you, Enjoy!


MKDas

Mithun K. Das; B.Sc. in EEE from KUET. Blog: https://labprojectsbd.com

14 Comments

djalltra · October 20, 2020 at 11:38 pm

please how do you calculate you calibration factor (41.8) am confused

    Mithun K. Das · October 21, 2020 at 5:53 am

    It comes from ADC calculation with little adjustment. 5/1024*(resistor voltage divider factor)*calibration factor.

djalltra · October 21, 2020 at 9:02 am

can you please explain clearly because I know resistor voltage divider factor is the gain but I can’t figure out how you got 41.8 as you gave little to no explanations on how you arrived at that also I don’t know why you divided result by 10

djalltra · October 21, 2020 at 10:05 am

still not clear as you gave no proper explanations on how you arrived at 41.8 ,I understand voltage divider factor is the gain and why do you divide by 10 in the end

djalltra · October 23, 2020 at 7:49 am

OK correct me if am wrong because the micro cannot measure negative voltages you added 2.5v to raise the opamp output voltage so from your circuit the calculated gain was 0.00322 so our vout from opamp will be 0.00322*(Max volt measured) =0.00322*500=1.61 so our total opamp output voltage is 1.61+voffset =1.61+2.5=4.11 am guessing you multiplied by 10 to get the 41.8 like I said correct me if am wrong

djalltra · October 24, 2020 at 2:39 am

i calculated my gain as R9/R2+R6+R7+R8 Which gives 0.00322 so our opamp output voltage will be Vout=0.00322×500=41.1 so our total opamp output wiltage is 1.61+voffset=1.61+2.5=4.11 am guessing you multiplied by 10 to get 41.8

sammy · October 25, 2020 at 3:37 pm

how did you arrive at 41.8

rico · October 26, 2020 at 9:08 pm

I tried this code and simulation and it doesn’t work I just get one constant reading of 528v

    Mithun K. Das · November 1, 2020 at 2:19 pm

    Kindly attach the simulation file and code. or email to admin’s email from the contact section. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *