Test Data & Analytics

Analyse de données de test temporelles

Apprenez à capturer, stocker et analyser des données de mesure en séries temporelles issues de tests matériels avec les tableaux multidimensionnels de.

JJulien Buteau
intermediate10 min de lecture14 mars 2026

Les tests matériels produisent des formes d'onde, pas seulement des nombres isolés. Un test d'ondulation d'alimentation capture des milliers d'échantillons de tension dans le temps. Un test de vibration enregistre des spectres d'accélération sur différentes bandes de fréquence. Les stocker nativement permet de suivre et comparer les formes d'onde sur l'ensemble de votre production.

Valeurs uniques vs. séries temporelles

La plupart des systèmes de test stockent un seul nombre par mesure : « tension de sortie = 3,31 V ». Mais l'histoire complète se trouve dans la forme d'onde. Ce 3,31 V peut être un signal DC propre ou un signal bruité qui se moyenne simplement à 3,31 V.

Type de donnéesExempleCe que cela révèle
Valeur uniqueVout = 3,31 VNiveau moyen de sortie
Série temporelle1000 échantillons sur 10 msOndulation, bruit, comportement transitoire
Spectre fréquentielFFT de la tension de sortieContenu fréquentiel du bruit de commutation
Multi-axesAccélération X/Y/ZVibration dans toutes les directions

Les mesures dimensionnées gèrent tous ces types.

Capture de données en séries temporelles

Avec OpenHTF

Utilisez des mesures dimensionnées pour stocker les données en séries temporelles.

ripple_test_openhtf.py
35 lines
import openhtf as htffrom tofupilot.openhtf import upload@htf.measures(    htf.Measurement("output_ripple_mv")        .with_dimensions("time_us")        .with_units("mV"),    htf.Measurement("ripple_pk_pk_mv")        .in_range(0, 50)        .with_units("mV"),)def ripple_test(test):    # Capturer 1000 échantillons à 100 kHz (espacement de 10 us)    waveform = capture_oscilloscope(channel=1, samples=1000, rate_hz=100000)    for i, sample in enumerate(waveform):        test.measurements.output_ripple_mv[i * 10] = sample  # temps en microsecondes    # Stocker aussi le résumé scalaire    test.measurements.ripple_pk_pk_mv = max(waveform) - min(waveform)def main():    test = htf.Test(        ripple_test,        procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",  # UUID de procédure du dashboard        part_number="PSU-100",    )    test.add_output_callbacks(upload())    test.execute(lambda: "PSU-2025-0099")if __name__ == "__main__":    main()

Installez-le avec pip install "tofupilot[openhtf]". Le callback upload() lit TOFUPILOT_API_KEY dans l'environnement.

Notez que la limite de conformité porte sur le scalaire (ripple_pk_pk_mv), pas sur la forme d'onde. Cette répartition est délibérée et vaut la peine d'être conservée : le scalaire décide du verdict et alimente les tendances, tandis que la forme d'onde est ce qu'on ouvre quand le scalaire signale un problème.

Avec le SDK Python

Si vous n'utilisez pas OpenHTF, créez l'exécution directement :

ripple_test_client.py
36 lines
import osfrom datetime import datetime, timedelta, timezoneimport numpy as npfrom tofupilot.v2 import TofuPilotstarted = datetime.now(timezone.utc) - timedelta(seconds=5)ended = datetime.now(timezone.utc)waveform = capture_oscilloscope(channel=1, samples=1000, rate_hz=100000)pk_pk = float(np.max(waveform) - np.min(waveform))outcome = "PASS" if pk_pk < 50 else "FAIL"with TofuPilot(api_key=os.getenv("TOFUPILOT_API_KEY")) as client:    client.runs.create(        procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",        serial_number="PSU-2025-0099",        part_number="PSU-100",        outcome=outcome,        started_at=started,        ended_at=ended,        phases=[{            "name": "Output Ripple",            "outcome": outcome,            "started_at": started,            "ended_at": ended,            "measurements": [{                "name": "Ripple Peak to Peak",                "measured_value": pk_pk,                "units": "mV",                "validators": [                    {"operator": "<=", "expected_value": 50},                ],            }],        }],    )

Ceci envoie le scalaire extrait plutôt que les 1000 échantillons. Si vous devez conserver la capture brute à côté du résultat, joignez-la comme fichier plutôt que de l'étendre en mesures.

Types de données de test en séries temporelles

Formes d'onde tension/courant

Capturées depuis des oscilloscopes ou des DAQ lors de séquences de mise sous tension, tests d'ondulation ou tests de réponse transitoire. Stockez la forme d'onde brute plus les résumés scalaires (crête-à-crête, RMS, temps de montée).

Profils de température

Enregistrés pendant les cycles thermiques, le déverminage ou les tests de dissipation thermique. Plusieurs capteurs produisent des données multi-canaux sur des minutes ou des heures.

thermal_profile.py
# Test thermique avec 4 capteurs échantillonnés chaque seconde pendant 30 minutessensors = ["junction", "ambient", "heatsink", "case"]duration_s = 1800samples_per_sensor = duration_s  # 1 échantillon/secondefor sensor_name in sensors:    readings = read_thermal_sensor(sensor_name, samples=samples_per_sensor)    measurements.append({        "name": f"temp_{sensor_name}",        "measured_value": max(readings),   # la température de pic est la valeur qui décide        "units": "degC",        "validators": [            {"operator": "<=", "expected_value": 85},        ],    })

Quatre capteurs à 1800 échantillons chacun font 7200 points par unité. En volume de production, stockez les caractéristiques qui décident du résultat (pic, temps au-dessus du seuil, régime établi final) et gardez le profil complet en pièce jointe.

Spectres de vibration

Données FFT d'accéléromètres lors de tests de vibration. La fréquence sur un axe, l'amplitude sur l'autre.

Courbes pression/débit

Mesures de pression et de débit en séries temporelles lors de tests d'étanchéité, tests pneumatiques ou validation hydraulique.

Analyse des séries temporelles sur l'ensemble de la production

La puissance du stockage de formes d'onde plutôt que de simples scalaires réside dans la comparaison entre unités.

Superposition de formes d'onde

Comparez les formes d'onde de 100 unités. Si 99 se ressemblent et qu'une a un pic supplémentaire, cette unité a un problème que la mesure crête-à-crête seule n'aurait peut-être pas détecté.

Bornes statistiques

Calculez la moyenne et l'écart type de votre forme d'onde à chaque point temporel sur toutes les unités. Cela donne une enveloppe de comportement normal. Toute unité qui en sort est signalée.

waveform_statistics.py
import numpy as np# Toutes les formes d'onde de la production (chacune est une liste de 1000 échantillons)all_waveforms = np.array(waveforms_from_production)  # forme : (N_unités, 1000)mean_waveform = np.mean(all_waveforms, axis=0)std_waveform = np.std(all_waveforms, axis=0)upper_bound = mean_waveform + 3 * std_waveformlower_bound = mean_waveform - 3 * std_waveform# Vérifier si la forme d'onde d'une nouvelle unité est dans les bornesnew_waveform = np.array(new_unit_data)is_anomalous = np.any(new_waveform > upper_bound) or np.any(new_waveform < lower_bound)

Deux réserves avant d'en faire un critère de rejet. Avec 1000 points et une bande à 3 sigma, environ 3 points par unité sortiront par simple hasard, donc np.any signalera une large part des bonnes unités. Exigez une série de points consécutifs hors bande, ou comparez à une bande de tolérance plutôt qu'à un sigma par point. Et l'enveloppe doit être construite sur une période où le process était stable, sinon vous encodez une dérive comme normale.

Analyse de tendance sur les caractéristiques

Extrayez des caractéristiques de chaque forme d'onde (temps de montée, temps d'établissement, dépassement, RMS) et suivez leur tendance. Une augmentation progressive du temps de montée suggère une dérive de composant ou de processus.

C'est généralement l'analyse la plus rentable des trois, et la moins coûteuse à stocker : quelques nombres par unité, qui alimentent tendances et alertes comme toute autre mesure.

Bonnes pratiques

PratiquePourquoi
Stocker à la fois la forme d'onde brute et les résumés scalairesLes formes d'onde pour l'analyse approfondie, les scalaires pour les tableaux de bord et le suivi
Utiliser des taux d'échantillonnage cohérentsComparer des formes d'onde nécessite le même nombre de points et le même timing
Inclure les métadonnées de l'axe temporelTaux d'échantillonnage ou horodatages pour reconstruire la forme d'onde
Définir des limites sur les résumés scalairesLes scalaires déterminent la conformité, les formes d'onde servent à l'analyse des causes
Limiter la taille des formes d'ondeGarder les tableaux sous 10 000 points par mesure
Capturer les traces brutes sur échec ou par échantillonnageChaque unité à pleine cadence dépasse vite son utilité

Plus de guides

Mettez ce guide en pratique