UPS

Notes

https://www.waveshare.com/ups-hat-e.htm

The pogo pins didn’t supply voltage until I used a pencil eraser to clean the bottom of the Pi’s contacts, and them too for good measure.

Once working, I downloaded the python same as described in

https://www.waveshare.com/wiki/UPS_HAT_(E)

You must sudo the first example, but the second injects into the GUI seemingly OK (though I didn’t test to see if it was accurate).

Then I used ChatGPT to make a UPS monitoring script. It did a really good job. I’d have hacked something up in bash, but python is better for reading registers (probably)

I had the gui version of RaspOS installed so there might have been other libraries than described in the wiki that were used without being explicitly called out.

sudo vi /usr/local/bin/ups-monitor.py
sudo chmod +x /usr/local/bin/ups-monitor.py
#!/usr/bin/env python3
import time
import subprocess
from smbus2 import SMBus

I2C_ADDR = 0x2D            # UPS HAT (E) I2C address
RUNTIME_LOW  = 0x28        # low 8-bit of remaining time (minutes)
RUNTIME_HIGH = 0x29        # high 8-bit

SHUTDOWN_LIMIT = 20        # minutes

def get_remaining_minutes():
    try:
        with SMBus(1) as bus:
            lo = bus.read_byte_data(I2C_ADDR, RUNTIME_LOW)
            hi = bus.read_byte_data(I2C_ADDR, RUNTIME_HIGH)
            remaining = (hi << 8) | lo
            return remaining
    except Exception as e:
        print(f"UPS read error: {e}")
        return None

def shutdown():
    print("Remaining runtime below threshold — initiating shutdown …")
    subprocess.run(["sudo", "shutdown", "-h", "now"])

def main():
    while True:
        remaining = get_remaining_minutes()
        if remaining is not None:
            print(f"[UPS HAT E] Remaining runtime: {remaining} minutes")
            if remaining < SHUTDOWN_LIMIT:
                shutdown()
                break
        else:
            print("Could not read remaining runtime from UPS — retrying")

        time.sleep(30)  # check every 30 seconds

if __name__ == "__main__":
    main()
sudo nano /etc/systemd/system/ups-monitor.service
[Unit]
Description=Waveshare UPS Runtime Monitor
After=multi-user.target
StartLimitIntervalSec=0

[Service]
Type=simple
ExecStart=/usr/local/bin/ups-monitor.py
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable ups-monitor.service
sudo systemctl start ups-monitor.service

Last modified April 7, 2026: waveshare updates (83e1bfa)