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
| Rail | Typical Source | Nominal (V) | Common Tolerance | Load Range |
|---|---|---|---|---|
| 3.3V | LDO or buck (e.g. TPS62840) | 3.3 | +/-2% | 0-500 mA |
| 5V | Boost or USB VBUS | 5.0 | +/-5% | 0-2 A |
| 1.8V | LDO (e.g. TLV75518) | 1.8 | +/-2% | 0-300 mA |
| 1.2V | Core LDO or buck | 1.2 | +/-3% | 0-1 A |
| 12V | Boost or input direct | 12.0 | +/-5% | 0-3 A |
| VBAT | Li-ion cell | 3.0-4.2 | varies | N/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
| Measurement | Instrument | When to Use |
|---|---|---|
| DC voltage | DMM / ADC | Every unit |
| No-load current | Current clamp or sense resistor | First article, incoming inspection |
| Full-load current | Power supply readback | Functional test |
| Ripple (peak-to-peak) | Oscilloscope or RMS ADC | Design validation, process escapes |
Power Sequencing
- Enable bench supply or fixture relay
- Wait for the slowest regulator to settle (typically 1-5 ms)
- Measure all rails
- Execute functional tests
- Disable rails in reverse order
Complete OpenHTF Test with TofuPilot
tests/power_rails_test.py
import timeimport openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import TofuPilotclass 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
| Symptom | Likely Cause | First Check |
|---|---|---|
| Voltage reads 0 V | Regulator not enabled; blown input fuse | Check enable pin logic level; measure input voltage |
| Voltage below minimum | Current limit reached; input undervoltage | Measure current draw; check input supply voltage drop |
| Voltage above maximum | Feedback resistor open or wrong value | Measure feedback voltage divider; confirm BOM |
| Voltage oscillates / noisy | Output cap missing or wrong type | Check ESR of output cap; inspect for tombstoned parts |
| Correct voltage, excessive current | Short on downstream net | Disconnect loads one by one to isolate short |
| Soft-start too slow | Large output cap; wrong soft-start resistor | Compare measured rise time to datasheet spec |