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

  3. Dobromire RANGELOV 09/06/2017 at 12:54

    Dear Adam,

    Many thanks for yor excellent job.
    Unfortunately can not complete this projec witth ATTINY85..
    Can you confirm that the scetch above is correct also layot diagram.
    As per the scetch ATTINNY85 LEG3 mesure volatale ( analog input),
    LEG2 – PWM ourput to transistor 2N3904..
    Acording layot – LEG3 Output,LEG2 – analog input.
    Succefuly loaded the code but the sheme not working.
    The measrements of ATTINY85 are as follow :
    LEG 1- 4,4V
    LEG2- 5V
    LEG3- 0V
    LEG4 -0V
    LEG7- 0V

    Hope to receive your comments.
    Thanks in advance.



  4. Adri 26/07/2017 at 10:37

    Hi Adam
    What is the function of the TVS diode?

    • Tony 26/08/2017 at 10:17

      A transient-voltage-suppression; removes noise/spikes on the input.

  5. ElectroDiscover 13/06/2018 at 15:35

    I was wondering if someone made EasyEda schematic or something similar?
    Thanks in advance.

  6. Andy 24/07/2019 at 10:26

    Is there an update to this please?

    There are some errors in the parts list (nano instead of attiny, no regulator, 470nF should be 4.7uF).

    As mentioned by #Dobromire RANGELOV – the analogue read and write pins are reversed in relation to the layout.

    Missing } at end of sketch.

    I don’t get a PWM output on PB3 with the sketch as written. If I reverse the pins to match the layout, I get a 231Hz squarewave on PB3 and PB4.

    I wish I was knowledgeable enough to fix this; it’s just what I need.

    • Andy 24/07/2019 at 14:29

      After a bit more research, I found that PB3 and PB4 were giving out complementary square-wave, so PB3 was unsuitable as an input. I changed it to PB2 (leg7), and it now seems to work, although I’ve not tried it in the circuit yet, as that needs to be reconfigured.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.