ATTiny85 PWM Solar Charge Controller

Posted on 10/12/2015 by Adam

After receiving Julian’s comment on my first Arduino solar charge controller Youtube video I’ve been thinking of ways to reduce the power consumption, but after a fair bit of reading (and a bit of guessing) I’ve been able to come up with a working prototype. In the video below I look at the code, how to program ATTinys and the trade offs that come with reducing power consumption.

Layout Diagram:
layout stripboard v4-4

Parts List
1x Arduino Nano Clone:
1x IRF3205 Mosfet:
1x 2N3904 NPN Transistor:
2x 2N3906 PNP Transistor:
4x 1N4148 Diode:
1x P6KE33CA TVS Diode:
1x 90SQ035 Schottky Diode 9A/35v (or similar):
2x 47nF 50v Ceramic Capacitor:
1x 1uF 50v Ceramic Capacitor:
1x 220pF 100v Ceramic Capacitor:
1x 470nF 10v Tantalum Capacitor:
2x 1uF 35v Tantalum Capacitor:
1x 82k 1% 0.25w Resistor:
1x 20K 1% 0.25w Resistor:
3x 220K 0.5w Resistor:
1x 4.7K 0.5w Resistor:
1x Verobaord:


//PWM Solar charge controller using Julian Iletts design and code ( but adapted to work on the ATTiny25/45/85 by Adam Welch (
const int setPoint = 13.5 * 20 / (20+82) * 1024 / 5 ;
int measurement = 0;
int pulseWidth = 0;
int difference = 0;
int stepSize = 0;

void setup() {
    TCCR0A = 2<<COM0A0 | 3<<COM0B0 | 3<<WGM00;  // Timer 0 Control Register A - Set None Inverting Mode, Set Inverting Mode, Enable Fast PWM
    TCCR0B = 0<<WGM02 | 1<<CS00;  // Timer 0 Control Register B - Enable Fast PWM, No Prescaler
    TCCR1 = 0<<PWM1A | 0<<COM1A0 | 1<<CS10;  // Timer 1 Control Register - Prevent timer using pin OC1A, again prevents use, No Prescaler
    GTCCR = 1<<PWM1B | 2<<COM1B0;  // General Control Register for Timer 1 - Enable use of pin OC1B, None inverting mode.
  analogWrite(0, 117); //ATTiny85 Leg 5 // OC0A
  analogWrite(1, 137); //ATTiny85 Leg 3 // OC1B

void loop() {
  measurement = analogRead(4); //ATTiny85 Leg 3
  difference = abs(setPoint - measurement);
  stepSize = difference;
  if (measurement < setPoint)
    pulseWidth += stepSize;
    if (pulseWidth > 255) pulseWidth = 255;
  else if (measurement > setPoint)
    pulseWidth -= stepSize;
    if (pulseWidth < 0) pulseWidth = 0;
  analogWrite(3, pulseWidth); //ATTiny Leg 2 

What Others Are Saying

  1. Carl 28/03/2016 at 20:43

    The Arduino code seems to have some errors in it. Could you re-post it or send it to me an in email?

    • Adam 31/03/2016 at 14:58

      Sorry to hear that – I’ve not had an issue. Which IDE version are you using and have you installed the ATTiny hardware in Board Manager?

      • Carl Recktenwald Jr. 05/04/2016 at 21:48

        IDE is 1.6.6 in line 22 it reads

        if (measurement < setPoint) { pulseWidth += stepSize; if (pulseWidth > 255) pulseWidth = 255;

        The error is the &lt.

        I was able to fix the code on my end and the code works fine now.

        • Adam 03/05/2016 at 08:14

          So sorry for the delay. It seems some of the special characters have been mangled in the webpage. I’ve rectified this now.

  2. Raphael 21/01/2017 at 19:37

    Can i replace the 1uf and470n Tantalum caps with electrolytics?

    • Raphael 21/01/2017 at 19:49

      oh i just noticed that on Julian Ilett’s website the 470N is an 4u7

Leave a Reply

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