Cpl and Cpu are one-sided capability indices. Cpl measures how far the process mean is from the lower specification limit. Cpu measures how far it is from the upper specification limit. Together they form Cpk: Cpk = min(Cpl, Cpu).
The Formulas
Cpu = (USL - X̄) / 3σ
Cpl = (X̄ - LSL) / 3σ
Where:
- USL is the upper specification limit
- LSL is the lower specification limit
- X̄ is the process mean
- σ is the sample standard deviation (n-1 divisor)
Each index expresses the distance from the process mean to one spec limit in units of 3σ. A value of 1.0 means the 3σ boundary exactly touches that limit. Above 1.0, there's margin. Below 1.0, some units are likely exceeding that limit.
How Cpl and Cpu Build Cpk
Cpk is simply the minimum of the two: Cpk = min(Cpl, Cpu). This means Cpk always reflects the side that's closest to its spec limit.
But looking at Cpl and Cpu separately tells you more than Cpk alone.
| Cpl | Cpu | Cpk | What It Tells You |
|---|---|---|---|
| 1.8 | 1.2 | 1.2 | Process is closer to the upper limit. Mean is shifted high. |
| 0.9 | 1.6 | 0.9 | Process is closer to the lower limit. Mean is shifted low. |
| 1.4 | 1.4 | 1.4 | Process is centered. Both sides have equal margin. |
When Cpk is low, Cpl and Cpu tell you which direction to adjust. If Cpu is the bottleneck, the process mean needs to shift down. If Cpl is the bottleneck, it needs to shift up.
One-Sided Specifications
Many measurements only have one spec limit. Maximum leakage current, maximum response time, minimum signal strength. For these, only one index applies.
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
@htf.measures(
# Upper limit only: TofuPilot computes Cpu
htf.Measurement("leakage_current")
.in_range(maximum=0.001)
.with_units(units.AMPERE),
# Lower limit only: TofuPilot computes Cpl
htf.Measurement("signal_strength")
.in_range(minimum=-80),
# Both limits: TofuPilot computes Cpl, Cpu, and Cpk
htf.Measurement("output_voltage")
.in_range(minimum=4.75, maximum=5.25)
.with_units(units.VOLT),
)
def measure_board(test):
test.measurements.leakage_current = 0.00034
test.measurements.signal_strength = -62
test.measurements.output_voltage = 5.01
def main():
test = htf.Test(measure_board)
with TofuPilot(test):
test.execute(test_start=lambda: "PCB-0042")
if __name__ == "__main__":
main()TofuPilot handles this automatically. When only maximum is set, it shows Cpu and displays "--" for Cpl. When only minimum is set, it shows Cpl and displays "--" for Cpu.
Reading Cpl and Cpu in TofuPilot
Open the Process Control page, select a numeric measurement, and switch to the Capability tab. The first KPI row shows Cpk, Cp, Cpl, and Cpu left to right.
Hover over Cpl or Cpu to see its formula. Click either to toggle its line on the daily trend chart. Tracking Cpl and Cpu separately over time reveals directional drift. If Cpu is falling while Cpl is rising, the process mean is shifting upward toward USL.
Ppl and Ppu
The long-term equivalents are Ppl and Ppu. Same formulas but with overall σo (n divisor) instead of sample σ (n-1 divisor). They appear in the second (teal) KPI row and help you see whether one-sided drift is a short-term event or a persistent long-term trend.