Standalone C++ application for monitoring Waveshare UPS HAT (E) and performing safe system shutdown on power loss or low battery voltage.
This project provides a lightweight, systemd-integrated solution for monitoring the Waveshare UPS HAT (E) expansion board on Raspberry Pi systems. It communicates with the UPS HAT via I2C and automatically shuts down the system when power is lost or battery voltage drops below safe thresholds.
For detailed hardware specifications and register documentation, refer to:
- I2C communication with Waveshare UPS HAT (E) (I2C address: 0x2D)
- Real-time monitoring of battery status, charging state, and cell voltages
- Automatic shutdown on power loss (configurable delay)
- Low voltage protection with configurable thresholds
- Thermal monitoring (CPU temperature and cooling state)
- Comprehensive logging via syslog/journald
- Systemd service integration
- No ROS2 dependencies - pure C++ standalone application
- Raspberry Pi with I2C enabled
- Waveshare UPS HAT (E) hardware
- CMake 3.10 or higher
- C++17 compatible compiler (GCC/Clang)
- Linux system with systemd
git clone <repository-url>
cd ups-hat-controller
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
sudo make installConfiguration can be provided via:
- Configuration file:
/etc/ups-hat-controller/ups-hat-controller.conf - Environment variables: Set in
/etc/ups-hat-controller/ups-hat-controller.envor systemd service - Command line:
--config <path>option
I2C_BUS: I2C bus number (default: 1)I2C_ADDR: I2C device address in decimal (default: 45 = 0x2d)PUBLISH_RATE_HZ: Monitoring rate in Hz (default: 1.0)SHUTDOWN_DELAY_SEC: Delay before shutdown on power loss in seconds (default: 60)LOW_VOLTAGE_THRESHOLD: Low voltage threshold in millivolts (default: 3150)LOW_VOLTAGE_THRESHOLD_COUNT: Number of consecutive low voltage detections before shutdown (default: 30)ENABLE_SYSLOG: Enable syslog logging (default: true)
After building:
sudo make installThis will install:
- Executable:
/usr/local/bin/ups_hat_controller - Systemd service:
/etc/systemd/system/ups-hat-controller.service - Config file:
/etc/ups-hat-controller/ups-hat-controller.conf
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable ups-hat-controller.service
sudo systemctl start ups-hat-controller.serviceCheck status:
sudo systemctl status ups-hat-controller.serviceView logs:
sudo journalctl -u ups-hat-controller.service -fThe service needs access to I2C devices. Ensure the user running the service (or root) has access to /dev/i2c-* devices. You may need to add the user to the i2c group:
sudo usermod -aG i2c <username>Logs are written to systemd journal (journald) via syslog. View logs using:
sudo journalctl -u ups-hat-controller.service -fThe application logs status changes only (power transitions, charge state changes) to reduce log verbosity.
The controller will initiate system shutdown when:
- Power loss: Mains power is lost and not restored within
SHUTDOWN_DELAY_SECseconds - Low voltage: Any cell voltage drops below
LOW_VOLTAGE_THRESHOLDmV while battery current is below 50 mA, detected forLOW_VOLTAGE_THRESHOLD_COUNTconsecutive cycles
Shutdown is performed by:
- Sending shutdown command to UPS HAT (register 0x01 = 0x55)
- Executing
systemctl poweroff
The application monitors charge states according to the UPS HAT (E) Register documentation:
- 0: Standby
- 1: Trickle Charge
- 2: Constant Current Charge
- 3: Constant Voltage Charge
- 4: Charging Pending
- 5: Full State
- 6: Charge Timeout
Check I2C device availability:
ls -l /dev/i2c-*
i2cdetect -y 1The UPS HAT should appear at address 0x2D.
Ensure user is in i2c group or run as root:
groups
sudo usermod -aG i2c $USERCheck service logs:
sudo journalctl -u ups-hat-controller.service -n 50Check configuration:
sudo /usr/local/bin/ups_hat_controller --helpIf I2C is not enabled:
sudo raspi-config
# Navigate to: Interfacing Options -> I2C -> Enable
sudo rebootMIT License - see LICENSE file for details.