Une station de test, plusieurs produits : configurez votre test OpenHTF pour détecter le SKU au moment de l'exécution, charger les limites et phases spécifiques au SKU depuis un fichier de configuration, et laisser TofuPilot suivre le rendement par numéro de pièce automatiquement.
Pourquoi les stations multi-SKU sont importantes
Exécuter des stations séparées par SKU gaspille de l'espace au sol et des fixtures. Une seule station qui gère une famille de produits réduit :
- Le nombre de fixtures (lit de clous ou carte à sondes partagés)
- La formation des opérateurs (un seul flux de travail, pas cinq)
- La surface de maintenance (une seule station à calibrer)
Méthodes de détection du SKU
| Méthode | Quand l'utiliser | Fiabilité |
|---|---|---|
| Scan code-barres | Étiquette scannée par l'opérateur, pas de contact électrique nécessaire | Élevée |
| Résistance d'identification | Le PCB possède un diviseur résistif codant le SKU | Moyenne |
| EEPROM I2C | Le PCB stocke le numéro de pièce dans une mémoire embarquée | Élevée |
Scan code-barres
import openhtf as htfclass BarcodePlug(htf.plugs.BasePlug): """Lit le SKU depuis le scan de code-barres de l'opérateur.""" def setUp(self): pass def scan(self) -> str: raw = input("Scanner le code-barres : ").strip() if not raw: raise ValueError("Scan de code-barres vide") return raw def tearDown(self): passRésistance d'identification
import openhtf as htf_VOLTAGE_MAP = { (0.0, 0.4): "SKU-A", (0.4, 0.8): "SKU-B", (0.8, 1.2): "SKU-C", (1.2, 1.6): "SKU-D",}class ResistorIdPlug(htf.plugs.BasePlug): """Identifie le SKU depuis la tension du diviseur résistif.""" def setUp(self): pass def read_sku(self, adc_voltage: float) -> str: for (low, high), sku in _VOLTAGE_MAP.items(): if low <= adc_voltage < high: return sku raise ValueError(f"Tension non reconnue : {adc_voltage:.3f} V") def tearDown(self): passSélection de test pilotée par configuration
Stockez les définitions de SKU dans un fichier YAML. Cela sépare les limites de la logique de test.
SKU-A: part_number: "PCB-001-A" description: "Variante standard 5 V" phases: - power_on - voltage_check - current_check limits: supply_voltage: min: 4.85 max: 5.15 supply_current: min: 0.080 max: 0.120SKU-B: part_number: "PCB-001-B" description: "Variante basse consommation 3,3 V" phases: - power_on - voltage_check - current_check - sleep_current_check limits: supply_voltage: min: 3.2 max: 3.4 supply_current: min: 0.030 max: 0.060 sleep_current: min: 0 max: 0.000050Chargez la configuration au démarrage de la station :
from pathlib import Pathimport yamldef load_sku_config(path: str = "station/config/skus.yaml") -> dict: config_path = Path(path) if not config_path.exists(): raise FileNotFoundError(f"Configuration SKU introuvable : {config_path}") with config_path.open() as f: return yaml.safe_load(f)Limites de mesure spécifiques au SKU avec OpenHTF
Utilisez une phase factory pour intégrer les limites spécifiques au SKU dans les mesures OpenHTF :
import openhtf as htffrom openhtf.util import unitsdef make_voltage_phase(min_v: float, max_v: float): """Retourne une phase de tension avec des limites intégrées.""" @htf.measures( htf.Measurement("supply_voltage") .in_range(minimum=min_v, maximum=max_v) .with_units(units.VOLT), ) def voltage_check(test): test.measurements.supply_voltage = read_voltage() return voltage_checkdef make_current_phase(min_a: float, max_a: float): """Retourne une phase de courant avec des limites intégrées.""" @htf.measures( htf.Measurement("supply_current") .in_range(minimum=min_a, maximum=max_a) .with_units(units.AMPERE), ) def current_check(test): test.measurements.supply_current = read_current() return current_checkExemple complet fonctionnel
import openhtf as htffrom tofupilot.openhtf import TofuPilotfrom station.config.loader import load_sku_configfrom station.phases.factory import make_voltage_phase, make_current_phaseSKU_CONFIG = load_sku_config()def power_on(test): """Met le DUT sous tension et attend la stabilisation.""" import time time.sleep(0.5)def run_station(): # 1. Détecter le SKU sku_id = input("Scanner le code-barres : ").strip() if sku_id not in SKU_CONFIG: raise ValueError(f"SKU inconnu '{sku_id}'. Disponibles : {list(SKU_CONFIG)}") sku = SKU_CONFIG[sku_id] limits = sku["limits"] part_number = sku["part_number"] # 2. Composer les phases depuis la configuration phases = [power_on] if "supply_voltage" in limits: lim = limits["supply_voltage"] phases.append(make_voltage_phase(lim["min"], lim["max"])) if "supply_current" in limits: lim = limits["supply_current"] phases.append(make_current_phase(lim["min"], lim["max"])) # 3. Construire et exécuter le test test = htf.Test(*phases, test_name=f"Station ({sku_id})") with TofuPilot(test): test.execute(test_start=lambda: input("Scanner le numéro de série : "))if __name__ == "__main__": run_station()Suivi du rendement par SKU dans TofuPilot
TofuPilot regroupe les statistiques de rendement par numéro de pièce. Chaque SKU obtient son propre graphique de rendement sans configuration supplémentaire.
| Numéro de pièce | SKU | Exécutions | Taux de réussite |
|---|---|---|---|
| PCB-001-A | SKU-A | 240 | 97,5 % |
| PCB-001-B | SKU-B | 180 | 94,4 % |
Filtrez par numéro de pièce dans le tableau de bord TofuPilot pour comparer les tendances des SKU côte à côte.