Open-source firmware for the UPSPlus uninterruptible power supply (UPS) module (EP-0136) designed for Raspberry Pi. The device has been declared as EOL. This firmware runs on the STM32F030F4P6 microcontroller and provides battery monitoring, power management, and I2C communication capabilities.
The code has been re-written from the ground up using a combination of ChatGPT and Cursor and the documents/UPSPlus_Refactoring_Plan.md document.
- UPSPlus HAT EP-0136
- Raspberry Pi (compatible models)
- Battery monitoring via I2C register map.
- Protection shutdown at configured protection voltage.
- Auto power-on with configurable low-battery threshold and load-on delay.
- Boot brownout backoff learning (see Boot Brownout Backoff).
- Factory Testing pages (0xFC–0xFF) for diagnostics.
- OTA firmware update support.
- The Func Key button is debounced at 50 ms.
- If the load is off, short press powers on the load when the UPS is off and conditions are safe (aka there is sufficient charge in the batteries).
- If the load is on, short press has no action.
- Long press (>= 10 s) when the load is on: powers off.
- Long press (>= 10 s) when the load is off: triggers a factory reset.
If the RPi browns out shortly after power-on (battery voltage drops to or below the protection
threshold within 5 minutes of RPi being powerd on), the firmware treats this as a boot failure
and increments the internal load.on.delay by 1 minute before the next auto power-on attempt.
Learning stops after a successful 5-minute run without a protection-triggered shutdown. The
learned delay is clamped to 60 minutes, persists across power cycles, and is cleared only by
factory reset. A user write to load.on.delay becomes the new baseline; any further learning
adds minutes on top of that value.
- Ensure the UPSPlus is connected to your Raspberry Pi.
- Put the UPSPlus into OTA mode by removing all power supplies and batteries.
- Hold the Func Key button down and insert batteries.
- Verify OTA mode with
i2cdetect -y 1; register 0x18 should be visible. - Copy the compiled binary to the same directory as
tools/OTA_upgrade.pyand rename it toupsplus_oss.binif needed. - Run:
python3 tools/OTA_upgrade.py
I2C address: 0x17 on bus 1 (Raspberry Pi default).
Read examples:
i2cget -y 1 0x17 0x01
i2cget -y 1 0x17 0x0D w
i2cdump -y 1 0x17
Note: multi-byte registers are little-endian (LSB at lower address).
0x01–0x0CVoltages and temperature (RO)0x01–0x02MCU voltage (mV)0x03–0x04Pogopin voltage (mV)0x05–0x06Battery voltage (mV)0x07–0x08USB-C voltage (mV)0x09–0x0AMicro-USB voltage (mV)0x0B–0x0CTemperature (°C, integer)
0x0D–0x12Battery thresholds (RW)0x0D–0x0EFull voltage (mV)0x0F–0x10Empty voltage (mV)0x11–0x12Protection voltage (mV)
0x13–0x14Battery percent (RO; LSB=percent, MSB=0x00)0x15–0x16Sample period minutes (RW)0x17Power status (RO; bit0=power, bit1=calibration window active)0x18Shutdown countdown seconds (RW)0x19Auto power on (RW; 0/1)0x1ARestart countdown seconds (RW)0x1BFactory reset (RW; write 1 to reset)0x1C–0x27Runtime counters (RO)0x1C–0x1FCumulative runtime (s)0x20–0x23Charging time (s)0x24–0x27Current runtime (s)
0x28–0x29Firmware version (RO)0x2ABattery parameters self-programmed (RW; 0=self-program, 1=manual)0x2BLow battery percent threshold (RW)0x2C–0x2DLoad on delay (RW, seconds)0x2E–0xEFReserved (RO 0x00, writes ignored)0xF0–0xFBMCU serial number (RO)0xFC–0xFFFactory Testing (RW selector + RO pages)0xFCSelector (0=disabled)0xFD–0xFFPage data
Factory Testing selectors:
0x01State page: power_state, charger_state, learning_mode (legacy name; indicates calibration window active)0x02Button page: button_state, click, hold_ticks (LSB)0x03Charger/window page: charger_present, window_active, window_due0x04Protection page: protection_active, below_count, pending_power_cut
- Development setup and build steps:
documents/Development_Guide.md - Behavior specification (contract for features):
documents/UPSPlus_Behavior_Spec.md - Refactoring plan and rationale:
documents/UPSPlus_Refactoring_Plan.md
A pre-built Linux NUT driver for UPSPlus is available here: https://github.com/dacarson/nut/releases/tag/v2.8.2-upsplus
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
This firmware is provided as-is. Use at your own risk. The authors are not responsible for any damage to hardware or data loss resulting from the use of this firmware.