Introduction: NiMH Battery Over-discharge Protection Circuit

Picture of NiMH Battery Over-discharge Protection Circuit

I like to power my electronic projects with two nickel metal hydride batteries in series. NiMH cells are cheaper and safer than lithium ion batteries (brand name vs brand name), and, like Li-ion batteries, can deliver a lot more current than alkaline cells. A NiMH cell has a voltage of ~1.4 when fully charged, and 1.2 V when 5% to 95% charged. When a cell is nearly empty, the voltage rapidly drops below 1.1 V.

Ideally, you should stop using a NiMH cell as soon it reaches 0.8-1V. Allowing it to discharge further will lead to damage. In theory, with two cells in series, the cut-off voltage should be between 1.6 and 2 V. In practice one of the cells will lose charge faster, and will have a lower voltage than the other one. Assuming the worst case scenario where one cell drops to 0.8-0.9 V while the other one remains at 1.2 V, we would like to set the threshold to 2-2.1 V.

There are specialized ICs that can be used to prevent over-discharge. One example is MAX8212CPA. Unfortunately, these ICs cost over US $5/unit, and are not very easy to come by. For comparison, AVR ATtiny85 microcontrollers are sold for just one US dollar on ebay. Fortunately, it is possible to replace a voltage monitor IC with an ATtiny MCU. In addition to being cheaper, an MCU can be programmed to perform multiple functions (e.g. cut off power, indicate with an LED, send a message to a transmitter). This ATtiny85 based circuit consumes little power (approximately 60 uA at 3.3 V), and can initiate battery cutoff at any point set below 2.5 V.

Step 1: Gathering Parts

Picture of Gathering Parts

First we need to build a calibration setup on the breadboard. The following parts are needed:

– an ATtiny85-20PU microcontroller (ATtiny25 or 45 should work as well)
– an ISP programmer or an Arduino running the "Arduino ISP" code
– an N-channel MOSFET such as P30N06LE (FQP30N06L)
– two 330 Ohm resistors (can be anything up to 1 kOhm)
– a 0.1-1 MOhm resistor
– a capacitor (1-10 uF)
– an LED
– a potentiometer between 1-10 kOhm
– a multimeter

For the final assembly of the circuit on a perforated PCB I recommend to replace the resistors, LED and capacitor with their 0805 counterparts. You will also need a boost converter to step-up battery voltage to 3.3 or 5 V. I have purchased several units on ebay, and they are all equipped with 3-pin headers (Vin, GND, Vout) for convenience. The photo shows two of the boost converters I own.

Step 2: Calibration Circuit

Picture of Calibration Circuit

ATtiny utilizes an internal 2.56V reference to measure the battery voltage. Unfortunately, this reference voltage is not exact and varies slightly from one chip to another. That is why we first need to assemble a calibration circuit to find the threshold value that would match our target cut-off voltage.

The breadboard circuit on the photo has an ATtiny in the centre. The top breadboard terminal strips (3.3 or 5 V and ground) are connected to pins 4 (GND) and 8 (Vcc). There is a bypass capacitor between these pins (mind the polarity if you are using an electrolytic capacitor).

Voltage is measured on pin 7 which is connected to a potentiometer. We need to connect a multimeter to pin 7 (or the centre of the potentiometer) and the ground.

An LED is installed between pin 3 and GND in series with a 330 Ohm resistor.

Finally, pin 2 is connected to the gate of a MOSFET via a 330 Ohm resistor. The gate is also connected to ground via a 0.5 MOhm resistor. It will pull down the gate when there is no signal from the microcontroller. A load (e.g. an LED in series with a resistor) can be connect to the middle pin of the MOSFET and Vcc, but we don't need it for calibration. Instead we will later confirm the MOSFET switches as it should with the multimeter.

Step 3: Firmware and Calibration

Compiling and uploading

The attached file contains the code that needs to be compiled and uploaded to the microcontroller. If you are going to use an Arduino as a programmer, you can find the wiring diagram in this tutorial. You need to follow steps only in the following sections (ignore the rest):

– Configuring Arduino Uno as a ISP (In-System Programming)

– Connecting ATtiny85 with Arduino Uno

To compile and upload the firmware, you will need either CrossPack (for Mac OS) or AVR toolchain (for Windows).

The following command needs to be executed to compile the code:

avr-gcc -Os -mmcu=attiny85 -c main.c; avr-gcc -mmcu=attiny85 -o main.elf main.o; avr-objcopy -j .text -j .data -O ihex main.elf main.hex

To upload the firmware, run the following:

avrdude -c arduino -p attiny85 -P /dev/cu.usbmodem1411 -b 19200 -e -U flash:w:main.hex

Instead of "/dev/cu.usbmodem1411" you will likely need to insert the serial port to which your Arduino is connected (you can find it in the Arduino IDE: Tools --> Port).

How it works

The code contains two functions: deep_sleep() and read_volt(). The first function makes the microcontroller enter a very low power state for a quarter of a second. The second one is in charge of reading voltage on pin 7 using the microcontroller's ADC, and assigning it to the "result" variable. This result will be a number from 0 to 1023. Assuming the internal voltage reference is exactly 2.56 V, a value of 800 will correspond to 2.56/1024*800 = 2 V. In practice, it will differ slightly from one unit to another.

Once read_volt() has been executed, the microcontroller will compare the reading against the "threshold" constant:

if (result > (threshold + hyst)) {}

If the condition is true, the MCU will blink pin 3 (PB4), and keep pin 2 (PB3) high. Otherwise it will make both pins low. You have probably noticed another variable in the if statement — "hyst". It stands for hysteresis. When the voltage is above the threshold, it will be equal to zero. But should the voltage on pin 7 drop below the threshold, it will be set to 140 (approximately 0.3V). This way if the voltage is hovering just around the threshold level, noise won't keep triggering the MOSFET on and off. Instead, "hyst" will effectively raise the threshold by 0.3 V.

Calibration

Once you have uploaded this firmware, you should verify with your calibration circuit that the threshold is set correctly. Rotate the potentiometer very slowly to avoid rapid changes on pin 7. Watch the multimeter and note the voltage that causes blinking to stop. If the circuit is triggered at a voltage that is too high, you will need to lower the threshold constant. Remember, once triggered, the effective threshold will be higher because of hysteresis. If you want to repeat the measurement, you will need to first raise the voltage to reset "hyst". Depending on the type of the potentiometer used, you might want to limit its range by adding resistors in series with the pot ground and Vcc.

Step 4: Final Assembly and Afterthoughts

Picture of Final Assembly and Afterthoughts

Once I found the required threshold value for my microcontroller and uploaded the final version of the firmware, my goal was to create a compact PCB with a header able to accept any of my 3-pin boost converters. With 0805 parts I was able to fit everything on a 15x27mm board (0.6x1.1") in accordance with the attached schematics. To create connections between holes I soldered on individual strands from an AWG24 wire. They aren't easy to work with, but it helps to solder them in one spot in the middle, then stretch and solder the ends. Once the soldering was finished, I trimmed the board with tin snips and rough sand paper.

If you don't have 0805 parts, it is not difficult to adapt the circuit layout to use the through-hole parts from the calibration circuit. To save space you can mount resistors vertically.

Although this circuit is designed only to blink an LED when the battery voltage is good, and switch off the MOSFET when it's below the threshold, it is possible to add additional functions. For example, a piezo buzzer can be connected to one of the unused pins to beep in case of low battery voltage (like smoke alarms do).

Step 5: Legal Disclaimer

This circuit is designed by a non-professional hobbyist for hobby applications only. This design is shared in good faith, but with no warranty whatsoever. Use it and share with others at your own risk. By recreating the circuit you agree that the inventor will not be held liable for any damage (including but not limited to impairment of assets and personal injury) that may occur directly or indirectly through malfunction or normal usage of this circuit. If the laws of your country nullify or prohibit this waiver of liability, you may not use this design. If you share this design or a modified circuit based on this design, you must credit the original inventor by indicating the url of this instructable.

Comments

The Lost Puppy (author)2017-09-07

This is such a neat idea. I am wondering though how one would modify this circuit to take 3 NiMH batteries in series. I don't have a lot of knowledge on the subject so I am hoping that someone else can help me.

Im_int (author)The Lost Puppy2017-09-11

The cut-off voltage for 3 NiMH batteries in series should be around 3.3 V. The built-in voltage reference on attiny85 is only 2.56 V, so the battery voltage would have to be decreased in order to be measured against the internal reference. The easiest way to do it is with a simple voltage divider (https://learn.sparkfun.com/tutorials/voltage-divid...) which is just two resistors in series between the battery voltage input and the ground:

[Vbat terminal] —/\/\/\/\/-(R5)— [attiny85 sensing point] —/\/\/\/\/\/-(R6)— [GND terminal]

Here's what the underside would look like: https://imgur.com/4mR6iV4

Aiming for R5+R6 ~10 kOhm (so the parasitic current through the divider stays under 0.5 mA) we could use R5 = 3.3 kOhm and R6 = 6.8 kOhm which give a scaling factor of 0.673 at the sensing point. 3.3 V cut-off then becomes 3.3*0.673 = 2.22 V. The cut-off threshold in the code ("const uint16_t threshold = 800;") would need to be changed to 2.22/2.56*1024 = 888.

The Lost Puppy (author)Im_int2017-09-11

Thank you for this reply. It was very detailed and should help me when I build my portable raspberry pi project.

robojeron (author)2017-01-19

This is a great instructable, it's thorough and well written. I hope to see more content from you in the future, keep up the good work!

Im_int (author)robojeron2017-01-19

robojeron, thank you very much for your kind words!

nqtronix (author)2017-01-19

This is not only useful, but actual competition to the commercial product. Especially when you don't have the time for oversea shipping this might come in handy!

For battery protection with removable batteries I'd properly add a function to disable the watchdog timer after a certain time below the minimum voltage to reduce the current consumption even further. Removing the batteries would then reset the chip.

Im_int (author)nqtronix2017-01-19

That's a very good idea! The protection circuit on its own draws ~60 uA, and with one of those 3.3V boost converters from ebay it is at least twice as much. If for some reason it is impossible to replace the battery immediately (e.g. it's powering a remote sensor), a reduction in current draw could be very helpful.

The creator sid (author)2017-01-19

The best way is to get a TP 4056 Protection circuit.

The TP4056 is not a protection circuit, it's a LiPo charging IC. The protection IC, which often is on the same board is the DW01, but also exclusively designed for LiPo batteries.

Swansong (author)2017-01-19

I wish I had had this before, lol! This is great, thanks :)