Source code for qblox_instruments.qcodes_drivers.spi_rack

# ----------------------------------------------------------------------------
# Description    : SPI Rack QCoDeS interface
# Git repository :
# Copyright (C) Qblox BV (2021)
# ----------------------------------------------------------------------------

from time import time
from typing import Union, Optional

from qcodes.instrument.base import Instrument

from qblox_instruments.native import SpiRack as SpiRackNative
from qblox_instruments.qcodes_drivers.spi_rack_modules import SpiModuleBase, DummySpiModule
from qblox_instruments.qcodes_drivers.spi_rack_modules import S4gModule, D5aModule

[docs]class SpiRack(SpiRackNative, Instrument): """ SPI rack driver class based on `QCoDeS <>`_. Example usage: .. highlight:: python .. code-block:: python from qblox_instruments import SpiRack from qblox_instruments.qcodes_drivers.spi_rack_modules import S4gModule spi = SpiRack("my_spi_rack", "COM4") # connects to an SPI rack on COM port 4 spi.add_spi_module(3, "D5a", "alice") # adds an D5a module with address 3 named "alice" spi.add_spi_module(2, "S4g", "bob") # adds an S4g module with address 2 named "bob" spi.add_spi_module(6, S4gModule) # adds an S4g module with address 6 with the default name module6 spi.bob.dac0.current(10e-3) # sets the current of output 1 of the S4g module named "bob" to 10 mA spi.alice.dac6.voltage(-2) # sets the voltage of output 7 of the D5a module named "alice" to -2 V """
[docs] def __init__( self, name: str, address: str, baud_rate: int = 9600, timeout: float = 1, is_dummy: bool = False, ): """ Instantiates the driver object. Parameters ---------- name : str Instrument name. address : str COM port used by SPI rack controller unit (e.g. "COM4") baud_rate : int Baud rate timeout : float Data receive timeout in seconds is_dummy : bool If true, the SPI rack driver is operating in "dummy" mode for testing purposes. Returns ---------- """ t0 = time() super().__init__(address, baud_rate, timeout, is_dummy) Instrument.__init__(self, name) # If drivers are created for different modules they should be added # here self._MODULES_MAP = { "S4g": S4gModule, "D5a": D5aModule, "dummy": DummySpiModule, } self._add_qcodes_params() self.connect_message(begin_time=t0)
def _add_qcodes_params(self) -> None: """ Function to add the QCoDeS parameters to the instrument. """ self.add_parameter( "temperature", unit="C", set_cmd=False, get_cmd=self.spi_rack.get_temperature, docstring="Returns the temperature in the C1b module. Reads the " "temperature from the internal C1b temperature sensor. Accuracy " "is +- 0.5 degrees in 0-70 degree range.", ) self.add_parameter( "battery_voltages", unit="V", set_cmd=False, get_cmd=self.spi_rack.get_battery, docstring="Calculates the battery voltages from the ADC channel " "values. Returns: [VbatPlus, VbatMin]", )
[docs] def add_spi_module( self, address: int, module_type: Union[SpiModuleBase, str], name: Optional[str] = None, **kwargs, ) -> None: """ Add a module to the driver. Parameters ---------- address : int Address that the module is set to (set internally on the module itself with a jumper). module_type : Union[str, :class:`~qblox_instruments.qcodes_drivers.spi_rack_modules.spi_module_base.SpiModuleBase`] Either a str that is defined in _MODULES_MAP, or a reference to a class derived from :class:`~qblox_instruments.qcodes_drivers.spi_rack_modules.spi_module_base.SpiModuleBase`. name: Optional[str] Optional name of the module. If no name is given or is None, a default name of "module{address}" is used. Returns ---------- Raises ---------- ValueError module_type is not a string or a subclass of :class:`~qblox_instruments.qcodes_drivers.spi_rack_modules.spi_module_base.SpiModuleBase` """ name, module_obj = SpiRackNative.add_spi_module( self, address, module_type, name, **kwargs ) self.add_submodule(name, module_obj)
[docs] def close(self) -> None: """ Closes connection to hardware and closes the Instrument. """ SpiRackNative.close(self) Instrument.close(self)
[docs] def connect_message( self, idn_param: str = "IDN", begin_time: Optional[float] = None ) -> None: """ Print a standard message on initial connection to an instrument. Overridden from superclass to accommodate IEEE488.2 for IDN. Parameters ---------- idn_param: str Name of parameter that returns ID dict. Default ``IDN``. begin_time: Optional[float] ``time.time()`` when init started. Default is ``self._t0``, set at start of ``Instrument.__init__``. """ # start with an empty dict, just in case an instrument doesn't # heed our request to return all 4 fields. idn = { "manufacturer": None, "model": None, "serial": None, "firmware": None } idn.update(self.get(idn_param)) t = time() - (begin_time or self._t0) con_msg = ( "Connected to: {manufacturer} {model} " + "(serial:{serial}, firmware:{firmware}) " + "in {t:.2f}s" ).format(t=t, **idn) print(con_msg)"Connected to instrument: {idn}")