How to design a voltage stabilizer using a micro-controller from A to Z

Published by MKDas on

In the previous article, we have seen how we can make an analog voltage stabilizer. We have seen that the circuit was pretty complex like a bird’s nest. In this article, we are going to learn how we can use a micro-controller for that purpose and make a smart voltage stabilizer for our own. Let’s start!

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.

If you have not read the previous article, I’m requesting you to read the previous article first. Then continue this article.

What is the benefit of using a micro-controller?

Most people have a fear of using a micro-controller for any work. But it is not like that. Until you learn about something, it is fear. But once you learned it, you’ll become a master of that. Anyway, there is no need to use different circuits for different works when you are using a micro-controller. It already has many blocks inside. You just need to code to use those.

One of the most significant benefits of using a micro-controller is you get the freedom to design the circuit. If you write the code properly, you can get lots of flexibility in circuit designing.

Circuit diagram:

Explanation:

The circuit is very simple and using ULN2003A rather than a set of devices as relay driver with transistor, diode, resistors made the circuit cleaner. Each driver section of ULN2003A is configured with darling tone transistors, resistors, and diodes. The ULN2003A driver IC has common and GND pin from those the GND pin is not shown in the diagram. But it is available in real IC. The pin must be connected to GND.

Each driver has necessary components so no need to use any extra components. It makes it easier to use with micro-controllers. In comparison to the cost, it is also economic rather than using separate transistors and other component sets.

The relay switching part is not complex at all too.

Here RL1:RL4 are used to select different taps and the RL5 is used to switch the input to inject the mains to the selected tap. Here as the input line is not connected to the transformer tap in the first. So there is no power in the auxiliary winding at the beginning. That is why it can not start the control circuit. To solve this problem, an X2 type capacitor is used between the input line and the lowest tap (150V here). This will energize the control circuit. Once the control circuit is turned on and relays are switched, the control circuit can be run from the auxiliary power.

Sensing:

It may seem strange to use resistors directly. But it is the best way to sense the mains voltage using a resistor for voltage stabilizer. This way the line voltage sensing is not interrupted for any relay switching or other part of the circuit. Also as the control circuit is completely away from the user’s touch so it is not a problem to use resistors. The configuration works like a simple voltage divider circuit. To tune, a POT can be used with a 1K resistor in series to fine-tune the measurement. A simple 100nF capacitor is enough to filter the signal. The rest of the work will be done in coding.

Note: here the 1MΩ resistors are used of 0.5W. You should use the 5band metalflim one like this one:

There is no more part to explain I think. So let’s do the coding.

Coding:

/*******************************************************************************
Program for, "Micro-controller based 5 relay voltage stabilizer"
Program Written by_ Engr. Mithun K. Das; mithun060@gmail.com
MCU:PIC16F676; X-Tal: 4MHz (internal); Complier: mikroC pro for PIC v7.6.0
Date: 19-04-2021
*******************************************************************************/
#define     relay1          RC1_bit
#define     relay2          RC2_bit
#define     relay3          RC3_bit
#define     relay4          RC4_bit
#define     relay5          RC5_bit

#define     delay_led       RA2_bit
#define     high_led        RA1_bit
#define     low_led         RA0_bit


unsigned int line_voltage=0,max_point=0,temp=0;
int i=0,k=0;



void main() 
{
  TRISA=0x00;//all output
  TRISC=0x01;//all out except RC0_bit
  ANSEL = 0b00010000;//AN4 active
  CMCON=0x07;//comparator off
  ADCON1=0x10;//Fosc/8 speed
  
  
  while(1)
  {
  
     //read input voltage
     line_voltage = 0;
     max_point=0;
     temp=0;
     ADCON0 = 0x11; //AN4
     for(i=0;i<5;i++)
     {
         for(k=0;k<500;k++)
         {
            if(temp=ADC_Read(4),temp>max_point)
            {
               max_point = temp;
               Delay_us(1);
            }
         }
         line_voltage+=max_point*37/100;
     }
     line_voltage/=5; //get average value
     
  
  
  }//while(1)
}//void main()

This is the first step of our coding. Here, I’ve done very simple works. First I defined the pins according to the functions.

#define     relay1          RC1_bit
#define     relay2          RC2_bit
#define     relay3          RC3_bit
#define     relay4          RC4_bit
#define     relay5          RC5_bit

#define     delay_led       RA2_bit
#define     high_led        RA1_bit
#define     low_led         RA0_bit

Then in the initialization section:

  TRISA=0x00;//all output
  TRISC=0x01;//all out except RC0_bit
  ANSEL = 0b00010000;//AN4 active
  CMCON=0x07;//comparator off
  ADCON1=0x10;//Fosc/8 speed

Each line is commented so that it becomes easy to understand the code. Now we’ll measure the voltage I mean the AC voltage from our voltage divider circuit. It may become a little complex to understand. I’ll request to read one of my previous article where I explained about AC voltage measurement.

     //read input voltage
     line_voltage = 0;
     max_point=0;
     temp=0;
     ADCON0 = 0x11; //AN4
     for(i=0;i<5;i++)
     {
         for(k=0;k<500;k++)
         {
            if(temp=ADC_Read(4),temp>max_point)
            {
               max_point = temp;
               Delay_us(1);
            }
         }
         line_voltage+=max_point*37/100;
     }
     line_voltage/=5; //get average value

Here a peak point finder algorithm is used and taking the peak point data only. Then making an average value from 5 data. More the raw value, more the accuracy. The 37/100 is coming from our ADC calculation.

Here the voltage divider is actually forming like this with respect to our MCU GND pin:

You may think why I’m not putting all the values in the coding and let the MCU calculate the value. Let’s see what happen if I do that.

If I keep the calculation as it is:

It consume 81% of ROM and 31% of RAM. But if I simplify it to even: 0.37 then:

Still 79% is consumed. But I it is simplified in another step:

WOW!!! It takes only 26%. This is how we can actually use less ROM & RAM and do more coding with a micro-controller. Even we can tune in some steps more to get optimum results.

Now, one very important issue we have to handle. Did you notice we are using a POT of 10KΩ and a 1KΩ resistor in series with our voltage divider? Those are actually in parallel with our 27K resistor. Also, each of these resistors has some tolerance. As a result, we will never get a calculated result from this type of measurement. That is why we must calibrate the measurement code by testing with line voltage and practical circuit which can be finalized once it is ready for testing. Anyway, I hope it is now clear to you about the voltage reading.

Note: Here we measured a peak point result. But we know that we use the RMS value not the peak value. So we must calculate the RMS value from the peak value. The calculation is easy,

VP = VRMS × √2

Now let’s add more part of the code but before that, we have to calculate the input vs output voltage relation for transformer taps. I mean in which input voltage which the tap will be selected?

If you check the transformer again:

What you see? The tap difference is 30V. And the transformer calculation is:

So we can calculate the relation and set when to change the transformer tap. We can use Microsoft Excel for this calculation which will make our job easy.

And the equations is:

Here, the yellow marked points are important for us. As you see, when the input voltage is 170V and the in tap is 150 the output voltage is 238, at the same time if we use the in tap 180V then the output is 198V. In this situation, if we switch the relay sharply, the output voltage will be fluctuating from 198V to 238V which is very dangerous for the load. So what’s the solution?

Solution:

In this situation, we have to create a hysteresis in the code. So let’s complete the code.

/*******************************************************************************
Program for, "Micro-controller based 5 relay voltage stabilizer"
Program Written by_ Engr. Mithun K. Das; mithun060@gmail.com
MCU:PIC16F676; X-Tal: 4MHz (internal); Complier: mikroC pro for PIC v7.6.0
Date: 19-04-2021
*******************************************************************************/
#define     relay1          RC1_bit
#define     relay2          RC2_bit
#define     relay3          RC3_bit
#define     relay4          RC4_bit
#define     relay5          RC5_bit

#define     delay_led       RA2_bit
#define     high_led        RA1_bit
#define     low_led         RA0_bit


unsigned int line_voltage=0,max_point=0,temp=0;
int i=0,k=0;
bit gap1,gap2,gap3,gap4,gap5;



void main() 
{
  TRISA=0x00;//all output
  TRISC=0x01;//all out except RC0_bit
  ANSEL = 0b00010000;//AN4 active
  CMCON=0x07;//comparator off
  ADCON1=0x10;//Fosc/8 speed
  
  top:
  PORTA = 0x00;//clear port
  PORTC = 0x00;//clear port
  delay_led = 1;
  Delay_ms(180000);//3min delay = 180000;
  delay_led = 0;
  
  while(1)
  {
  
     //read input voltage
     line_voltage = 0;
     max_point=0;
     temp=0;
     ADCON0 = 0x11; //AN4
     for(i=0;i<5;i++)
     {
         for(k=0;k<500;k++)
         {
            if(temp=ADC_Read(4),temp>max_point)
            {
               max_point = temp;
               Delay_us(1);
            }
         }
         line_voltage+=max_point*37/10;
     }
     line_voltage/=5; //get average value
     
     
     if(line_voltage<145 || line_voltage>305)
     {
        relay5 = 0;
        if(line_voltage<145)low_led = 1;
        else if(line_voltage>305)high_led = 1;
        Delay_ms(10000);//wait 10sec
        goto top;
     }
     else
     {
        if(line_voltage>145 && line_voltage<170)
        {
           relay1 = 0;// 150V Tap connected
           relay2 = 0;
           relay3 = 0;
           relay4 = 0;
           relay5 = 1;//injection on
           gap1 = 1;
           gap2 = 0;
        }
        else if(line_voltage>=170 && line_voltage<=172)
        {
           if(gap1)
           {
             relay1 = 0;// 150V Tap connected
             relay2 = 0;
             relay3 = 0;
             relay4 = 0;
             relay5 = 1;//injection on
           }
           if(gap2)
           {
             relay1 = 1;// 180V Tap connected
             relay2 = 0;
             relay3 = 0;
             relay4 = 0;
             relay5 = 1;//injection on
           }
        }
        else if(line_voltage>172 && line_voltage<204)
        {
           relay1 = 1;// 180V Tap connected
           relay2 = 0;
           relay3 = 0;
           relay4 = 0;
           relay5 = 1;//injection on
           gap2 = 1;
           gap1 = 0;
           gap3 = 0;
        }
        else if(line_voltage>=204 && line_voltage<=206)
        {
           if(gap2)
           {
             relay1 = 1;// 180V Tap connected
             relay2 = 0;
             relay3 = 0;
             relay4 = 0;
             relay5 = 1;//injection on
           }
           if(gap3)
           {
             relay1 = 0;
             relay2 = 1;// 210V Tap connected
             relay3 = 0;
             relay4 = 0;
             relay5 = 1;//injection on
           }
        }
        else if(line_voltage>206 && line_voltage<238)
        {
           relay1 = 0;
           relay2 = 1;// 210V Tap connected
           relay3 = 0;
           relay4 = 0;
           relay5 = 1;//injection on
           gap3 = 1;
           gap4 = 0;
           gap2 = 0;
        }
        else if(line_voltage>=238 && line_voltage<=240)
        {
           if(gap3)
           {
             relay1 = 0;
             relay2 = 1;// 210V Tap connected
             relay3 = 0;
             relay4 = 0;
             relay5 = 1;//injection on
           }
           if(gap4)
           {
             relay1 = 0;
             relay2 = 0;
             relay3 = 1;// 240V Tap connected
             relay4 = 0;
             relay5 = 1;//injection on
           }
        }
        else if(line_voltage>240 && line_voltage<270)
        {
           relay1 = 0;
           relay2 = 0;
           relay3 = 1;// 240V Tap connected
           relay4 = 0;
           relay5 = 1;//injection on
           gap3 = 0;
           gap4 = 1;
           gap2 = 0;
        }
        else if(line_voltage>=270 && line_voltage<=272)
        {
           if(gap4)
           {
             relay1 = 0;
             relay2 = 0;
             relay3 = 1;// 240V Tap connected
             relay4 = 0;
             relay5 = 1;//injection on
           }
           if(gap5)
           {
             relay1 = 0;
             relay2 = 0;
             relay3 = 0;
             relay4 = 1;//270V Tap connected
             relay5 = 1;//injection on
           }
        }
        else if(line_voltage>272 && line_voltage<305)
        {
           relay1 = 0;
           relay2 = 0;
           relay3 = 0;
           relay4 = 1;// 270V Tap connected
           relay5 = 1;//injection on
           gap4 = 0;
           gap5 = 1;
        }
     }
     
  
  
  }//while(1)
}//void main()

So this is our full code. As you see, I’ve changed some calculations. While I was simulating, I found that I’ve to multiply by 10 when reading the line voltage. Once you make ready the hardware, you have to calibrate this constant value (37/10) to match with your reading.

Note: I always use valid licenses, if you do not have valid license you can use this hex code directly. Download Hex code.

In the relay control section, you can see I’m using a bit variable gap1~gap5. These are actually used to create a hysteresis I mentioned earlier. This step must be written carefully.

OK, now we can check if our code works in simulation:

Simulation result:

I’ve simulated this project in proteus. I hope you’ll make in real life and show me the result.

PCB design:

I’ve designed the PCB in single layer. Simple layout for this product. You can draw yourself using my layout:

Or you can buy the layout both in pdf format and Gerber format and print it from my PCB partner JLCPCB.

Buy using PayPal (US $12.00) or BDT: 1,000.00 from Bangladesh through bKash.

To buy from Bangladesh kindly pay through bKash (personal): 01972448270 then, fill this order form below:

Once payment is verified, the files will be sent to your email.

Conclusion:

I’ve described almost all the basics to make a micro-controller based voltage stabilizer. Now it’s your turn to utilize this knowledge to develop your own voltage stabilizer or related product or project. I hope you enjoyed this article.

I’m professional in designing professional products. If you need any help feel free to contact me. E-mail: mithun060@gmail.com. Thanks.

If this article is helpful to you kindly subscribe to my YouTube channel and here as well. Also share on Facebook, Twitter, and other social media. Thanks.

You can subscribe to this blog so that you get a notification when an article is posted.

Loading

MKDas

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

10 Comments

Joy · April 19, 2021 at 2:28 pm

Sir you are great.I salute you .It is impossible to compare you with any other Bangladeshi programmer.

Asimiyu · April 20, 2021 at 8:59 am

wao! this is what i have been looking for, you are a very great man engr Mithun. How i wish i have money to donate to your company, because any person who value KNOWLEDGE would know the great things you have been doing. Honestly speaking, I am always extremely happy when come to your blog, every hours, i can’t spent a day without visiting here. you have really impacted knowledge to human kinds and may God Almighty Allah will continue increasing you in Knowledge, wisdom, prosperity and uplift you more higher in this life and the hereafter.
However, all project circuits you have been posted here, are working, with crystal cleared!, theories, practical and its computation analyzes.
i will still go through it sir if there is questions.

ROBERT · April 23, 2021 at 9:33 pm

Hello sir, this is a great work, i appreciate ur effort by given out this educative project that may help many in programming experience. I am one of the benefactor this work.
thans for sharing ur ideas to all. Keep the good work going.

Mohamed · May 6, 2021 at 7:08 am

great, but i need circuit to make constant voltage 220v ac however the input change using automatic voltage stabilizer

    MKDas · May 6, 2021 at 11:29 am

    In that case you can look for Static Voltage Stabilizer.

Flex · May 8, 2021 at 3:43 am

Nice explanations can you do a project on ac current measurement using opamp and current sensor preferably using the type of current sensor one can easily purchase or make thank you

Leave a Reply

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