Les tests HIL génèrent beaucoup de données : mesures, captures de formes d'onde, versions de firmware, conditions environnementales. Sans journalisation structurée, repérer les régressions entre les versions de firmware se transforme en projet d'archéologie de tableurs. Ce guide montre comment étiqueter, joindre et interroger les résultats HIL dans TofuPilot pour que les régressions remontent automatiquement.
Prérequis
- Python 3.8+
- OpenHTF installé (
pip install openhtf) - Client Python TofuPilot (
pip install tofupilot) - Un test HIL fonctionnel (voir Comment configurer les tests HIL pour systèmes embarqués avec TofuPilot)
Étape 1 : Étiqueter les exécutions avec la version du firmware et la révision matérielle
Chaque exécution de test HIL doit porter la version du firmware et la révision matérielle du DUT. TofuPilot les stocke comme des métadonnées structurées que vous pouvez filtrer et interroger ultérieurement.
Interrogez la version du firmware depuis le DUT au début du test, puis transmettez-la à TofuPilot via les mesures.
import openhtf as htf
from tofupilot.openhtf import TofuPilot
from hil_regression.phases import (
read_firmware_info,
test_adc_accuracy,
test_pwm_output,
test_sleep_current,
)
def main():
test = htf.Test(
read_firmware_info,
test_adc_accuracy,
test_pwm_output,
test_sleep_current,
)
with TofuPilot(test):
test.execute(test_start=lambda: input("Scanner le numéro de série du DUT : "))
if __name__ == "__main__":
main()La version du firmware et la révision matérielle sont enregistrées comme mesures, ce qui les rend recherchables sur toutes les exécutions.
import openhtf as htf
from hil_regression.serial_plug import SerialCommandPlug
@htf.plug(serial=SerialCommandPlug)
@htf.measures(
htf.Measurement("firmware_version"),
htf.Measurement("hardware_revision"),
htf.Measurement("bootloader_version"),
)
def read_firmware_info(test, serial):
"""Enregistrer les identifiants firmware et matériel pour la traçabilité."""
test.measurements.firmware_version = serial.send_command("VERSION")
test.measurements.hardware_revision = serial.send_command("HWREV")
test.measurements.bootloader_version = serial.send_command("BLVER")Cela vous donne trois champs filtrables sur chaque exécution. Quand le FPY baisse après une mise à jour du firmware, filtrez par firmware_version dans le tableau de bord de TofuPilot pour isoler le changement.
Étape 2 : Joindre les fichiers de formes d'onde et de logs
Les tests HIL capturent souvent des formes d'onde d'oscilloscope, des traces d'analyseur logique ou des logs de console du DUT. Joignez-les à l'exécution de test pour qu'ils soient disponibles pour l'analyse post-mortem sans fouiller dans des partages de fichiers.
import csv
import time
import openhtf as htf
from openhtf.plugs import BasePlug
class WaveformCapturePlug(BasePlug):
"""Capture des échantillons analogiques et les enregistre en CSV pour pièce jointe."""
def setUp(self):
pass
def capture_waveform(self, adc, channel: int, duration_s: float, sample_rate_hz: int) -> str:
"""Échantillonne un canal ADC et écrit les résultats dans un fichier CSV."""
filepath = f"/tmp/waveform_ch{channel}_{int(time.time())}.csv"
samples = []
interval = 1.0 / sample_rate_hz
for i in range(int(duration_s * sample_rate_hz)):
voltage = adc.read_voltage(channel)
samples.append((i * interval, voltage))
time.sleep(interval)
with open(filepath, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["time_s", "voltage_v"])
writer.writerows(samples)
return filepath
def tearDown(self):
passPuis joignez le fichier dans votre phase de test :
import openhtf as htf
from openhtf.util import units
from hil_regression.capture import WaveformCapturePlug
from hil_regression.analog_plug import AnalogInputPlug
from hil_regression.serial_plug import SerialCommandPlug
@htf.plug(serial=SerialCommandPlug, adc=AnalogInputPlug, capture=WaveformCapturePlug)
@htf.measures(
htf.Measurement("pwm_voltage_mean").in_range(minimum=1.6, maximum=1.7).with_units(units.VOLT),
)
def test_pwm_output(test, serial, adc, capture):
"""Commander un PWM à 50% et capturer la forme d'onde de sortie."""
serial.send_command("PWM SET 50")
# Capturer 1 seconde de données à 1 kHz
waveform_path = capture.capture_waveform(adc, channel=3, duration_s=1.0, sample_rate_hz=1000)
# Joindre le CSV de forme d'onde à l'exécution de test
test.attach("pwm_waveform", waveform_path, "text/csv")
# Enregistrer également la tension moyenne comme mesure
import csv
with open(waveform_path) as f:
reader = csv.DictReader(f)
voltages = [float(row["voltage_v"]) for row in reader]
test.measurements.pwm_voltage_mean = sum(voltages) / len(voltages)Les pièces jointes apparaissent dans la vue détaillée de l'exécution dans TofuPilot. Vous pouvez les télécharger ultérieurement pour une analyse hors ligne ou une comparaison entre versions de firmware.
Étape 3 : Utiliser les sous-unités pour les configurations HIL multi-cartes
De nombreux produits contiennent plusieurs cartes (carte CPU principale, carte d'alimentation, carte capteur) qui sont testées ensemble dans un montage HIL. Les sous-unités de TofuPilot permettent de suivre chaque carte indépendamment tout en les maintenant liées à l'assemblage parent.
import openhtf as htf
from tofupilot.openhtf import TofuPilot
from hil_regression.phases import (
test_cpu_board,
test_power_board,
test_sensor_board,
)
def main():
test = htf.Test(
test_cpu_board,
test_power_board,
test_sensor_board,
)
with TofuPilot(
test,
sub_units=[
{"serial_number": "CPU-BRD-0042", "part_number": "PCB-CPU-R3"},
{"serial_number": "PWR-BRD-0019", "part_number": "PCB-PWR-R2"},
{"serial_number": "SNS-BRD-0088", "part_number": "PCB-SNS-R1"},
],
):
test.execute(test_start=lambda: input("Scanner le numéro de série de l'assemblage : "))
if __name__ == "__main__":
main()Chaque sous-unité obtient son propre enregistrement de traçabilité dans TofuPilot. Si la carte capteur commence à échouer après un changement de révision matérielle, vous pouvez filtrer par PCB-SNS-R1 et voir exactement quand les défaillances ont commencé.
import openhtf as htf
from openhtf.util import units
from hil_regression.analog_plug import AnalogInputPlug
from hil_regression.serial_plug import SerialCommandPlug
@htf.plug(serial=SerialCommandPlug)
@htf.measures(
htf.Measurement("cpu_clock_mhz").in_range(minimum=79, maximum=81).with_units(units.HERTZ),
htf.Measurement("cpu_temp").in_range(maximum=85).with_units(units.DEGREE_CELSIUS),
)
def test_cpu_board(test, serial):
"""Vérifier l'horloge et la température de la carte CPU."""
test.measurements.cpu_clock_mhz = float(serial.send_command("CLOCK?"))
test.measurements.cpu_temp = float(serial.send_command("TEMP?"))
@htf.plug(adc=AnalogInputPlug)
@htf.measures(
htf.Measurement("pwr_12v_rail").in_range(minimum=11.4, maximum=12.6).with_units(units.VOLT),
htf.Measurement("pwr_efficiency_pct").in_range(minimum=85),
)
def test_power_board(test, adc):
"""Vérifier les rails de sortie et le rendement de la carte d'alimentation."""
test.measurements.pwr_12v_rail = adc.read_voltage(channel=0)
vin = adc.read_voltage(channel=4)
vout = adc.read_voltage(channel=5)
test.measurements.pwr_efficiency_pct = (vout / vin) * 100 if vin > 0 else 0
@htf.plug(serial=SerialCommandPlug, adc=AnalogInputPlug)
@htf.measures(
htf.Measurement("sensor_offset_mv").in_range(minimum=-5, maximum=5),
htf.Measurement("sensor_gain_error_pct").in_range(minimum=-1, maximum=1),
)
def test_sensor_board(test, serial, adc):
"""Vérifier la calibration de la carte capteur."""
serial.send_command("SENSOR CAL_CHECK")
test.measurements.sensor_offset_mv = float(serial.send_command("SENSOR OFFSET?"))
test.measurements.sensor_gain_error_pct = float(serial.send_command("SENSOR GAIN_ERR?"))Détecter les régressions dans TofuPilot
TofuPilot suit chaque valeur de mesure sur toutes les exécutions. Pour détecter les régressions firmware :
- Filtrer par version de firmware. Ouvrez l'onglet Analytique de la procédure et filtrez les exécutions par la mesure
firmware_version. Comparez les taux de réussite et les distributions de mesures entre les versions. - Vérifier les tendances des mesures. Les graphiques de tendance de TofuPilot montrent les valeurs de mesure dans le temps. Un changement soudain après une mise à jour firmware est un signal clair de régression.
- Comparer le Cpk par version. Si le Cpk d'une mesure baisse après un changement de firmware, la capabilité du processus s'est dégradée.
Suivi manuel vs TofuPilot
| Aspect | Tableur / Manuel | TofuPilot |
|---|---|---|
| Étiquetage version firmware | Copier-coller dans une colonne | Métadonnées automatiques par exécution |
| Stockage des formes d'onde | Disque partagé avec conventions de nommage | Joint à l'exécution, toujours trouvable |
| Traçabilité multi-cartes | Feuilles ou onglets séparés | Sous-unités liées à l'assemblage parent |
| Détection de régression | Inspection manuelle des graphiques | Filtrer par version firmware, comparer les tendances |
| Comparaison inter-stations | Fusionner des fichiers de différents PC | Toutes les stations envoient vers un seul espace de travail |
| Recherche historique | « Dans quel dossier c'était déjà ? » | Recherche par numéro de série, référence ou date |
| Piste d'audit | Espérer que personne n'a supprimé une ligne | Enregistrements immuables avec horodatage |