The Raspberry Pi is primarily powered by a 5V DC supply via its USB-C port (requiring a 5V/5A PD profile for the Pi 5), but it can also accept power directly through the 5V and GND pins on the 40-pin GPIO header, or via a Power over Ethernet (PoE+) HAT. While plugging in the official power supply is trivial, designing a robust embedded node that monitors its own power rail, logs current draw, and gracefully handles brownouts requires a deeper understanding of the Pi's Power Management IC (PMIC) and I2C sensor integration.
How Is Raspberry Pi Powered? Delivery Methods Compared
Before wiring up sensors, you need to know exactly how juice gets to the board's 3.3V and 5V rails. The Pi 5 uses a Renesas DA9098 PMIC, which is far more capable than the linear regulators on older Pi 3 and 4 boards, but it still strictly enforces voltage thresholds. Here is how the main power delivery methods stack up for embedded deployments.
| Power Method | Nominal Voltage | Max Current | Best Use Case | Risk Level |
|---|---|---|---|---|
| USB-C (Official 27W PSU) | 5.0V (PD negotiated) | 5.0A | Standard desktop, heavy peripheral loads (NVMe, USB 3.0 hubs) | Low (Safest, isolated) |
| GPIO 5V Injection (Pins 2/4) | 5.0V - 5.25V | Depends on wire AWG | Custom PCBs, robotics, bypassing USB-C PD negotiation delays | High (No reverse polarity protection, bypasses PMIC input FETs) |
| PoE+ HAT (e.g., Pi 5 PoE+ HAT) | 5.0V (Stepped down from 48V) | 5.0A (via onboard buck converter) | Remote IP cameras, ceiling-mounted IoT gateways, long cable runs | Medium (Requires 802.3at switch, thermal output on the HAT) |
| UPS HAT (e.g., PiJuice V2) | 5.0V (Battery backed) | 3.0A - 5.0A | Off-grid weather stations, data loggers requiring safe shutdown | Medium (Lithium cell management, I2C bus contention risks) |
If you are injecting power via the GPIO header, never exceed 5.25V. The board lacks the robust overvoltage clamping found on dedicated industrial PLCs. For the project below, we will use the standard USB-C path but monitor the 5V rail behavior using an external I2C shunt sensor.
Project Build: Pi 5 INA219 Power Monitor & Safe Shutdown
This build creates a headless power-monitoring node. It reads the bus voltage and current draw of a 12V load (like a solenoid or a high-power LED array) using an INA219 sensor, while simultaneously keeping an eye on the Pi's own health. If the sensor detects a severe voltage sag on the monitored rail, the script triggers a safe OS shutdown to prevent filesystem corruption.
Parts List
- Microcontroller: Raspberry Pi 5 (8GB Model B)
- Power Supply: Official Raspberry Pi 27W USB-C Power Supply (5.1V/5A)
- Sensor: Adafruit INA219 High Side DC Current Sensor Breakout (Product ID: 904)
- Wiring: 4x Female-to-Female jumper wires (22 AWG silicone)
- Load (for testing): 12V DC water pump or solenoid valve with a separate 12V power brick
Pin Mapping Table
The INA219 breakout includes a 3.3V regulator and logic-level shifting, making it safe to connect directly to the Pi 5's 3.3V I2C bus without an external level shifter.
| Raspberry Pi 5 GPIO | Physical Pin # | INA219 Breakout Pin | Function |
|---|---|---|---|
| 3V3 Power | 1 | VCC | Logic power (3.3V) |
| Ground | 6 | GND | Common ground reference |
| GPIO 2 (SDA1) | 3 | SDA | I2C Data Line |
| GPIO 3 (SCL1) | 5 | SCL | I2C Clock Line |
Wiring Steps and Python Monitoring Code
Follow these steps to wire the hardware and deploy the monitoring script. According to the Adafruit INA219 guide, the sensor measures the voltage drop across a 0.1 ohm shunt resistor to calculate current.
- De-energize everything. Unplug the Pi's USB-C power and the 12V load supply.
- Wire the I2C bus. Connect Pi Pin 1 to INA219 VCC, Pin 6 to GND, Pin 3 to SDA, and Pin 5 to SCL.
- Wire the load through the sensor. Connect your 12V supply positive to the INA219
VIN+screw terminal. ConnectVOUT-to the positive lead of your 12V load. Connect the 12V supply negative directly to the load's negative lead (the INA219 is a high-side sensor; it does not break the ground path). - Enable I2C on the Pi. Boot the Pi, open a terminal, and run
sudo raspi-config. Navigate to Interface Options > I2C and enable it. Reboot. - Install the Python library. Because Raspberry Pi OS Bookworm enforces PEP 668 (externally managed environments), you must use a virtual environment.
Bench Tip: Never use
sudo pip3 installon Bookworm. It will break your OS package manager. Always create a venv for hardware scripts.mkdir ~/power-monitor && cd ~/power-monitor python3 -m venv venv source venv/bin/activate pip3 install adafruit-circuitpython-ina219
Below is the complete, compilable Python script. It initializes the I2C bus, configures the INA219 for 16V/400mA range (adjustable for your specific shunt), and polls the bus voltage every two seconds.
import time
import board
import busio
from adafruit_ina219 import INA219, ADCResolution, BusVoltageRange
import subprocess
import sys
# Pin definitions are handled by the 'board' module mapping to physical I2C pins
i2c = busio.I2C(board.SCL, board.SDA)
# Initialize the INA219 sensor at default I2C address 0x40
try:
ina219 = INA219(i2c, addr=0x40)
except ValueError as e:
print(f'Hardware Error: {e}')
sys.exit(1)
# Configure sensor for up to 16V bus voltage and 400mA max current
ina219.bus_voltage_range = BusVoltageRange.RANGE_16V
ina219.adc_resolution = ADCResolution.ADCRES_12BIT_32S
def safe_shutdown():
print('Critical voltage sag detected! Initiating safe shutdown...')
subprocess.run(['sudo', 'shutdown', '-h', 'now'])
print('Monitoring power rail. Press Ctrl+C to exit.')
try:
while True:
bus_voltage = ina219.bus_voltage
current_ma = ina219.current
power_mw = ina219.power
print(f'Bus: {bus_voltage:6.3f} V | Current: {current_ma:7.2f} mA | Power: {power_mw:6.3f} mW')
# If the 12V rail drops below 10.5V under load, trigger shutdown to protect the load/controller
if bus_voltage < 10.5 and current_ma > 50:
safe_shutdown()
break
time.sleep(2.0)
except OSError as e:
print(f'I2C Communication Lost: {e}')
except KeyboardInterrupt:
print('Monitoring stopped by user.')
finally:
i2c.deinit()
Debugging Power Failures: Exact Errors and Fixes
When working with I2C sensors and Pi power rails, you will inevitably hit communication or brownout errors. Here is how to debug the two most common failures in this exact build.
Error 1: Python I2C Initialization Failure
Exact Error String: ValueError: No I2C device at address: 0x40
This means the Python busio library scanned the I2C bus but the INA219 did not acknowledge its default address.
Ranked Causes:
- I2C Interface Disabled: You forgot to enable I2C in
raspi-configor forgot to reboot after enabling it. - Swapped SDA/SCL: You wired GPIO 2 to SCL and GPIO 3 to SDA. The Pi 5 is strict about these assignments.
- Address Jumper Bridged: The Adafruit INA219 breakout has address jumpers on the back. If you accidentally bridged the 'A0' jumper with solder, the address shifts to
0x41.
1. Run
sudo i2cdetect -y 1 in the terminal. If you don't see 40 in the grid, it's a wiring or config issue.2. Verify continuity between Pi Pin 3 and INA219 SDA using a multimeter in beep-test mode.
3. Check the back of the INA219 breakout for accidental solder bridges on the address pads.
Error 2: OS-Level Brownout Warning
Exact Error String: Under-voltage detected! (0x00050005) (Visible in dmesg or as a lightning bolt icon on desktop).
According to the official Raspberry Pi configuration docs, this flag is thrown when the PMIC detects the 5V input rail dropping below the safe threshold (typically ~4.63V on older Pis, and managed dynamically via the DA9098 on the Pi 5).
Ranked Causes:
- Undersized Power Supply: Using a standard 5V/3A phone charger instead of the official 27W (5A) supply. The Pi 5 will throttle and throw this error if you plug in a high-draw USB peripheral.
- Voltage Drop in the Cable: Using a cheap, thin-wire USB-C cable. A 3-foot cable with 28 AWG power wires can drop 0.5V at a 4A draw, pushing the PMIC input below the threshold.
- Backpowering via USB Peripherals: A powered USB hub that is backfeeding 5V into the Pi's USB port, confusing the PMIC's input multiplexer.
Extending and Simplifying Your Power Build
Depending on your deployment environment, you may want to scale this project up for industrial use or strip it down for a quick weekend prototype.
How to Simplify the Build
If you only need to know how much power the Pi is drawing from the wall and don't care about monitoring a secondary 12V load, ditch the INA219 entirely. Instead, use a smart plug with local energy monitoring, like the Shelly Plug US or a TP-Link Tapo P110. You can query these devices over your local network using the python-kasa or shelly Python libraries. This eliminates I2C wiring, removes the risk of frying the Pi's GPIO pins, and provides mains-level AC wattage data.
How to Extend the Build
To turn this into a production-ready remote telemetry node:
- Add MQTT Publishing: Import the
paho-mqttlibrary and publish thebus_voltageandcurrent_mavariables to a local Mosquitto broker. This allows Home Assistant to graph the current draw of your 12V load over time. - Hardware Cutoff Relay: Instead of just shutting down the Pi's OS when a voltage sag occurs, wire a GPIO pin (e.g., GPIO 17) to an opto-isolated relay module. If the INA219 detects a short circuit or massive overcurrent event on the 12V rail, the Python script can pull GPIO 17 high, physically cutting power to the load before the wiring melts.
- Watchdog Timer (WDT): Enable the Pi's hardware watchdog via
systemd. If your Python script crashes due to anOSError: [Errno 121] Remote I/O error(which happens if the I2C bus gets locked up by electrical noise), the WDT will hard-reboot the Pi automatically.
Understanding how the Raspberry Pi is powered at the PMIC level transforms it from a fragile desktop toy into a resilient embedded controller. Always respect the 5V/5A PD requirements of the Pi 5, use high-quality USB-C cables with 20 AWG power lines, and never inject GPIO power without a fused, regulated buck converter.






