Skip to content
Test Types & Methods

IPC-A-610 Inspection Tracking with TofuPilot

Learn how to track IPC-A-610 visual inspection results for PCBA acceptability using TofuPilot's structured test records.

JJulien Buteau
intermediate9 min readMarch 13, 2026

IPC-A-610 Inspection Tracking with TofuPilot

IPC-A-610 is the acceptability standard for electronic assemblies. It defines what "good" looks like for solder joints, component placement, cleanliness, and mechanical assembly. TofuPilot tracks inspection results systematically instead of relying on paper checklists.

What IPC-A-610 Covers

IPC-A-610 classifies defects into three product classes:

ClassApplicationAcceptance criteria
Class 1General electronics (consumer)Least strict
Class 2Dedicated service electronics (industrial)Moderate
Class 3High-performance electronics (medical, aerospace, military)Most strict

Inspection criteria include:

CategoryExamples
Solder jointsWetting, fillets, bridges, cold joints
Component placementAlignment, orientation, polarity
CleanlinessFlux residue, contamination, corrosion
MechanicalWire routing, strain relief, conformal coating
MarkingLabels, part numbers, date codes

Logging Inspection Results to TofuPilot

Per-Board Inspection

ipc610_inspection.py
from tofupilot import TofuPilotClient

client = TofuPilotClient()

def log_inspection(serial, inspector, defects):
    """Log IPC-A-610 inspection results."""
    measurements = [
        {"name": "inspector_id", "value": inspector, "unit": ""},
        {"name": "ipc_class", "value": 2, "unit": "class"},
        {"name": "total_defects", "value": len(defects), "unit": "count", "limit_high": 0},
    ]

    # Log each defect category
    defect_categories = {
        "solder": 0, "placement": 0, "cleanliness": 0,
        "mechanical": 0, "marking": 0,
    }
    for d in defects:
        if d["category"] in defect_categories:
            defect_categories[d["category"]] += 1

    for cat, count in defect_categories.items():
        measurements.append({
            "name": f"defects_{cat}",
            "value": count,
            "unit": "count",
            "limit_high": 0,
        })

    passed = len(defects) == 0

    client.create_run(
        procedure_id="IPC610-VISUAL-INSPECTION",
        unit_under_test={
            "serial_number": serial,
            "part_number": "MAIN-BOARD-V4",
        },
        run_passed=passed,
        steps=[{
            "name": "IPC-A-610 Class 2 Inspection",
            "step_type": "measurement",
            "status": passed,
            "measurements": measurements,
        }],
    )

# Example: board with two defects
log_inspection(
    serial="PCB-2025-04521",
    inspector="OP-012",
    defects=[
        {"category": "solder", "location": "U12-pin3", "type": "insufficient_wetting"},
        {"category": "cleanliness", "location": "J5-area", "type": "flux_residue"},
    ],
)

Defect Classification

Log specific defect types to build a defect pareto.

defect_logging.py
# Detailed defect logging
defect_types = {
    "solder_bridge": "Solder bridge between adjacent pins",
    "cold_joint": "Cold or disturbed solder joint",
    "insufficient_wetting": "Insufficient solder wetting on pad or lead",
    "solder_ball": "Loose solder ball on board surface",
    "tombstone": "Component standing on end (tombstoning)",
    "misalignment": "Component offset from pad center",
    "wrong_polarity": "Polarized component installed backwards",
    "missing_component": "Component not placed",
    "flux_residue": "Excessive flux residue after cleaning",
    "damaged_component": "Component body cracked or chipped",
}

# Log each defect with its type
for defect in board_defects:
    measurements.append({
        "name": f"defect_{defect['type']}",
        "value": 1,
        "unit": "count",
        "limit_high": 0,
    })

Defect Pareto Analysis

TofuPilot's analytics show you the most common defect types across production.

RankDefect typeCountPercentage
1Insufficient wetting4532%
2Solder bridge2820%
3Flux residue2216%
4Misalignment1511%
5Cold joint129%
-All others1813%

Fix the top defect type first. Insufficient wetting (32%) is likely a solder paste issue (stencil wear, paste viscosity, or reflow profile).

Inspector Consistency

Track defect detection rates by inspector to identify training needs.

inspector_analysis.py
from tofupilot import TofuPilotClient

client = TofuPilotClient()

runs = client.get_runs(
    procedure_id="IPC610-VISUAL-INSPECTION",
    limit=1000,
)

# Group by inspector
inspector_stats = {}
for run in runs:
    for step in run.get("steps", []):
        for m in step.get("measurements", []):
            if m["name"] == "inspector_id":
                inspector = m["value"]
                if inspector not in inspector_stats:
                    inspector_stats[inspector] = {"total": 0, "rejected": 0}
                inspector_stats[inspector]["total"] += 1
                if not run["run_passed"]:
                    inspector_stats[inspector]["rejected"] += 1

for inspector, stats in inspector_stats.items():
    reject_rate = stats["rejected"] / stats["total"] * 100
    print(f"Inspector {inspector}: {stats['total']} boards, {reject_rate:.1f}% rejection rate")

If Inspector A rejects 8% and Inspector B rejects 2% on the same product, either A is too strict or B is missing defects. Calibrate inspectors using reference boards with known defects.

Connecting Inspection to Electrical Test

The real power is correlating visual inspection results with electrical test results.

If boards that pass visual inspection but fail functional test at a specific measurement, there may be a defect type that visual inspection isn't catching. Conversely, if visually rejected boards are reworked and always pass functional test, the visual criteria may be too strict for your product class.

TofuPilot links both inspection and electrical test results to the same serial number, making this correlation straightforward.

AOI Integration

Automated Optical Inspection (AOI) systems can push results to TofuPilot the same way manual inspections do.

aoi_upload.py
# Parse AOI machine output and upload to TofuPilot
import json

with open("aoi_results.json") as f:
    aoi_data = json.load(f)

for board in aoi_data["boards"]:
    defects = board.get("defects", [])
    client.create_run(
        procedure_id="AOI-INSPECTION",
        unit_under_test={"serial_number": board["serial"]},
        run_passed=len(defects) == 0,
        steps=[{
            "name": "AOI Scan",
            "step_type": "measurement",
            "status": len(defects) == 0,
            "measurements": [
                {"name": "defect_count", "value": len(defects), "unit": "count", "limit_high": 0},
                {"name": "scan_coverage_pct", "value": board.get("coverage", 100), "unit": "%"},
            ],
        }],
    )

Combine AOI data with manual inspection data and electrical test data in TofuPilot for a complete quality picture of every board.

More Guides

Put this guide into practice