Connectez un multimètre Keysight 34461A ou 34465A à Python via PyVISA, envoyez des commandes SCPI pour mesurer la tension DC, la tension AC, la résistance et le courant, puis enregistrez automatiquement les résultats dans TofuPilot via un plug OpenHTF.
Prérequis
- Multimètre Keysight 34461A ou 34465A (ou série 344xxA compatible)
- Python 3.8+
- OpenHTF et TofuPilot installés
- Keysight IO Libraries Suite (pour USB) ou accès réseau (pour Ethernet)
pip install pyvisa pyvisa-py tofupilot openhtfÉtape 1 : Se connecter à l'instrument
Les multimètres Keysight prennent en charge deux interfaces principales : USB-TMC et Ethernet (LXI).
| Interface | Chaîne de ressource VISA | Cas d'utilisation |
|---|---|---|
| USB-TMC | USB0::0x0957::0x1A07::MY12345678::INSTR | Poste unique, connexion PC directe |
| Ethernet (VXI-11) | TCPIP0::192.168.1.100::inst0::INSTR | Systèmes de test en réseau |
| Ethernet (HiSLIP) | TCPIP0::192.168.1.100::hislip0::INSTR | Débit plus élevé, recommandé pour le 34465A |
Trouvez la chaîne de ressource de votre instrument :
import pyvisa
rm = pyvisa.ResourceManager()
print(rm.list_resources())Ouvrez une connexion et vérifiez l'identité :
import pyvisa
rm = pyvisa.ResourceManager()
dmm = rm.open_resource("USB0::0x0957::0x1A07::MY12345678::INSTR")
dmm.timeout = 5000 # ms
print(dmm.query("*IDN?"))
# Keysight Technologies,34461A,MY12345678,A.02.14-02.40-02.14-00.49-01-01Étape 2 : Configurer les mesures SCPI
Réinitialisez toujours l'instrument à un état connu avant de configurer.
dmm.write("*RST")
dmm.write("*CLS")
print(dmm.query("SYST:ERR?"))
# +0,"No error"Tension DC
# Tension DC en auto-range
dmm.write("CONF:VOLT:DC AUTO,DEF")
reading = float(dmm.query("READ?"))
print(f"Tension DC : {reading:.6f} V")
# Calibre manuel : calibre 10 V
dmm.write("CONF:VOLT:DC 10,DEF")
reading = float(dmm.query("READ?"))Tension AC
dmm.write("CONF:VOLT:AC AUTO,DEF")
reading = float(dmm.query("READ?"))
print(f"Tension AC (RMS) : {reading:.6f} V")Résistance (2 fils et 4 fils)
# Résistance 2 fils, auto-range
dmm.write("CONF:RES AUTO,DEF")
reading = float(dmm.query("READ?"))
print(f"Résistance 2 fils : {reading:.4f} Ohm")
# Résistance 4 fils (élimine la résistance des fils de mesure)
dmm.write("CONF:FRES AUTO,DEF")
reading = float(dmm.query("READ?"))
print(f"Résistance 4 fils : {reading:.4f} Ohm")Courant DC
dmm.write("CONF:CURR:DC AUTO,DEF")
reading = float(dmm.query("READ?"))
print(f"Courant DC : {reading:.6f} A")Référence des commandes SCPI
| Mesure | Commande CONF | Valeurs de calibre |
|---|---|---|
| Tension DC | CONF:VOLT:DC {range},DEF | 0.1, 1, 10, 100, 1000 V |
| Tension AC | CONF:VOLT:AC {range},DEF | 0.1, 1, 10, 100, 750 V |
| Résistance 2 fils | CONF:RES {range},DEF | 100, 1k, 10k, 100k, 1M, 10M, 100M Ohm |
| Résistance 4 fils | CONF:FRES {range},DEF | Utiliser pour les valeurs inférieures à 100 Ohm |
| Courant DC | CONF:CURR:DC {range},DEF | 0.0001, 0.001, 0.01, 0.1, 1, 3 A |
| Courant AC | CONF:CURR:AC {range},DEF | 0.001, 0.01, 0.1, 1, 3 A |
Étape 3 : Ajuster le compromis vitesse/précision avec NPLC
NPLC (Number of Power Line Cycles) contrôle le temps d'intégration. Un NPLC plus élevé moyenne davantage le bruit mais prend plus de temps.
dmm.write("CONF:VOLT:DC 10,DEF")
dmm.write("VOLT:DC:NPLC 1") # équilibré (par défaut)
dmm.write("VOLT:DC:NPLC 10") # haute précision, plus lent
dmm.write("VOLT:DC:NPLC 0.02") # rapide, plus de bruit| NPLC | Temps d'intégration (60 Hz) | Lectures/sec | Cas d'utilisation |
|---|---|---|---|
| 0.02 | 333 us | ~50 | Tri rapide en production |
| 0.2 | 3.3 ms | ~15 | Bon compromis vitesse/bruit |
| 1 | 16.7 ms | ~5 | Précision standard |
| 10 | 167 ms | ~0.6 | Mesures haute précision |
| 100 | 1.67 s | ~0.1 | Niveau calibration |
Le calibre manuel élimine le délai d'auto-range (~20-50 ms) et est recommandé pour le débit des tests de production.
Étape 4 : Créer un plug OpenHTF pour le multimètre Keysight
import pyvisa
import openhtf as htf
class KeysightDMM(htf.plugs.BasePlug):
"""Plug OpenHTF pour les multimètres Keysight série 344xxA."""
RESOURCE = "USB0::0x0957::0x1A07::MY12345678::INSTR"
NPLC = 1.0
def setUp(self):
self._rm = pyvisa.ResourceManager()
self._dmm = self._rm.open_resource(self.RESOURCE)
self._dmm.timeout = 5000
self._dmm.write("*RST")
self._dmm.write("*CLS")
def tearDown(self):
if self._dmm:
self._dmm.close()
self._rm.close()
def measure_dc_voltage(self, range_v: float = None) -> float:
range_str = str(range_v) if range_v else "AUTO"
self._dmm.write(f"CONF:VOLT:DC {range_str},DEF")
self._dmm.write(f"VOLT:DC:NPLC {self.NPLC}")
return float(self._dmm.query("READ?"))
def measure_ac_voltage(self, range_v: float = None) -> float:
range_str = str(range_v) if range_v else "AUTO"
self._dmm.write(f"CONF:VOLT:AC {range_str},DEF")
return float(self._dmm.query("READ?"))
def measure_resistance(self, four_wire: bool = False, range_ohm: float = None) -> float:
cmd = "FRES" if four_wire else "RES"
range_str = str(range_ohm) if range_ohm else "AUTO"
self._dmm.write(f"CONF:{cmd} {range_str},DEF")
self._dmm.write(f"{cmd}:NPLC {self.NPLC}")
return float(self._dmm.query("READ?"))
def measure_dc_current(self, range_a: float = None) -> float:
range_str = str(range_a) if range_a else "AUTO"
self._dmm.write(f"CONF:CURR:DC {range_str},DEF")
self._dmm.write(f"CURR:DC:NPLC {self.NPLC}")
return float(self._dmm.query("READ?"))Étape 5 : Écrire les tests de production avec TofuPilot
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
from keysight_dmm_plug import KeysightDMM
@htf.plug(dmm=KeysightDMM)
@htf.measures(
htf.Measurement("output_voltage_3v3")
.in_range(minimum=3.267, maximum=3.333)
.with_units(units.VOLT),
htf.Measurement("output_voltage_5v0")
.in_range(minimum=4.900, maximum=5.100)
.with_units(units.VOLT),
)
def test_output_voltages(test, dmm):
"""Vérifie que les tensions de sortie régulées sont dans la tolérance."""
test.measurements.output_voltage_3v3 = dmm.measure_dc_voltage(range_v=10)
test.measurements.output_voltage_5v0 = dmm.measure_dc_voltage(range_v=10)
@htf.plug(dmm=KeysightDMM)
@htf.measures(
htf.Measurement("sense_resistor_value")
.in_range(minimum=0.099, maximum=0.101)
.with_units(units.OHM),
)
def test_sense_resistor(test, dmm):
"""Vérifie la résistance de mesure de courant en 4 fils."""
r = dmm.measure_resistance(four_wire=True, range_ohm=100)
test.measurements.sense_resistor_value = r
@htf.plug(dmm=KeysightDMM)
@htf.measures(
htf.Measurement("quiescent_current")
.in_range(maximum=0.005)
.with_units(units.AMPERE),
)
def test_quiescent_current(test, dmm):
"""Vérifie que le courant de repos ne dépasse pas 5 mA."""
test.measurements.quiescent_current = dmm.measure_dc_current(range_a=0.01)
@htf.plug(dmm=KeysightDMM)
@htf.measures(
htf.Measurement("ac_ripple")
.in_range(maximum=0.050)
.with_units(units.VOLT),
)
def test_output_ripple(test, dmm):
"""Vérifie l'ondulation AC sur la sortie 5 V."""
test.measurements.ac_ripple = dmm.measure_ac_voltage(range_v=1)
def main():
test = htf.Test(
test_output_voltages,
test_sense_resistor,
test_quiescent_current,
test_output_ripple,
test_name="Power Supply Board Functional Test",
)
with TofuPilot(test):
test.execute(test_start=lambda: input("Entrez le numéro de série du DUT : ").strip())
if __name__ == "__main__":
main()Étape 6 : Mode de mesure rapide multi-échantillons
Pour les lignes à haut débit, utilisez SAMP:COUN pour l'échantillonnage en rafale.
import pyvisa
import numpy as np
rm = pyvisa.ResourceManager()
dmm = rm.open_resource("USB0::0x0957::0x1A07::MY12345678::INSTR")
dmm.timeout = 10000
dmm.write("*RST")
dmm.write("CONF:VOLT:DC 10,DEF")
dmm.write("VOLT:DC:NPLC 0.2")
dmm.write("SAMP:COUN 10")
dmm.write("TRIG:SOUR IMM")
dmm.write("TRIG:DEL 0")
dmm.write("INIT")
raw = dmm.query("FETC?")
readings = [float(x) for x in raw.split(",")]
print(f"Moyenne : {np.mean(readings):.6f} V")
print(f"Écart-type : {np.std(readings):.6f} V")Dépannage
| Symptôme | Cause probable | Solution |
|---|---|---|
VI_ERROR_RSRC_NFOUND | Chaîne de ressource incorrecte ou pilote non installé | Exécuter rm.list_resources(), installer Keysight IO Libraries |
+1,"Hardware error" | Surcharge sur les bornes d'entrée | Vérifier les connexions des sondes, réduire le signal d'entrée |
La lecture retourne +9.9E+37 | Le signal dépasse le calibre sélectionné | Utiliser l'auto-range ou augmenter le calibre manuel |
| Les lectures dérivent sur 30 secondes | Multimètre pas encore en température | Laisser 30 minutes de chauffe pour une précision inférieure à 10 ppm |
| Périphérique USB non trouvé sous Linux | Règles udev manquantes | Ajouter SUBSYSTEM=="usb", ATTRS{idVendor}=="0957", MODE="0666" |
| Connexion HiSLIP refusée | HiSLIP non activé | Activer via le panneau avant : Utilities > I/O Config > LAN > HiSLIP |
La commande NPLC retourne une erreur | Préfixe de fonction incorrect | NPLC est par fonction : VOLT:DC:NPLC, RES:NPLC |
| Débit lent via LAN | Overhead du protocole VXI-11 | Passer à HiSLIP pour des transactions 10x plus rapides |
| La lecture 4 fils est identique à la lecture 2 fils | Mauvaises bornes | Vérifier que SENSE HI/LO sont connectés aux bornes séparées |