Single 3.7V Li-ion cell battery back-up for Raspberry Pi

 I have a small application continuously running on Raspberry Pi board. Sometimes, in my country, we have (short time) mains power failures. In such situation, my Raspberry board, powered by the wall adapter, turns off immediatly, without any attention for open files, transmissions in act, etcetera. This is really a problem. I decided to use some materials purchased in the past on ebay to realize a small power back-up unit, using a single Li-ion cell. First of all, you need for a battery charger circuit, to maintain the back-up battery fully charged. The battery is 3.7V typical, and 4.2V when fully charged, but the Raspberry Pi board wants 5V supply, so we need for a Step-Up circuit. As third element, we need for a switch that disconnects the load from battery when mains supply is present, ‘cause the charger can’t see the real battery level if you connect a load while charging. I suggest to read this document released from Microchip: AN1149.

circuit-view

The prototype (click to enlarge)

The charger can be easily found on ebay searching for “1A Li-ion battery charger”. It’s based on well known chip named TP4056. In the picture there is a circle indicating Rchg. The component circled is the charge resistor. The value of such resistor sets the charging current. In the original circuit, the value of Rchg was 1K2 (smd mark 122) that sets 1A charge current. I removed such resistor and placed a new one with value 3K3 (smd mark 332). With this resistor, the charging current will be about 370 mA. I don’t want to charge the battery at higher rate for two reasons: the first is the capacity of the cell (I used a small one), the second is that the wall adapter MUST have enough current to drive the charger AND the Raspberry Pi board. In the next picture you can see three different situations:

Charge / discharge steps (click to enlarge)

Charge / discharge steps (click to enlarge)

Starting from the left, you can see the circuit connected to the wall adapter and the battery charging (red led ON), then the battery fully charged (blue led ON), then the wall adapter has been removed (both leds OFF). Note that the multimeter measures 5.13V in all cases.

The step-up module can be found with a search on ebay, looking for step-up regulator with variable voltage (mine is based on recent XL6009 chip). The XL6009 regulator is rated for Vin_min = 5V, but I tested that works with 3.5V. For best operative conditions, look for a step-up module that mounts an LM2577S-ADJ chip, that is rated for Vin_min = 3.5V. Note that you must trim the variable resistor to have 5V output. Please, connect a 1K resistor as load to the output when setting the Vout, ‘cause there is a capacitor that remains charged when you turn the trimmer decreasing the output voltage. After setting, remove the load resistor.

The switch element cannot be purchased on ebay (sorry) and you must build it by yourself. I started from the circuit proposed in the Microchip’s application note and just modified something. For the P-channel mosfet, I used a free sample received from NXP: the PMV48XP. This SOT23 mosfet is very small (look at the picture “The SWITCH”), but it’s really powerful. I used two 1N5819 Schottky diodes (not one) to reduce the voltage drop and increase the current. The circuit is very simple:

The Switch (click to enlarge)

And finally, look at the next picture. The circuit is connected to my Raspberry Pi board. In the animation you can see that the board doesn’t turn off when the wall adapter is disconnected. The time of back-up depends from the capacity of the cell that you use. Remember that the current drawn from the battery (when wall adaptor is disconnected) is the nominal current of the Raspberry Pi board multiplied for the efficiency of the step-up in converting from Vbat  to 5V.

Conenctin and disconnecting the wall adapter (click to enlarge and animate)

Connecting and disconnecting the wall adapter (click to enlarge and animate)

Test report
Test conditions: battery fully charged, Raspberry Pi running Raspbian Wheezy and connected to HDMI monitor and to USB interface for RF keyboard and mouse. No other applications running, just the desktop and the default services. I disconnected the wall adapter exactly at 17:17 .
Test results: the battery discharged from 4.2V to 3.7V (about 20% of residual charge) at 18:18, so in about 1 hour.

Please, note that a 3.7V cell must never be fully discharged. If the cell goes below 2.2V, it will probably not recharge anymore. If the cell is “protected”, probably has an electronic switch that disconnects the battery itself from the load when such limit is reached, but if it is a “pure” cell, you must avoid the undervoltage condition.

Questions and answers:

Email – 06/03/2016 – 15:26 from Max:

I am using the same TP4056 charger as you, just with a 240mah lipo battery (with built in protection circuit)
I want to do more or less that you are describing, but power outages are very rare where i live. will it potentially harm the battery that it will be kept fully charged all the time?

The charging IC “disconnects” or “floats” the battery at the end of the CC/CV cycle, so when 4.2V is reached and the current flowing into the battery is less than C/10, where C is the current programmed via the R_chrg resistor. If you use 240 mA battery, modify the standard R_chrg on your TP4056 charger circuit in order to set the charge current to about 120 mA (battery C/2).

I am still very new to selecting more advanced components, but will i be able to use an AO3401 mosfet (http://www.aosmd.com/pdfs/datasheet/AO3401.pdf) instead of your example?
I can see that the GATE voltage is rated at +-12v which is the same as the PMV48XP, but the AO3401 is rated at 30v/4A and i dont really know what other characteristics is important to selecting the right mosfet?

I looked at the AO3401 datasheet and it seems to be right for this use.

Also, this might seem a bit stupid, but i dont understand why you use 2 diodes. Is the reason that they both have a inner resistance and putting them in parallel basically halves this resistance? Could you just have selected another diode ? And since i am using a small 240mah battery should i still use two diodes? (i see that the AN1149 document mentions a lower voltage as a positive, so i am guessing that low drop is always good here)

You are right, I used two low-drop Schottky diodes to obtain a “very-low-drop” diode. If you have a “natural born” very-low-drop diode, you can use just one.

One button, two leds using single GPIO on RPi

Once again, a “superused” GPIO… This time, the RPi I/O is used for driving two leds (one blue, one red) and a pushbutton. The schematic is simple, look at the pic below:

tri-schAnd here is the prototype realized on perfboard:

tri-picNote: pictures are taken with leds off, red led on, blue led on.

There is also a new Python script named service2.py :

import RPi.GPIO as GPIO
import time
from subprocess import call

cnt = 0  # reset counter for pushbutton pressed
toggle = 0  # reset toggle flag
GPIO.setmode(GPIO.BCM)  # set GPIO mode
while True:  # main loop
    GPIO.setup(4, GPIO.OUT)  # GPIO.4 set as output
    GPIO.output(4, False)  # GPIO.4 output set at low level (red led ON)
    time.sleep(0.2)  # 200mS pause with red led ON
    if toggle != 0:  # if toggle flag set
        GPIO.output(4, True)  # GPIO.4 output set at high level (blue led ON)
        time.sleep(0.2)  # 200mS pause with blue led ON
    GPIO.setup(4, GPIO.IN, pull_up_down = GPIO.PUD_OFF)  # GPIO.4 set as input, no pull-ups (both leds OFF)
    for n in range(0,2):  # exec twice
        time.sleep(0.1)  # wait for 100 mS prior to read pushbutton status
        if GPIO.input(4):  # if GPIO.4 is high (button NOT pressed)
            if cnt >= 4 and cnt <= 6:  # if was pressed for 2-3 sec
                 toggle ^= 1  # invert toggle flag
                 if toggle == 0:  # if changed to 0
                     call("sudo killall x11vnc", shell=True)  # terminate x11vnc server
                 else:  # if changed to 1
                     call("sudo x11vnc", shell=True)  # start x11vnc server
             cnt = 0  # reset counter for pushbutton pressed
         else:  # if GPIO.4 is low (button pressed)
             cnt += 1  # increment counter for pushbutton pressed
     if cnt >= 10:  # if continuously pressed for 5 seconds (cnt increments 2 times in a second)
        GPIO.setup(4, GPIO.OUT)  # GPIO.4 set as output
        GPIO.output(4, False)  # GPIO.4 output set at low level (fix red led ON as signal for user)
        call("sudo poweroff", shell=True)  # terminate and shutdown
        break  
    if toggle != 0:  # if toggle flag set
        time.sleep(0.4)  # (blue blinked for 0.2 Sec) wait the remaining time for 1 Sec main cycle
    else:  
        time.sleep(0.6)  # (blue off) wait the remaining time for 1 Sec main cycle

How it works:

Normally, the red led is lighted for 200 mS, then the button is sampled for pressed state. If the button is pressed for a time between 2 and 3 seconds, then the variable toggle is inverted. When toggle is “1”, after the red led turns off, the blue one turns on for 200 mS. If the button is pressed again for 2-3 Sec, the variable toggle is inverted again and at next cycle the blue led will no more turn on. When the toggle variable changes, there are two actions performed by the script : if toggle is 0 (off) then a call to “killall x11vnc” is performed, while if is 1 (on) a call to “x11vnc” is done. This means that I can control the start or stop of x11vnc server with my pushbutton. If I press the button for a time over 5 seconds, there is a call to the “poweroff” and the board will turn off. Please, note that when the pushbutton is pressed the blue led can’t turn on, while the red one will be forced on (at low current, 1mA).

Here is a video of circuit and program running:

tri-film di robotop

Hope this will be useful for someone… 🙂

Double function GPIO on RPi

I’m using the Raspberry Pi board in some projects. Many of these needs to run 24/7, so the hardware has battery backup in case of power fail. Sometimes, the device controlled by RPi board has to be powered off for maintenance, so it’s also necessary to turn off the control board, but there’s no video, no keyboard, neither mouse attached. The operator must connect all of these to perform a clean shutdown. Ok, that’s unacceptable: I decided to add a blinking led to inform the operator that the board is running and a switch to manually perform the shutdown, without the need for keyboard, mouse and video.
There was a problem: I just had ONE single GPIO free, the GPIO.4 , so I decided to use it for both led driving and pushbutton input. The principle is very simple: change the port direction and use it alternatively for led and for pushbutton. Here is the schematic:

rpi-led-sw-schAnd this is the prototype circuit mounted for testing purposes:

rpi-led-sw-picThe 1K resistor limits the current from GPIO.4 to about 1.5mA (the red led lights well) and the 470 Ohm resistor limits the current from the pin in case of software error (it happens, sometime) that sets the GPIO.4 as output and its value as high (3.3v). In such case, even if you press the pushbutton switch, the GPIO.4 is loaded with max 7mA (3.3V / 470 Ohm) that is acceptable for the output. When you press the button, the led turns ON even if the GPIO is in input mode, but the current that flows in the led is smaller than in case of GPIO is output-low, being the resistor value 1K + 470 Ohm (approx 1mA will flow thru the led). Note that the resistor values are important : you can’t decrease significantly the value of 470 Ohm, ‘cause the current drawn from GPIO in case of “output high” will be out of GPIO current limits and you also can’t increase that value, ‘cause the partition with led and 1K resistor will supply a voltage out of specs when pressing the pushbutton while the port is in input mode. With actual values, the voltage at GPIO pin when in input and with switch closed is about 0.5V that is in range for being read as logical “0”. Voltage over 0.8V may create unstable “0” reads or can be interpreted as “1” (switch open). Similarly, you can’t increase the value of 1K, ‘cause the current that flows in the led (and its brightness) will proportionally decrease. So, the values proposed in the schematic are “well balanced”…

Now, we have a double function pin. Here is the listing of a Python script I realized to make all this principle working : it’s named “service.py”.

import RPi.GPIO as GPIO
import time
from subprocess import call

# reset counter for pushbutton pressed
cnt = 0
# set GPIO mode
GPIO.setmode(GPIO.BCM)
# main loop
while True:
	# GPIO.4 set as output
	GPIO.setup(4, GPIO.OUT)
	# GPIO.4 output set at low level (led ON)
	GPIO.output(4, False)
	# 200mS pause with led ON
	time.sleep(0.2)
	# GPIO.4 set as input with pull-up (led OFF)
	GPIO.setup(4, GPIO.IN, pull_up_down = GPIO.PUD_UP)
	# wait for 100 mS prior to read pushbutton status
	time.sleep(0.1)
	if GPIO.input(4):
		# if GPIO.4 is high (button NOT pressed)
		# reset counter for pushbutton pressed
		cnt = 0
	else:
		# if GPIO.4 is low (button pressed)
		# increment counter for pushbutton pressed
		cnt += 1
	# repeat pushbutton read after 100 mS (ensure isn't a spike)
	time.sleep(0.1)
	if GPIO.input(4):
		cnt = 0
	else:
		cnt += 1
	if cnt >= 10:
		# if continuously pressed for 5 seconds (cnt increments 2 times in a second)
		# GPIO.4 set as output
		GPIO.setup(4, GPIO.OUT)
		# GPIO.4 output set at low level (fix led ON as signal for user)
		GPIO.output(4, False)
		# terminate and shutdown
		call("sudo poweroff", shell=True)
		break  
	# if not terminated, wait the remaining time for 1 Sec main cycle
	time.sleep(0.6)

The main loop has 1 Sec total time : led turns ON for 200mS (so the GPIO is used as output and value is 0) then turns off when the port mode changes to input. After a delay of 100mS the pushbutton state is tested (twice) and a counter is incremented if the switch is closed; if the switch opens, the counter is reset to zero. When the counter reaches 10, so the button was continuously pressed for 5 seconds, the led is forced ON putting the GPIO in output mode with value 0. The shutdown command is then sent to the OS and the Raspberry turns off. At end of shutdown the led that was fixed ON will turn off, obviously.

Note: when you push the button, the led will turn ON ‘cause you connect the cathode to gnd via 1K + 470 Ohm resistence, but you still can see the 200mS blinks due to difference of current flowing in the led when the GPIO is in input state and in output state with value = low (gnd).

Hope this will be useful for someone. It was for me 🙂