PWM Solar Charge Controller with PIC12F675

Published by MKDas on

In the previous article, we have learned about the basic operation principle of solar charge controller and besides, we have seen a working circuit with both analog and micro-controller based on/off charge controller. In this article, we are going to learn how to make a PWM charge controller using that same circuit and micro-controller. Here, only some programming skill is applied. So 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.

What is a charge controller?

I’ve already discussed about this in the previous article. So I’m not discussing again. Kindly read that article first.

PWM Charge controller circuit diagram:

As mentioned earlier, there is no difference between the on/off and PWM charge controller diagram. Only difference is the charging pulse.

We can use this same diagram. Now, in this circuit, we will modify the programming only.

Coding:

/*******************************************************************************
Program for, PWM charge controller
Program Written by_ Engr. Mithun K. Das; mithun060@gmail.com
MCU:PIC12F675; X-Tal: 4MHz(internal). Compiler: mikroC pro for PIC v7.6.0
Date: 31-03-2021; © labprojectsbd.com
*******************************************************************************/
#define  charge_pin     GP0_bit
#define  load_pin       GP4_bit
#define  ch_led         GP5_bit
#define  ld_led         GP2_bit
#define  solar_sense    GP3_bit
#define  bulk           1
#define  absorbation    2
#define  flot           3

unsigned int battery=0;
int i=0;
bit charge;
bit load;
short charge_level=0;

unsigned int scale=0,duty=0;
unsigned int cycle1=0,cycle2=0;

void InitTimer0()
{
  OPTION_REG         = 0x80;
  TMR0                 = 230;
  INTCON         = 0xA0;
}


void Timer_interrupt() iv 0x0004 ics ICS_AUTO
{
  if (TMR0IF_bit)
  {
    TMR0IF_bit         = 0;
    TMR0         = 230;
    scale++;
    if(scale<duty)
    {
        charge_pin = 1;
    }
    else
    {
        charge_pin = 0;
    }

    if(scale>100)
    {
      scale=0;
      cycle1++;
      if(cycle1>5000)
      {
         if(cycle2<5001)cycle2++;
         cycle1=0;
      }
    }
  }
}


void main() 
{
  TRISIO = 0b00001010;//set I/O ; 1=input, 0=output
  GPIO = 0x00;
  CMCON = 0x07;//comparator off
  ANSEL = 0b00000010;//AN1 analog only
  ADCON0 = 0x05;//AN1 channel selected
  InitTimer0();
  charge_level = bulk;
  while(1)
  {
     //read battery voltage
     battery=0;//clear previous data
     for(i=0;i<20;i++)
     {
        battery += ADC_Read(1)*27/100; // *5/1023*(10+2.2)/2.2*10*calibration
        Delay_ms(10);//keep a delay for smooth measurement
     }
     battery/=20; // make an average result from 20 samples.

     //Note: here rather than taking floating point variable, unsigned int
     //is used and while calculating, eliminated fractions to reduce further
     //RAM & ROM use.


     //charge control
     if(solar_sense)
     {
        //charging control
        if(charge_level==bulk)
        {
           duty = 99;
           if(battery>145)
           {
              charge_level = absorbation;
           }
           ch_led = ~ch_led; //fast blinking
        }
        else if(charge_level == absorbation)
        {
           if(battery>138)
           {
              if(duty>2)duty--;
           }
           else if(battery<137)
           {
              if(duty<99)duty++;
           }
           
           
           if(cycle2>1000)      //as we are not sensing current
           {                    //we we'll count cycles.
              charge_level = flot;
              cycle2=0;
           }
           ch_led = ~ch_led;Delay_ms(200);//slow blinking
        }
        else      //full charge
        {
           if(battery>128)
           {
              if(duty>1)duty--;
           }
           else if(battery<128)
           {
              if(duty<15)duty++;
           }
           ch_led = 1;//charge is full
        }
     }
     else
     {
        charge_pin = 0; //do not charge
        ch_led = 0; //indicator off

        charge_level = bulk;//reset level
        cycle1=0;
        cycle2=0;
     }


     //load control
     if(battery>126)load = 1;//load reconnect
     if(battery<116)load = 0;//load disconnect

     if(load)
     {
        load_pin = 1; //load MOSFET on
        ld_led = 1;//LOAD on indication
     }
     else
     {
        load_pin = 0; //load MOSFET off
        ld_led=~ld_led;//LOAD off indication
     }

  
  }//end of while(1)
}//end of void main




//End

If you need, you can use this hex file directly.

Result:

Simulation result:

PCB layout:

If you want to develop this project in a PCB, you can follow this layout.

Or you can buy the layout for pdf files or Garber files and can print from our PCB partner JLCPCB.com

Buy the PCB file through PayPal for the US $5.0 only. Or BDT 500.00 only from Bangladesh through bKash: 01972448270 (personal).

After payment kindly fill this form below. File will be sent to your email after payment verification.

Conclusion:

The article is very basic and informative to design a PWM based solar charge controller. Only a small software trick can make the device more powerful.

I hope this project was helpful to you. If you make one for yourself, it will be a great pleasure for me. Anywhere you need help, let me know. Please share this project and subscribe to my blog. Thank you.

Loading

MKDas

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

19 Comments

Asimiyu · March 31, 2021 at 4:31 pm

Please, sir. When I was going through the PWM source codes, I found a little bit confusion I would like you to throw more light upon sir. (1) you assign 1 to Bulk, 2 to absorpation, and 3 to flot. What does these 1,2 & 3 represent?. (bit or significant number?) And what does each have to do with Pulse.( Or are they represent FLAGs?)
(2) if(battery >138) // battery voltage at 13V
{
if(duty>2)duty–;. // Need comment sir about “2”
}
else
if(battery <137)
{
if(duty<99) duty++; // duty cycle 2) duty–; in the code above I thought, “2” represents 2% duty cycle, it supposed to increment the dutycycle not decriment?. Please put me through.
(3) lastly, what are the functions of variables cycle1 and cycle2 in the codes?. Thank you, looking forward to your response. God bless you.

    Mithun K. Das · April 1, 2021 at 3:12 am

    1>> Just a variable to select the mode.
    2>> we should not turn off the pwm or use very small duty. That is why minimum range is 2
    3>> cycle1 & 2 is for creating a time delay without interrupting other works, this time delay is used in absorption mode. as we are not using any current sensing.

      Asimiyu · April 1, 2021 at 7:52 am

      Thank you. It is now cleared.

Asimiyu · April 4, 2021 at 11:16 am

Good afternoon engr Mithun. Please, I recently built the solar charge controller hardware on a veroboard, and even simulated it on the Proteus and I used mikroc version 7.2 to simulate it. However, I discovered something sir. Without solar panel voltage connected, while Battery was connected, the controller would not trigger the gate of LOAD MOSFET and hence, load remains off. However, if solar panel is connected, and Battery is also connected, the following are what I observed:
(1) pin#1(Vcc)= 4.98v from 7805 reg.
(2) pin#2(GP5), charg_LED = 0.0v
(3) pin#3(GP4), load_pin = 2.38v
(4) pin#4(GP3),solar_sense = 4.3v(here, I have using variable resistor of 5K, with series with 3k9 to form voltage divider to give 5v at 18V solar panel proposed to be used.
(5) pin#5 (GP2), load_LED = 4.98V
(6) pin#6 (GP1), Battery_sense = 2.46v at 13.05V(no-load) and (12.98v when connected to load).
(7) pin#7 (GP0), charg_pin = 0.0v
Pin#8 (GND) normal 0.v.
However, from these data I took, it means the solar is not charging the battery, which I observed from both simulation and the hardware circuit.
What could be the problem sir. I troubleshooting the hardware and the it behave in the simulation, the same way on the hardware too.
Finally, I also observed that, if solar panel voltage is not connected, the controller will not trigger the load MOSFET even at battery Voltage =13.05v. it shouldn’t be so, bcs even the solar Voltage is not present in night, while the battery Voltage is at Max(at least above 11v,) the load MOSFET should connected. Please, look into it. I am just self interested learner. I have already built the hardware,. I also tried to upload everything here, but I was on able to do so, I copy and trying to past it here but it couldn’t be pasted. I will send it through your email.

    Mithun K. Das · April 5, 2021 at 3:24 am

    Seems like you forgot to do a configuration. Go to edit project from mikroC. Set GP3/MCLR >> disabled.

    As this is enabled by default, the micro-controller is not working if GP3 pin is low. Solar is sensed through this pin. So when solar is not available, the MCU is in reset condition. And only when the solar is on, MCU works.

    Also, to turn the load on, first you need to charge the battery to higher than the load reconnect voltage. Once it is done, load will be normal.

    1> OK, no prob.
    2> OK
    3> due to MCLR low
    4> No need to use any voltage divider, once the mosfet is on, it is 0.7V+B+. Also internal diode cliper protects the pin. Note: MCLR max input range: 12V
    5> No prob
    6> good
    7> ok.

    Also if you do not have any license for mikroC, you can use my hex. I always use valid licenses for each compiler & other software.

Joy · April 5, 2021 at 3:21 am

Sir I want use 200 W solar panel (Mono) and output 12V 150A battery. so how to do this increased hardware part.

    Mithun K. Das · April 5, 2021 at 3:38 am

    Use Diode 10A10 3 nos in parallel, Use MOSFETs 3 in parallel. Increase current-carrying layer thick and pasted with solder lead & wire.

Asimiyu · April 5, 2021 at 6:05 am

Thank you very much sir. I will go to edit project and and do that. Thank you once again.

Joy · April 5, 2021 at 12:34 pm

Soler output voltage 22v When sun light full .But that time 22v Direct 12v battery input. so battery input high current carry . +12v battery charging volt 13.5v fixed but this system not fixed. so It’s problem or not ?

Asimiyu · April 5, 2021 at 2:56 pm

Hello engr Mithun. Thank you for your efforts, free offer knowledge, and your guidance you have been impacted on many people in the world. I have disabled the GP3/MCLR in mikroc project edited and also set INTOSC Oscillator: CLKOUT…… Everything is now working fine, even at the moment I am writing this message, the Battery is still charging and is at 13.04. I really appreciate your efforts.
HOWEVER, please, I am sorry for being asking too much question. I so love embedded systems, and being part of chips programming is my passion, and I have your blogs here as an opportunity for me to learn.
From previous post on IR REMOTE CONTROL WITH SONNY SIRC REMOTE PROTOCOL, I am trying to convert the code to control A.C (220VAC, 50Hz) fan regulator in such a way that, if I press (+vol), the speed should increase sequentially, and decrease it by pressing (-vol). There should be one digit segment to indicate count. I have been cracking my brain, I haven’t succeed since you posted it. Please, I need your guidance sir.

    Mithun K. Das · April 6, 2021 at 3:57 am

    Thank you.

    >> I’ve a plan for that.

      Asimiyu · April 6, 2021 at 5:57 am

      Looking forward sir. Thank you God bless.

Mahasetra · April 12, 2021 at 12:47 pm

Hello and thank you for this very interesting article. Can the schematic be modified to integrate a current sensor instead of the load control (pin 3), and a synchronous buck topology (with IR2104) to increase the efficiency? I know that the efficiency will be lower than a MPPT but the goal is to keep the small microcontroller and convert the excess voltage into current while charging the battery in 3 steps.

    MKDas · April 12, 2021 at 1:11 pm

    Thank you for your comment. There is a pin limitation as well as memory limitation. Adding MPPT function is almost impossible to add in this tiny MCU. But I’m keeping a note, if somehow it is possible to increase the efficiency, I’ll try. Thanks. Requesting to subscribe.

      Mahasetra · April 28, 2021 at 2:59 pm

      Hey, can i use an attiny85 or attiny84 instead of a pic?
      And please how does the absorption phase work in your code? How long does the solar controller stay in the phase 2 of charging?
      Thanks

        MKDas · April 29, 2021 at 10:41 am

        Using the same technique, you can use other MCUs rather than PIC. No problem with that.
        The absorption phase should be determined sensing current. But as there is no such option in this design, so a timer is used here. Approximate time: timer speed X counters. Around 2~4hrs will be good timing.

          Mahasetra · May 3, 2021 at 3:29 am

          Thank you for replying.
          I’ve done a diagram of what I’had on my mind after reading two of your articles about solar charge controllers.
          It’s a basic buck converter with 3 steps charging (but it doesn’t have any mppt algorithm).
          (There are some modifications to be done to improve efficiency)
          What do you think Sir?

          https://drive.google.com/file/d/1vwZKdSB8KVUy655E0h0CBr12mZCQ2rQV/view?usp=sharing

          MKDas · May 3, 2021 at 11:41 am

          The circuit seems ok. Add capacitor after rectifier on solar side. D4 must be Ultra Fast Diode. There is no need of any buzzer in solar charge controllers. Use on another purpose. Check OP-Amp for resistor values. Best of luck.

Leave a Reply

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