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 poses inherent risks. Adequate skills are crucial for handling it safely. Undertake tasks at your own risk; the author disclaims responsibility for misuse, harm, or errors. Website content is unique and copyrighted; refrain from unauthorized copying. Most articles are open-source for your benefit. Feel free to use the knowledge freely, and consider purchasing available resources. For assistance or guidance, comment below; the author aims to help. Some articles may contain affiliate links, having no impact on you but supporting the author with a commission. Thank you for your understanding.

Advertisements

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:

microcontroller based voltage stabilizer circuit

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:

The relay switching part is not complex at all too.

microcontroller based voltage stabilizer circuit

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:

microcontroller based voltage stabilizer circuit

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 happens if I do that.

Calculation in coding:

If I keep the calculation as it is:

Read more:

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

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

Result for changes:

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 parts 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:

microcontroller based voltage stabilizer circuit, transformer calculation

What do 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.

Input & output voltage chart:

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. You can build your hex file using mikroC Pro for PIC compiler. Alternatively, you can get my generated hex file from here.

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 it in real life and show me the result.

PCB design:

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

microcontroller based voltage stabilizer PCB

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.

For Professional Designs or Help:

Loading

Check this out: Voltage Stabilizer Circuit with 4 Relays

Categories: Complete ProjectsElectronicsHome AppliancesPICPower ElectronicsProductive

MKDas

Mithun K. Das; B. Sc. in EEE from KUET; Head of R&D @ M's Lab Engineering Solution. "This is my personal blog. I post articles on different subjects related to electronics in the easiest way so that everything becomes easy for all, especially for beginners. If you have any questions, feel free to ask through the contact us page." Thanks.

48 Comments

Joy · 19/04/2021 at 2:28 pm

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

Asimiyu · 20/04/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.

    MKDas · 20/04/2021 at 9:04 am

    Thank you.

      Inayat · 30/09/2021 at 3:06 pm

      If we use this pcb for 50 volt to 220 volt what can be do?
      Ur 1st tapping is 150 and I want my 1st loop is 50 volt

        MKDas · 30/09/2021 at 3:17 pm

        Try to understand the concept of the circuit. Once you understand it, you can make any changes you need.

ROBERT · 23/04/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 · 06/05/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 · 06/05/2021 at 11:29 am

    In that case you can look for Static Voltage Stabilizer.

Flex · 08/05/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

Chandana · 11/05/2021 at 8:15 am

Does ADC input safe from the negative half of the AC signal? I cannot understand can you kindly explain?

    MKDas · 11/05/2021 at 9:24 am

    Yes no problem. ADC is internally protected.

      Chandana · 11/05/2021 at 10:49 am

      Many thanks for the reply.
      Thank you so much for excellent projects and clear explanations

RKHam · 14/05/2021 at 3:19 am

Mr. MKDas,
Can you please explain the connection between sampling rate and the AC wave form.
As per my understanding, 20ms takes for a cycle when AC frequency is 50Hz.

I am trying to understand following code

for(k=0;kmax_point)
{
max_point = temp;
Delay_us(1);
}
}

    RKHam · 14/05/2021 at 3:22 am

    Sorry I missed some parts of the code in my question above

    for(k=0;kmax_point)
    {
    max_point = temp;
    Delay_us(1);
    }
    }

      MKDas · 16/05/2021 at 12:39 pm

      You missed again. read again please.

    MKDas · 16/05/2021 at 12:38 pm

    First you made a mistake to read the code. Check again. It is simply a peak point finding algorithm. I’ve explained this in my other articles. You should read that before this one.

Monir · 02/08/2021 at 8:38 pm

Bought the PCB file. Waiting for the print arrives. Then I’ll get the hex file.

Selvakumar · 05/09/2021 at 7:57 am

Hello sir I am doing audio related circuit I need microcontroller for display input volt, output volt, brand name, and master, bass, treble, values in lcd display can u help me

    MKDas · 06/09/2021 at 12:19 pm

    There are some other articles on voltmeters. Kindly read those. It will be helpful I think.

    Elektronik Experts · 14/03/2022 at 8:33 pm

    Hello MKDas, I can help you for product development on paid basis, send email me back.

md . sumon · 18/09/2021 at 1:10 pm

hi im sumon your project is very nice but ..not 100 parcent ! you not use display lcd or seven seg

i want display sys volatage stab c code pls help….

    MKDas · 18/09/2021 at 3:30 pm

    This is an educative project that helps people making their own. If someone’s requirement is different then it’s not the project’s fault not to be his/her 100%. Read the article, try to understand the mechanism. Read similar articles that uses LCD then combine them into one.

Harish popat · 19/09/2021 at 5:08 pm

For 3 relay 5 step with 30 sec dela
Send contact no

ezekiel iyamu · 28/11/2021 at 12:08 pm

I tried this code on both mplab and the mikroc which you recommended but it shows more than 20 different undeclared identifiers…. is something missing here

Md Ariful Islam · 19/06/2022 at 8:33 pm

Osadharon vai..ey code ami kaj korty parchi…

Dario · 17/08/2022 at 5:20 am

The code has many errors, it is a pity that it is not right, I would like you to upload a new post that is more explained, especially in programming.

    MKDas · 17/08/2022 at 11:06 am

    What error you are having? The code is 100% working and perfect.

      Dario · 18/08/2022 at 6:16 am

      Excuse me but what is happening to me with the code is that when I copy it in mikroc it does not generate the Hexadecimal file I do not know why that happens, before copying it checks all the mikroc libraries, but it does not copy properly, I would like you to help me With that, thank you very much.

        MKDas · 18/08/2022 at 11:58 am

        That is the problem with your copy or mikroC. Not code.

        Zira · 01/06/2023 at 11:17 pm

        Is a great project but when I want to simulate is not working the pic16f676 is not responding

          MKDas · 02/06/2023 at 12:13 pm

          check the learning tutorials to learn about the settings. Then you can find yourself.

Yuri · 07/12/2022 at 4:27 am

Undeclared identifier ‘ADC_Read’ in expression

error when using Build function to complie

    MKDas · 07/12/2022 at 11:54 am

    tick mark library , right side.

JatinderBir Singh Chawla · 21/04/2023 at 9:02 pm

Nice , i will surely try this

Md. Moniruzzaman · 30/06/2023 at 7:38 pm

Dear brother,
At first spacial thanks for your help full post, I have read your post ,it is almost good but I have a question, when all relay is stop that time control voltage provide by capacitor, as your discretion , but I think it will generate malfunctioning because 210 voltage tape directly connected to load, if load circuit current flowing that time maximum voltage will be dropped in capacitor 105, 400v. How to solved it ??

    MKDas · 02/07/2023 at 7:21 pm

    Design is well tested, it will not malfunction if your starting capacitor is good one.

mehranal · 03/10/2023 at 4:47 pm

I programmed your ready code on pic16f676, but it doesn’t work at all, I completed the circuit according to your specifications, but it doesn’t show any reaction, where is the problem?

    MKDas · 10/10/2023 at 8:37 pm

    fix your crystal settings first then MCLR then try again.

      mehanal · 11/10/2023 at 11:54 am

      How do I set mclr for Micro 676? There is no specific reference, please help

        MKDas · 11/10/2023 at 3:51 pm

        There is a tutorial series with PIC MCU. kindly read those step by step. then you can understand this easily. Once you understand this, you’ll get it for lifetime. But if I say it here, you’ll forget that after some time. Thanks

Leave a Reply

Avatar placeholder

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