"""Multimeter SCPI driver. This module implements a client-side driver for digital multimeters that communicate via SCPI commands. """ from py_dvt_ate.instruments.drivers.base import BaseDriver from py_dvt_ate.instruments.interfaces import IMultimeter class MultimeterDriver(BaseDriver, IMultimeter): """SCPI driver for digital multimeters. Provides high-level Python API for making measurements with DMMs via SCPI commands. Implements the IMultimeter interface. SCPI Commands Used: MEAS:VOLT:DC? - Measure DC voltage MEAS:CURR:DC? - Measure DC current CONF:VOLT:DC - Configure for DC voltage measurement CONF:CURR:DC - Configure for DC current measurement CONF? - Query current configuration READ? - Take measurement with current configuration Example: >>> transport = TCPTransport("localhost", 5003) >>> dmm = MultimeterDriver(transport) >>> dmm.connect() >>> voltage = dmm.measure_dc_voltage() >>> current = dmm.measure_dc_current() """ def measure_dc_voltage(self, range: str = "AUTO") -> float: """Measure DC voltage. Configures the meter for DC voltage and takes a measurement. Args: range: Measurement range. Default "AUTO" for auto-ranging. Note: Range parameter currently not supported by simulator. Returns: Measured voltage in volts. Raises: ConnectionError: If not connected. IOError: If query fails. """ # Note: Range parameter not yet implemented in virtual instrument return self.query_float("MEAS:VOLT:DC?") def measure_dc_current(self, range: str = "AUTO") -> float: """Measure DC current. Configures the meter for DC current and takes a measurement. Args: range: Measurement range. Default "AUTO" for auto-ranging. Note: Range parameter currently not supported by simulator. Returns: Measured current in amps. Raises: ConnectionError: If not connected. IOError: If query fails. """ # Note: Range parameter not yet implemented in virtual instrument return self.query_float("MEAS:CURR:DC?") def measure_resistance(self, range: str = "AUTO") -> float: """Measure resistance. Configures the meter for resistance and takes a measurement. Args: range: Measurement range. Default "AUTO" for auto-ranging. Returns: Measured resistance in ohms. Raises: ConnectionError: If not connected. IOError: If query fails. NotImplementedError: If instrument does not support resistance. """ # Note: Resistance measurement not yet implemented in virtual instrument raise NotImplementedError( "Resistance measurement not yet supported by virtual instrument" ) def set_integration_time(self, nplc: float) -> None: """Set the integration time. Args: nplc: Integration time in number of power line cycles (NPLC). Typical values: 0.02, 0.2, 1, 10, 100. Raises: ConnectionError: If not connected. IOError: If command fails. NotImplementedError: If instrument does not support integration time. """ # Note: Integration time not yet implemented in virtual instrument raise NotImplementedError( "Integration time setting not yet supported by virtual instrument" ) def configure_dc_voltage(self) -> None: """Configure meter for DC voltage measurement. Sets the measurement function without taking a measurement. Use read() to take a measurement after configuring. Raises: ConnectionError: If not connected. IOError: If command fails. """ self.write("CONF:VOLT:DC") def configure_dc_current(self) -> None: """Configure meter for DC current measurement. Sets the measurement function without taking a measurement. Use read() to take a measurement after configuring. Raises: ConnectionError: If not connected. IOError: If command fails. """ self.write("CONF:CURR:DC") def get_configuration(self) -> str: """Get the current measurement configuration. Returns: Configuration string (e.g., "VOLT:DC", "CURR:DC"). Raises: ConnectionError: If not connected. IOError: If query fails. """ return self.query("CONF?").strip('"') def read(self) -> float: """Take a measurement using the current configuration. Must call configure_dc_voltage() or configure_dc_current() first to set the measurement function. Returns: Measured value (voltage in V or current in A). Raises: ConnectionError: If not connected. IOError: If query fails. """ return self.query_float("READ?")