LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Blog-Übersicht /Raspberry Pi/Tutorials / Tutorial: Eine USV für den Raspberry Pi...
Diesen Artikel in anderen Sprachen lesen:

Tutorial: Eine USV für den Raspberry Pi auslegen und die Notabschaltung einrichten

Tutorial: Eine USV für den Raspberry Pi auslegen und die Notabschaltung einrichten

Management Summary

Eine unterbrechungsfreie Stromversorgung versorgt den Raspberry Pi nach einem Stromausfall vorübergehend weiter. Bei Heimservern und Hausautomation schafft diese Reserve Zeit, Dateien zu schließen und geordnet herunterzufahren. Zur Auswahl zählt neben der Akkukapazität auch, ob die Versorgung alle angeschlossenen Geräte trägt und einen Ausfall rechtzeitig meldet. Ebenso wichtig ist der Wiederanlauf: Zurückkehrender Netzstrom startet einen heruntergefahrenen Pi nicht zwangsläufig, solange die Akkuversorgung bestehen bleibt.

Inhalt
  1. 1. Die vollständige Last messen
  2. 2. Energie und Reserve nachvollziehbar rechnen
  3. 3. Netzausfall und kritischen Akkustand unterscheiden
  4. 4. Ein einfaches Overlay oder ein verzögerter Monitor
  5. 5. Den Dienst erst nach der Signalprüfung aktivieren
  6. 6. Abschalten und Wiederanlauf gemeinsam prüfen
  7. Fragen und Antworten
  8. Quellen

Eine unterbrechungsfreie Stromversorgung (USV) muss den Raspberry Pi unter Last versorgen, einen Netzausfall melden und genügend Energie für ein geordnetes Herunterfahren behalten. Die Kapazitätsangabe allein beantwortet keine dieser drei Fragen. Entscheidend sind die nutzbare Energie am Ausgang, die zulässige Spitzenlast und das Zusammenspiel zwischen USV und Betriebssystem.

Die folgende Rechnung ist ein Planungsbeispiel. Die Abschaltlogik setzt eine dokumentierte, zum Pi passende USV mit einem gegen Masse schaltenden Netzausfallsignal voraus. Zellpaket, Ladegerät und Schutzschaltung müssen zueinander passen; maßgeblich sind die Freigaben des Herstellers.

Drei Felder zeigen angenommene Energiebilanz, berechnete Laufzeiten und Grenzen der Abschaltüberwachung.
Beispielannahmen, keine gemessenen Produkteigenschaften. Akkuzustand, Ausgangsstrom, Überwachungsfehler und Wiederanlauf müssen gesondert geprüft werden.

1. Die vollständige Last messen

Die Nennleistung des Netzteils bezeichnet dessen Lieferfähigkeit, nicht den Verbrauch des Pi. Eine Messung am 5-V-Eingang erfasst den Pi samt darüber versorgten USB-Geräten. Das Messgerät muss zur verwendeten USB-C-Stromversorgung und zum benötigten Strom passen. Separat versorgte Geräte brauchen eine eigene Energiebilanz.

Auf dem Pi 5 liefert vcgencmd pmic_read_adc interne Messwerte. USB-Verbrauch und direkt an 5 V angeschlossene Lasten fehlen jedoch in der Summe der PMIC-Schienen. Diese Summe ist deshalb keine vollständige Eingangsmessung und keine allgemeine Messmethode für Pi 4 und Pi 5.

Für die Auslegung zählen Leerlauf, typische Arbeit und die höchste tatsächlich vorgesehene Last einschließlich Speicherzugriffen und Anlaufspitzen. Zusätzlich zur Energie muss der USV-Ausgang diesen Strom ohne unzulässigen Spannungseinbruch liefern. Ein großes Akkupaket gleicht einen zu schwachen Wandler nicht aus.

2. Energie und Reserve nachvollziehbar rechnen

Wattstunden ergeben sich näherungsweise aus Amperestunden mal Nennspannung. Zwei beispielhafte Zellen mit jeweils 3,4 Ah und 3,7 V ergeben zusammen 25,16 Wh. Maßgeblich ist die tatsächliche Nennspannung des freigegebenen Pakets, nicht die Ladeschlussspannung. Eine mAh-Angabe auf Zellebene lässt sich ohne Spannung und Wandlerdaten nicht als USB-Laufzeit lesen.

Für dieses Beispiel werden 80 Prozent nutzbare Zellenergie und 88 Prozent Wandlerwirkungsgrad angenommen. Die 80 Prozent stehen für den gewählten Auslegungsfall einschließlich Alter, Temperatur und nutzbarem Entladebereich; beide Faktoren sind ausdrücklich keine allgemeingültigen Messwerte. Weitere 1 Wh bleiben am Ausgang für das Herunterfahren reserviert.

Text
E_cells = 2 × 3.4 Ah × 3.7 V = 25.16 Wh
E_output = 25.16 Wh × 0.80 × 0.88 = 17.71264 Wh
E_runtime = 17.71264 Wh − 1 Wh = 16.71264 Wh
t_runtime = E_runtime / P_load
Angenommene LastRechnerische Zeit bis zur Reserve
6 Wetwa 2 h 47 min
9 Wetwa 1 h 51 min
12 Wetwa 1 h 24 min

Die Leistungsstufen sind Rechenfälle, keine typischen Pi-Konfigurationen. Bei konstant 12 W entsprechen 1 Wh fünf Minuten. Ein angenommenes Herunterfahren von 60 Sekunden benötigt dabei 0,2 Wh. Die tatsächliche Dauer muss mit laufenden Diensten, Datenträgern und möglichen Zeitüberschreitungen gemessen werden.

Eine bereits am 5-V-Ausgang gemessene nutzbare Energiemenge enthält die Wandlerverluste schon. Ein erneuter Wirkungsgradabzug wäre doppelt. Auch ein im Kapazitätstest bereits enthaltener Entladeschluss darf nicht noch einmal pauschal als Verlust abgezogen werden.

3. Netzausfall und kritischen Akkustand unterscheiden

Ein Netzausfallsignal erlaubt eine Wartezeit für kurze Unterbrechungen. Ein kritischer Akkuzustand kann dagegen sofortiges Herunterfahren erfordern. Ein fester 60-Sekunden-Timer ist nur vertretbar, wenn die vorhandene Restenergie selbst beim Start des Monitors und nach wiederholten Ausfällen noch Wartezeit plus Abschaltung abdeckt. Eine geeignete USV benötigt eine unabhängige Schutzschaltung; die zum Gerät gehörende Überwachung kann zusätzlich einen früheren Notfallpfad bereitstellen.

Ein MAX17048 schätzt den Ladezustand eines Einzelzellen-Systems; der verwandte MAX17049 ist für zwei Zellen in Reihe vorgesehen. Der INA219 misst dagegen Strom, Spannung und Leistung und ist allein keine Prozentanzeige für Restkapazität. Auch ein geschätzter Ladezustand ersetzt die Prüfung bei hoher Last nicht. Ein pauschaler Grenzwert von 20 Prozent garantiert keine bestimmte Restlaufzeit.

4. Ein einfaches Overlay oder ein verzögerter Monitor

Das Overlay gpio-shutdown erzeugt ein Tastaturereignis KEY_POWER. Das Herunterfahren übernimmt beispielsweise systemd-logind. Ohne funktionierenden Empfänger im Betriebssystem besteht keine Abschaltgarantie, insbesondere nicht während jeder Bootphase. GPIO-Nummer, Polarität und Beschaltung müssen zur Platine passen. Das Overlay und der folgende Monitor dürfen dieselbe Leitung nicht gleichzeitig belegen.

Der Monitor verwendet die Python-Schnittstelle von libgpiod 2. Eine ältere 1.x-Installation ist nicht kompatibel. Chipgerät und Leitungs-Offset werden anhand der lokal verfügbaren GPIO-Werkzeuge und der Boarddokumentation ermittelt; eine physische Steckleistennummer ist kein Leitungs-Offset. gpiochip0 und Offset 17 sind keine universellen Vorgaben.

Vorausgesetzt wird ein dokumentierter, 3,3-V-kompatibler Open-Drain-Ausgang: Low bedeutet Netzausfall, High vorhandenes Netz, gemeinsame Masse und geeigneter Pull-up. Open Drain bedeutet, dass der Ausgang das Signal gegen Masse zieht oder freigibt. Ein Pull-up-Widerstand hält das freigegebene Signal auf dem zulässigen hohen Pegel. Ein Kabelbruch kann durch den Pull-up wie vorhandenes Netz aussehen; das Beispiel erkennt diesen Fehler nicht. Ein 5-V-Signal darf nicht direkt an den GPIO. Eine andere Signalausgabe benötigt eine passende elektrische Anpassung und entsprechend geprüfte Logik.

Python
#!/usr/bin/env python3
import argparse
import math
import subprocess
import time


class OutageTimer:
    def __init__(self, delay):
        if not math.isfinite(delay) or delay <= 0:
            raise ValueError("delay must be positive and finite")
        self.delay = delay
        self.since = None
        self.previous = None

    def sample(self, failed, now):
        if type(failed) is not bool or not math.isfinite(now):
            raise ValueError("invalid sample")
        if self.previous is not None and not 0 <= now - self.previous <= 5:
            raise RuntimeError("monitoring gap exceeds 5 seconds")
        self.previous = now
        if not failed:
            self.since = None
            return False
        if self.since is None:
            self.since = now
        return now - self.since >= self.delay


def monitor(read_failed, delay, action, clock=time.monotonic, sleep=time.sleep):
    timer = OutageTimer(delay)
    while True:
        failed = read_failed()  # Read immediately, including at startup.
        if timer.sample(failed, clock()):
            action()
            return
        sleep(1)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--chip", required=True)
    parser.add_argument("--line", required=True, type=int)
    parser.add_argument("--delay", type=float, default=60)
    parser.add_argument("--poweroff", action="store_true")
    args = parser.parse_args()
    OutageTimer(args.delay)
    if args.line < 0:
        parser.error("line offset must be non-negative")

    import gpiod
    from gpiod.line import Bias, Direction, Value
    settings = gpiod.LineSettings(direction=Direction.INPUT,
                                  active_low=False, bias=Bias.PULL_UP)
    with gpiod.request_lines(args.chip, consumer="ups-watch",
                            config={args.line: settings}) as request:
        last = [None]

        def read_failed():
            value = request.get_value(args.line)
            if value not in (Value.ACTIVE, Value.INACTIVE):
                raise RuntimeError("unknown GPIO state")
            failed = value == Value.INACTIVE  # Physical low = mains failure.
            if failed != last[0]:
                print("UPS mains_failed=" + str(failed), flush=True)
                last[0] = failed
            return failed

        def action():
            print("UPS delay reached; poweroff=" + str(args.poweroff), flush=True)
            if args.poweroff:
                subprocess.run(["/usr/bin/systemctl", "--no-block", "poweroff"],
                               check=True, timeout=10)

        monitor(read_failed, args.delay, action)


if __name__ == "__main__":
    main()

Der erste Pegel wird sofort gelesen. Ein bereits aktiver Netzausfall startet damit ebenfalls den Timer. Ein beobachteter High-Pegel setzt die Wartezeit zurück. Die Zeitmessung verwendet eine monotone Uhr. Dieser Zeitgeber misst verstrichene Zeit und springt bei einer Korrektur von Datum oder Systemuhrzeit nicht mit. Zwischen den Abfragen liegt ungefähr eine Sekunde; kurze Pegelwechsel dazwischen können unbemerkt bleiben. Das Beispiel beweist deshalb keine lückenlos anhaltende Unterbrechung und ist keine Echtzeit-Schutzfunktion.

Lesefehler und beobachtete Abfragelücken über fünf Sekunden beenden den Prozess mit Fehler. Ein Neustart setzt den Timer zurück; wiederholte Fehler dürfen deshalb nicht unbemerkt bleiben. Ohne --poweroff protokolliert das Programm nur den erreichten Grenzwert und beendet sich. Dieser Modus eignet sich für die erste kontrollierte Signalprüfung, löst aber keinen Shutdown aus.

5. Den Dienst erst nach der Signalprüfung aktivieren

Das geprüfte Skript gehört nach /usr/local/lib/ups_watch.py, die folgende Unit nach /etc/systemd/system/ups-watch.service. Die Datei /etc/ups-watch.conf muss UPS_CHIP mit dem überprüften Gerätepfad und UPS_LINE mit dem überprüften Offset enthalten. Skript und Konfiguration dürfen nur administrativ verändert werden. Die Unit enthält ausdrücklich --poweroff und kann den Rechner abschalten.

Konfiguration
[Unit]
Description=UPS mains-failure monitor
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
EnvironmentFile=/etc/ups-watch.conf
ExecStart=/usr/bin/python3 /usr/local/lib/ups_watch.py --chip ${UPS_CHIP} --line ${UPS_LINE} --delay 60 --poweroff
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Nach einer Signalprüfung ohne Abschaltoption folgen das Neuladen der systemd-Konfiguration und die bewusste Aktivierung des Dienstes. Ein zusätzliches After=multi-user.target gehört hier nicht hinein: Zusammen mit der Einbindung in dieses Target kann eine zyklische Startreihenfolge entstehen. Die begrenzten Neustarts behandeln vorübergehende Fehler; ein dauerhaft fehlgeschlagener Dienst braucht eine eigene Alarmierung.

6. Abschalten und Wiederanlauf gemeinsam prüfen

systemctl --no-block poweroff stößt das Herunterfahren an. Der Aufruf bestätigt weder dessen Abschluss noch das physische Abschalten der 5-V-Schiene. Eine USV mit Abschalthandshake muss dem Betriebssystem ausreichend Zeit lassen. Bootloaderoptionen für geringen Verbrauch im Haltzustand ersetzen diesen Ablauf nicht.

Auch PSU_MAX_CURRENT=5000 ist keine allgemeine USV-Einstellung: Eine solche Stromvorgabe ersetzt keine tatsächlich für 5 A geeignete Versorgung. Änderungen an Stromgrenzen gehören ausschließlich zu einem passend dokumentierten Aufbau.

Die Abnahme erfolgt mit gesicherter Wiederherstellungsmöglichkeit und kontrollierter Testlast. Zum Testplan gehören ein kurzer Ausfall, ein langer Ausfall, Start bei bereits fehlendem Netz, niedriger Akkustand, erneuter Ausfall vor vollständigem Nachladen sowie Netzwiederkehr während und nach dem Herunterfahren. Ein Produktivdateisystem absichtlich bis zum Spannungskollaps laufen zu lassen ist dafür nicht erforderlich. Die verbleibende Ausgangsenergie lässt sich separat mit einer geeigneten Prüflast messen.

Vorherige Bootprotokolle sind nur bei verfügbarer dauerhafter Speicherung aussagekräftig. Fehlende Einträge in journalctl -b -1 beweisen keinen abrupten Stromverlust; nur im Arbeitsspeicher gehaltene Protokolle verschwinden ebenfalls. Protokoll, beobachteter Shutdown und gemessene Ausgangsspannung ergänzen sich.

Alterung hängt unter anderem von Zellchemie, Temperatur, Ladezustand und Nutzung ab. Eine feste Lebensdauerverdopplung durch eine beliebig abgesenkte Ladespannung ist daraus nicht ableitbar. Lade- und Entladegrenzen bleiben beim freigegebenen Herstellerprofil. Wiederholte Kapazitäts- und Abschalttests nach angemessenem Wartungsplan liefern die Grundlage für einen rechtzeitigen Austausch.

Fragen und Antworten

Startet ein heruntergefahrener Pi bei Netzwiederkehr automatisch?

Nicht zwingend. Bleibt die 5-V-Schiene der USV durchgehend aktiv, entsteht kein neuer Einschaltimpuls. Ein verlässlicher Wiederanlauf benötigt einen dafür vorgesehenen Ausgangszyklus oder eine passende Aufwecksteuerung. Beide Rückkehrfälle – vor und nach Abschalten des USV-Ausgangs – gehören in den Test.

Reicht die 60-Sekunden-Frist als Schutz?

Nur bei nachgewiesener Restenergie für Wartezeit und vollständiges Herunterfahren. Ein bereits fast leerer Akku kann früher ausfallen. Schutzschaltung, Akkumeldung und Fehleralarm bleiben erforderlich.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Eine Frage oder eine Idee für ein Webprojekt? Schreib mir kurz, worum es geht. Das Formular nutzt reCAPTCHA zum Schutz vor Spam.

Kommentar schreiben

Erfahrungen mit anderen Modellen und Rückfragen zum Aufbau sind hier willkommen.

Die E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind mit einem Stern versehen.