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 our PWM Solar Charge Controller.

Disclaimer: Electricity is always dangerous. Proper skill is required to work with electricity. Do work at your own risk. The author will not be responsible for any misuse or harmful act or any mistake you make. The contents of this website are unique and copyright protected. Kindly don’t do any nonsensical act copying and claiming it as yours. Most of the articles published here are kept as open-source to help you. Take the knowledge for free and use it, but if you are interested you can buy the ready resources offered here. If you need any help or guide feel free to comment below, the author will try to help 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.


Program for, PWM charge controller
Program Written by_ Engr. Mithun K. Das;
MCU:PIC12F675; X-Tal: 4MHz(internal). Compiler: mikroC pro for PIC v7.6.0
Date: 31-03-2021; ©
#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;
        charge_pin = 1;
        charge_pin = 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
  charge_level = bulk;
     //read battery voltage
     battery=0;//clear previous data
        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
        //charging control
           duty = 99;
              charge_level = absorbation;
           ch_led = ~ch_led; //fast blinking
        else if(charge_level == absorbation)
           else if(battery<137)
           if(cycle2>1000)      //as we are not sensing current
           {                    //we we'll count cycles.
              charge_level = flot;
           ch_led = ~ch_led;Delay_ms(200);//slow blinking
        else      //full charge
           else if(battery<128)
           ch_led = 1;//charge is full
        charge_pin = 0; //do not charge
        ch_led = 0; //indicator off

        charge_level = bulk;//reset level

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

        load_pin = 1; //load MOSFET on
        ld_led = 1;//LOAD on indication
        load_pin = 0; //load MOSFET off
        ld_led=~ld_led;//LOAD off indication

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


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


Simulation result:

PCB layout:

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


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.

Don’t forget to subscribe for the next update.


JLCPCB – Only $2 for PCB Prototype (Any Color)

24 Hours fast turnaround, Excellent quality & Unbeatable prices

$18 Welcome Bonus for new registrations Now!!!

Check this out: 5 coolest multimeters you can buy


I'm Mithun K. Das; B.Sc. in EEE from KUET, Bangladesh. Blog: "First, electronics was my passion, then it was my education, and finally, electronics is now my profession." I run my own electronics lab, M's Lab ( Where I work with the creation of new products from ideas to something in real life. Besides this is my personal blog where I write for hobbyists and newcomers in the electronics arena. I also have a YouTube channel where I publish other helpful videos, you can find the link inside the articles. I always try to keep it simple so that it becomes easy to understand. I hope these will help them to learn electronics and apply the knowledge in their real life.


  • 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”
    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?

          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?


            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.

    Subramanian · August 15, 2021 at 10:28 pm

    Hi i have a build error

    Line no : 78 Message no : 324 Error : Undeclared identifier ‘ADC_Read’ in expression

      MKDas · August 16, 2021 at 11:05 am

      Mark the ADC library from the right side of the compiler window.

        Subramanian · August 16, 2021 at 11:23 am

        Ok Thankyou

    Subramanian · August 16, 2021 at 11:20 am

    Hi build Error Undeclared identifier ‘ADC_Read’ in expression

      MKDas · August 16, 2021 at 12:00 pm

      Mark the ADC library from the right side of the compiler window.

    Leave a Reply

    Avatar placeholder

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