Overview:

This is what this UPS must do:

  1. Communicate to the Pi the battery chemistry used and the charging status (Charging or Fault). This is a must for this application, where multiple chemistries are allowed.
  2. Provide power to the output ( the Pi power input) when external power is lost by drawing from the battery source.
  3. Let the Pi know that this has occurred, using a 2-pin I2C interface, so that it can do a proper shutdown at an appropriate time before the battery is exhausted.
  4. Allow the Raspberry Pi to monitor the state of the battery to decide when to shutdown its power. As a last resort the UPS should notify the Raspberry Pi that the battery is exhausted and that it is shutting off power.
  5. Accept a shutdown command from the Pi and handshake to confirm the shutdown command was received, and after shutdown is complete, switch the Pi off by disconnecting the power.
  6. Reconnect the power to the Pi, which causes the Pi to boot, when the external power returns.
  7. Maintain the battery in good condition near its maximum capacity.

New Stuff:

I was researching battery management ICs when I ran across the LTC4040. It is billed as a "2.5A Battery Backup Power Manager". The similarities between the LTC4040 and the LTC4041 (which I was using for a supercap UPS circuit -- see my other projects) were too much to ignore. I already had several working UPSs using a lithium battery -- why another one?

After spending a bit of time reading and understanding the data sheet I thought that the LTC4040 could add a lot of capability that was missing in the previous design:

  1. Multi-chemistry charger: capable of charging/maintaining both LiIon and LiFe batteries.
  2. Programmable charge termination voltage: four programmable termination voltages for each battery chemistry to maximize battery longevity.
  3. Synchronous buck charger for increased efficiency.
  4. A safety timer for the charger.
  5. A temperature sensor to prevent charging outside safe limits.
  6. A fault indicator for problem batteries.
  7. Automatic switchover from AC input to battery backup when AC power fails.
  8. Input current limiting to prevent overloading the AC adapter when charging.
  9. Potentially lower current drain from the battery in both normal mode and sleep mode.
  10. Lower component count -- the jury is out on this one. The LTC4040 replaces a $0.60 stand-alone Li battery charger and the Ti boost converter ($2.50). It also simplifies the input switch.
  11. Lower cost -- OK it's not. The PCB is the same size, and the LTC4040 is about $6, which is more than the cost of the two ICs that it replaces, but you're getting a lot more functionality. I don't know if it's worth it yet. [Edit 2019-03-03: Yeah...it's worth it. The ability to monitor charging and faults via the I2C interface is probably worth a couple extra dollars.]

The Current Schematics:

The schematic is not very pretty. That's because the connections of the PIC micro controller were decided by the efficiencies of the layout rather than niceties of the schematic page. There are now two versions -- a "Hat-like" version using a 14500 battery, and a standalone version using an 18650 battery.

Originally, I was going to use a 3 position DIP switch to program the battery chemistry and the charge termination voltage without the Raspberry Pi being aware of those parameters, since there were not enough pins on the PIC to monitor all of it. The problem with that approach is that the Raspberry Pi, and the PIC, can't know which battery chemistry is being used, and therefore it can't determine when to pull the plug and shutdown the system in order to prevent damage to the battery. I then considered, briefly, allowing the PIC to set the battery chemistry and charging parameters via software. The problem with using software to set the charger parameters is that it is potentially susceptible to being hacked and might cause a hazardous situation. When I found the PIC16F18323, with an additional 6 pins, I decided to allow the Raspberry Pi to monitor the charger options via the I2C interface. Since the Raspberry Pi is aware of the end-of-life of the two battery chemistries, it can make a more informed decision regarding when to shutdown the system prior to battery exhaustion. That's more work on my part, but probably a better solution in the long run. 

The good stuff:

Battery Chemistry Options

The UPS will operate with either LiFePO4 or LiIon batteries. Some people are saying that the LiFePO4 chemistry provides longer lifetime via more charge cycles. The user can select the battery chemistry and also a range of charger termination voltages, via the I2C interface, to extend the longevity of the backup battery. The lower the termination voltage, the longer the battery will last. Here's a snippet from the data sheet:

In the LiIon case, every 100mV decrease in termination voltage corresponds to potentially 1000 more charge cycles.

AC Adapter Current Limiting

The LTC4040 will reduce the charger current if the sum of the load current and charger current exceeds a programmed limit. This is to avoid overloading the AC adapter.

Indicators

I'm not a big fan of LED indicators, but they have their place. There is a [green] LED to indicate when the charger is active. There is also a [yellow or orange] LED to indicate a charger fault condition. (The LED indicators are only implemented in the Hat version since the 18650 unit will have the PCB mounted underneath the battery and LEDs will not be visible.) A charger fault can occur if the battery voltage will not increase above 2.75V after trickle charging it for 30 minutes. Temperatures above or below allowed limits will trigger another fault condition, but they are usually temporary. I have provided terminals for a NTC thermistor for sensing battery temperature.

Both CHRG and FAULT status will be available to the Raspberry Pi over the I2C interface.

Charger Safety

As mentioned previously, there is a provision to prevent charging outside of safe limits. There is also a safety timer that terminates charging after a predetermined time limit to prevent battery damage. 

AC Present Detection

The LTC4040 has a power fail comparator to detect when the input voltage is above/below a minimum level and take appropriate action. Unfortunately, the PIC controller can't rely on the 4040 power fail comparator because the 4040 is normally completely shutdown while the AC adapter is not providing power. Therefore the PIC uses a Schmidt Trigger input to detect when AC power is available (before the LTC4040 is activated) and then allows the LTC4040 to more accurately tell it when the AC power has failed.

Lower Current Operation

My prior UPS implementation used a kluge circuit to reduce the current drain on the battery from the PIC micro controller. Diode D1 allows the PIC to draw power from the AC input power when available, but then switches the PIC over to battery power when the AC power goes away. This method prevents the PIC from discharging the battery during normal operation and increases the time periods between battery recharges. The LTC4040 only draws 40µA typically from the battery when AC is present and it is not charging the battery.

When there is not AC power available the current drain from the battery should be just a few micro-Amperes -- not much more than the self-discharge rate of the battery.

Since the power fail indicator is provided by the LTC4040 it frees one pin to measure the battery voltage. The PIC ADC range is 0V - 4.096V, which is coincidentally the same as the maximum charge termination voltage for a LiIon battery. This arrangement is more straightforward than measuring the ratio of PIC supply voltage to its internal reference voltage.

The Bad Stuff

 The LTC4040 is a 24-pin leadless QFN package with an exposed pad. This is not friendly to hobbyists. You have to have appropriate tools and knowledge to get the desired result. The input FET switch is also a  leadless PowerPak package, but I have not had any difficulties with obtaining a good solder job.

The LTC4040 is not cheap.