Instrument Control

Automatiser une alimentation Rigol

Contrôlez une alimentation Rigol série DP800 depuis Python avec PyVISA, incluant le contrôle multi-canaux, la protection OVP/OCP et l'intégration.

JJulien Buteau
beginner10 min de lecture14 mars 2026

Contrôlez une alimentation Rigol série DP800 via USB ou Ethernet avec Python, encapsulez-la dans un plug OpenHTF et enregistrez les résultats dans TofuPilot. Ce guide couvre la connexion, le contrôle multi-canaux, les paramètres de protection et un exemple complet de test de production.

Prérequis

  • Alimentation Rigol série DP800 (DP821, DP831, DP832 ou DP832A)
  • Python 3.8+
  • Câble USB-B ou connexion réseau vers l'alimentation
terminal
pip install pyvisa pyvisa-py tofupilot openhtf

Étape 1 : Se connecter à l'instrument

Les instruments Rigol DP800 exposent une interface VISA via USB-TMC et TCP/IP.

ConnexionExemple d'adresse VISA
USB-TMCUSB0::0x1AB1::0x0E11::DP8C224200001::INSTR
Ethernet (VXI-11)TCPIP0::192.168.1.50::inst0::INSTR
Ethernet (socket brut)TCPIP0::192.168.1.50::5555::SOCKET
connect_rigol.py
import pyvisa

rm = pyvisa.ResourceManager()
psu = rm.open_resource("USB0::0x1AB1::0x0E11::DP8C224200001::INSTR")
psu.timeout = 5000
psu.write_termination = "
"
psu.read_termination = "
"

print(psu.query("*IDN?"))
# Rigol Technologies,DP832,DP8C224200001,00.01.14

Étape 2 : Comprendre la syntaxe SCPI Rigol

La syntaxe SCPI des Rigol DP800 diffère de Keysight sur plusieurs points importants.

OpérationRigol DP800Keysight E36xx
Sélectionner le canal:INST CH1:INST:SEL OUT1
Définir la tension:VOLT 5.0:VOLT 5.0
Définir le courant limite:CURR 1.0:CURR 1.0
Activer la sortie:OUTP CH1,ON:OUTP ON
Lire la tension:MEAS:VOLT? CH1:MEAS:VOLT?
Lire le courant:MEAS:CURR? CH1:MEAS:CURR?
Activer OVP:OUTP:OVP CH1,ON:VOLT:PROT:STAT ON
Niveau OVP:OUTP:OVP:VAL CH1,5.5:VOLT:PROT:LEV 5.5

Étape 3 : Contrôler la tension, le courant et la sortie

rigol_basic_control.py
import pyvisa

rm = pyvisa.ResourceManager()
psu = rm.open_resource("USB0::0x1AB1::0x0E11::DP8C224200001::INSTR")
psu.timeout = 5000

def set_channel(psu, channel: int, voltage: float, current: float) -> None:
    psu.write(f":INST CH{channel}")
    psu.write(f":VOLT {voltage:.3f}")
    psu.write(f":CURR {current:.3f}")

def enable_output(psu, channel: int) -> None:
    psu.write(f":OUTP CH{channel},ON")

def disable_output(psu, channel: int) -> None:
    psu.write(f":OUTP CH{channel},OFF")

def measure_voltage(psu, channel: int) -> float:
    return float(psu.query(f":MEAS:VOLT? CH{channel}"))

def measure_current(psu, channel: int) -> float:
    return float(psu.query(f":MEAS:CURR? CH{channel}"))

# Exemple : alimenter un rail 3,3 V à 500 mA maximum
set_channel(psu, 1, voltage=3.3, current=0.5)
enable_output(psu, 1)

vout = measure_voltage(psu, 1)
iout = measure_current(psu, 1)
print(f"CH1: {vout:.3f} V, {iout:.4f} A")

Étape 4 : Contrôle multi-canaux (DP832)

Le DP832 dispose de trois canaux indépendants. Configurez tous les canaux avant d'activer une sortie.

rigol_multichannel.py
import pyvisa
import time

rm = pyvisa.ResourceManager()
psu = rm.open_resource("USB0::0x1AB1::0x0E11::DP8C224200001::INSTR")
psu.timeout = 5000

CHANNELS = {
    1: {"voltage": 5.0, "current": 2.0},   # Rail principal 5 V
    2: {"voltage": 3.3, "current": 1.0},   # Rail logique
    3: {"voltage": 12.0, "current": 0.5},  # Rail analogique
}

for ch, cfg in CHANNELS.items():
    psu.write(f":INST CH{ch}")
    psu.write(f":VOLT {cfg['voltage']:.3f}")
    psu.write(f":CURR {cfg['current']:.3f}")

for ch in CHANNELS:
    psu.write(f":OUTP CH{ch},ON")

time.sleep(0.1)

for ch in CHANNELS:
    v = float(psu.query(f":MEAS:VOLT? CH{ch}"))
    i = float(psu.query(f":MEAS:CURR? CH{ch}"))
    print(f"CH{ch}: {v:.3f} V  {i:.4f} A")

Étape 5 : Configurer la protection OVP et OCP

Configurez toujours la protection avant d'activer la sortie dans un environnement de production.

rigol_protection.py
def configure_protection(psu, channel: int, ovp_volts: float, ocp_amps: float) -> None:
    psu.write(f":OUTP:OVP:VAL CH{channel},{ovp_volts:.3f}")
    psu.write(f":OUTP:OVP CH{channel},ON")
    psu.write(f":OUTP:OCP:VAL CH{channel},{ocp_amps:.3f}")
    psu.write(f":OUTP:OCP CH{channel},ON")

# Rail 5 V : déclenchement à 5,5 V ou 2,5 A
configure_protection(psu, 1, ovp_volts=5.5, ocp_amps=2.5)

Les seuils de déclenchement OVP et OCP doivent être réglés 10 à 15 % au-dessus des valeurs nominales pour éviter les déclenchements intempestifs tout en détectant rapidement les défauts.

Étape 6 : Créer un plug OpenHTF

plugs/rigol_dp800.py
import time
import pyvisa
import openhtf as htf


class RigolDP800(htf.plugs.BasePlug):
    """Plug OpenHTF pour les alimentations Rigol série DP800."""

    VISA_ADDRESS = "USB0::0x1AB1::0x0E11::DP8C224200001::INSTR"

    def setUp(self):
        self._rm = pyvisa.ResourceManager()
        self._psu = self._rm.open_resource(self.VISA_ADDRESS)
        self._psu.timeout = 5000
        self._psu.write_termination = "
"
        self._psu.read_termination = "
"

    def tearDown(self):
        for ch in (1, 2, 3):
            try:
                self._psu.write(f":OUTP CH{ch},OFF")
            except Exception:
                pass
        if self._psu:
            self._psu.close()
        self._rm.close()

    def configure(self, channel: int, voltage: float, current: float):
        self._psu.write(f":INST CH{channel}")
        self._psu.write(f":VOLT {voltage:.3f}")
        self._psu.write(f":CURR {current:.3f}")

    def set_protection(self, channel: int, ovp: float, ocp: float):
        self._psu.write(f":OUTP:OVP:VAL CH{channel},{ovp:.3f}")
        self._psu.write(f":OUTP:OVP CH{channel},ON")
        self._psu.write(f":OUTP:OCP:VAL CH{channel},{ocp:.3f}")
        self._psu.write(f":OUTP:OCP CH{channel},ON")

    def enable(self, channel: int):
        self._psu.write(f":OUTP CH{channel},ON")

    def disable(self, channel: int):
        self._psu.write(f":OUTP CH{channel},OFF")

    def measure_voltage(self, channel: int) -> float:
        return float(self._psu.query(f":MEAS:VOLT? CH{channel}"))

    def measure_current(self, channel: int) -> float:
        return float(self._psu.query(f":MEAS:CURR? CH{channel}"))

Étape 7 : Écrire le test de production avec TofuPilot

test_power_supply.py
import time
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
from plugs.rigol_dp800 import RigolDP800


@htf.plug(psu=RigolDP800)
def power_on_dut(test, psu):
    """Configure les rails, active la protection et alimente le DUT."""
    psu.configure(channel=1, voltage=5.0, current=2.0)
    psu.set_protection(channel=1, ovp=5.5, ocp=2.5)
    psu.configure(channel=2, voltage=3.3, current=1.0)
    psu.set_protection(channel=2, ovp=3.7, ocp=1.2)
    psu.enable(channel=1)
    psu.enable(channel=2)
    time.sleep(0.5)


@htf.plug(psu=RigolDP800)
@htf.measures(
    htf.Measurement("ch1_voltage")
    .in_range(minimum=4.85, maximum=5.15)
    .with_units(units.VOLT),
    htf.Measurement("ch1_current")
    .in_range(maximum=2.0)
    .with_units(units.AMPERE),
    htf.Measurement("ch2_voltage")
    .in_range(minimum=3.20, maximum=3.40)
    .with_units(units.VOLT),
    htf.Measurement("ch2_current")
    .in_range(maximum=1.0)
    .with_units(units.AMPERE),
)
def measure_power_rails(test, psu):
    """Lit et valide tous les rails d'alimentation sous charge."""
    test.measurements.ch1_voltage = psu.measure_voltage(channel=1)
    test.measurements.ch1_current = psu.measure_current(channel=1)
    test.measurements.ch2_voltage = psu.measure_voltage(channel=2)
    test.measurements.ch2_current = psu.measure_current(channel=2)


@htf.plug(psu=RigolDP800)
def power_off_dut(test, psu):
    """Désactive toutes les sorties après le test."""
    psu.disable(channel=1)
    psu.disable(channel=2)


def main():
    test = htf.Test(
        power_on_dut,
        measure_power_rails,
        power_off_dut,
        test_name="Power Supply Validation",
    )

    with TofuPilot(test):
        test.execute(test_start=lambda: input("Entrez le numéro de série : ").strip())


if __name__ == "__main__":
    main()

Dépannage

SymptômeCause probableSolution
Instrument non trouvé via USBRègles udev manquantes (Linux)Ajouter SUBSYSTEM=="usb", ATTR{idVendor}=="1ab1", MODE="0666" aux règles udev
VI_ERROR_TMO lors d'une requêteread_termination non définiDéfinir `psu.read_termination = "
"`
La sortie déclenche l'OCP immédiatementL'appel de courant capacitif dépasse la limiteAugmenter la limite OCP de 20 % au-dessus du régime permanent ou monter la tension progressivement
Les mesures indiquent 0 VCanal en mode CC, charge trop lourdeAugmenter la limite de courant ou réduire la charge
La connexion Ethernet se coupeTimeout d'inactivité VXI-11 (~60 s)Rouvrir la ressource ou envoyer un *IDN? périodique comme keep-alive
La commande ne retourne aucune donnéeUtilisation de query() pour une commande setUtiliser write() pour les commandes qui ne retournent pas de données

Plus de guides

Mettez ce guide en pratique