The Pi Zero (and Zero W) are quite tolerant in respect to their power requirements. They can even be run from a LiFePO4 battery that has a voltage range of 3.6 to 2.5V. LiPo batteries are better-suited as their voltage ranges from 4.2 down to about 3V. When running the boards from the blank cell (it should have protection circuitry!), they last even longer because fewer losses occur since there is no boost converter in the system. In fact, the 5V is only needed for the USB host, although many devices are supposed to work from voltages down to 3V.
Unfortunately, these single board computers lack power management and don’t have shutdown buttons and there are not that many simple and cost-effective solutions for these problems. https://www.tindie.com/products/xorbit/lifepo4weredpi/ is one nice example, but unfortunately not fully open source.
My idea was to combine a MAX17043 LiPo fuel gauge with a pushbutton and a LiPo charging circuit to create a battery and safe shutdown management add-on for the Pi Zero.
The little board occupies only the first 10 pins and uses only GPIO4 and SDA + SCL. Design files for the tiny custom TP4056 charger board can be downloaded as a .zip archive:
The Python script the make the thing work is attached below. Add it to rc.local to execute on startup.
#!/usr/bin/python #Python Script for MAX17043 fuel gauge and safe shutdown button #in order to execute on startup add the following line to /etc/rc.local #(sleep 10;python /home/pi/fuelgauge.py) & #assuming that fuelgauge.py is in /home/pi #sleep 10 is probably not necessary import RPi.GPIO as GPIO import smbus import time import os #threshold in % below which the pi gets shut down threshold=15.0 buttonPin=4 # I2C-Adddress of MAX17043 address = 0x36 #registers VCELL_REGISTER=0x02 SOC_REGISTER=0x04 MODE_REGISTER=0x06 VERSION_REGISTER=0x08 CONFIG_REGISTER=0x0C COMMAND_REGISTER=0xFE # open the bus by creating an instance MAX17043 = smbus.SMBus(1) #set up GPIO for shutdown button GPIO.setmode(GPIO.BCM) #Using GPIO nr 4 GPIO.setup(buttonPin,GPIO.IN,pull_up_down=GPIO.PUD_UP) def reset(): MAX17043.write_byte_data(address, COMMAND_REGISTER, 0x00) MAX17043.write_byte_data(address, COMMAND_REGISTER, 0x04) def quickStart(): MAX17043.write_byte_data(address, MODE_REGISTER, 0x40) MAX17043.write_byte_data(address, MODE_REGISTER, 0x00) #get state of charge def getSOC(): # Konfiguration des MAX17043 MSB= MAX17043.read_byte_data(address, SOC_REGISTER) LSB = MAX17043.read_byte_data(address, SOC_REGISTER) percentage= MSB+ LSB/256.0 #print percentage if percentage < threshold: os.system("sudo shutdown -h now") #Arduino map function for convenience def arduino_map(x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min #setup reset() quickStart() # Loop while True: getSOC() time.sleep(1.5) #shutdown if button is pressed and held if (GPIO.input(buttonPin)==0): os.system("sudo shutdown -h now") if __name__ == "__main__": main()