SPI, AOI and AXI are the three automated inspection steps on an SMT line. They look at the board rather than testing it electrically, and together they catch most assembly defects before any power is applied. This guide covers what each one sees, where it belongs in the line, and how to get more out of the data than a pass/fail count.
The Three Inspections
| Step | Full name | Where it sits | What it sees |
|---|---|---|---|
| SPI | Solder Paste Inspection | After paste printing, before placement | Paste volume, area, height, offset, bridging |
| AOI | Automated Optical Inspection | After reflow (often also after placement) | Presence, polarity, offset, tombstoning, visible solder defects |
| AXI | Automated X-ray Inspection | After reflow | Hidden joints: BGA, QFN, bottom-terminated parts, voiding |
The order is the logic. SPI checks the process input, AOI checks what the process produced where a camera can see it, and AXI checks what a camera cannot see at all.
SPI: Solder Paste Inspection
Roughly 60-70 % of SMT defects originate at paste print. SPI is where they are cheapest to catch, because nothing has been placed yet and the board can simply be wiped and reprinted.
| Measurement | Typical spec | What a drift means |
|---|---|---|
| Volume | 80-120 % of aperture | Stencil wear, squeegee pressure, paste viscosity |
| Height | Within ±25 % of stencil thickness | Stencil damage, board support |
| Area | 80-120 % | Aperture clogging |
| Offset X/Y | Under 25 % of pad width | Stencil-to-board alignment |
| Bridging | None | Excess paste, poor gasketing |
SPI is the strongest candidate on the line for statistical process control, because it produces a continuous numeric value per pad, thousands per board. A control chart on paste volume shows stencil wear days before AOI starts flagging opens.
AOI: Automated Optical Inspection
AOI compares the board against a golden image or a rules model.
| Defect class | Detected reliably |
|---|---|
| Missing component | Yes |
| Wrong component (visibly different) | Yes |
| Polarity / orientation | Yes, with good lighting and marking |
| Tombstoning, billboarding | Yes |
| Offset, rotation | Yes |
| Solder bridge (visible) | Yes |
| Insufficient / excess solder (visible fillet) | Usually |
| Cold joint under a part body | No |
| BGA / QFN joints | No |
AOI's weakness is a generic one: false calls. A machine tuned to catch every real defect will also stop good boards, and an operator who overrides 50 false calls an hour will eventually wave a real one through. The false-call rate is worth tracking as a number in its own right.
AXI: Automated X-ray Inspection
AXI sees through the package. It is the only inspection that reaches BGA, QFN and other bottom-terminated joints.
| Measurement | Why it matters |
|---|---|
| Void percentage | Thermal and mechanical reliability, typically under 25 % for BGA |
| Joint shape and standoff | Cold joints, head-in-pillow, insufficient collapse |
| Open joints | Not visible by any optical method |
| Solder volume per ball | Paste and reflow consistency at the package level |
AXI is slower and more expensive per board than AOI, so many lines sample rather than inspect 100 %, or apply it only to the packages that need it.
Where They Sit
Paste print → SPI → Place → Reflow → AOI → AXI → ICT/FCT
Each step is a decision point with its own yield. That is the single most useful thing to get right in the data: one procedure per inspection step, so a drop at SPI is visibly an SPI problem and not blended into a line-wide number.
Getting the Data Out of the Machines
SPI, AOI and AXI machines all produce results, usually as CSV, XML, or a database row per board. The common mistake is to keep only the verdict. A board that passed SPI at 119 % paste volume is a different board from one that passed at 101 %, and only one of them is telling you the stencil needs cleaning.
The useful pattern is a thin importer per machine: read its output, map the values onto named measurements, and upload one run per board per step.
plugs/spi_machine.py22 lines
import csvclass SpiMachine: """Reads the SPI machine's CSV export for one board.""" def __init__(self): self._rows = None def load(self, path: str): with open(path, newline="") as fh: self._rows = list(csv.DictReader(fh)) def volume_stats(self) -> tuple[float, float, float]: vols = [float(r["volume_pct"]) for r in self._rows] return min(vols), sum(vols) / len(vols), max(vols) def offset_max(self) -> float: return max(float(r["offset_pct"]) for r in self._rows) def bridges(self) -> int: return sum(1 for r in self._rows if r["bridge"] == "1")def spi_import(measurements, spi_machine): """One run per board, carrying the numbers rather than the verdict.""" spi_machine.load("/data/spi/latest.csv") lo, mean, hi = spi_machine.volume_stats() measurements.paste_volume_min = lo measurements.paste_volume_mean = mean measurements.paste_volume_max = hi measurements.paste_offset_max = spi_machine.offset_max() measurements.bridge_count = spi_machine.bridges()procedure.yaml44 lines
name: SPI Inspectionversion: 1.0.0description: Solder paste inspection results per boardunit: serial_number: default_value: "PCBA000001" part_number: default_value: "PCBA-100"plugs: - name: spi_machine python: plugs.spi_machine:SpiMachinemain: - name: SPI Import python: phases.spi_import measurements: - name: Paste Volume Min unit: "%" validators: - operator: ">=" expected_value: 80 - name: Paste Volume Mean unit: "%" validators: - operator: ">=" expected_value: 90 - operator: "<=" expected_value: 110 - name: Paste Volume Max unit: "%" validators: - operator: "<=" expected_value: 120 - name: Paste Offset Max unit: "%" validators: - operator: "<=" expected_value: 25 - name: Bridge Count validators: - operator: "==" expected_value: 0Run it with tofupilot run ./procedure.yaml --upload, triggered by the machine's export or a file watcher.
Record which machine and which stencil produced the board, so a drift has somewhere to point:
def record_context(run): run.metadata["spi_machine"] = "SPI-02" run.metadata["stencil_id"] = "STN-4417-C" run.metadata["line"] = "L3"Do the same for AOI and AXI with their own procedures: component-level defect counts for AOI, void percentage and joint measurements for AXI.
What the Data Then Tells You
| Question | How the data answers it |
|---|---|
| Is the stencil wearing? | Control chart on paste volume mean, per stencil ID |
| Which component fails AOI most? | Pareto of AOI defect types |
| Are BGA voids trending up? | Control chart on void percentage |
| Is one line worse than another? | Filter by the line metadata |
| Did the new paste lot change anything? | Compare volume distributions before and after |
| Are our SPI limits too tight? | Cpk on paste volume against the current limits |
The last two are only possible because the numbers were stored. A pass/fail column cannot answer either.
Inspection Is Not Test
A board that passes SPI, AOI and AXI has been inspected, not tested. None of the three applies power or exercises a function. The electrical gates are ICT and FCT, and they catch a different class of problem entirely: a correctly-soldered board with a marginal design or a firmware fault passes all three inspections.
The complementary failure is also worth naming: a board that passes FCT can still have a 40 % BGA void that will fail in the field in eighteen months. That is precisely what AXI is for.
Common Mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Storing pass/fail only | No SPC, no drift detection, no limit review | Store the measured values |
| One blended inspection yield | A paste problem looks like a placement problem | One procedure per inspection step |
| Ignoring the false-call rate | Operators start waving real defects through | Track false calls as a measurement |
| No machine or stencil ID on the run | A drift has nowhere to point | Record them as run metadata |
| Treating AOI as a substitute for AXI | Hidden joint defects ship | Use AXI for bottom-terminated packages |
| Treating inspection as a substitute for test | Functional and firmware faults ship | Keep ICT/FCT downstream |
