# This file is part of the scanning-squid package.
#
# Copyright (c) 2018 Logan Bishop-Van Horn
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from qcodes import VisaInstrument, InstrumentChannel, ChannelList
from qcodes.utils.validators import Enum, Strings, Numbers, Ints, MultiType
import visa
class SensorChannel33x(InstrumentChannel):
"""
A single sensor channel of a temperature controller
"""
_CHANNEL_VAL = Enum("A", "B")
def __init__(self, parent, name, channel):
super().__init__(parent, name)
# Validate the channel value
self._CHANNEL_VAL.validate(channel)
self._channel = channel # Channel on the temperature controller. Can be A-B
# Add the various channel parameters
self.add_parameter('temperature', get_cmd='KRDG? {}'.format(self._channel),
get_parser=float,
label='Temerature',
unit='K')
self.add_parameter('sensor_raw', get_cmd='SRDG? {}'.format(self._channel),
get_parser=float,
label='Raw_Reading',
unit='V') # TODO: This will vary based on sensor type
self.add_parameter('sensor_status', get_cmd='RDGST? {}'.format(self._channel), get_parser=int,
val_mapping={'OK': 0, 'Invalid Reading': 1, 'Temp Underrange': 16, 'Temp Overrange': 32,
'Sensor Units Zero': 64, 'Sensor Units Overrange': 128}, label='Sensor_Status')
self.add_parameter('sensor_name', get_cmd='INNAME? {}'.format(self._channel),
get_parser=str, set_cmd='INNAME {},\"{{}}\"'.format(self._channel), vals=Strings(),
label='Sensor_Name')
[docs]class Model_331(VisaInstrument):
"""
Lakeshore Model 331 Temperature Controller Driver
Controlled via sockets
Adapted from QCoDeS Lakeshore 336 driver
"""
def __init__(self, name, address, **kwargs):
super().__init__(name, address, terminator="\r\n", **kwargs)
# Allow access to channels either by referring to the channel name
# or through a channel list.
# i.e. Model_331.A.temperature() and Model_331.channels[0].temperature()
# refer to the same parameter.
# Serial parameters if instrument is connected via RS-232:
# self.visa_handle.baud_rate = 57600
# self.visa_handle.stop_bits = visa.constants.StopBits.one
# self.visa_handle.parity = visa.constants.Parity.odd
# self.visa_handle.data_bits = 7
channels = ChannelList(self, "TempSensors", SensorChannel33x, snapshotable=False)
for chan_name in ('A'):
channel = SensorChannel33x(self, 'Chan{}'.format(chan_name), chan_name)
channels.append(channel)
self.add_submodule(chan_name, channel)
channels.lock()
self.add_submodule("channels", channels)
###############
self.add_parameter(name='set_temperature',
get_cmd='SETP?',
get_parser=float,
set_cmd='SETP 1,{}',
label='Set Temerature',
vals=Numbers(3, 300),
unit='K')
self.add_parameter(name='heater_range',
get_cmd='RANGE?',
get_parser=int,
set_cmd='RANGE {}',
label='Heater range',
vals=Enum(0, 1, 2, 3),
unit='')
self.add_parameter(name='ramp_rate',
get_cmd='RAMP? 1',
get_parser=str,
set_cmd='RAMP 1,1,{}',
label='Heater range',
vals=Numbers(min_value=0, max_value=100),
unit='K/min')
##############
self.connect_message()
[docs]class Model_335(VisaInstrument):
"""
Lakeshore Model 335 Temperature Controller Driver
Controlled via sockets
Adapted from QCoDeS Lakeshore 336 driver
"""
def __init__(self, name, address, **kwargs):
super().__init__(name, address, terminator="\r\n", **kwargs)
# Allow access to channels either by referring to the channel name
# or through a channel list.
# i.e. Model_335.A.temperature() and Model_335.channels[0].temperature()
# refer to the same parameter.
# Serial parameters if instrument is connected via RS-232:
self.visa_handle.baud_rate = 57600
self.visa_handle.stop_bits = visa.constants.StopBits.one
self.visa_handle.parity = visa.constants.Parity.odd
self.visa_handle.data_bits = 7
channels = ChannelList(self, "TempSensors", SensorChannel33x, snapshotable=False)
for chan_name in ('A'):
channel = SensorChannel33x(self, 'Chan{}'.format(chan_name), chan_name)
channels.append(channel)
self.add_submodule(chan_name, channel)
channels.lock()
self.add_submodule("channels", channels)
###############
self.add_parameter(name='set_temperature',
get_cmd='SETP?',
get_parser=float,
set_cmd='SETP 1,{}',
label='Set Temerature',
vals=Numbers(4, 300),
unit='K')
self.add_parameter(name='heater_range',
get_cmd='RANGE?',
get_parser=int,
set_cmd='RANGE 1,{}',
label='Heater range',
vals=Enum(0, 1, 2, 3),
unit='')
self.add_parameter(name='ramp_rate',
get_cmd='RAMP? 1',
get_parser=str,
set_cmd='RAMP 1,1,{}',
label='Heater range',
vals=Numbers(min_value=0),
unit='K/min')
##############
self.connect_message()
class SensorChannel372(InstrumentChannel):
"""
A single sensor channel of a temperature controller
"""
valid_channels = ('A',) + tuple('ch{}'.format(i) for i in range(1,17))
_CHANNEL_VAL = Enum(*valid_channels)
def __init__(self, parent, name, channel, sensor_name):
super().__init__(parent, name)
# Validate the channel value
self._CHANNEL_VAL.validate(channel)
self._channel = channel # Channel on the temperature controller. Can be 1-16
# Add the various channel parameters
self.add_parameter('temperature', get_cmd='KRDG? {}'.format(self._channel[2:]),
get_parser=float,
label='Temerature',
unit='K')
self.add_parameter('sensor_raw', get_cmd='SRDG? {}'.format(self._channel[2:]),
get_parser=float,
label='Raw_Reading',
unit='Ohms') # TODO: This will vary based on sensor type
self.add_parameter('sensor_status', get_cmd='RDGST? {}'.format(self._channel[2:]), get_parser=int,
val_mapping={'OK': 0, 'CS Overload': 1, 'VCM Overload': 2, 'VMIX Overload': 4,
'VDIF Overload': 8, 'Resisance Overrange': 16, 'Resistance Underrange': 32,
'Temp Overrange': 64, 'Temp Underrange': 128}, label='Sensor_Status')
self.add_parameter('sensor_name', get_cmd='INNAME? {}'.format(self._channel[2:]),
get_parser=self._sensor_name_parser, set_cmd='INNAME {},\"{{}}\"'.format(self._channel[2:]),
vals=Strings(), label='Sensor_Name')
self.sensor_name(sensor_name)
def _sensor_name_parser(self, msg):
return str(msg).strip()
[docs]class Model_372(VisaInstrument):
"""
Lakeshore Model 372 Temperature Controller Driver
Controlled via sockets
Adapted from QCoDeS Lakeshore 336 driver
"""
def __init__(self, name, address, active_channels={'ch1': '50K Plate', 'ch2': '3K Plate'}, **kwargs):
super().__init__(name, address, terminator="\r\n", **kwargs)
# Allow access to channels either by referring to the channel name
# or through a channel list.
# i.e. Model_335.A.temperature() and Model_335.channels[0].temperature()
# refer to the same parameter.
# Serial parameters if instrument is connected via RS-232:
# self.visa_handle.baud_rate = 57600
# self.visa_handle.stop_bits = visa.constants.StopBits.one
# self.visa_handle.parity = visa.constants.Parity.odd
# self.visa_handle.data_bits = 7
channels = ChannelList(self, "TempSensors", SensorChannel372, snapshotable=False)
for chan_name, sensor_name in active_channels.items():
channel = SensorChannel372(self, 'Chan{}'.format(chan_name), chan_name, sensor_name)
channels.append(channel)
self.add_submodule(chan_name, channel)
channels.lock()
self.add_submodule("channels", channels)
###############
# self.add_parameter(name='set_temperature',
# get_cmd='SETP?',
# get_parser=float,
# set_cmd='SETP 1,{}',
# label='Set Temerature',
# vals=Numbers(4, 300),
# unit='K')
# self.add_parameter(name='heater_range',
# get_cmd='RANGE?',
# get_parser=int,
# set_cmd='RANGE 1,{}',
# label='Heater range',
# vals=Enum(0, 1, 2, 3),
# unit='')
# self.add_parameter(name='ramp_rate',
# get_cmd='RAMP? 1',
# get_parser=str,
# set_cmd='RAMP 1,1,{}',
# label='Heater range',
# vals=Numbers(min_value=0),
# unit='K/min')
##############
self.connect_message()
class SensorChannel34x(InstrumentChannel):
"""
A single sensor channel of a temperature controller
"""
valid_channels = ('A', 'B', 'C', 'D')
_CHANNEL_VAL = Enum(*valid_channels)
def __init__(self, parent, name, channel, sensor_name):
super().__init__(parent, name)
# Validate the channel value
self._CHANNEL_VAL.validate(channel)
self._channel = channel # Channel on the temperature controller. Can be 1-16
# Add the various channel parameters
self.add_parameter('temperature', get_cmd='KRDG? {}'.format(self._channel),
get_parser=float,
label='Temerature',
unit='K')
self.add_parameter('sensor_raw', get_cmd='SRDG? {}'.format(self._channel),
get_parser=float,
label='Raw_Reading',
unit='Ohms') # TODO: This will vary based on sensor type
self.add_parameter('sensor_status', get_cmd='RDGST? {}'.format(self._channel), get_parser=int,
val_mapping={'OK': 0, 'Invalid Reading': 1, 'Old Reading': 2, 'Temp Underrange': 16,
'Temp Overrange': 32, 'Units Zero': 64, 'Units Overrange': 128}, label='Sensor_Status')
# self.add_parameter('sensor_name', get_cmd='INNAME? {}'.format(self._channel),
# get_parser=self._sensor_name_parser, set_cmd='INNAME {},\"{{}}\"'.format(self._channel),
# vals=Strings(), label='Sensor_Name')
# self.sensor_name(sensor_name)
def _sensor_name_parser(self, msg):
return str(msg).strip()
[docs]class Model_340(VisaInstrument):
"""
Lakeshore Model 340 Temperature Controller Driver
Controlled via sockets
Adapted from QCoDeS Lakeshore 336 driver
"""
def __init__(self, name, address, active_channels={'A': 'cernox', 'B': 'diode'}, **kwargs):
super().__init__(name, address, terminator="\r\n", **kwargs)
# Allow access to channels either by referring to the channel name
# or through a channel list.
# i.e. Model_340.A.temperature() and Model_340.channels[0].temperature()
# refer to the same parameter.
# Serial parameters if instrument is connected via RS-232:
# self.visa_handle.baud_rate = 57600
# self.visa_handle.stop_bits = visa.constants.StopBits.one
# self.visa_handle.parity = visa.constants.Parity.odd
# self.visa_handle.data_bits = 7
channels = ChannelList(self, "TempSensors", SensorChannel34x, snapshotable=False)
for chan_name, sensor_name in active_channels.items():
channel = SensorChannel34x(self, chan_name, chan_name, sensor_name)
channels.append(channel)
self.add_submodule(chan_name, channel)
channels.lock()
self.add_submodule("channels", channels)
###############
self.add_parameter(
name='set_temperature',
get_cmd='SETP?',
get_parser=float,
set_cmd='SETP 1,{}',
label='Set Temperature',
vals=Numbers(0.3, 300),
unit='K'
)
self.add_parameter(
name='heater_range',
get_cmd='RANGE?',
get_parser=int,
set_cmd='RANGE {}',
label='Heater range',
vals=Enum(0, 1, 2, 3, 4, 5),
unit=''
)
self.add_parameter(
name='ramp_rate',
get_cmd='RAMP? 1',
get_parser=str,
set_cmd='RAMP 1,1,{}',
label='Heater range',
vals=Numbers(min_value=0),
unit='K/min'
)
self.add_parameter(
name='analog_out_config',
get_cmd='ANALOG? 1',
get_parser=str,
label='Analog output configuration.',
unit=''
)
#############
self.connect_message()
def configure_analog_output(self, input_name, low_value, high_value, maunal_value=0,
output=1, bipolar=0, source=1, mode=1):
msg = 'ANALOG {},{},{},{},{},{},{},{}'.format(
output, bipolar, mode, input_name, source, high_value, low_value, maunal_value)
self.write(msg)