Skip to content
Test Types & Methods

Test Power Rails on a PCBA

Learn how to test PCBA power rails with Python, including voltage regulator limits, current draw checks, sequencing, and automated logging via OpenHTF.

JJulien Buteau
beginner8 min readMarch 14, 2026

Power rail testing validates that voltage regulators produce correct output before any downstream components are exercised. Run these checks first: a failed rail contaminates every subsequent measurement and risks damaging the device under test.

Prerequisites

  • TofuPilot account and API key
  • OpenHTF and TofuPilot installed (pip install openhtf tofupilot)
  • Bench power supply or fixture with controllable power enable line
  • Digital multimeter or DAQ accessible from Python

Common Power Rails on a PCBA

RailTypical SourceNominal (V)Common ToleranceLoad Range
3.3VLDO or buck (e.g. TPS62840)3.3+/-2%0-500 mA
5VBoost or USB VBUS5.0+/-5%0-2 A
1.8VLDO (e.g. TLV75518)1.8+/-2%0-300 mA
1.2VCore LDO or buck1.2+/-3%0-1 A
12VBoost or input direct12.0+/-5%0-3 A
VBATLi-ion cell3.0-4.2variesN/A

Setting Limits from Datasheets

Pull limits directly from the voltage regulator datasheet.

TPS62840 (3.3V buck, Texas Instruments)

  • Typical output accuracy: +/-1.5% at room temperature
  • Over temperature: +/-2.5%
  • Production test at room temp, use +/-2%: 3.234 V to 3.366 V

TLV75518 (1.8V LDO, Texas Instruments)

  • Initial accuracy: +/-0.75%
  • Add +/-0.5% for resistor divider tolerance
  • Production test, use +/-1.5%: 1.773 V to 1.827 V

Always add margin for your measurement system's accuracy. A 16-bit ADC with a 5 V reference introduces roughly +/-0.08 mV of quantization.

Measurement Techniques

MeasurementInstrumentWhen to Use
DC voltageDMM / ADCEvery unit
No-load currentCurrent clamp or sense resistorFirst article, incoming inspection
Full-load currentPower supply readbackFunctional test
Ripple (peak-to-peak)Oscilloscope or RMS ADCDesign validation, process escapes

Power Sequencing

  1. Enable bench supply or fixture relay
  2. Wait for the slowest regulator to settle (typically 1-5 ms)
  3. Measure all rails
  4. Execute functional tests
  5. Disable rails in reverse order

Complete OpenHTF Test with TofuPilot

tests/power_rails_test.py
import time
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot


class PowerFixturePlug(htf.plugs.BasePlug):
    """Controls fixture relay and reads voltages from a DAQ."""

    def enable_power(self):
        # Assert fixture relay to apply supply voltage to DUT
        pass

    def disable_power(self):
        # De-assert fixture relay
        pass

    def read_voltage(self, channel: str) -> float:
        # Return DC voltage in volts on the named channel
        # Replace with your actual instrument driver
        voltages = {
            "rail_3v3": 3.312,
            "rail_1v8": 1.796,
            "rail_5v0": 4.985,
        }
        return voltages.get(channel, 0.0)

    def read_current_amps(self, channel: str) -> float:
        # Return current draw in amps via sense resistor
        currents = {
            "rail_3v3_current": 0.142,
            "rail_1v8_current": 0.085,
            "rail_5v0_current": 0.310,
        }
        return currents.get(channel, 0.0)

    def tearDown(self):
        self.disable_power()


@htf.plug(fixture=PowerFixturePlug)
def enable_and_settle(test, fixture):
    """Enable DUT power and wait for all regulators to settle."""
    fixture.enable_power()
    time.sleep(0.010)  # 10 ms covers TPS62840 and TLV75518 soft-start


@htf.plug(fixture=PowerFixturePlug)
@htf.measures(
    htf.Measurement("rail_3v3_voltage")
    .in_range(minimum=3.234, maximum=3.366)
    .with_units(units.VOLT)
    .doc("3.3V rail: TPS62840 +/-2% at room temp"),
    htf.Measurement("rail_3v3_current")
    .in_range(minimum=0.0, maximum=0.500)
    .with_units(units.AMPERE)
    .doc("3.3V rail current draw"),
)
def check_3v3_rail(test, fixture):
    test.measurements.rail_3v3_voltage = fixture.read_voltage("rail_3v3")
    test.measurements.rail_3v3_current = fixture.read_current_amps("rail_3v3_current")


@htf.plug(fixture=PowerFixturePlug)
@htf.measures(
    htf.Measurement("rail_1v8_voltage")
    .in_range(minimum=1.773, maximum=1.827)
    .with_units(units.VOLT)
    .doc("1.8V rail: TLV75518 +/-1.5% including divider tolerance"),
    htf.Measurement("rail_1v8_current")
    .in_range(minimum=0.0, maximum=0.300)
    .with_units(units.AMPERE)
    .doc("1.8V rail current draw"),
)
def check_1v8_rail(test, fixture):
    test.measurements.rail_1v8_voltage = fixture.read_voltage("rail_1v8")
    test.measurements.rail_1v8_current = fixture.read_current_amps("rail_1v8_current")


@htf.plug(fixture=PowerFixturePlug)
@htf.measures(
    htf.Measurement("rail_5v0_voltage")
    .in_range(minimum=4.750, maximum=5.250)
    .with_units(units.VOLT)
    .doc("5V boost rail +/-5%"),
    htf.Measurement("rail_5v0_current")
    .in_range(minimum=0.0, maximum=2.000)
    .with_units(units.AMPERE)
    .doc("5V rail current draw"),
)
def check_5v0_rail(test, fixture):
    test.measurements.rail_5v0_voltage = fixture.read_voltage("rail_5v0")
    test.measurements.rail_5v0_current = fixture.read_current_amps("rail_5v0_current")


@htf.plug(fixture=PowerFixturePlug)
def disable_power_phase(test, fixture):
    """Disable DUT power after all measurements complete."""
    fixture.disable_power()


def main():
    test = htf.Test(
        enable_and_settle,
        check_3v3_rail,
        check_1v8_rail,
        check_5v0_rail,
        disable_power_phase,
        test_name="Power Rails Test",
    )

    with TofuPilot(test):
        test.execute(test_start=lambda: input("Enter serial number: ").strip())


if __name__ == "__main__":
    main()

Power Rail Failure Diagnostics

SymptomLikely CauseFirst Check
Voltage reads 0 VRegulator not enabled; blown input fuseCheck enable pin logic level; measure input voltage
Voltage below minimumCurrent limit reached; input undervoltageMeasure current draw; check input supply voltage drop
Voltage above maximumFeedback resistor open or wrong valueMeasure feedback voltage divider; confirm BOM
Voltage oscillates / noisyOutput cap missing or wrong typeCheck ESR of output cap; inspect for tombstoned parts
Correct voltage, excessive currentShort on downstream netDisconnect loads one by one to isolate short
Soft-start too slowLarge output cap; wrong soft-start resistorCompare measured rise time to datasheet spec

More Guides

Put this guide into practice