Programmable Battery Protection [Open Source]




Every battery needs protection.

When I couldn't find a board that suited my needs, I set out to create one myself.

If you discharge a battery completely it can be permanently damaged. This PCB monitors the voltage (and thus the State Of Charge) and if it dips below the programmed voltage it will disconnect the load. For a lead-acid battery this is ~11.5V for example. Please note that this battery monitors total pack voltage, it doesn't offer individual cell protection. It can be used on any battery chemistry you want, as long as the pack voltage is between 5.5 and 29V.

This solution is based on an ATTiny microcontroller which remains in very low power shutdown unless the button is pressed. If the battery voltage is above the programmed treshold the load will be switched 'on' using a mosfet.

A couple of key features include: reverse battery protection, very low power consumption, able to switch high current loads, compact board, cheap to make.

In the video you will see the design process step by step. A more detailed explanation in text format can be found on the following pages. On the last page you can download all the files, including schematic, layout, GERBERs and code.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: R&D

The three main things I wanted to achieve:

-low cost

-small footprint

-high flexibility

This project doesn't require many pins, so I chose the popular ATTINY85 microcontroller (6 I/O's) in a SOIC package. An ATTiny gives a very flexible solution that is cheap and requires almost no external parts.

For the mosfet I needed something that was small, cheap and can switch 8A+. N-Channel would be the most practical, because then you can connect one side to the ground plane of the PCB. It can switch about 13A continuous and 110A (!) pulsed.

For the voltage regulator I needed something that has low quiescent (idle) current, because the power usage has to be almost zero when 'off'. The LM2936 satifies this requirement with only 15uA of idle current.

Step 2: Schematic

I was able to keep the required part count very low.

Couple design notes;

-The voltage divider on the input has to have high resistance to keep power dissipation low

-Max input voltage times the divider ratio should be about 3.3V (Vcc)

-1%+ tolerance resistors should be used to guarantee precision

-Pull down resistances prevent parasitic toggling of the mosfet and switch

-Small decoupling capacitors keep voltage stable

-LED current limiting resistors can be increased to decrease power consumption at the cost of brightness

I was not aware that the ATTiny came in a different SOIC package than the mosfet and regulator. That's why they don't fit properly on my PCB's. It's fixed in the downloadable files at the end of this Instructable.


Step 3: Breadboard Testing (AutoCAD)

I have made a 'breadboard schematic' of how I tested my plan. This setup allows me to see if my powerdown, treshold and mosfet output is working. It's best to use a labbench to power the circuit. This way you can vary the voltage and test the switching treshold.

Step 4: Layout

Layout is pretty simple. It's a 2 layer PCB with stitched groundplane on both sides.

In/Output terminal on the left, programming header on the right.

JST 2P for the switch at the top, JST 3P for the bicolor status LED on the bottom

Step 5: Code

A microcontroller in powerdown uses almost no current (I measured ~300nA). That's a lot less than the self-discharge of the battery itself. You can wake a microcontroller from its sleep by using a pin-change interrupt. I commented my code so it's easier to understand.

Current consumption when active is 2,06mA. It's the same at all voltages because a linear voltage regulator is used.

There is a download link to the .INO arduino file on the last step. Attached code doesn't have the lines for the led control, I might change the file later. If you need help with that, message me.

The Arduino UNO can be used as ISP to program the ATTiny as seen here:


Thanks to user frarugi87 for noticing some flaws in the code I uploaded. The picture above and the file in the download now have been corrected to a fixed and optimized version of the code.

Step 6: BoM and Files Download

Bill of Materials (ordercode at Farnell):

-ATTiny85 [1455164]

-Mosfet, N-Channel SOIC [2322618]

-Resistors, 1% tol 0805 [9332405; 9333606; 9333509]

-Capacitors, 35V+ 0805 [2496944]

-Terminal block, 6way 5mm [9633006]

-Regulator, 3.3V SOIC low IQ [2492178]

I got my JST 2P and JST 3P connectors plus cables from eBay.

As you can see, I listed the key specs so you can find replacement parts if needed/wanted.

Minimum PCB order quantity is 10 pieces. At that quantity BoM is around 5$ per board.

Files can be downloaded here

-Production ready GERBERs

-.INO Arduino C code

-Schematic and Layout [DipTrace]

If you need help with ordering pcb's, modifying code, programming the chip or anything else; send me a message.

Circuits Contest 2016

Participated in the
Circuits Contest 2016

Be the First to Share


    • Made with Math Contest

      Made with Math Contest
    • Multi-Discipline Contest

      Multi-Discipline Contest
    • Robotics Contest

      Robotics Contest

    31 Discussions


    2 years ago

    What is the code for a momentary button?

    I made the circuit board and uploaded the code. with the current code the mosfet turns on when pushing the button. when i release the button the mosfet turns off.

    i tried to change the digitalread(sw) to LOW. but then it works vice versa


    Reply 2 years ago

    It's in the zip file on the last page of the instructable


    2 years ago

    Great project! I found an error in the schematic picture, in the voltage divider it says 820 and it must be 820K.

    1 reply

    Reply 2 years ago

    kun je me mailen zof dat we via PM ff praten?
    ik zou graag zoon pcb willen kopen. of info
    dan vertel ik daar wel waar ik weg kom enze.
    ik wil nix op het net hebben, snappie


    Reply 2 years ago

    Begrijp ik, stuur maar een PM via de Instructables site


    2 years ago

    A great project!

    I was thinking to make something extremely similar to this just a a few days ago, and I was already designing it.

    This will help me a lot. Thank you!


    2 years ago

    Perhaps in your intro you could elaborate about what batteries you are protecting, and why. I hope I didn't just miss that part. Apologies if I did.

    Apparently everyone else who has posted comments already knows about this - sorry for my ignorance.

    None of my batteries are protected that I know of.


    1 reply

    Reply 2 years ago

    Thanks for the feedback, I added some lines to the intro post

    Wrrr 10-G

    2 years ago

    Very cool of you to open source this hands-on design.

    Thanks Lutkeveld!


    2 years ago

    Wondeful ! What is your design software and how did you print your circuit ?

    2 replies

    Reply 2 years ago

    I used DIPTrace for pcb schematic/layout. You can order them using Seeedstudio or Elecrow (about 15$ for 10pcs with standard shipping)


    2 years ago

    If I understood your program correctly, there are a couple of failure points (or at least I haven't understood everything).

    1) if you press the button and the battery is discharged, your load will not turn on (ok), but the attiny will never enter the low power mode until the battery is charged again. This is a bad behavior (it should enter the sleep phase immediately)

    2) as soon as you leave the button the load will be shut down (maybe this is the wanted behavior, though, but I think it is more useful if the button can act as a turn-on - turn-off button)

    3 and most important) while the load is powered, if the battery gets discharged the attiny will stop monitoring the button, thus leaving the load powered on even if the button is released. This is a real problem...

    I think that the first and third points can be solved modifying your code in

    digitalWrite(mosfet, HIGH);

    while (systemstate == 1) {

    if (analogRead(voltdiv) < threshold)

    systemstate = 0;

    if (digitalRead(sw) == HIGH)

    systemstate = 0;


    digitalWrite(mosfet, LOW);

    Moreover you can avoid using the systemstate variable, modifying the loop in

    while (1) {

    if (analogRead(voltdiv) < threshold)


    if (digitalRead(sw) == HIGH)



    Best regards

    3 replies

    Reply 2 years ago

    I think you misunderstood the code. The ATTiny is always in sleep mode, but when the state of pin 3 changes the interrupt will wake the system up. Then it'll go through the loop: 1) check if switch is in 'on'-state 2) check if input voltage is high enough 1) if yes: mosfet enable.

    The code I posted isn't suited for momentary buttons, but it can be modified to work with those.

    As long as the battery voltage is higher than 5.5V, the ATTiny will be able to turn on. Just as long as the voltdiv is below treshold, it won't.

    I think I don't fully understand your third comment. The ATTiny is always in sleep mode (veerrry low power consumption). Once a pin-change interrupt happens, it'll go through the loop and do the checks. If the requirements to turn on aren't met, it'll go to sleep again.


    Reply 2 years ago

    Uhm.. Maybe there are two versions of your code, but in the image posted in step 5 there is a while loop (while (systemstate == 1)). You exit this loop (and consequently power off the MOS and enter the lop power state) only when the voltage is greater than the threshold AND the button is not pressed. If you enter this loop and the voltage decreases, you will never come out of it..

    As for the button/switch, sorry, I misunderstood ;) yes, with a switch it will work


    Reply 2 years ago

    I see what you mean, I might have accidently uploaded an early version of the code. It should go through a while loop which loops while systemstate=1, in the loop it checks if both the button is pressed and the voltage is above the treshold. At the end of the routine it should check if the switch is low, if yes: systemstate=0 (breaks the while loop) after which it writes the mosfet low and enters low power untill an interrupt is fired. I'll look into this when I get home.