How to Design an End-of-Line Test Operator Screen
An end-of-line (EOL) test operator runs the same test hundreds of times per shift. The screen they see must communicate three things instantly: what to do, whether it passed, and what to do next. This guide covers design principles for EOL operator screens and how to implement them with OpenHTF and TofuPilot.
Design Principles
1. The 3-Second Rule
An operator should understand the screen state within 3 seconds of looking at it. This means:
| Element | Requirement |
|---|---|
| Pass/fail indicator | Full-screen green or red background, visible from 3 meters |
| Current step | Large text showing what's happening now |
| Operator action | Bold instruction when input is needed |
| Everything else | Secondary, smaller, or hidden |
2. Minimize Decisions
Every decision the operator makes is a chance for error. Reduce them:
| Bad | Better |
|---|---|
| Type the serial number | Scan the barcode |
| Choose the product variant | Auto-detect from barcode prefix |
| Select the test procedure | One station, one procedure |
| Click "Start Test" | Auto-start after barcode scan |
| Click "Print Label" | Auto-print on pass |
3. Error-Proof the Workflow
| Risk | Mitigation |
|---|---|
| Wrong serial format | Validate barcode format before starting |
| Testing the same unit twice | Warn if serial was already tested today |
| Skipping the test | Lock packaging station until test passes |
| Missing a failure | Audible alert on fail, require acknowledgment |
Prerequisites
- Python 3.10+
- OpenHTF installed (
pip install openhtf) - TofuPilot Python SDK installed (
pip install tofupilot)
Step 1: Design the Test Flow
An EOL test should follow this sequence:
Scan barcode → Auto-start → Run phases → Show result → Ready for next unit
No menus, no configuration, no extra clicks.
import openhtf as htf
from openhtf.util import units
from openhtf import PhaseResult
@htf.measures(
htf.Measurement("supply_current_mA")
.in_range(minimum=90, maximum=110)
.with_units(units.MILLIAMPERE),
)
def phase_power_up(test):
"""Apply power and verify current draw."""
test.measurements.supply_current_mA = 101.2
@htf.measures(
htf.Measurement("firmware_version").equals("3.1.0"),
)
def phase_firmware(test):
"""Check firmware version matches production release."""
test.measurements.firmware_version = "3.1.0"
@htf.measures(
htf.Measurement("self_test").equals("PASS"),
)
def phase_self_test(test):
"""Run the DUT's built-in self-test."""
test.measurements.self_test = "PASS"
@htf.measures(
htf.Measurement("output_voltage_V")
.in_range(minimum=11.8, maximum=12.2)
.with_units(units.VOLT),
)
def phase_output_check(test):
"""Measure main output voltage."""
test.measurements.output_voltage_V = 12.03Step 2: Fail Fast
Put the most likely failure first. If power-up fails, skip everything else. The operator sees the failure in under 5 seconds instead of waiting for the full test cycle.
@htf.measures(
htf.Measurement("power_good").equals("PASS"),
)
def phase_power_good(test):
"""Quick power check before running full test."""
result = "PASS"
test.measurements.power_good = result
if result != "PASS":
return PhaseResult.STOPStep 3: Connect and Stream
TofuPilot's operator UI handles the display. The operator sees each phase progress, measurements with limits, and a full-screen pass/fail result.
from tofupilot.openhtf import TofuPilot
test = htf.Test(
phase_power_good,
phase_power_up,
phase_firmware,
phase_self_test,
phase_output_check,
)
with TofuPilot(test):
test.execute(test_start=lambda: input("Scan serial: "))Screen Layout Recommendations
| Zone | Content | Size |
|---|---|---|
| Top bar | Station name, current time, units tested today | Small |
| Center | Current phase name and status, or pass/fail result | Large (60% of screen) |
| Prompt area | Operator instruction when input is needed | Medium, highlighted |
| Bottom | Last 5 results (pass/fail per serial) | Small, scrolling |
Color Coding
| State | Color | Meaning |
|---|---|---|
| Idle | Gray or blue | Waiting for barcode scan |
| Running | Blue | Test in progress |
| Pass | Green | Unit passed all phases |
| Fail | Red | Unit failed one or more phases |
| Prompt | Yellow/amber | Waiting for operator input |
Cycle Time Optimization for EOL
EOL tests run continuously. Every second of cycle time matters.
| Optimization | Effect |
|---|---|
| Auto-start after scan | Saves 2-3 seconds per unit |
| No unnecessary prompts | Saves 5-10 seconds per prompt |
| Fail-fast phase ordering | Reduces average cycle time on bad units by 50%+ |
| Parallel instrument commands | Saves 100-500ms per phase |
| Kiosk mode (no browser chrome) | Prevents accidental navigation |
What to Avoid
| Mistake | Why |
|---|---|
| Small pass/fail text | Operator must lean in to read it |
| Detailed measurement tables during test | Distracts from the current step |
| Multiple windows or tabs | Operator gets lost |
| Login screens | Operators share stations across shifts |
| Dark theme in bright factory lighting | Low contrast, hard to read |
| Animations or transitions | Slow down perception of state changes |