diff --git a/doc/source/apiref/lakeshore.rst b/doc/source/apiref/lakeshore.rst index a16bf29c..75f3dd2d 100644 --- a/doc/source/apiref/lakeshore.rst +++ b/doc/source/apiref/lakeshore.rst @@ -7,6 +7,13 @@ Lakeshore ========= +:class:`Lakeshore336` Cryogenic Temperature Controller +====================================================== + +.. autoclass:: Lakeshore336 + :members: + :undoc-members: + :class:`Lakeshore340` Cryogenic Temperature Controller ====================================================== diff --git a/src/instruments/abstract_instruments/comm/serial_manager.py b/src/instruments/abstract_instruments/comm/serial_manager.py index dcc6bec5..b8b0edd1 100644 --- a/src/instruments/abstract_instruments/comm/serial_manager.py +++ b/src/instruments/abstract_instruments/comm/serial_manager.py @@ -31,7 +31,7 @@ # METHODS ##################################################################### -def new_serial_connection(port, baud=460800, timeout=3, write_timeout=3): +def new_serial_connection(port, baud=460800, timeout=3, write_timeout=3, **kwargs): """ Return a `pyserial.Serial` connection object for the specified serial port address. The same object will be returned for identical port @@ -56,7 +56,11 @@ def new_serial_connection(port, baud=460800, timeout=3, write_timeout=3): if port not in serialObjDict or serialObjDict[port] is None: conn = SerialCommunicator( serial.Serial( - port, baudrate=baud, timeout=timeout, writeTimeout=write_timeout + port, + baudrate=baud, + timeout=timeout, + writeTimeout=write_timeout, + **kwargs ) ) serialObjDict[port] = conn diff --git a/src/instruments/lakeshore/__init__.py b/src/instruments/lakeshore/__init__.py index ac32a5d2..a7e04b16 100644 --- a/src/instruments/lakeshore/__init__.py +++ b/src/instruments/lakeshore/__init__.py @@ -4,6 +4,7 @@ """ +from instruments.lakeshore.lakeshore336 import Lakeshore336 from instruments.lakeshore.lakeshore340 import Lakeshore340 from instruments.lakeshore.lakeshore370 import Lakeshore370 from instruments.lakeshore.lakeshore475 import Lakeshore475 diff --git a/src/instruments/lakeshore/lakeshore336.py b/src/instruments/lakeshore/lakeshore336.py new file mode 100644 index 00000000..33aee9cb --- /dev/null +++ b/src/instruments/lakeshore/lakeshore336.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +""" +Provides support for the Lakeshore Model 336 cryogenic temperature controller. +""" + +# IMPORTS ##################################################################### + +from instruments.generic_scpi import SCPIInstrument +from instruments.units import ureg as u +from instruments.util_fns import ProxyList + +# CLASSES ##################################################################### + + +class Lakeshore336(SCPIInstrument): + """ + The Lakeshore Model 336 is a multi-sensor cryogenic temperature controller. + + Example usage: + + >>> import instruments as ik + >>> import instruments.units as u + >>> import serial + >>> inst = ik.lakeshore.Lakeshore336.open_serial('/dev/ttyUSB0', baud=57600, bytesize=serial.SEVENBITS, parity=serial.PARITY_ODD, stopbits=serial.STOPBITS_ONE) + >>> print(inst.sensor[0].temperature) + >>> print(inst.sensor[1].temperature) + """ + + # INNER CLASSES ## + + class Sensor: + """ + Class representing a sensor attached to the Lakeshore Model 336. + + .. warning:: This class should NOT be manually created by the user. It is + designed to be initialized by the `Lakeshore336` class. + """ + + def __init__(self, parent, idx): + _idx_mapper = {0: "A", 1: "B", 2: "C", 3: "D"} + self._parent = parent + self._idx = _idx_mapper[idx] + + # PROPERTIES ## + + @property + def temperature(self): + """ + Gets the temperature of the specified sensor. + + :units: Kelvin + :type: `~pint.Quantity` + """ + value = self._parent.query(f"KRDG?{self._idx}") + return u.Quantity(float(value), u.kelvin) + + # PROPERTIES ## + + @property + def sensor(self): + """ + Gets a specific sensor object. The desired sensor is specified like + one would access a list. + + For instance, after opening the connection as described in the overview, + this would query the temperature of the first sensor: + + >>> print(inst.sensor[0].temperature) + + The Lakeshore 336 supports up to 4 sensors (index 0-3). + + :rtype: `~Lakeshore336.Sensor` + """ + return ProxyList(self, Lakeshore336.Sensor, range(4)) diff --git a/tests/test_lakeshore/test_lakeshore336.py b/tests/test_lakeshore/test_lakeshore336.py new file mode 100644 index 00000000..8796c044 --- /dev/null +++ b/tests/test_lakeshore/test_lakeshore336.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +""" +Module containing tests for the Lakeshore 336 +""" + +# IMPORTS #################################################################### + +import pytest + +import instruments as ik +from instruments.units import ureg as u +from tests import expected_protocol + +# TESTS ###################################################################### + +# pylint: disable=protected-access + +# TEST SENSOR CLASS # + + +def test_lakeshore336_sensor_init(): + """ + Test initialization of sensor class. + """ + with expected_protocol( + ik.lakeshore.Lakeshore336, + [], + [], + ) as cryo: + sensor = cryo.sensor[0] + assert sensor._parent is cryo + assert sensor._idx == "A" + + +@pytest.mark.parametrize("idx_ch", [(0, "A"), (1, "B"), (2, "C"), (3, "D")]) +def test_lakeshore336_sensor_temperature(idx_ch): + """ + Receive a unitful temperature from a sensor. + """ + idx, ch = idx_ch + with expected_protocol( + ik.lakeshore.Lakeshore336, + [f"KRDG?{ch}"], + ["77"], + ) as cryo: + assert cryo.sensor[idx].temperature == u.Quantity(77, u.K)