In principle, the ESP32 can be powered directly from a LiFePO4 cell, as the cell voltage range perfectly matches the ESP32's recommended operating conditions (2.3V - 3.6V). But the customer who is driving this project requires regulated 3.3V for the ESP32 and the application-specific external circuitry he is connecting.
This means that instead of a simple load switch to prevent over-discharge of the battery, we need to have a buck-boost converter because the battery voltage can be both higher (up to 3.6V) or lower (down to 2.0V or so) than the 3.3V output voltage.
To provide true UPS functionality, I have always designed my LiFePO4wered products to have the battery permanently in the power path, instead of switching from external power to battery when the external power fails. Plenty of user complaints about system resets in other products designed with such a switching topology prove this is the right way to go for maximum reliability (and to be a proper UPS). Using LiFePO4 makes it possible to do this without affecting battery lifetime, due to the low float voltage. In my topology, no switching takes place. External power always passes the battery and when external power fails, the battery is right there to pick up the slack. Think of it as a giant decoupling capacitor.
The downside of this topology is that the battery (or a large cap) needs to be present for the power system to work. This is of course not a big problem since this is assumed for a product under the LiFePO4wered brand name. :) Also, predictable shutdowns go a long way in creating reliable embedded/IoT systems anyway. True, an ESP32 isn't a Linux system for which a clean system shutdown is much more critical to prevent corruption. But even an ESP32 or similar deeply embedded device can benefit from knowing when the power fails and having the opportunity to take some action. Think being able to report the power failure to a cloud system, or finishing a write to flash or an SD card. Or continuing normal operation for quite a long time on battery power only, and being completely unaffected by crappy input power.
So I'm sticking to the same battery-in-the-power-path topology for this project. Initially I had assumed I was going to use the tried and true CN3801 LiFePO4 charging chip used in the #LiFePO4wered/Solar1 and #LiFePO4wered/Pi+ for this project as well. After all, it has been working very well in those products. But there is another option to consider this time.
I have been working on a proprietary system for a customer that implements a microcontroller based MPPT charger. The customer has graciously allowed me to apply some of the IP to other products, as long as they don't compete in his market.
Now his system is a bit different because it uses a boost topology to charge the battery from a single solar cell with ~0.5V output voltage, while in this project, I'd need to use a buck topology to charge the battery from 5-28V input. But some of the IP could still be applied.
There's a good list of advantages in taking this approach:
- Unlike with the CN3801, where the MPP voltage for a particular solar panel needs to be configured with a resistor, this would provide automatic MPP tracking using a perturb and observe approach. Just connect any power source, even a weak one like a solar panel, and it will work with maximum efficiency.
- Set points that are software configurable over the I2C bus for things such as battery charge and discharge voltage thresholds, maximum charge current, temperature thresholds, ...
- Battery, power system and temperature measurements that are readable over the I2C bus for smart system management and remote monitoring.
- Since the system is continuously measuring incoming and outgoing power, it may be possible to offer a coulomb counter based battery gauge. To be developed, don't hold your breath. :)
- Since charge and discharge thresholds would be settable, this would make it possible to also support Lithium Titanate (LTO) chemistry batteries in addition to LiFePO4! I've been looking at providing this option for a while now. If you're not familiar with them, LTO batteries are like LiFePO4 on steroids and unmatched when it comes to battery life (>10K cycles) and ruggedness (charge/discharge at any outdoor temperature).
- It would be possible to monitor both on-board temperature and, if available, battery thermistor temperature. Use the thermistor to control charging if it is available, but use on-board as a fallback if there is no battery thermistor.
- Battery heater control, and the power applied to the heater could automatically match incoming power so it's MPP tracked as well.
- Now there's a micro, we can have a smart low power system manager and can easily implement things like low power sleep modes with wake timer or wake on certain events, and have software control over whether the 3.3V power or the Ethernet PHY should be on or not. All of this controllable over the I2C bus from either the ESP32 or another connected micro, which means no lost GPIO pins.
- Since we lose some ESP32 GPIO due to the PSRAM and we already didn't have that many because of what is in use by the Ethernet PHY, we may be able to use the micro as a GPIO expander.
- My own IP versus relying on a single-source Chinese vendor. In these times where chaos rules, that might be prudent.
Of course, there are some downsides as well:
- Likely more costly.
- New / untried technology. We're much more likely to run into some issues during development and need a respin.
- Will take significantly longer to develop the hardware compared to copying the CN3801 circuitry I already have.
- A good chunk of firmware development is needed.
Since I like to push my technology forward instead of being stagnant and just repackaging the same stuff, I am leaning heavily toward going the microcontroller charger route. :)
Any thoughts, comments? Anything you need that would become possible with a separate system/power manager micro?