Single SuperCapacitor UPS for Raspberry Pi

A last gasp Uninterruptible Power Supply for any Raspberry Pi computer.

Similar projects worth following
The circuit provides about 30 seconds of backup power (at up to 2.5A) to a Raspberry Pi computer when the power fails -- using a single supercapacitor. This allows the Pi to shutdown gracefully without damage to the SD card. Power is automagically restored when it becomes available again.

[Edit 2019-11-15: This is becoming the never-ending project. I have been prodded by several people that want to extend the design to work with a stack of supercapacitors. I had no need for that, so I did not put any effort to insure the functionality of a stack, other than allowing for it by programming some component values on the PCB. But since the capability is there it should function correctly. I'll be trying to implement the dual supercapacitor functionality over the next few days/weeks.]

I have 3 Raspberry Pi computers running 24/7 in headless mode scattered around my residence. One of them is an old Pi1B that manages my heating system and monitors my water well. I consider it a mission critical piece of hardware. Invariably, when I leave for a trip in the winter the power will fail, so I need a means to automagically and gracefully shutdown all of the headless Pi’s.

I built a working UPS using a stack of two 400F supercapacitors about three years ago: It was a relatively simple solution that did not make very efficient use of the supercaps, but now with more power hungry versions of the Raspberry Pi I decided it was time to build a new one with higher load capacity (and re-purpose the supercaps).

The energy that you can get from a capacitor is simply

where V1 is the initial voltage across the capacitor and V2 is the final voltage across the capacitor. The output energy is in Joules (Watt-seconds). It is evident from this equation that you can get much more energy out of the capacitor if you can get a lot of voltage across it and take more voltage from it. The problem is that affordable supercaps don’t exist with voltage ratings above 3V (typically 2.7VDC).

So just stack them like batteries then. What’s the big deal? When you stack two identical capacitors in series you get half the capacitance value. This is actually not as bad as it sounds since your energy capacity goes up with the square of the applied voltage. So if we had a stack of 4 supercaps that we could put 10V across would produce 4X more energy than a single supercap with 2.5V across it. Or conversely, you could use smaller supercaps to get the same energy output. The basic problem with this thinking is that the prices of supercaps don’t scale linearly with size — a 400F is $12 while a 100F is $8-$12, so 4 of them will cost a lot more. Another issue with stacked supercaps is one of balancing. The capacitor voltages need to be kept in balance to avoid exceeding the rated voltage. This requires extra circuitry, cost and complexity in the charging circuitry.

My heating system only needs backup power long enough to shutdown the system — a last gasp.

The current design:

Analog Devices recently (as of 2018-10-1) released the LTC4041, a supercapacitor backup IC. It takes care of the charging of the supercapacitor and the balancing, if there are two of them. It also manages the switchover from powering the load from an AC source to powering the load from the supercapacitor backup. What it doesn't manage is the timers required for the interval when the Raspberry Pi is committed to shutting down and the power-off interval which resets the Raspberry Pi and allows it to reboot when AC power becomes available again. This is the required functionality of the design:

  1. Provide 5V±0.25V power to the RPi @ 500mA to 2A max.
  2. If the power fails, continue to provide 5V from a single (or dual) SuperCap charged to 2.7V (or 5V). And indicate the power failure to the RPi.
  3. Backup power must be provided for a minimum of 35 seconds. The current load will be high until the RPi shuts down into a low current state that only draws about 50-80mA. It takes about 10-20 seconds to enter the shutdown state.
  4. The RPi will assert a SHUTDN input to indicate to the UPS that it has committed to the shutdown sequence. The UPS must provide backup power for 15-20 seconds after the SHUTDN...
Read more »


A crude Bill of Materials in spreadsheet form for the latest LTC4041 version. Some sources are included.

ms-excel - 10.50 kB - 12/15/2019 at 16:43


Python code to manage the UPS from the Raspberry Pi.

x-python-script - 6.87 kB - 12/15/2019 at 16:31


A compressed folder containing all of the gerber files to create the PCB for the latest LTC4041 version of the UPS. You can upload this file directly to OSH Park and then order boards.

Zip Archive - 48.21 kB - 12/15/2019 at 16:29


MPLABX project containing the assembler code and hex code for the PIC10F322.

Zip Archive - 38.61 kB - 11/20/2019 at 02:28



Hex file used to program the PIC10F202 ┬ÁP.

hex - 356.00 bytes - 01/19/2019 at 00:26


View all 7 files

  • Fifth Time is the Charm?

    Bud Bennett12/14/2019 at 23:12 0 comments

    I populated one of the three PCBs received from OSH Park a couple of days ago. It is configured for a single supercap. I had to remove the LTC4041, PIC, and M1 from an LG4 PCB to avoid having to buy/reprogram a component for the new PCB. There was a problem with a trace on the LG5 PCB and I had to add a 30AWG wire to correct it. Final board looks like this:

    I've contacted OSH Park about the problem...they refunded the order. But with my ugly fix the board is working as expected. I have tested the UPS with three versions of the Raspberry Pi: RPiZW, RPi2B and RPi1B. The same code works well for all of the tested Raspberry Pi variants. The new code allows the final SCAP voltage to drop to 2.3V (for a single supercap). I found that the SCAP voltage at the end of the shutdown sequence was within a few tens of mV from 2.3V. I left the target SCAP voltage with 2 supercaps at 2.4V since the rate of change is a lot higher when using two smaller supercaps -- a bit of margin to error.

    In any case, the UPS is working better in all respects and I'm ready to call it a day and complete this project once again.

  • Raspberry Tests with new python code

    Bud Bennett12/11/2019 at 05:43 0 comments

    The updated LG5 boards just arrived from OSH Park today, so all of these results, such as they are, were obtained with a modified LG4 board. 

    I decided to update the python code that monitors the status of the ups and decides when to shutdown the Pi. I took current load data on alll of the Raspberry Pi units that aren’t currently dedicated: RPi1B, RPi2B, RPi3B, RPiZW. The single-core units, RPi1B and RPiZW, were measured at idle, 100%, and shutdown. The 2B and 3B units were measured at idle, 25%, 50%, 75%, 100%, and shutdown. This is the data that I obtained on the units that I measured. 

    All of the RPi models were connected to HDMI, a powered USB expander for the keyboard and mouse, and had a 16GB thumb drive connected to the USB on the RPi (except the RPiZW). The other columns of the spreadsheet calculate the minimum capacitance values required to support the model at max current with dual or single supercapacitors, and the parameters for counting out the period to shutdown as a function of cpu loading.

    The new code now takes into account the number and value of supercaps, the Raspberry Pi model, and the loading of the cpu on a dynamic basis in order to determine when to begin the shutdown procedure. The code relies on psutil to calculate the percentage of cpu activity on a second-by-second basis and adjust the time to shutdown accordingly. Since the code is written in python3, the psutil module is installed by:

    sudo apt-get update
    sudo apt-get install python3-psutil [Edit 2019-12-14: made a few changes to improve robustness. Improved the calculation to determine time to recharge the supercap if PWRGOOD goes high before a shutdown event. Changed the calculation for a single supercapacitor to allow voltage drop to 2.3V, as long as the current draw is less than 1A. Latest code can be downloaded from the files section of this project.]

    #!/usr/bin/env python
    This program monitors the status of the PWRGOOD signal from the UPS circuit.
    PWRGOOD is normally high. If it goes low then the input power has failed.
    This program senses when PWRGOOD falls and then samples it once/second. An
    accumulator counts up by 1+(cpu_pc * (imax/idle - 1)) if power is bad and
    counts down by icharge/idle if power is good. This accounts for the difference in
    supercap charge current vs. load current.
    If the accumulator exceeds count_max then it signals the UPS to disconnect the
    power by asserting SHUTDOWN. This will still cause a shutdown condition even when
    the power is cycling on and off. After it commits the hardware to shutdown it also
    sends a shutdown command to the Linux system. The UPS will hold power up for 20 seconds
    after it receives the SHUTDOWN signal, which allows the Pi to enter a shutdown state
    prior to power removal.
    import RPi.GPIO as GPIO
    import time
    import logging
    import logging.handlers
    import psutil
    from math import sqrt
    import subprocess, sys
    #--logger definitions
    logger = logging.getLogger(__name__) 
    logger.setLevel(logging.INFO)  # Could be e.g. "TRACE", "ERROR", "" or "WARNING"
    handler = logging.handlers.RotatingFileHandler("/var/log/bud_logs/ups_mon.log", maxBytes=10000, backupCount=4) # save 4 logs
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
    class MyLogger():
        A class that can be used to capture stdout and sterr to put it in the log
        def __init__(self, level, logger):
                '''Needs a logger and a logger level.'''
                self.logger = logger
                self.level = level
        def write(self, message):
            # Only log if there is a message (not just a new line)
            if message.rstrip() != "":
                    self.logger.log(self.level, message.rstrip())
        def flush(self):
            pass  # do nothing -- just to handle the attribute for now
    def powerfail_detect(count_max, idle, imax, ichrg, cap_num, cap_value):
        # if the count exceeds 20 the system will shutdown.
        count = 0
        Vsys = 5.0
        if cap_num == 2:
            cap = cap_value/cap_num
            Vmax = 4.5
    Read more »

  • You Get What You Pay For

    Bud Bennett12/04/2019 at 23:39 0 comments

    After the failure of the eBay 100F supercaps, I plunked down a few $$ and ordered some from Digikey:

    100F +30/-10% manufactured by AVX. 8mΩ ESR. $8/each.

    50F +30/-10% manufactured by Illinois Capacitor. 15mΩ ESR. $4/each.

    25F +30/-10% manufactured by Eaton. 27mΩ ESR. $4.35/each.

    Executive summary: they all performed as expected.

    The discharge recovery of the 100F supercap was the worst:

    The snap-back was 25mV after more than nearly 7 minutes of rest (and still rising). 

    The 50F supercaps were stellar -- less than 10mV snap back (but I think they have higher leakage current):

    The 25F supercaps were very good as well:

    All of these supercaps would work well in the UPS. Real world testing next.

  • SuperCapacitor Quality Issues

    Bud Bennett11/25/2019 at 23:33 0 comments

    I have purchased three sets of supercapacitors over the last few years. The first two pairs of Supercaps were 350F and 400F units that I bought directly from Digikey. I believe that they were priced somewhere around $12 per supercap (here's a link to the Digikey webpage for the 400F unit). The last two pair of 100F supercaps I bought from eBay, for about $3 per pair. I thought that the eBay stuff was a great deal...until today.

    I was attempting to test the 100F supercaps in a dual supercap UPS configuration and write some new code for the UPS in general. I was getting squirrelly results. The UPS would shutdown properly, but after a few minutes it would attempt to turn on the booster, which would cause the Raspberry Pi to begin its boot sequence, but there wasn't enough juice remaining in the supercaps and the output voltage collapsed after a few seconds. This process would repeat every few minutes for what seemed like hours.

    Bad Supercaps

    I noticed that there was a significant difference between the two supercap voltages: 1.5V and 1.1V. At the end of each false startup attempt the larger voltage would decrease by less than 100mV, but the smaller voltage dropped to about 0.8V but then climbed slowly back until the total of the stack reached 2.65V and the LTC4041 would fire up the booster again. This behavior (behaviour?) was not supposed to happen.

    I extracted the two 100F supercaps from the breadboard and charged each of them with a power supply to 2.25V with a current limit of 0.5A. I let the charge current drop below 10mA and then I discharged each capacitor with a 10Ω resistor to 1.5V. Here are the results SCAPB (the bad one):

    SCAPB dropped to 1.5V in about 2 minutes. Note the large step at the beginning of the discharge and recovery cycles. The voltage eventually recovered past 2.0V after a 20 minute wait.

    SCAPA faired better:

    SCAPA has a much smaller step at the beginning of the discharge, takes longer to reach 1.5V, and recovers by only 165mV (it was still increasing after 22 minutes). But even this performance is pretty bad -- two supercaps with this behavior would still creep up enough to cause the LTC4041 to enable the booster when it should not.

    So I dug one of the 400F supercaps out of a junk box and repeated the experiment -- this time using a 2Ω load for discharge:

    This is what the behavior should look like. There is a sharp drop when the >1A load is applied -- attributed to the ESR. There is another sharp rise when the load is removed -- ESR again. But there is no significant ballooning of the voltage afterward. 

    I'm tempted to spend a few $$ to obtain some legitimate supercaps in lower Farads to see if there is a difference between Digikey and eBay. I need a 100F supercap ( a real one...not from eBay) to power my heating system. I also would like to see how a couple of 20F supercapacitors from Vishay (Digikey) compare to the eBay stuff. Stay tuned.

  • Unintended Consequences

    Bud Bennett11/19/2019 at 17:25 0 comments

    I did not understand all of the implications of changing the PIC code to monitor the SCAP voltage. I was putting final touches on the new design when I started thinking about how it would work if the input power was applied while the UPS was in the delay period after the Raspberry Pi issued a SHUTDN command to the UPS. Since the PIC is now monitoring the SCAP voltage it will not shutdown the LTC4041 charger or booster if the input power is reapplied -- the LTC4041 will begin charging the supercapacitor and the SCAP voltage won't drop below the cutoff threshold. Therefore the RPi will just hang in a shutdown state as long as power is applied.

    My solution was to add M3 to force the LTC4041 into a powerfail condition after the RPi asserts the SHUTDN input. This will prevent the supercap from charging and allow the UPS to complete its booster/discharge cycle before removing power to the RPi.

    It is not a perfect solution. It might be subject to noise, but I'm hoping that the deglitching in the PIC will eliminate false hits. If M3 gets a short noise pulse it will cycle the UPS to provide power for a short time -- the RPi should ride through that without issues.

    The addition of M3 to the PCB layout was easier than I expected.

    Unfortunately, I will now get two PCBs from Osh Park...

    More Consequences:

    The addition of M3 only works if the RPi keeps the SHUTDN input high during and after its shutdown or poweroff. There are methods to force this in software, but I not a trusting guy when it comes to system software not changing over long periods. 

    I came up with a solution in firmware (it's not software, is it?) Since the gate of M3 is connected to the PIC RA0 pin I could change the pin to be an output and force VDD, 5V, on the gate of M3 after the PIC had committed to shutdown. The 1k series resistance, R14, would prevent the RPi from changing the voltage at RA0. It only takes two lines of assembler code:

    bcf    TRISA, 0      ; make RA0 an output
    bsf    PORTA, 0    ; latch RA0 high to keep LTC4041 in powerfail mode.

    This is much simpler, and more robust over time, than messing with the GPIO settings during/after shutdown/poweroff. I will update the code in the files section. If it doesn't work for some reason I'll edit this log with an explanation.

    Note: this might require a change to the values of R13 and R14 to prevent a latchup condition in the RPi when current is forced into the GPIO pin.

    Breadboard Learning[2018-11-20]:

    I decided that it might be instructive to take my only unused LG4 module and add the new components to see if there was anything else I might have missed. I had some TO92 2N7000 FETs in a box somewhere that could be used. I programmed a PIC10F322 SOT-23-6 package to replace the PIC10F202. I did not add C11, partly to see how good the noise immunity was and partly because it was difficult to add to the tenuous connection already tied to the PIC's AN2 input.

    The first thing I did was reconfigure the UPS for two 100F supercaps and test for functionality. The SCAP voltage climbed slowly to 4.55V and stayed there. When I removed the input power the output voltage dropped from 5.1V to 4.84V, with a pretty light load of only 22Ω. The voltages on the supercaps was within 20mV during charging, so the balancing seems to work. 

    I then added all of the new components and applied 5.2V to the input, but this time I did not allow it to charge SCAP to 4.55V -- only to about 3V to keep the discharge time short with a 22Ω load. When I removed the input power the output again dropped to 4.84V and remained at that potential. The SCAP voltage dropped to 2.45V when the booster was disabled and the output voltage dropped to zero. I noticed that the SCAP voltage recovered to 2.55V after the load was removed, but the LTC4041 did not restart the booster after the 7 second disable period ended. 

    I performed several tests to see if there were...

    Read more »

  • PIC Code for 2 Supercapacitor Stac

    Bud Bennett11/18/2019 at 03:04 0 comments

    It took a while to get this done. Apple recently updated its OS to 10.15 - Catalina - and that threw a monkey wrench into the works. Microchip’s MPLABX software is 32-bit software that Apple had declared “persona non grata”.  It doesn’t work on my iMac anymore. I had to install the MPLABX software on my Parallels incantation of Windoze 10, which went smoothly, but even afterward MPLABX refused to work with the old files since they did not conform to Windoze path naming conventions. I was forced to move the Microchip design files onto the Parallels partition in order for the software to cease its complaints. 

    Enough of that. I managed to get the new code for the PIC10F322 working in spite of the Microchip software’s limitations. The changes from the PIC10F202 are significant. Here’s the flowchart for the 322:

    Most of this is the same as the PIC10F202 program. The RA0 input is the shutdown command from the Raspberry Pi. The code requires it to be asserted for 5 continuous samples, 10ms apart, before committing to a shutdown after a 20 second delay. The only addition is to monitor the voltage on the supercapacitor stack and prevent shutdown of the LTC4041 until the voltage at SCAP has decreased below 2.5V. Even so, the code expanded dramatically. I’m kind paranoid about stuff not working in noisy environments, so I built in a few safeguards. All of the measurements are averaged via an 8-sample rolling average. This creates a bit of delay, but also reduces any interference or noise by a factor of nearly 3-fold. The MEASURE FSCAP block contains a bit of code:

    The PIC10F322 has an 8-bit ADC, but it is referenced to VDD. It has an internal voltage reference, but the ADC can only use it as a in input. Therefore, in order to get rid of the VDD sensitivity, the ADC must take two measurements: one of the internal reference voltage wrt VDD, and another of the desired input voltage wrt VDD. The first measurement must be divided into the second to eliminate VDD.'s difficult to divide without floating point arithmetic, so I had to be a bit creative. Here's the math:

    X  = Vref/VDD*255

    Y = Vin/VDD*255

    256* Y/X = Vin/Vref * 256

    I figured out that the result of the division had to be multiplied by 2^8 (256) in order to maintain the fixed point arithmetic of the division. So a ratio of 1 is equal to 255. Any result above 255 is more than unity and below 255 is less than unity. I found a PIC routine on the internet here that accomplishes this nicely. I used it almost word for word.

    I also found that I needed to divide the result by a factor of 4 in order to keep it within an 8-bit range. The result of the division creates a 2-byte result, if the ratio is larger than unity. Dividing by 4 keeps it within 8-bits over the expected range. To create a threshold for high or low input value I added a constant to the divider result and checked for the overflow in the carry bit.

    I programmed an 8-pin DIP version of the PIC10F322 and tested it in on the bench. The first item was the 20 second delay prior to shutdown:

    Close enough. The remaining tests involved determining the accuracy of the VSCAP measurement vs. VDD:

    VDD          AN2

    4.60V     2.442V

    5.00V     2.442V

    5.40V     2. 447V

    That's pretty good! Better than expectations, considering the resolution of the 8-bit ADC is about 20mV.

    The last test was to determine what the latency in detecting the SCAP voltage falling through the threshold, given all of the mathematical processing involved:

    It's not bad -- less than 10ms to detect that SCAP is falling below the threshold. The trace above shows the RA1 output responding to a falling voltage on AN2. The voltage dropped 100mV, from 2. 525V to 2.425V. 

    It appears the PIC code is good enough to prove the concept. I'll be ordering new PCBs from OSH Park tomorrow. The PIC code is posted in the files section of this project....

    Read more »

  • Modifications for a Stack of 2 Supercapacitors

    Bud Bennett11/15/2019 at 21:40 0 comments

    I've recently been working with Xenon462, who wants to use this design with a stack of 2 supercapacitors. It got me thinking about how to overcome the problem of insuring that the voltage on SCAP is below 2.5V before shutting down the LTC4041 by yanking on the BSTEN_ and CHGEN_ pins. I came up with this possible solution:

    The changes to the previous design (the UPS4041-LG4) are the substitution of the PIC10F202 with a PIC10F322 and the addition of R18 and M2. The PIC10F322 has an internal 8-bit ADC that is assigned to RA2/AN2 to monitor the voltage at SCAP. R18 and M2 switch the SCAP voltage to the PIC to prevent unwanted current drain from the supercapacitor stack when there is no power applied.

    The PIC code will be modified so that the RA1 output won't be asserted until the shutdown period has expired and the voltage at RA2 is below 2.5V. This will insure that the LTC4041 wont restart the booster when the voltage at BSTEN_ and CHGEN_ fall below their 1.4V threshold, unless there is input power present.

    [Edit 2019-11-17: Added C11 as insurance.]

    A side benefit to this design is that it will revert back to the UPS4041-LG4 design by depopulating R18 and M2, and substituting the PIC10F202 as U2 (it is pin-compatible.)

    The changes to the PCB were straightforward and increased the size by about 0.075 inch in one dimension.

    I'll be ordering new PCBs after completing the new PIC code.

  • Completed.

    Bud Bennett08/22/2019 at 20:47 1 comment

    No Drama. I installed the latest UPS version into my Heating System/Well Monitor enclosure. I was pretty confident that I would work as designed so the only testing that I employed was to disconnect the wall adapter and then reconnected after a couple of seconds. The system didn't show any signs of distress and the log file registered the event:

    2019-07-28 12:48:05,181 INFO     Enabled
    2019-07-28 13:17:12,174 INFO     Power has failed
    2019-07-28 13:17:15,181 INFO     Power is good
    2019-07-28 13:17:16,185 INFO     Returning to normal status
    2019-08-15 23:42:13,903 INFO     Power has failed
    2019-08-15 23:42:14,909 INFO     Power is good
    2019-08-15 23:42:14,912 INFO     Returning to normal status
    2019-08-16 09:39:35,642 INFO     Power has failed
    2019-08-16 09:39:44,661 INFO     powerfail iminent...shutting down the Pi!
    2019-08-16 09:40:47,147 INFO     Enabled

    Since I installed it, on 2019-07-28, there have been two power loss events recorded in the log. One event was only a second in duration so the UPS did not have to shut down the RPi (but my hot tub and range needed some service.) The second outage was long enough to cause a shutdown, but it performed as designed. 

    At this point I'm marking this project as completed.

  • Testing With Raspberry Pi as Load

    Bud Bennett01/10/2019 at 22:55 0 comments

    It took longer than expected to get results from using Raspberry Pi 2 and ZeroW. I first pugged in the RPi2, let the supercap charge and then pulled the wall wart. The red power light on the RPi2 began to flash hysterically and the dreaded lightning bolt appeared on the display. Something was wrong with the voltage delivered to the Pi. I measured 4.81V between the OUT+ and OUT- terminals on the UPS, but the PI was getting around 4.7V. It was that damn pink micro-USB cable that I got from the dollar store (for a dollar!). The power leads on that cable were pretty small -- 30 or 32 AWG. I did not want to cut into any of my other micro-USB cables, so I ordered a set of six micro-USB cables, 12 inches long, for $7 from Amazon. They arrived today.

    I cut the USB type-A connector off the end of the cable and trimmed off the shielding and the unnecessary data wires. The power wires did look beefier. Substituting the new black power cable for the cheap(er) pink cable fixed the problem. I got a flash from the RPi2's red power LED when the AC adapter was disconnected, but the LED stayed on after that, and no lightning bolt appeared on the screen. I the ran the RPi2 with all 4 cores at 100% without issue. The 100F supercap voltage, after  going through 15 seconds of waiting and then 20 seconds of shutting down, was 2.3V -- very acceptable. 

    I also tested the UPS with the Raspberry Pi ZeroW. The current drain is quite a bit lower -- the UPS can supply power to the ZeroW for 35 seconds (using a 100F supercap) before having to enter the shutdown sequence. I tried all of my various AC adapters to see if the dreaded relaxation oscillation would return, but the UPS reliably applied power and dutifully shutdown without incident, independent of the AC adapter.

    I'm very close to the end of this project. The only task remaining is to swap the current UPS for this new UPS in my heating system controller. Since it is the middle of winter, and I'm a bit risk averse, that task will have to wait until warmer weather. 

    OLD vs. NEW:

    Just for grins and giggles I took a photo of the first version of the UPS next to the latest version.

    Some items of note:

    • The first version did provide 2.5A from a single supercap charged to 2.7V. The latest version can't do that -- it requires a stack of 2 supercaps to output 2.5A (per spec).
    • There is no trim pot on the new version -- a savings of around $1 (and board space).
    • The new version can charge the supercap much faster without heating the PCB too much since it uses a switched-mode charger. The old version used a linear charger with foldback current limit.
    • Input power jack. Old -- barrel jack. New -- micro USB.
    • The new version is less susceptible to noise between the Raspberry Pi and UPS. The PIC SHUTDN input noise rejection seems to be working.
    • The new version uses a synchronous switcher for both charging and booster -- lower power dissipation in both cases.
    • The old version required nearly 4 hours to populate the PCB. I can populate the new board in less than 1 hour.

  • PIC Code

    Bud Bennett01/06/2019 at 14:59 0 comments

    The assembler code for the PIC10F202 is below. I will also place the hex file for programming it in the files section of this project. The main body is only 21 lines of code. The comments should clearly document what is going on, but here's an overview:

    1. Setup I/O and watchdog timer.
    2. Sample SHUTDN pin every 10ms.
    3. SHUTDN must be high for 5 consecutive samples to be considered "HIGH". This is a noise filter.
    4. If SHUTDN is high, then delay for 20 seconds and set the GP1 high for 750µs, which disables the LTC4041.
    5. Loop forever until power is cut by the LTC4041.
    ; WARNING!!! Don't erase this part before programming. It will erase the
    ; calibration value stored in 0x01ff.
    ; PIC10F202 Configuration Bit Settings
    ; Assembly source line config statements
    #include ""
    ; CONFIG
    ; __config 0xFFFB
     ; General Notes:
     ; Internal oscillator is 4MHz (1MHz system clock). No external
     ; oscillator needed. 
     ; Watchdog timer is set for 18ms x 16 = 288ms.
     ; Only 2 stack registers. Can't call more than 1 nested subroutine.
     ; Pin Assignments:
     ;  1 - GP0: SHUTDN input
     ;  2 - VSS
     ;  3 - GP1: Shutdown output to the base of Q1
     ;  4 - GP2: unused. Set as output.
     ;  5 - VDD
     ;  6 - MCLR_, GP3: unused. tied to VDD in circuit.
    ;***** Define addresses of the General Purpose Registers ****
    ; 24 general purpose registers available starting at 0x08
    COUNT1    equ 0x08    ;First counter for delay loops
    COUNT2    equ 0x09    ;Second counter for delay loops
    COUNT3    equ 0x0a    ;Third counter for delay loops
    SCRATCH    equ 0x0b    ;Scratchpad variable for everthing else.
        org    0x0000          ; processor reset vector
        movwf    OSCCAL        ; load the calibration value into the OSCCAL reg.
    ;**** Disable unused peripherals ****
        movlw    b'11001100' ; disable Wake on Change, disable Weak pullups, 
        OPTION                ; internal clk -> Timer0, Timer0 source edge don't care,
                    ; Prescaler Assignment -> WDT, Prescaler = 16
    ;**** Setup GPIO inputs/outputs ****
        movlw    b'00000000' ; load GPIO register before TRIS assignment
        movwf    GPIO
        movlw    b'00001001' ; set GP1 & GP2 as output, all others are inputs
        TRIS    GPIO
        clrwdt            ; reset watchdog
        call    Delay10ms   
        btfss    GPIO, 0        ; sample SHUTDN input every 10ms
        goto    Start        ; back to START if SHUTDN = 0
        movlw    d'5'        ; number of samples to deglitch SHUTDN input.
        movwf    COUNT3
    Sample    call    Delay10ms
        btfss    GPIO, 0
        goto    Start        ; back to START if SHUTDN = 0
        decfsz    COUNT3, 1   ; SHUTDN must be high 5x in a row
        goto    Sample
        clrwdt            ; clear the watchdog
        call    Delay20        ; commit to shutdown at this point. Wait 20 sec.
        bsf    GPIO, 1        ; set the shutdown output high
    Stuck    clrwdt            ; reset watchdog    
        goto Stuck        ; infinite loop until power is cut
    ;**** subroutines begin here ****    
    Delay1                ; total count = 1Meg = 1 second
        movlw    d'8'        ; put 8 into COUNT3
        movwf    COUNT3        ; COUNT3 x (COUNT1 x 3 + 3)(COUNT2 + 5) = 1001472
        movlw    d'255'        ; put 255 
        movwf    COUNT1        ; into COUNT1
    Loop2    movlw    d'158'        ; put 158
        movwf    COUNT2        ; into COUNT2        
    Loop1    decfsz    COUNT1,1    ; counts down from 255
            goto    Loop1       ;
            decfsz    COUNT2,1    ; counts down from 158
        goto    Loop1        ;
        clrwdt            ; clear the watchdog timer every 125ms
        decfsz    COUNT3,1    ; counts down from 8
        goto    Loop2        ; 
        RETLW    0
    Delay10ms            ; delay = 1us x (255x3+3) x (8 + 5) = 9.98ms
        movlw    d'255'
        movwf    COUNT1
        movlw    d'8'
        movwf    COUNT2        
        decfsz    COUNT1,1    
            goto    Loop10       
            decfsz    COUNT2,1    
        goto    Loop10        
        RETLW    0    
        movlw    d'20'        ; 20 x 1 = 20 seconds
        movwf    SCRATCH        ; into SCRATCH reg.
        call    Delay1        ; 1 sec delay
        decfsz    SCRATCH,1   ;
            goto    Loop20       ;
        RETLW    0

    Edit 2019-01-18: I change the shutdown output from a 750µs pulse to just a high value after the 20 second delay. Apparently, the pulse was too short to accomplish the task and it works fine with the step output. I updated the hex code in the files section to match.

View all 20 project logs

Enjoy this project?



Rob wrote 12/23/2021 at 23:59 point

Hello Bud,

Hopefully, final last question from me.

I have finally built one unit, plan to build 3. Although difficult to do with micro smd components  but I managed to do a reasonable job first time paste soldering this small of components. Im not sure how to tell if the chips are soldered correctly but that leads me onto the, hopefully, final question.

1) What is the best way of testing the board. Presuming to leave the supercap off first, just power it up and test various voltages?

Any ideas appreciated.



  Are you sure? yes | no

Bud Bennett wrote 12/24/2021 at 16:09 point

Hi Rob, It's been a long time since I played with this board. I have found that the easiest method to verify that the LTC4041 is properly connected to the board is to check for a diode to GND on each pin. It should read between -0.5V and -0.7V wrt GND. The only pin where this method fails is PFI since M3 is connected to it.

After that I usually current limit the supply (with no load at OUT+) and ramp the supply until power is applied to OUT+. You could attach some large capacitors in place of the supercaps to check out the charging a boost operations. If that all works then remove the current limiting, attach the supercaps and test the functionality.

  Are you sure? yes | no

Rob wrote 10/19/2021 at 21:01 point

Hi Bud, Sorry if this is a simple question or I had a man look at the information provided, but what Supercap value should one use for this project? There wasnt any indication in the BOM file and the description switches between one and two 400F supercaps as you had them left over. Should one 400F supercap be all that is needed, or a larger value would be better? Im only looking at using 1 supercap. Thanks.

  Are you sure? yes | no

Bud Bennett wrote 10/19/2021 at 23:32 point

Hi Rob, Check out the log titled “Raspberry Tests with new Python Code”. There is a table which calls out the size of supercap depending upon which Raspberry Pi board you are using. I’m currently using a single 100F capacitor to provide power to my Raspberry Pi Model 1B.

  Are you sure? yes | no

Rob wrote 10/19/2021 at 23:54 point

Thanks Bud. I did see this table, but ignored it because there was nothing for the Pi 4B that I will be using.. However, that should give me something to go by. Much appreciated. Rob

  Are you sure? yes | no

Rob wrote 10/02/2021 at 00:26 point

This is exactly what I was looking for and have started to get the components... However, the main component, the LTC4041, I cannot find who is selling it. Digikey state 52 week lead time. Anyone recently bought this? Do you mind sharing where you purchased from. Thanks.

  Are you sure? yes | no

Bud Bennett wrote 10/13/2021 at 03:03 point


  Are you sure? yes | no

Rob wrote 10/16/2021 at 22:03 point

Thanks Bud... Digikey said they had stock, but drilling down into the product, they have no stock and stating 52 week lead time. I did find some in stock at Mouser in the end (when I originally checked Mouser they had none). So, all good. Thanks

  Are you sure? yes | no

Robotex wrote 09/30/2021 at 08:16 point

Hello Bud,

This is a really nice project! However I am not much familiar with PIC controllers and would like to use either Atmel or STM controllers, for this I would like to modify the board and I was looking for the board design project files. Can you please write if you can share the PCB project?

  Are you sure? yes | no

Bud Bennett wrote 10/13/2021 at 03:01 point

Hi Robotex, I don't know what you are referring to. I have uploaded the design files for the PIC chip that I'm using. Can't help you much if that doesn't work for you . The PCB files are in Gerber format...pretty standard.

  Are you sure? yes | no

Will wrote 02/03/2021 at 00:02 point

Hello Bud,

Weird question here and not sure if you will be able to share thought on this. I have been trying out this circuit but with a Wurth 10F 2.7V supercapacitor (850617021004). Weirdly when I try to power on the raspberry pi zero w at ~1.955V (Super capacitor charge voltage) the LTC4041 will not turn on. I used a USB multimeter and the load equivalent impedance is extremely high at 1K Ohm. However, weirdly if the supercapacitor is at higher voltage or lower (drained), the LTC4041 will turn on the system properly and function properly as UPS. Do you think it has something to do with my setting on the LTC or some form of inrush current issue I have to resolve?

  Are you sure? yes | no

Bud Bennett wrote 02/03/2021 at 00:22 point

That question might be more appropriately directed to Analog Devices rather than me. I know that the load has something to do with whether the boost converter can deliver the proper voltage/current. I found that the supercap voltage had to be above a minimum voltage in order to deliver 2.5A to the load. But the RPi ZW is not much of a load...

Ask ADI. Maybe it a bug.

  Are you sure? yes | no

Will wrote 02/03/2021 at 00:39 point

Hello Bud,

Thank you for such a fast response. This is definitely still some insight and I will ask if ADI has any information as well and update here for the community. 

  Are you sure? yes | no

Will wrote 01/05/2021 at 23:59 point

Hello Bud,

Thank you for sharing this design. It has been so helpful.

I just got a quick question and hope it's not too stupid. I found that for your M1, you used TSM038N03PQ33 instead of the SiS488DN from the reference design on the LTC4041 Datasheet. Is there particular reasoning for the selection? Also the NMOS out of IGATE seems to be missing from the schematic compare to the reference design. I am just trying to understand the circuitry but had a lot of trouble with this part. Would you be able to help out with some clarification?

  Are you sure? yes | no

Bud Bennett wrote 01/09/2021 at 02:41 point

M1 was selected because it satisfied the required parameters and was cheaper than the reference part. Discrete MOSFETs are improving constantly. The reference part is just a suggestion from what was available in the past. 

There is only one MOSFET because I only needed one. This application is a specific case, where the power source is known to go "open circuit" when the power is lost. If the power source could short the input to GND then you would require two MOSFETs to prevent reverse current flow from the output. When the application engineers at LTC (or ADI) create a reference circuit they provide for a wide range of applications. I didn't need two series input MOSFETs for this particular application, therefore I decided that using only one would be good enough.

  Are you sure? yes | no

Will wrote 01/13/2021 at 17:58 point

Thank you for answering! That helps me understand it better!

  Are you sure? yes | no

lobster wrote 04/17/2020 at 09:28 point

Hello Bud, thanks for sharing this design.

About the old design, you say: "The wall wart is 5VDC@2-2.5A. It is not quite standard issue in that it must provide 5.15-5.25V minimum."  Is that requirement present for the new design too?

  Are you sure? yes | no

Bud Bennett wrote 05/16/2020 at 21:32 point

Not really. The power fail comparator is set to 4.75V. I've increased the booster output to near 5V. It depends upon the wire gauge, and voltage drop, of the AC adapter that you intend to use. I find that it is better to have a bit more voltage applied -- and now you can find adapters that are specified at 5.25V @ 2.4A.

  Are you sure? yes | no

alcor6502 wrote 12/16/2019 at 14:47 point

I want to thank you and acknowledge that your article inspired me to develop a similar device built around the LTC4041 (Raspberry Supercapacitor UPS power supply). If you have time, I would be very grateful if you can post your opinion about it.

I've noticed you do not use the SYSGD comparator, which, in my solution, helped me to detect when the supercapacitors have reached the minimum charge to drive the buck converter. Hoping (and failing) to avoid a microcontroller, I initially asked Analog if the comparator was an independent circuit, and they have confirmed.

  Are you sure? yes | no

Bud Bennett wrote 12/16/2019 at 18:57 point

Yes I will post in in your project's comment area, but I say something here as well. Your soft latching power switch is very similar to what I used on my first discrete version of my project. I don't use SYSGD because I am now monitoring the voltage at SCAP with the PIC ADC -- it doesn't disable the booster until the voltage at SCAP falls below 2.45V, which ensures that the booster won't be enabled again until input power is present. The python code takes care of the timing and shutdown to avoid over-discharging the supercaps -- and I get a log file.

  Are you sure? yes | no

Silviu EU wrote 05/01/2019 at 14:30 point

Hey Bud, 

I have all the components and PCB's printed , but I'm having problems in programming the PIC 10f202 either with MPLAB IDE or IPE I have tried different connections and ways to program but no success and lost e few good days and hours ,Can you help me with some wiring from PicKit 3 to the Pic in order to program it , maybe some advises, this is the error message that I get when trying to program:


Connecting to MPLAB PICkit 3...

Currently loaded firmware on PICkit 3
Firmware Suite Version.....01.55.01
Firmware type..............Baseline

Programmer to target power is enabled - VDD = 5.000000 volts.
Target has invalid calibration data (0x00).


The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x35
configuration memory
program memory
Address: 0 Expected Value: 25 Received Value: 0
Failed to program device

  Are you sure? yes | no

Bud Bennett wrote 08/28/2019 at 04:27 point

I'm sorry for the late reply, but I just noticed this comment today. I didn't receive any notification. Did you get it to program eventually? The PIC10F202 has a strange pinout -- you need to make a custom breakout board to program it. It also works better if you set the programing speed to "slow".

  Are you sure? yes | no

Melgar wrote 11/06/2018 at 14:02 point


I was inspired by your project here to make my own UPS for the RPi based on this chip. Thank you for explaining everything in this project. I wanted to ask you some questions.

1. Why did you add the slightly complicated timer circuit, I want to do something similar but wouldn’t it be much easier to connect a pin from the raspberry to the shutdown pins of the LTC4041? With “gpio-poweroff” a pin can be set high at the end of the Linux shutdown (more info:

2. You said: “If 2 supercaps are used, then make sure that the voltage on the SCAP pin has discharged below 2.5V when the one-shot timer expires or else the booster could be re-enabled and reboot the Raspberry Pi even if there is no input power applied.” I think the datasheet is very vague on this point, do you have a source for this information or did you test it?

3. If the Vscap > 2.5V restarts the chip, then what would be a suitable solution? Lowering the voltage of the SCAP(‘s) is an option, but I expect it to have less performance (more current, closer to minimum Vscap).

Kind regards and good luck with your project,

  Are you sure? yes | no

Bud Bennett wrote 11/09/2018 at 06:34 point

1. I was not aware of that feature, but I don't trust external code to not change over time. There used to be a Pi hardware watchdog, but that no longer works. I've been burned before. 

2. You're right about the data sheet being vague. The datasheet discusses this point in the paragraph titled "Max (Vsys, Vscap) Undervoltage Lockout." I got assurance from the designer of the LTC4041 that it works as described. I'll be testing it in the next few days.

3. Smartass answer: Don't use 2 supercaps. Otherwise make sure that the SCAP voltage is below 2.5V before you shutdown the Raspberry Pi. You could also disconnect the SCAP pin from the supercap stack and force it below 2.5V at the end of the timer period somehow. (The SCAP pin is not high current. -- hoping that the data sheet is right about that...) 

I didn't think very hard about how to handle the 2 supercap case. If I implement that option I believe that I will just program the Pi to adjust the period between PWRGOOD going low and when it asserts SHUTDN to guarantee the SCAP drops below 2.5V.

Good luck to you as well. These UPS projects are more complicated than most people realize.


  Are you sure? yes | no

Melgar wrote 11/09/2018 at 06:48 point

Thanks for answering

  Are you sure? yes | no

Paul wrote 04/29/2018 at 13:58 point

Cool! I need something like this. If I send this to OSH Park, will they make the board with components or just an empty board? I'm more of a software guy and I'm just starting to learn electronics.

  Are you sure? yes | no

Bud Bennett wrote 04/29/2018 at 21:54 point

They will make three empty boards. You get to stuff 'em. All surface mount...the MSOP part is ridiculously difficult to do without shorts. Discretion is the better part of valor.

  Are you sure? yes | no

Michael wrote 01/16/2019 at 05:44 point

Hey Bud, I like your project very much. I think it would be a huge progress for all raspberrys as you can damage the SD card with one single power loss. But like Paul, I'm just a software guy.
Is it possible to get this board already assembled? 

  Are you sure? yes | no

Bud Bennett wrote 01/16/2019 at 23:57 point

Michael: The only possible way to get an assembled board is for me to build it for you. I can assure you that you can't afford me. I don't consider it much fun to populate/solder PCBs. I wish there was some way of transferring manufacturing rights to a third party -- but this is open hardware so anyone can make the board if they choose. I'm getting ready to make 2 more PCBs just to use some parts I have on hand -- PM me and you might get one.

  Are you sure? yes | no

slado wrote 03/12/2018 at 11:25 point

The 400F capacity seems to me an overkill for 30 seconds backup power. The Raspberry Pi draws only about 300mA average current. Too much capacity prolongs the charging time. From the circuit diagram I could see that the charger is a linear circuit and not a step-down DC/DC converter hence charge current is limited and/or heat production could be an issue. I just compare your circuit with another supercapacitor UPS:

  Are you sure? yes | no

Bud Bennett wrote 04/25/2018 at 13:33 point

I've been traveling quite a bit the last couple of months and did not see this comment until recently. I will address each issue that you raised:

1. I stated that I repurposed the 400F supercaps from a previous project. It is overkill for this, but there was no good reason to spend more money for a smaller supercap when I had these on hand.

2. The Pi by itself is low current drain, but any peripherals will add to it. Your 300mA number is for older, single core Rasperry Pi units. I believe that the Raspberry Pi designers specify a 2.5A wall wart to accommodate the total range of load current. I was attempting to design the circuit that would meet that high end. The juice4halt design uses two 22F supercaps in series. If you assume that their circuit charges the caps to 5.4V and discharges to 2V (highly unlikely) then you get a grand total of 127 W-sec of energy. That will provide less than 10  seconds of power to a 5V load drawing 2.5A. The Raspberry Pi 3 will draw 750mA with 4 cores at 100% -- the juice4halt will only last 33 seconds -- not much margin -- even less with peripherals.

3. You are correct about the initial charge time -- it will be long. But after the supercap is charged, the time to replace the charge is pretty short because the discharge time is limited to 30 seconds or so. The recharge time will be around 1 minute no matter what size supercap is employed.

4. The linear charger is simple and the power dissipation is accounted for in the design. Even a switch-mode converter has limited charge current given the limitations of the wall wart. The total current draw from the Pi and peripherals, plus the charger, can't exceed the wall wart rating.

The juice4halt looks like a nice alternative, but doesn't meet my stated requirements. Your comment appears to be an advertisement for it. 

This was my first foray into switch-mode boost converter design. If I did another one, would it look like this -- most definitely not. But it does the job and I'm pretty satisfied with its performance.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates