Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a new hardware file #31

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 181 additions & 0 deletions src/qudi/hardware/switches/power_switch_keysight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# -*- coding: utf-8 -*-

"""
Control the Radiant Dyes flip mirror driver through the serial interface.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected


Copyright (c) 2021, the qudi developers. See the AUTHORS.md file at the top-level directory of this
distribution and on <https://github.com/Ulm-IQO/qudi-iqo-modules/>

This file is part of qudi.

Qudi is free software: you can redistribute it and/or modify it under the terms of
the GNU Lesser General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.

Qudi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with qudi.
If not, see <https://www.gnu.org/licenses/>.
"""

try:
import visa
except ImportError:
import pyvisa as visa
from qudi.core.configoption import ConfigOption
from qudi.core.statusvariable import StatusVar
from qudi.util.mutex import RecursiveMutex
from qudi.interface.switch_interface import SwitchInterface


class PowerSwitch(SwitchInterface):
""" This class is implements communication with the Keysight E36234A power supply using pyVISA

Example config for copy-paste:

power_switch3:
module.Class: 'switches.power_switch_keysight.PowerSwitch'
options:
interface: 'USB0::0x2A8D::0x3402::MY59001224::INSTR'
hardware_name: 'Keysight_Power2' # optional
switch_time: 1 # optional
remember_states: False # optional
switches:
APD: ['OFF', 'ON'] # optional
Amplifier: ['OFF', 'ON'] # optional
"""

# customize available switches in config. Each switch needs a tuple of at least 2 state names.
_switches = ConfigOption(name='switches', missing='error')
# optional name of the hardware
_hardware_name = ConfigOption(name='hardware_name', default='power_supply', missing='nothing')
# if remember_states is True the last state will be restored at reloading of the module
_remember_states = ConfigOption(name='remember_states', default=False, missing='nothing')
# switch_time to wait after setting the states for the solenoids to react
_switch_time = ConfigOption(name='switch_time', default=0.5, missing='nothing')
# name of the serial interface where the hardware is connected.
# Use e.g. the Keysight IO connections expert to find the device.
serial_interface = ConfigOption('interface', 'USB0::0x2A8D::0x3402::MY59001224::INSTR')

# StatusVariable for remembering the last state of the hardware
_states = StatusVar(name='states', default=None)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.lock = RecursiveMutex()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the lock is not needed in this module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines are used in all switch hardwares. I think we may keep it for now for unification

self._resource_manager = None
self._instrument = None
self._switches = self._chk_refine_available_switches(self._switches)

def on_activate(self):
""" Prepare module, connect to hardware.
"""

self._resource_manager = visa.ResourceManager()
self._instrument = self._resource_manager.open_resource(self.serial_interface)
# set the maximum/protection output Voltage/current of the power supply
# Excelitas APD: 5V,1.3A
self._instrument.write('INST CH1')
self._instrument.write('OUTP 0')
self._instrument.write('VOLT 5')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maximum voltages should be ConfigOptions, not hardcoded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the voltages and currents are taken from ConfigOption

self._instrument.write('CURR 1.3')
# Minicircuits amplifier: 28V, 4A
self._instrument.write('INST CH2')
self._instrument.write('OUTP 0')
self._instrument.write('VOLT 28')
self._instrument.write('CURR 4')

# To be safe, power off during activation
self._states = dict()
self._states = {switch: states[0] for switch, states in self._switches.items()}


def on_deactivate(self):
""" Disconnect from hardware on deactivation.
"""
# switch off outputs of the power supply
for switch in (0, len(self._switches)):
self._instrument.write('INST CH{}'.format(switch+1))
self._instrument.write('OUTP 0')
self._instrument.close()
self._resource_manager.close()

@property
def name(self):
""" Name of the hardware as string.

@return str: The name of the hardware
"""
return self._hardware_name

@property
def available_states(self):
""" Names of the states as a dict of tuples.

The keys contain the names for each of the switches. The values are tuples of strings
representing the ordered names of available states for each switch.

@return dict: Available states per switch in the form {"switch": ("state1", "state2")}
"""
return self._switches.copy()

@property
def states(self):
""" The current states the hardware is in.

The states of the system as a dict consisting of switch names as keys and state names as values.

@return dict: All the current states of the switches in a state dict of the form {"switch": "state"}
"""
return self._states.copy()

@states.setter
def states(self, state_dict):
""" The setter for the states of the hardware.

The states of the system can be set by specifying a dict that has the switch names as keys
and the names of the states as values.

@param dict state_dict: state dict of the form {"switch": "state"}
"""
assert isinstance(state_dict, dict), 'Parameter "state_dict" must be dict type'
for switch, state in state_dict.items():
self.set_state(switch, state)

def get_state(self, switch):
""" Query state of single switch by name

@param str switch: name of the switch to query the state for
@return str: The current switch state
"""
# find the correlated output channel for the switch
switch_index = list(self._switches).index(switch)
# Select the switch
self._instrument.write('INST CH{}'.format(switch_index+1))
response = self._instrument.query('OUTP?').strip()
assert int(response) in [0, 1], 'Device not giving proper response'
self._states[switch] = self._switches[switch][int(response)]

return self._states[switch]

def set_state(self, switch, state):
""" Set state of single switch by name

@param str switch: name of the switch to change
@param str state: name of the state to set
"""
# find the correlated output channel for the switch
switch_index = list(self._switches).index(switch)
# get the state index, 0==off, 1==on
state_index = self._switches[switch].index(state)
# do the job
if self._states[switch] != state:
# Select the output channel
self._instrument.write('INST CH{}'.format(switch_index+1))
# Switch the switch
self._instrument.write('OUTP {}'.format(int(state_index)))
self._states[switch] = state