"""Basic drivers for an Oxford Instruments model IPS120
Note that this module does **not** represent an `Instrument` subclass, since
the IPS120 is never used by itself---it is always part of a larger system
driving both a magnet power supply and temperature controllers, and the power
supply often cannot be used in an isolated way.
"""
import time
from src.instruments.noauto.oxford_common import OxfordCommon
HEATER_DELAY = 20
[docs]class IPS120(OxfordCommon):
"""This is a basic driver for an Oxford Instruments model IPS120 power
supply. It should be included in an `Instrument` class representing a
cryostat-magnet system.
Parameters
----------
name : str
A name to identify the instrument
protocol : {'ISOBUS', 'GPIB', 'Serial', 'Gateway Master', 'Gateway Slave'}
The protocol for communication between the computer and the power
supply.
isobusAddress : str
An integer string representing the ISOBUS address, if relevant. An
integer will be accepted and converted.
visaAddress : str
A full VISA resource address (including the bus) to locate the
instrument (e.g. "GPIB0::27").
serialConfig : dict
A dictionary to indicate how to configure a serial port, which is used
with both the 'ISOBUS' and 'Serial' protocols.
"""
def __init__(self, name="Magnet", protocol='ISOBUS', isobusAddress='0',
visaAddress='GPIB0::23', serialConfig=None):
"""Create a new power supply instance.
Initialization for this object really only involves passing all
arguments into the `OxfordCommon` superclass.
"""
super(IPS120, self).__init__(name, protocol, isobusAddress,
visaAddress, serialConfig)
self._activity = None
self._polarity1 = None
self._polarity2 = None
[docs] def initialize(self):
"""Prepare the power supply for use.
Prepare the power supply for use by
1. opening the appropriate communication channel;
2. setting the control mode to 'remote and unlocked';
3. setting the activity to 'hold';
4. setting the polarity to 'forward';
5. setting the sweep rate to 0.5 T/min;
6. setting the sweep mode to 'Tesla, sweep, fast'; and
7. setting the switch heater to 'Off, magnet at zero'.
"""
super(IPS120, self).openCommunication()
self.setControlMode()
self.setActivity()
self.setPolarity('1')
self.setSweepRate()
self.setSweepMode()
self.setSwitchHeater()
self.getStatus()
[docs] def getStatus(self):
"""Update the power supply status.
Read the power supply status, and set the local variables to reflect
the new status.
Notes
-----
The power supply returns a string of the form ``XmnAnCnHnMmnPmn``. The
meanings and values of the parts of this are described here.
``Xmn``: System status
``m``: Status 1
- 0: Normal
- 1: Quenched
- 2: Over-heated
- 4: Warming up
- 8: Fault
``n``: Status 2
- 0: Normal
- 1: On positive voltage limit
- 2: On negative voltage limit
- 4: Outside negative current limit
- 8: Outside positive current limit
``An``: Activity
- 0: Hold
- 1: To setpoint
- 2: To zero
- 4: Output clamped
``Cn``: Control status
- 0: Local and locked
- 1: Remote and locked
- 2: Local and unlocked
- 3: Remote and unlocked
- 4: Auto-run-down
- 5: Auto-run-down
- 6: Auto-run-down
- 7: Auto-run-down
``Hn``: Switch heater status
- 0: Off---magnet at zero (switch closed)
- 1: On (switch open)
- 2: Off---magnet at field (switch closed)
- 5: Heater fault (heater is on, but current is low)
- 8: No switch fitted
``Mmn``: Mode
``m``: Mode 1
- 0: Amps, Fast
- 1: Tesla, Fast
- 4: Amps, Slow
- 5: Tesla, Slow
``n``: Mode 2
- 0: At rest (output constant)
- 1: Sweeping (output changing)
- 2: Rate limiting (output changing)
- 3: Sweeping and rate limiting (output changing)
``Pmn``: Polarity
``m``: Polarity 1 (see below)
- 0: pos, pos, pos
- 1: pos, pos, neg
- 2: pos, neg, pos
- 3: pos, neg, neg
- 4: neg, pos, pos
- 5: neg, pos, neg
- 6: neg, neg, pos
- 7: neg, neg, neg
``n``: Polarity 2 (verification flags)
- 1: Negative contactor closed
- 2: Positive contactor closed
- 3: Both contactors open
- 4: Both contactors closed
.. note:: Unlike with the PS120, with the IPS120, Immediate mode is
indicated by Mode 2 returning the value '2' (sweep limiting, but not
sweeping); it does not have its own flag.
.. note:: For the IPS power supplied, the polarity flags have been
superceded by signed numbers for currents and fields.
"""
status = self.communicate('X')
self._activity = status[4]
self._polarity1 = status[13]
self._polarity2 = status[14]
return {'system_status_1': status[1],
'system status 2': status[2],
'activity': self._activity,
'control_mode': status[6],
'switch_heater': status[8],
'mode_1': status[10],
'mode_2': status[11],
'polarity_1': self._polarity1,
'polarity_2': self._polarity2}
[docs] def setControlMode(self, controlMode='3'):
"""Set the control mode for the power supply.
Parameters
----------
controlMode : str, optional
An integer string representing the desired control mode. Allowed
values are the following.
- '0': Local and locked (power-up state).
- '1': Remote and locked.
- '2': Local and unlocked.
- '3': Remote and unlocked (default).
"""
self.communicate('C' + controlMode)
[docs] def setActivity(self, activity='0'):
"""Set the activity mode of the power supply.
Parameters
----------
activity : str
An integer string representing the desired activity. The accepted
values are listed below.
- '0': Hold at current field (default).
- '1': Ramp the field to the setpoint.
- '2': Ramp the field to zero.
- '4': Clamp the output.
"""
self.communicate('A' + activity)
self._activity = activity
[docs] def setPolarity(self, polarity='0'):
"""Set the power supply polarity.
Parameters
----------
polarity : str
A string containing a single integer representing the desired
polarity (or polarity-changing action). The following values are
accepted.
- '0': Do nothing (default).
- '1': Set the polarity to forward.
- '2': Set the polarity to reverse.
- '4': Swap the polarity.
.. note:: This method is included for backward compatibility. The
polarity has been deprecated in favor of signed numbers for the
field or current setpoints.
"""
self.communicate('P' + polarity)
self.getStatus()
[docs] def setSweepMode(self, sweepMode='9'):
"""Set the power supply's sweep mode.
The power supply's sweep mode consists of two parameters:
Display:
The instrument's front-panel display units (amps or tesla)
Magnet sweep rate:
One of two user-defined sweep profiles: "fast" and "slow"; the
"fast" mode is entered upon power supply startup. The names have
no significance, and the actual rates are user-defined
variables.
Parameters
----------
sweepMode : str, optional
The integer string code to specify the sweep mode of the power
supply. The allowed codes are the following.
- 0: Amps, Fast
- 1: Tesla, Fast
- 4: Amps, Slow
- 5: Tesla, Slow
- 8: Amps, Unaffected
- 9: Tesla, Unaffected
"""
self.communicate('M' + sweepMode)
self.getStatus()
[docs] def setSwitchHeater(self, heaterStatus='0', delay=20.0):
"""Set the status of the switch heater.
Turn the switch heater on or off, optionally checking whether it is
safe to do so. Then wait a specified amount of time for the power
supply to carry out the command.
Parameters
----------
heaterStatus : {'0', '1', '2'}, optional
An integer string representing the desired switch heater status.
The following values are accepted.
- '0': Turn the heater off (default).
- '1': Turn the heater on if the power supply current and the
magnet current are equal. Otherwise, do nothing.
- '2': Turn the heater on without checking the currents.
delay : float, optional
The time to wait (in seconds) after commanding the switch heater to
adopt the specified status. The value should be *at least* 15s.
"""
self.communicate('H' + heaterStatus)
time.sleep(delay)
self.getStatus()
[docs] def setField(self, field):
"""Set the magnetic field in Tesla.
Parameters
----------
field : float
The magnetic field setpoint in Tesla.
"""
self.communicate('J%.4f' % field)
self.setActivity('1')
[docs] def setSweepRate(self, sweepRate=0.5):
"""Set the magnetic field sweep rate in Tesla/min.
Parameters
----------
sweepRate : float, optional
The desired sweep rate for the magnet in Tesla/min (default 0.5).
"""
self.communicate('T%.3f' % sweepRate)
[docs] def getField(self):
"""Return the magnetic field in Tesla.
Returns
-------
float
The magnetic field in Tesla.
"""
self.getStatus()
return float(self.communicate('R7'))
[docs] def getFieldSetpoint(self):
"""Return the field setpoint in Tesla.
Returns
-------
float
The magnetic field setpoint.
"""
self.getStatus()
return float(self.communicate('R8'))
[docs] def getSweepRate(self):
"""Return the field sweep rate in Tesla/min.
Returns
-------
float
The magnetic field sweep rate in Tesla/min.
"""
return float(self.communicate('R9'))