Une usine en cours de migration fait tourner des postes LabVIEW et Python côte à côte pendant un an ou plus, et la façon de garder cela sain est une procédure TofuPilot par produit avec deux implémentations qui y remontent leurs runs. Le FPY reste comparable sur toute la ligne, les responsabilités restent claires, et les postes basculent un par un au lieu d'un grand soir. Ce guide couvre quels postes migrer en premier, comment chaque côté remonte ses résultats, qui est responsable de quoi, et quoi comparer avant de basculer.
Décider quels postes restent sur LabVIEW pour l'instant
Notez chaque poste sur quatre critères. Les scores décident de l'ordre ; rien d'autre.
| Critère | Garder sur LabVIEW pour l'instant | Migrer en premier | Migrer en dernier |
|---|---|---|---|
| Volume | Quelques unités par semaine | Chaque unité y passe | Moyen, stable |
| Fréquence des changements | Les limites n'ont pas bougé depuis deux ans | Les limites ou la séquence changent tous les mois | Quelques changements par an |
| Qui sait l'ouvrir | Deux personnes ou plus savent ouvrir et modifier le VI | Une seule personne, ou plus personne depuis son départ | Une seule personne, et elle reste |
| Dépendance au DAQ NI | Forte : timing FPGA sur un châssis PXI, boucles cDAQ à des cadences de l'ordre du kHz | Aucune ou faible : SCPI sur VISA, série, USB | Quelques voies analogiques DAQmx (le package Python nidaqmx les couvre) |
Migrer en premier l'emporte dès que deux critères parmi le volume, la fréquence des changements et qui sait l'ouvrir le disent. Garder l'emporte sur la seule dépendance au DAQ NI : le timing FPGA sur PXI est une vraie raison de rester, et c'est le seul critère de la liste qui ne s'aggrave pas avec le temps.
Un poste qui obtient « garder » aujourd'hui n'est pas gardé pour toujours. Il est gardé jusqu'à la fin de vie du produit qu'il teste, ou jusqu'au remplacement du châssis PXI, selon ce qui arrive en premier.
Une procédure, deux implémentations
Dans TofuPilot, une procédure est la définition de test d'un produit, avec un seul procedure_id. Le poste LabVIEW et le poste Python remontent tous les deux leurs runs dans cette procédure unique. Le FPY, le Cpk par mesure, les histogrammes et le débit par poste sont alors filtrables par poste sur la même page, ce qui est la seule façon de comparer les deux honnêtement.
Trois règles gardent la comparaison valide :
| Règle | Pourquoi |
|---|---|
| Mêmes noms de phases, mêmes noms de mesures, mêmes unités | Les analyses s'appuient sur le nom. rail_3v3 sur un poste et Rail 3V3 sur l'autre sont deux mesures différentes |
| Mêmes limites, changées des deux côtés la même semaine | Une limite qui bouge d'un seul côté apparaît comme un écart de rendement qui n'existe pas |
procedure.yaml est la source de vérité pour les noms et les limites | Le côté Python est du texte, se diffe et se relit. Le côté LabVIEW le suit |
Le côté LabVIEW
Deux options. Choisissez A quand l'ingénieur LabVIEW reste et a du temps. Choisissez B quand il est parti, ou quand le poste est sur la liste « migrer en dernier » et que vous ne voulez pas toucher au VI.
Option A : envoyer les résultats à l'API REST depuis les VI HTTP Client
Le poste continue de tourner tel quel, et ajoute un appel à la fin : POST https://www.tofupilot.app/api/v2/runs avec un en-tête Authorization: Bearer <api key>, Content-Type: application/json, et ce corps.
run-payload.json26 lines
{ "procedure_id": "9f1c2d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f", "serial_number": "SN-000123", "part_number": "PCBA-100", "outcome": "PASS", "started_at": "2026-09-21T08:14:02Z", "ended_at": "2026-09-21T08:15:40Z", "phases": [ { "name": "Power Rails", "outcome": "PASS", "started_at": "2026-09-21T08:14:05Z", "ended_at": "2026-09-21T08:14:09Z", "measurements": [ { "name": "rail_3v3", "outcome": "PASS", "measured_value": 3.31, "units": "V", "lower_limit": 3.2, "upper_limit": 3.4 } ] } ]}En LabVIEW, c'est OpenHandle, AddHeader deux fois, POST avec la chaîne JSON, vérification du code de statut, CloseHandle. Construisez la chaîne avec Flatten To JSON à partir d'un cluster de la forme du payload, et gardez la clé API dans un fichier de configuration sur le PC de poste, pas dans le VI. outcome vaut PASS, FAIL, ERROR, TIMEOUT ou ABORTED ; le procedure_id se trouve sur la page de la procédure dans TofuPilot.
Il n'y a pas de SDK LabVIEW ni de package VIPM pour cela. C'est un simple appel HTTPS, ce qui est aussi la raison pour laquelle il ne casse pas à la prochaine version de LabVIEW.
Option B : envelopper l'exécutable LabVIEW dans une phase Python
Compilez le poste LabVIEW en un exécutable qui écrit un fichier de résultat, et appelez-le depuis une seule phase. Les mesures passent alors par procedure.yaml comme pour n'importe quel poste Python, et le code LabVIEW devient un instrument que le côté Python pilote.
phases/labview_fct.py20 lines
# Lancer le poste LabVIEW compilé en sous-processus, lire son fichier de résultat,# et renseigner les mesures pour que le run arrive dans TofuPilot comme les autres.import jsonimport subprocessfrom pathlib import PathRESULT = Path(r"C:\stations\fct\last_result.json")def labview_fct(measurements, unit): if RESULT.exists(): RESULT.unlink() subprocess.run( [r"C:\stations\fct\FCT.exe", "--serial", unit.serial_number], check=True, timeout=180, ) result = json.loads(RESULT.read_text()) measurements.rail_3v3 = result["rail_3v3"] measurements.idle_current = result["idle_current"]Les limites restent dans procedure.yaml, donc l'exécutable LabVIEW ne fait que rapporter des valeurs. C'est le but : un seul endroit pour les limites, même le temps que deux runtimes coexistent.
Le côté Python
Le poste Python est un dossier sous Git : procedure.yaml, phases/, plugs/. Les noms ci-dessous correspondent exactement au payload LabVIEW.
procedure.yaml25 lines
# Mêmes noms, mêmes unités, mêmes limites que le poste LabVIEW.name: PCBA-100 FCTversion: 2.3.0unit: serial_number: default_value: "SN-000001" part_number: default_value: "PCBA-100"plugs: - name: dmm python: plugs.dmm:Multimetermain: - name: Power Rails python: phases.power_rails measurements: - name: rail_3v3 unit: V validators: - operator: ">=" expected_value: 3.2 - operator: "<=" expected_value: 3.4La phase est def power_rails(measurements, dmm): measurements.rail_3v3 = dmm.read_voltage(), et le plug enveloppe PyVISA. Le guide de migration TestStand couvre le côté séquenceur quand TestStand chapeaute le poste LabVIEW.
Règles de responsabilité
Deux runtimes avec des responsabilités floues, c'est ainsi que les limites dérivent. Écrivez-les et mettez-les dans le README de chaque poste.
| Quoi | Responsable | Relecteur | Où ça vit |
|---|---|---|---|
| Noms de mesures, unités, limites | Lead ingénierie test | Qualité | procedure.yaml dans le dépôt Python, reporté sur le poste LabVIEW la même semaine |
| Code du poste LabVIEW | L'ingénieur LabVIEW | L'ingénieur Python relit le payload envoyé par rapport à un run Python, pas le VI | Le dépôt du poste, un par poste, exécutable compilé et tagué |
| Code du poste Python | L'ingénieur Python | L'ingénieur LabVIEW relit la logique des phases (il connaît le montage) | Le dépôt du poste, un par poste, un tag par release |
| Clés API | Lead ingénierie test | Personne d'autre | Un fichier de configuration sur chaque PC de poste, une clé par poste, renouvelée quand quelqu'un part |
| Quelle version tourne où | Celui qui livre | N'importe qui, dans TofuPilot | Le run porte la version de procédure ; le PC de poste porte le tag |
Un dépôt par poste, des releases taguées, et le tag sur le PC correspond à la version dans le fichier. Le guide de passation contient le modèle de README que les deux côtés utilisent. Les deux ingénieurs trouveront un bug dans le poste de l'autre dès la première semaine, ce qui est la revue qui fonctionne comme prévu.
Comparer avant de basculer
Faites tourner les deux implémentations sur les mêmes unités pendant deux semaines avant que le poste LabVIEW ne parte sur le banc de rechange. Mêmes numéros de série dans les deux postes, dans la même équipe de travail quand c'est possible. Tout ce qui suit se trouve sur la page de la procédure dans TofuPilot, filtrée par poste.
| Comparer | Où regarder | Basculer quand |
|---|---|---|
| Moyennes, par mesure | Histogramme de la mesure, une série par poste | L'écart entre postes est plus petit que la répétabilité de mesure que vous acceptez déjà |
| Dispersion, par mesure | Largeur de l'histogramme, carte de contrôle | La dispersion Python est égale ou plus étroite ; plus large signale une différence de timing ou de stabilisation dans le plug |
| FPY | Page de la procédure, par poste | Dans le bruit pour le volume, et pas de nouveau mode de défaillance |
| Pareto des défaillances | Pareto, par poste | Mêmes trois premières mesures en échec des deux côtés |
| Temps de cycle | Débit du poste | Égal ou meilleur ; plus lent signale en général un sleep fixe qu'une attente de stabilisation par interrogation remplace |
| Comportement au retest | Pages de run par unité | Les unités qui ont échoué puis réussi l'ont fait des deux côtés sur la même mesure |
Un écart de moyenne stable et petit est une différence de plug (NPLC différent, calibre différent) et se corrige dans le plug Python. Une dispersion plus large est un problème de stabilisation. Un Pareto différent signifie que les deux postes ne testent pas la même chose, et c'est une conversation avec la qualité, pas un changement de code.
Que faire des licences LabVIEW
LabVIEW est vendu uniquement par abonnement depuis 2023, environ 1 300 $ par an et par licence pour Base, 4 300 $ pour Full et 5 500 $ et plus pour Professional. Les licences de déploiement TestStand coûtent environ 1 000 à 1 500 $ par poste de test. Le guide des tarifs donne le détail.
Le plan découle de l'ordre de migration :
- Arrêtez de renouveler la licence de déploiement de chaque poste la semaine où il bascule. Les licences de déploiement sont par poste de test ; elles ne se transfèrent pas au poste Python, qui n'en a pas besoin.
- Gardez une licence Full tant qu'un poste figure sur la liste « garder ». Quelqu'un doit ouvrir le VI pour le lire pendant une migration, et pour réparer le poste PXI.
- Ne comptez pas sur la Community Edition comme solution de repli. Elle est réservée à un usage non commercial.
- Retirez la dernière licence quand le dernier poste gardé est retiré, pas avant. Un poste LabVIEW sans licence dans le bâtiment est un poste que personne ne peut réparer.
Budgétez les licences libérées dans la migration elle-même. Une licence Full par an paie une bonne partie de la prise en main de l'ingénieur Python.
Commencez par un poste
Choisissez le poste au plus gros volume, ou celui qu'une seule personne sait ouvrir. Reconstruisez-le en Python avec le TofuPilot Framework, puis faites-le tourner en parallèle de la version LabVIEW sur les mêmes unités pendant deux semaines, avec le tableau de comparaison ci-dessus. Le poste LabVIEW remonte dans la même procédure pendant tout ce temps, donc le jour où vous basculez, l'historique du FPY ne repart pas de zéro.
# Installer la CLI, lancer une procédure en local, puis la lancer avec upload.curl -fsSL https://www.tofupilot.app/install | shtofupilot run ./procedure.yamltofupilot run ./procedure.yaml --uploadLe guide de migration TestStand couvre la reconstruction du séquenceur étape par étape, et la page du Framework décrit l'organisation des fichiers. L'offre Lab est gratuite, et tofupilot run fonctionne sans compte.
