Test Types & Methods

Suivre les résultats PCBA multi-lignes

Découvrez comment étiqueter les exécutions de test OpenHTF avec les métadonnées de station, ligne, usine et équipe, puis interroger et comparer le.

JJulien Buteau
intermediate12 min de lecture14 mars 2026

TofuPilot associe chaque exécution de test à une station nommée. En encodant la ligne, l'usine et l'équipe dans le nom de la station et les métadonnées de l'exécution, vous obtenez une surface de requête unique qui couvre chaque ligne de production et chaque usine sans outillage personnalisé.

Pourquoi la traçabilité multi-lignes est importante

Quand un défaut PCBA apparaît sur le terrain, vous devez répondre rapidement à trois questions :

  • Quelle ligne de production a fabriqué les unités concernées ?
  • Quelle équipe était en service à ce moment-là ?
  • La défaillance est-elle isolée à une station ou systémique sur une ligne ?

Sans métadonnées structurées sur chaque exécution, répondre à ces questions nécessite de recouper manuellement les journaux d'opérateurs, les plannings d'équipes et les exports CSV de tests. TofuPilot résout ce problème en faisant de l'identité de la station et des métadonnées de l'exécution des champs de premier ordre sur chaque enregistrement de test.

Sans métadonnées structuréesAvec les métadonnées de station et d'exécution TofuPilot
Recoupement manuel des journauxFiltre unique dans le tableau de bord
Données d'équipe dans des tableursEncodées dans l'exécution au moment du test
Fichiers d'export par ligneRequête API unifiée
Comparaison de rendement dans ExcelGraphique de rendement par station intégré

Prérequis

  • Python 3.9+
  • OpenHTF installé (pip install openhtf)
  • Client TofuPilot installé (pip install tofupilot)
  • Un compte TofuPilot avec au moins une procédure créée

Configurer l'identité de la station dans TofuPilot

Chaque station de test physique correspond à une station nommée dans TofuPilot. La convention de nommage porte tout le contexte de traçabilité nécessaire.

Convention de nommage des stations

Utilisez un nom structuré qui encode l'usine, la ligne et le numéro de station :

{USINE}-{LIGNE}-FCT{NUMÉRO_STATION}

Exemples :

Nom de stationUsineLigneStation
SZX-L1-FCT01ShenzhenLigne 1Station FCT 1
SZX-L2-FCT01ShenzhenLigne 2Station FCT 1
TXL-L1-FCT01ToulouseLigne 1Station FCT 1
TXL-L1-FCT02ToulouseLigne 1Station FCT 2

Configuration de la station par variables d'environnement

Stockez l'identité de la station dans les variables d'environnement de chaque machine, pas dans le script de test :

/etc/environment
TOFUPILOT_API_KEY=tp_station_xxxxxxxxxxxxx
STATION_ID=SZX-L1-FCT01
FACTORY=SZX
LINE=L1

Chargez-les dans votre script de test au moment de l'exécution :

config.py
import os

STATION_ID = os.environ["STATION_ID"]
FACTORY = os.environ["FACTORY"]
LINE = os.environ["LINE"]

Cette approche signifie que le même binaire de script de test se déploie sur chaque station. Seul l'environnement diffère.

Étiqueter les exécutions avec les métadonnées de ligne, usine et équipe

Déterminer l'équipe en cours

shift.py
from datetime import datetime

def get_current_shift() -> str:
    """Retourne le libellé de l'équipe selon l'heure locale."""
    hour = datetime.now().hour
    if 6 <= hour < 14:
        return "morning"
    elif 14 <= hour < 22:
        return "afternoon"
    else:
        return "night"

Test OpenHTF complet avec métadonnées de station

Cet exemple teste une carte d'alimentation PCBA. L'identité de la station, la ligne, l'usine et l'équipe sont injectées au moment de l'initialisation du test et jointes à chaque exécution.

pcba_fct_test.py
import os

import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot

import config
from shift import get_current_shift


class PowerSupplyPlug(htf.plugs.BasePlug):
    """Contrôle l'alimentation de banc via USB-série."""

    def setUp(self):
        import serial
        self._port = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)

    def set_voltage(self, volts: float, channel: int = 1):
        self._port.write(f":APPL CH{channel},{volts},1.0
".encode())

    def measure_voltage(self, channel: int = 1) -> float:
        self._port.write(f":MEAS:VOLT? CH{channel}
".encode())
        return float(self._port.readline().strip())

    def tearDown(self):
        self._port.close()


@htf.plug(psu=PowerSupplyPlug)
@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(minimum=3.235, maximum=3.365)
    .with_units(units.VOLT)
    .doc("Rail 3,3V sous charge de 100 mA"),
    htf.Measurement("rail_5v0")
    .in_range(minimum=4.900, maximum=5.100)
    .with_units(units.VOLT)
    .doc("Rail 5,0V sous charge de 200 mA"),
)
def test_power_rails(test, psu):
    psu.set_voltage(3.3, channel=1)
    test.measurements.rail_3v3 = psu.measure_voltage(channel=1)

    psu.set_voltage(5.0, channel=2)
    test.measurements.rail_5v0 = psu.measure_voltage(channel=2)


@htf.plug(psu=PowerSupplyPlug)
@htf.measures(
    htf.Measurement("idle_current")
    .in_range(minimum=0, maximum=0.350)
    .with_units(units.AMPERE)
    .doc("Consommation totale de la carte au repos"),
)
def test_idle_current(test, psu):
    psu.set_voltage(5.0, channel=2)
    current_a = float(psu._port.readline().strip())
    test.measurements.idle_current = current_a


def main():
    serial_number = input("Scanner le numéro de série du DUT : ").strip()

    test = htf.Test(
        test_power_rails,
        test_idle_current,
        procedure_id="PCBA-FCT-001",
    )

    with TofuPilot(test):
        test.execute(test_start=lambda: serial_number)


if __name__ == "__main__":
    main()

Chaque exécution dans TofuPilot porte l'identité de la station comme métadonnée interrogeable aux côtés du résultat pass/fail standard et des mesures.

Comparer les résultats entre les lignes dans TofuPilot

Avec les exécutions envoyées depuis toutes les lignes, le filtrage et l'analytique de TofuPilot vous donnent une comparaison directe :

  • FPY par station affiche le rendement pour chaque station regroupée par préfixe de ligne. Si la Ligne B est systématiquement en retard par rapport à la Ligne A, le problème est systémique à cette ligne.
  • Les histogrammes de mesures révèlent si les valeurs d'une ligne sont décalées ou ont une dispersion plus large. Une moyenne décalée suggère un décalage de calibration.
  • Le Pareto des défaillances par station montre quels tests spécifiques échouent le plus souvent sur chaque station. Si une station concentre la majorité des défaillances, commencez l'investigation sur ce montage.
  • Les graphiques de tendance montrent si les écarts de rendement sont constants, croissants, ou sont apparus soudainement après un changement.

Investiguer les écarts de rendement

Quand vous trouvez un écart de rendement entre les lignes, cernez la cause de manière systématique :

  1. Vérifiez les distributions de mesures. Si les valeurs d'une ligne sont décalées, c'est probablement la calibration ou l'équipement. Si elles sont plus dispersées, c'est de la variation de processus.
  2. Vérifiez par tranche horaire. Des baisses de rendement en équipe de nuit pointent vers la formation des opérateurs ou des changements environnementaux.
  3. Vérifiez par station individuelle. Parfois le problème de « ligne » est en fait une mauvaise station qui tire la moyenne vers le bas.
  4. Vérifiez par lot de composants. Si vous suivez les numéros de lot comme métadonnées, filtrez par lot pour voir si des lots spécifiques provoquent la différence.

Une station avec un FPY inférieur à 95% alors que les stations voisines sont à 97-98% indique typiquement un problème de contact du montage, une dégradation de câble ou une dérive de calibration.

Liste de contrôle de déploiement

ÉtapeAction
Nommage des stationsSuivre la convention {USINE}-{LIGNE}-FCT{N}
Clés APIUne clé par station, stockée dans l'environnement
Identifiant de procédureMême identifiant sur toutes les lignes pour une vue de rendement unifiée
Tableau de bordVérifier que les noms de station apparaissent dès la première exécution avant le déploiement complet

Plus de guides

Mettez ce guide en pratique