{"id":12962,"date":"2026-09-11T07:35:00","date_gmt":"2026-09-11T05:35:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=12962"},"modified":"2026-10-24T05:43:54","modified_gmt":"2026-10-24T03:43:54","slug":"tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/","title":{"rendered":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown"},"content":{"rendered":"<p>A UPS must supply the Raspberry Pi under load, report a mains outage and retain enough energy for an orderly shutdown. Battery capacity alone answers none of these three questions. Usable output energy, peak current capability and cooperation between the UPS and operating system determine the result.<\/p>\n<p>The calculation below is a planning example. The shutdown logic requires a documented, compatible UPS with a mains-failure output that pulls a GPIO signal to ground. Battery pack, charger and protection circuit must match the manufacturer&#8217;s approved configuration.<\/p>\n<figure class=\"lw-diagram\"><img src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/dia-12962-review-20261024.png\" width=\"1120\" height=\"580\" decoding=\"async\" loading=\"lazy\" alt=\"Three panels show the assumed energy budget, calculated runtimes and limits of shutdown monitoring.\"><figcaption>Illustrative assumptions, not measured product specifications. Battery condition, output current, monitoring faults and restart behaviour need separate verification.<\/figcaption><\/figure>\n<h2>1. Measure the complete load<\/h2>\n<p>A power supply&#8217;s rating describes available capacity, not Pi consumption. Measurement at the 5 V input includes the Pi and USB devices powered through that input. The meter must support the USB-C supply arrangement and required current. Separately powered equipment needs a separate energy budget.<\/p>\n<p>On Pi 5, <code>vcgencmd pmic_read_adc<\/code> exposes internal measurements. USB consumption and loads connected directly to 5 V are absent from the sum of PMIC rails. That sum therefore cannot represent total input power and is not a general measurement method for both Pi 4 and Pi 5.<\/p>\n<p>Sizing requires idle, normal workload and the highest intended load, including storage activity and startup peaks. The UPS output must supply the corresponding current without an unacceptable voltage drop. A large battery cannot compensate for an undersized converter.<\/p>\n<h2>2. Calculate energy and reserve explicitly<\/h2>\n<p>Watt-hours are approximately amp-hours multiplied by nominal voltage. Two example cells rated at 3.4 Ah and 3.7 V each contain 25.16 Wh in total. The approved pack&#8217;s actual nominal voltage matters, not its full-charge voltage. A cell-level mAh rating cannot establish USB runtime without voltage and conversion information.<\/p>\n<p>This example assumes 80 percent usable cell energy and 88 percent converter efficiency. The first factor represents the selected design case, including age, temperature and usable discharge range. Neither factor is a universal measurement. A further 1 Wh at the output is reserved for shutdown.<\/p>\n<figure style=\"--cbb-digits:1\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"plain\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Text<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-plain\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\">E_cells = 2 \u00d7 3.4 Ah \u00d7 3.7 V = 25.16 Wh\n<\/span><span class=\"cbb-line\">E_output = 25.16 Wh \u00d7 0.80 \u00d7 0.88 = 17.71264 Wh\n<\/span><span class=\"cbb-line\">E_runtime = 17.71264 Wh \u2212 1 Wh = 16.71264 Wh\n<\/span><span class=\"cbb-line\">t_runtime = E_runtime \/ P_load<\/span><\/code><\/pre><\/figure>\n<table><thead><tr><th>Assumed load<\/th><th>Calculated time until reserve<\/th><\/tr><\/thead><tbody><tr><td>6 W<\/td><td>about 2 h 47 min<\/td><\/tr><tr><td>9 W<\/td><td>about 1 h 51 min<\/td><\/tr><tr><td>12 W<\/td><td>about 1 h 24 min<\/td><\/tr><\/tbody><\/table>\n<p>The power levels are calculation cases, not typical Pi configurations. At a constant 12 W, 1 Wh provides five minutes. An assumed 60-second shutdown consumes 0.2 Wh at that load. Actual shutdown duration needs measurement with the intended services, drives and possible timeouts.<\/p>\n<p>Usable energy already measured at the 5 V output includes converter losses. Applying efficiency again would subtract the same loss twice. A discharge cutoff already reflected in a capacity test also requires no second arbitrary deduction.<\/p>\n<h2>3. Distinguish mains failure from a critical battery<\/h2>\n<p>A mains-failure signal permits a delay for brief interruptions. A critical battery may require immediate shutdown instead. A fixed 60-second timer is suitable only when remaining energy covers the delay and shutdown, including at monitor startup and after repeated outages. A suitable UPS needs an independent protection circuit; a device-specific battery monitor may provide an earlier emergency path.<\/p>\n<p>The MAX17048 estimates state of charge for a single-cell system; the related MAX17049 supports two cells in series. The INA219 measures current, voltage and power and does not independently provide battery capacity in percent. Estimated charge does not remove the need to test at high load. A universal 20-percent threshold guarantees no particular remaining runtime.<\/p>\n<h2>4. Choose a simple overlay or a delayed monitor<\/h2>\n<p>The <code>gpio-shutdown<\/code> overlay generates a <code>KEY_POWER<\/code> input event. A component such as <code>systemd-logind<\/code> handles shutdown. Without a working operating-system handler, shutdown is not guaranteed, especially during every boot phase. GPIO assignment, polarity and wiring must match the board. The overlay and the following monitor must not claim the same line simultaneously.<\/p>\n<p>The monitor uses the libgpiod 2 Python interface. An older 1.x installation is incompatible. The chip device and line offset must be identified with the locally available GPIO tools and board documentation. A physical header pin number is not a line offset; <code>gpiochip0<\/code> and offset 17 are not universal settings.<\/p>\n<p>The electrical assumption is a documented 3.3 V-compatible open-drain output: low means mains failure, high means mains present, with common ground and an appropriate pull-up. A broken wire can appear as mains present because of the pull-up; this example does not detect that fault. A 5 V signal must not connect directly to the GPIO. Other signal arrangements need appropriate electrical adaptation and verified logic.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"python\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Python<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-python\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-comment\">#!\/usr\/bin\/env python3<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> argparse\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> math\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> subprocess\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">import<\/span> time\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">class<\/span> <span class=\"cbb-type\">OutageTimer<\/span>:\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">__init__<\/span>(<span class=\"cbb-variable\">self<\/span>, delay):\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-keyword\">not<\/span> math.<span class=\"cbb-function\">isfinite<\/span>(delay) <span class=\"cbb-keyword\">or<\/span> delay &lt;= <span class=\"cbb-number\">0<\/span>:\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">raise<\/span> <span class=\"cbb-function\">ValueError<\/span>(<span class=\"cbb-string\">\"delay must be positive and finite\"<\/span>)\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-variable\">self<\/span>.delay = delay\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-variable\">self<\/span>.since = <span class=\"cbb-constant\">None<\/span>\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-variable\">self<\/span>.previous = <span class=\"cbb-constant\">None<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">sample<\/span>(<span class=\"cbb-variable\">self<\/span>, failed, now):\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-function\">type<\/span>(failed) <span class=\"cbb-keyword\">is<\/span> <span class=\"cbb-keyword\">not<\/span> bool <span class=\"cbb-keyword\">or<\/span> <span class=\"cbb-keyword\">not<\/span> math.<span class=\"cbb-function\">isfinite<\/span>(now):\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">raise<\/span> <span class=\"cbb-function\">ValueError<\/span>(<span class=\"cbb-string\">\"invalid sample\"<\/span>)\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-variable\">self<\/span>.previous <span class=\"cbb-keyword\">is<\/span> <span class=\"cbb-keyword\">not<\/span> <span class=\"cbb-constant\">None<\/span> <span class=\"cbb-keyword\">and<\/span> <span class=\"cbb-keyword\">not<\/span> <span class=\"cbb-number\">0<\/span> &lt;= now - <span class=\"cbb-variable\">self<\/span>.previous &lt;= <span class=\"cbb-number\">5<\/span>:\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">raise<\/span> <span class=\"cbb-function\">RuntimeError<\/span>(<span class=\"cbb-string\">\"monitoring gap exceeds 5 seconds\"<\/span>)\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-variable\">self<\/span>.previous = now\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-keyword\">not<\/span> failed:\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-variable\">self<\/span>.since = <span class=\"cbb-constant\">None<\/span>\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">False<\/span>\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> <span class=\"cbb-variable\">self<\/span>.since <span class=\"cbb-keyword\">is<\/span> <span class=\"cbb-constant\">None<\/span>:\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-variable\">self<\/span>.since = now\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">return<\/span> now - <span class=\"cbb-variable\">self<\/span>.since &gt;= <span class=\"cbb-variable\">self<\/span>.delay\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">monitor<\/span>(read_failed, delay, action, clock=time.monotonic, sleep=time.sleep):\n<\/span><span class=\"cbb-line\">    timer = <span class=\"cbb-function\">OutageTimer<\/span>(delay)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">while<\/span> <span class=\"cbb-constant\">True<\/span>:\n<\/span><span class=\"cbb-line\">        failed = <span class=\"cbb-function\">read_failed<\/span>()  <span class=\"cbb-comment\"># Read immediately, including at startup.<\/span>\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">if<\/span> timer.<span class=\"cbb-function\">sample<\/span>(failed, <span class=\"cbb-function\">clock<\/span>()):\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-function\">action<\/span>()\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">return<\/span>\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-function\">sleep<\/span>(<span class=\"cbb-number\">1<\/span>)\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">main<\/span>():\n<\/span><span class=\"cbb-line\">    parser = argparse.<span class=\"cbb-function\">ArgumentParser<\/span>()\n<\/span><span class=\"cbb-line\">    parser.<span class=\"cbb-function\">add_argument<\/span>(<span class=\"cbb-string\">\"--chip\"<\/span>, required=<span class=\"cbb-constant\">True<\/span>)\n<\/span><span class=\"cbb-line\">    parser.<span class=\"cbb-function\">add_argument<\/span>(<span class=\"cbb-string\">\"--line\"<\/span>, required=<span class=\"cbb-constant\">True<\/span>, type=int)\n<\/span><span class=\"cbb-line\">    parser.<span class=\"cbb-function\">add_argument<\/span>(<span class=\"cbb-string\">\"--delay\"<\/span>, type=float, default=<span class=\"cbb-number\">60<\/span>)\n<\/span><span class=\"cbb-line\">    parser.<span class=\"cbb-function\">add_argument<\/span>(<span class=\"cbb-string\">\"--poweroff\"<\/span>, action=<span class=\"cbb-string\">\"store_true\"<\/span>)\n<\/span><span class=\"cbb-line\">    args = parser.<span class=\"cbb-function\">parse_args<\/span>()\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-function\">OutageTimer<\/span>(args.delay)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> args.line &lt; <span class=\"cbb-number\">0<\/span>:\n<\/span><span class=\"cbb-line\">        parser.<span class=\"cbb-function\">error<\/span>(<span class=\"cbb-string\">\"line offset must be non-negative\"<\/span>)\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">import<\/span> gpiod\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">from<\/span> gpiod.line <span class=\"cbb-keyword\">import<\/span> Bias, Direction, Value\n<\/span><span class=\"cbb-line\">    settings = gpiod.<span class=\"cbb-function\">LineSettings<\/span>(direction=Direction.INPUT,\n<\/span><span class=\"cbb-line\">                                  active_low=<span class=\"cbb-constant\">False<\/span>, bias=Bias.PULL_UP)\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">with<\/span> gpiod.<span class=\"cbb-function\">request_lines<\/span>(args.chip, consumer=<span class=\"cbb-string\">\"ups-watch\"<\/span>,\n<\/span><span class=\"cbb-line\">                            config={args.line: settings}) <span class=\"cbb-keyword\">as<\/span> request:\n<\/span><span class=\"cbb-line\">        last = &#91;<span class=\"cbb-constant\">None<\/span>&#93;\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">read_failed<\/span>():\n<\/span><span class=\"cbb-line\">            value = request.<span class=\"cbb-function\">get_value<\/span>(args.line)\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">if<\/span> value <span class=\"cbb-keyword\">not<\/span> <span class=\"cbb-keyword\">in<\/span> (Value.ACTIVE, Value.INACTIVE):\n<\/span><span class=\"cbb-line\">                <span class=\"cbb-keyword\">raise<\/span> <span class=\"cbb-function\">RuntimeError<\/span>(<span class=\"cbb-string\">\"unknown GPIO state\"<\/span>)\n<\/span><span class=\"cbb-line\">            failed = value == Value.INACTIVE  <span class=\"cbb-comment\"># Physical low = mains failure.<\/span>\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">if<\/span> failed != last&#91;<span class=\"cbb-number\">0<\/span>&#93;:\n<\/span><span class=\"cbb-line\">                <span class=\"cbb-function\">print<\/span>(<span class=\"cbb-string\">\"UPS mains_failed=\"<\/span> + <span class=\"cbb-function\">str<\/span>(failed), flush=<span class=\"cbb-constant\">True<\/span>)\n<\/span><span class=\"cbb-line\">                last&#91;<span class=\"cbb-number\">0<\/span>&#93; = failed\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">return<\/span> failed\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-keyword\">def<\/span> <span class=\"cbb-function\">action<\/span>():\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-function\">print<\/span>(<span class=\"cbb-string\">\"UPS delay reached; poweroff=\"<\/span> + <span class=\"cbb-function\">str<\/span>(args.poweroff), flush=<span class=\"cbb-constant\">True<\/span>)\n<\/span><span class=\"cbb-line\">            <span class=\"cbb-keyword\">if<\/span> args.poweroff:\n<\/span><span class=\"cbb-line\">                subprocess.<span class=\"cbb-function\">run<\/span>(&#91;<span class=\"cbb-string\">\"\/usr\/bin\/systemctl\"<\/span>, <span class=\"cbb-string\">\"--no-block\"<\/span>, <span class=\"cbb-string\">\"poweroff\"<\/span>&#93;,\n<\/span><span class=\"cbb-line\">                               check=<span class=\"cbb-constant\">True<\/span>, timeout=<span class=\"cbb-number\">10<\/span>)\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-function\">monitor<\/span>(read_failed, args.delay, action)\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-keyword\">if<\/span> __name__ == <span class=\"cbb-string\">\"__main__\"<\/span>:\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-function\">main<\/span>()<\/span><\/code><\/pre><\/figure>\n<p>The first state is read immediately, so a failure already present at startup also starts the timer. An observed high state resets the delay. Timing uses a monotonic clock. Samples are approximately one second apart; short transitions between samples may go undetected. The example therefore does not prove an uninterrupted outage and is not a real-time protection function.<\/p>\n<p>Read errors and observed sampling gaps above five seconds terminate the process with an error. Restarting resets the timer, so repeated failures need an alert. Without <code>--poweroff<\/code>, the program only logs the reached threshold and exits. This mode supports an initial controlled signal check but never requests shutdown.<\/p>\n<h2>5. Enable the service after signal checks<\/h2>\n<p>The verified script belongs at <code>\/usr\/local\/lib\/ups_watch.py<\/code> and the following unit at <code>\/etc\/systemd\/system\/ups-watch.service<\/code>. The file <code>\/etc\/ups-watch.conf<\/code> must define <code>UPS_CHIP<\/code> as the verified device path and <code>UPS_LINE<\/code> as the verified offset. Only administrative access should permit script or configuration changes. The unit explicitly includes <code>--poweroff<\/code> and can shut down the computer.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"ini\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">Config<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-ini\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-type\">&#91;Unit&#93;<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">Description<\/span>=UPS mains-failure monitor\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">StartLimitIntervalSec<\/span>=<span class=\"cbb-number\">60<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">StartLimitBurst<\/span>=<span class=\"cbb-number\">3<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-type\">&#91;Service&#93;<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">Type<\/span>=simple\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">EnvironmentFile<\/span>=\/etc\/ups-watch.conf\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">ExecStart<\/span>=\/usr\/bin\/python3 \/usr\/local\/lib\/ups_watch.py --chip <span class=\"cbb-variable\">${UPS_CHIP}<\/span> --line <span class=\"cbb-variable\">${UPS_LINE}<\/span> --delay 60 --poweroff\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">Restart<\/span>=on-failure\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">RestartSec<\/span>=<span class=\"cbb-number\">5<\/span>\n<\/span><span class=\"cbb-line\">\n<\/span><span class=\"cbb-line\"><span class=\"cbb-type\">&#91;Install&#93;<\/span>\n<\/span><span class=\"cbb-line\"><span class=\"cbb-attr\">WantedBy<\/span>=multi-user.target<\/span><\/code><\/pre><\/figure>\n<p>A signal check without the shutdown option precedes reloading systemd configuration and deliberately enabling the service. An additional <code>After=multi-user.target<\/code> does not belong here: combined with membership of that target, a cyclic startup order can result. Limited restarts handle transient failures; a persistently failed service needs separate alerting.<\/p>\n<h2>6. Test shutdown and recovery together<\/h2>\n<p><code>systemctl --no-block poweroff<\/code> requests shutdown. The call confirms neither completion nor removal of the physical 5 V supply. A UPS shutdown handshake must allow the operating system sufficient time. Bootloader settings that reduce halted power consumption do not replace this sequence.<\/p>\n<p><code>PSU_MAX_CURRENT=5000<\/code> is not a general UPS setting either. Declaring a current capability cannot create a supply capable of delivering 5 A. Current-limit changes require an appropriately documented hardware configuration.<\/p>\n<p>Acceptance testing needs a verified recovery path and a controlled test load. The plan covers a short outage, a long outage, startup without mains, low battery, another outage before full recharge, and mains returning during or after shutdown. Deliberately running a production filesystem until voltage collapses is unnecessary. Remaining output energy can be measured separately with a suitable test load.<\/p>\n<p>Previous-boot logs require available persistent storage. Missing entries in <code>journalctl -b -1<\/code> do not prove abrupt power loss; volatile journals disappear too. Logs, observed shutdown and measured output voltage provide complementary evidence.<\/p>\n<p>Ageing depends on chemistry, temperature, state of charge and usage. A fixed doubling of battery life from an arbitrary reduction in charging voltage cannot be inferred. Charging and discharge limits must follow the approved manufacturer profile. Repeated capacity and shutdown tests within an appropriate maintenance schedule provide a basis for timely replacement.<\/p>\n<div class=\"lw-faq\"><h2>Questions and answers<\/h2>\n<h3>Does a halted Pi restart automatically when mains returns?<\/h3><p>Not necessarily. If the UPS keeps the 5 V rail active throughout, no fresh power-on transition occurs. Reliable recovery requires a designed output power cycle or a compatible wake controller. Mains returning before and after the UPS output turns off are separate test cases.<\/p>\n<h3>Is the 60-second delay sufficient protection?<\/h3><p>Only with verified remaining energy for the delay and complete shutdown. An almost empty battery may fail sooner. Battery protection, battery-state reporting and failure alerts remain necessary.<\/p>\n<\/div>\n<div class=\"lw-quellen\"><h2>Sources<\/h2><ul>\n<li><a href=\"https:\/\/www.raspberrypi.com\/documentation\/computers\/raspberry-pi.html\">Raspberry Pi: hardware, GPIO, PMIC<\/a><\/li>\n<li><a href=\"https:\/\/www.raspberrypi.com\/documentation\/computers\/configuration.html\">Raspberry Pi: configuration<\/a><\/li>\n<li><a href=\"https:\/\/raw.githubusercontent.com\/raspberrypi\/linux\/rpi-6.12.y\/arch\/arm\/boot\/dts\/overlays\/README\">Raspberry Pi: gpio-shutdown<\/a><\/li>\n<li><a href=\"https:\/\/libgpiod.readthedocs.io\/en\/v2.3.1\/python_line_settings.html\">libgpiod 2: LineSettings<\/a><\/li>\n<li><a href=\"https:\/\/libgpiod.readthedocs.io\/en\/v2.3.1\/python_misc.html\">libgpiod 2: request_lines<\/a><\/li>\n<li><a href=\"https:\/\/www.freedesktop.org\/software\/systemd\/man\/latest\/systemd.target.html\">systemd: target ordering<\/a><\/li>\n<li><a href=\"https:\/\/www.freedesktop.org\/software\/systemd\/man\/latest\/journald.conf.html\">systemd: journal storage<\/a><\/li>\n<li><a href=\"https:\/\/www.analog.com\/en\/products\/max17048.html\">Analog Devices: MAX17048 \/ MAX17049<\/a><\/li>\n<li><a href=\"https:\/\/www.ti.com\/product\/INA219\">Texas Instruments: INA219<\/a><\/li>\n<li><a href=\"https:\/\/www.sandia.gov\/ess-ssl\/wp-content\/uploads\/2021\/03\/ESHB-Ch3_Lithium-Batteries_Preger.pdf\">Sandia: Lithium-Ion Batteries<\/a><\/li>\n<\/ul><\/div>","protected":false},"excerpt":{"rendered":"<p>Sizing a Raspberry Pi UPS requires measured load, usable output energy and a shutdown reserve. A GPIO monitor illustrates delayed shutdown, with explicit limits for battery state, faults and automatic recovery.<\/p>\n","protected":false},"author":1,"featured_media":23901,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[92630],"tags":[91113,91181,91219],"class_list":["post-12962","post","type-post","status-publish","format-standard","hentry","category-tutorials-en-raspberry-pi","tag-homelab","tag-raspberry-pi","tag-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-11T05:35:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-24T03:43:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown\",\"datePublished\":\"2026-09-11T05:35:00+00:00\",\"dateModified\":\"2026-10-24T03:43:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/\"},\"wordCount\":1246,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-12962-review-20261024-dark.png\",\"keywords\":[\"Homelab\",\"Raspberry Pi\",\"Tutorial\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/\",\"name\":\"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-12962-review-20261024-dark.png\",\"datePublished\":\"2026-09-11T05:35:00+00:00\",\"dateModified\":\"2026-10-24T03:43:54+00:00\",\"description\":\"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-12962-review-20261024-dark.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-12962-review-20261024-dark.png\",\"width\":1200,\"height\":630,\"caption\":\"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/raspberry-pi\\\/tutorials-en-raspberry-pi\\\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik","description":"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik","og_description":"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-09-11T05:35:00+00:00","article_modified_time":"2026-10-24T03:43:54+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown","datePublished":"2026-09-11T05:35:00+00:00","dateModified":"2026-10-24T03:43:54+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/"},"wordCount":1246,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png","keywords":["Homelab","Raspberry Pi","Tutorial"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/","name":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png","datePublished":"2026-09-11T05:35:00+00:00","dateModified":"2026-10-24T03:43:54+00:00","description":"Measuring the real power draw, converting cell capacity into runtime, and triggering a clean shutdown before the pack reaches its cut-off voltage.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-12962-review-20261024-dark.png","width":1200,"height":630,"caption":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/raspberry-pi\/tutorials-en-raspberry-pi\/tutorial-sizing-a-raspberry-pi-ups-and-wiring-the-automatic-shutdown\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tutorial: Sizing a Raspberry Pi UPS and Wiring the Automatic Shutdown"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/12962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=12962"}],"version-history":[{"count":4,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/12962\/revisions"}],"predecessor-version":[{"id":23916,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/12962\/revisions\/23916"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/23901"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=12962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=12962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=12962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}