Chapter 2: Measuring Power Consumption

You cannot optimize what you cannot measure. Before touching a single power setting, establish a baseline. This chapter covers the tools and techniques for measuring power consumption at every scale — from a microamp-drawing sensor node to a server pulling hundreds of watts.


2.1 The Basics: Voltage, Current, and Power

Power (in watts) is voltage multiplied by current: P = V × I. Energy consumed over time is E = P × t, commonly expressed in watt-hours (Wh) or milliamp-hours (mAh) at a given voltage.

When measuring a battery-powered device, you typically care about:


2.2 The INA219: Current Sensing over I2C

The INA219 is a bidirectional current and power monitor that communicates over I2C. It uses a shunt resistor (typically 0.1 Ω) to measure current through a small voltage drop, then reports voltage, current, and power via registers.

Wiring (for a 3.3 V device):

Battery (+) → INA219 VIN+ → INA219 VIN- → Device (+)
Battery (-) → Device (-)
Raspberry Pi SDA → INA219 SDA
Raspberry Pi SCL → INA219 SCL

The INA219 must be in series with the power supply rail you want to measure, not in parallel.

Python reading (smbus2):

import smbus2, struct, time

BUS, ADDR = 1, 0x40
SHUNT_OHMS = 0.1

def read_ina219(bus):
    raw = bus.read_i2c_block_data(ADDR, 0x01, 2)  # shunt voltage reg
    shunt_mv = struct.unpack('>h', bytes(raw))[0] * 0.01  # LSB = 10 µV
    raw = bus.read_i2c_block_data(ADDR, 0x02, 2)  # bus voltage reg
    bus_v = ((struct.unpack('>h', bytes(raw))[0] >> 3) * 4) / 1000
    current_ma = shunt_mv / SHUNT_OHMS
    power_mw = bus_v * current_ma
    return bus_v, current_ma, power_mw

with smbus2.SMBus(BUS) as bus:
    while True:
        v, i, p = read_ina219(bus)
        print(f"{v:.3f} V  {i:.1f} mA  {p:.1f} mW")
        time.sleep(1)

The full logger with CSV output is in code/ina219_logger.py.


2.3 Using a Multimeter for Current Measurement

A digital multimeter in current mode can measure average draw accurately. Place it in series with the power supply — never in parallel.

Key pitfalls:

For sleep current measurement, use a dedicated microammeter or the INA219 configured to its highest gain setting (±40 mV range with 0.1 Ω shunt → ±400 mA range; swap to 1 Ω shunt for ±40 mA range and better resolution at low currents).


2.4 Measuring Power on Linux: powertop

powertop is the primary tool for measuring and diagnosing power consumption on Linux systems. Run it as root:

sudo powertop

The Overview tab shows estimated power consumption by component. The Wakeups tab lists processes and kernel drivers ordered by how often they wake the CPU from idle — this is the most actionable view for reducing laptop idle power.

The Tunables tab shows settings that powertop recommends enabling. You can apply all of them at once with:

sudo powertop --auto-tune

Note: --auto-tune is not persistent across reboots. Chapter 7 covers how to make these settings permanent via TLP.

To export a report for later analysis:

sudo powertop --csv=report.csv --time=30

The CSV export includes per-process wakeup counts that you can analyze with the script in code/powertop_report_parser.py.


2.5 Intel RAPL: Reading CPU Power Programmatically

Intel’s Running Average Power Limit (RAPL) interface exposes energy consumption counters through sysfs. These are accurate enough for benchmarking and power profiling.

# List available RAPL domains
ls /sys/class/powercap/intel-rapl/

# Read current energy of package 0 (in microjoules)
cat /sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj

By reading energy_uj twice with a known time interval between, you can compute average package power:

import time, pathlib

def rapl_power_w(domain="intel-rapl:0", interval=1.0):
    p = pathlib.Path(f"/sys/class/powercap/intel-rapl/{domain}/energy_uj")
    e0 = int(p.read_text())
    time.sleep(interval)
    e1 = int(p.read_text())
    return (e1 - e0) / 1e6 / interval  # watts

print(f"Package power: {rapl_power_w():.2f} W")

RAPL covers CPU cores and uncore (integrated GPU, memory controller). It does not include disk, NIC, or display. The full monitoring script is in code/rapl_monitor.py.


2.6 Choosing the Right Tool

Scenario Tool
Embedded device current INA219 or shunt + oscilloscope
Laptop idle power powertop
CPU-specific power on x86 RAPL (turbostat, rapl_monitor.py)
Full system wall power Kill-a-Watt or smart plug with energy monitoring
Server total consumption IPMI (ipmitool) or smart PDU

Always cross-check software measurements against wall-power measurements at least once. RAPL in particular does not count all components and will underestimate total system power by 20–40%.


← Chapter 1: Battery Chemistry and BMS Table of Contents Chapter 3: Power Fundamentals and Voltage Regulators →