Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
160 changes: 160 additions & 0 deletions exopy_qcircuits/instruments/drivers/visa/keysight_voltage_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright 2022 by Qcircuit Authors, see AUTHORS for more details.
#
# Distributed under the terms of the BSD license.
#
# The full license is in the file LICENCE, distributed with this software.
# -----------------------------------------------------------------------------
"""Driver for the Keysight programmable DC power supplies

"""
import traceback
import threading
import re
from textwrap import fill
from inspect import cleandoc
import time
from pyvisa import constants

from exopy_hqc_legacy.instruments.drivers.driver_tools import (
InstrIOError, instrument_property, secure_communication)
from exopy_hqc_legacy.instruments.drivers.visa_tools import VisaInstrument, errors


class E3631A(VisaInstrument):
"""
Driver for the E3631A, using the VISA library.

This driver does not give access to all the functionnality of the
instrument but you can extend it if needed. See the documentation of the
`driver_tools` package for more details about writing instruments drivers.

Parameters
----------
see the `VisaInstrument` parameters in the `driver_tools` module

Attributes
----------
channel: str, instrument_property
Currently selected channel. Can be 'P6V', 'P25V' or 'N25V'
voltage : float, instrument_property
Voltage at the output of the current channel in volts.
current: float, instrument_property
Current at the output of the channel in amps.
output : bool, instrument_property
State of the output 'ON'(True)/'OFF'(False).

"""

def open_connection(self, **para):
"""Open the connection to the instr

"""
super(E3631A, self).open_connection(**para)
self.timeout = 3000

@instrument_property
def channel(self):
"""Channel getter method.

"""
c = self.query('INST:SEL?')
if c:
return c[:-1]
raise InstrIOError('Instrument did not return the channel')

@channel.setter
def channel(self, target_channel):
"""Channel getter method.

"""
if target_channel not in ['P6V', 'P25V', 'N25V']:
raise InstrIOError(f'Invalid channel name {target_channel}')
self.write(f'INST:SEL {target_channel}')
c = self.query('INST:SEL?')
if not (c and c[:-1] == target_channel):
raise InstrIOError("Instrument couldn't set the channel")

@instrument_property
def voltage(self):
"""Voltage getter method.

"""
v = self.query('VOLT?')
if v:
return float(v)
else:
raise InstrIOError('Instrument did not return the voltage')

@voltage.setter
def voltage(self, set_point):
"""Voltage setter method.

"""
self.write(f"VOLT {set_point}")
v = self.query('VOLT?')
if not v or abs(float(v) - set_point) > 10**-3:
raise InstrIOError('Instrument did not set correctly the voltage')

@instrument_property
def current(self):
"""Current getter method.

"""
v = self.query('CURR?')
if v:
return float(v)
else:
raise InstrIOError('Instrument did not return the current')

@current.setter
def current(self, set_point):
"""Current setter method.

"""
self.write(f"CURR {set_point}")
v = self.query('CURR?')
if not v or abs(float(v) - set_point) > 10**-3:
raise InstrIOError('Instrument did not set correctly the current')

@instrument_property
def output(self):
"""Output getter method

"""
v = self.query('OUTP:STAT?')
if v:
return '1' in v
raise InstrIOError('Instrument did not return the output')

@output.setter
def output(self, value):
"""Output setter method

"""
on = re.compile('on', re.IGNORECASE)
off = re.compile('off', re.IGNORECASE)
if on.match(value) or value == 1:
self.write('OUTP:STAT ON')
time.sleep(0.1)
v = self.query('OUTP:STAT?')
status = '1' in v
if not status:
raise InstrIOError(
cleandoc('''Instrument did not set
correctly the output'''))
elif off.match(value) or value == 0:
self.write('OUTP:STAT OFF')
time.sleep(0.1)
v = self.query('OUTP:STAT?')
status = '1' in v
if status:
raise InstrIOError(
cleandoc('''Instrument did not set
correctly the output'''))

def check_connection(self):
"""
"""
return False
22 changes: 21 additions & 1 deletion exopy_qcircuits/manifest.enaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ enamldef QcircuitsManifest(PluginManifest):
'VisaUSB': {'resource_class': 'INSTR'},
'VisaTCPIP': {'resource_class': 'INSTR'}
}
Drivers:
manufacturer = 'Keysight'
Driver:
driver = 'keysight_voltage_source:E3631A'
model = 'E3631A'
connections = {'VisaGPIB': {'resource_class': 'INSTR'},
'VisaUSB': {'resource_class': 'INSTR'},
'VisaTCPIP': {'resource_class': 'INSTR'},
'VisaRaw' :{}
}
Drivers:
manufacturer = 'Rohde and Schwarz'
Driver:
Expand Down Expand Up @@ -137,12 +147,22 @@ enamldef QcircuitsManifest(PluginManifest):
Task:
task = 'exopy_hqc_legacy.SetDCVoltageTask'
instruments = ['exopy_qcircuits.Qcircuits.Tenma']
Interface:
interface = 'exopy_qcircuits.tasks.tasks.instr.keysight_voltage_source_tasks:E3631AInterface'
views=['exopy_qcircuits.tasks.tasks.instr.views.keysight_voltage_source_views:IE3631AChannelLabel',
'exopy_qcircuits.tasks.tasks.instr.views.keysight_voltage_source_views:IE3631AChannelCombo']
instruments = ['exopy_qcircuits.Qcircuits.E3631A']
Task:
task = 'exopy_hqc_legacy.SetDCCurrentTask'
instruments = ['exopy_qcircuits.Qcircuits.Tenma']
Interface:
interface = 'exopy_qcircuits.tasks.tasks.instr.keysight_voltage_source_tasks:E3631AInterface'
views=['exopy_qcircuits.tasks.tasks.instr.views.keysight_voltage_source_views:IE3631AChannelLabel',
'exopy_qcircuits.tasks.tasks.instr.views.keysight_voltage_source_views:IE3631AChannelCombo']
instruments = ['exopy_qcircuits.Qcircuits.E3631A']
Task:
task = 'exopy_hqc_legacy.SetDCOutputTask'
instruments = ['exopy_qcircuits.Qcircuits.Tenma']
instruments = ['exopy_qcircuits.Qcircuits.Tenma', 'exopy_qcircuits.Qcircuits.E3631A']

Tasks:
path = 'exopy_qcircuits.tasks.tasks'
Expand Down
30 changes: 30 additions & 0 deletions exopy_qcircuits/tasks/tasks/instr/keysight_voltage_source_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright 2022 by exopyHqcLegacy Authors, see AUTHORS for more details.
#
# Distributed under the terms of the BSD license.
#
# The full license is in the file LICENCE, distributed with this software.
# -----------------------------------------------------------------------------
"""Interface for the multichannel E3631A voltage source

"""
from __future__ import (division, unicode_literals, print_function,
absolute_import)


from atom.api import Enum

from exopy.tasks.tasks.task_interface import TaskInterface


class E3631AInterface(TaskInterface):
channel = Enum('P6V','P25V', 'N25V').tag(pref=True)

def check(self, *args, **kwargs):
return True, {}

def perform(self, *args, **kwargs):
self.task.driver.channel = self.channel

return self.task.i_perform(*args, **kwargs)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from enaml.widgets.api import (Label, ObjectCombo)


enamldef IE3631AChannelLabel(Label):
attr root
attr interface

text = 'Channel'

enamldef IE3631AChannelCombo(ObjectCombo):
attr root
attr interface

items = ['P6V', 'P25V', 'N25V']
selected := interface.channel