Skip to content

Commit

Permalink
Merge pull request #209 from QDevil/master
Browse files Browse the repository at this point in the history
QDAC1: Allow slopes greater than 10V
  • Loading branch information
astafan8 authored Apr 4, 2023
2 parents 11a8456 + d6732ec commit 04cfd3d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
76 changes: 62 additions & 14 deletions qcodes_contrib_drivers/drivers/QDevil/QDAC1.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# QCoDeS driver for the QDevil QDAC using channels
# Adapted by QDevil from the qdev QDac driver in qcodes
# Version 2.1 QDevil 2020-02-10
# Version 2.2 QDevil 2023-02-20

import logging
import time
Expand Down Expand Up @@ -82,7 +82,7 @@ def __init__(self, parent: "QDac", name: str, channum: int):
label=f'Channel {channum} voltage',
unit='V',
set_cmd=partial(self._parent._set_voltage, channum),
get_cmd=f'set {channum}',
get_cmd=partial(self._parent._get_voltage, channum),
get_parser=float,
# Initial range. Updated on init and during
# operation:
Expand Down Expand Up @@ -444,6 +444,17 @@ def snapshot_base(
# Channel gets/sets
#########################

def _get_voltage(self, chan: int) -> str:
"""
Clear the output from the instrument and ask for the current voltage
Args:
chan (int): The 1-indexed channel number
"""
self.clear_read_queue()
self.write(f'set {chan}')
return self._write_response

def _set_voltage(self, chan: int, v_set: float) -> None:
"""
set_cmd for the chXX_v parameter
Expand All @@ -455,25 +466,38 @@ def _set_voltage(self, chan: int, v_set: float) -> None:
If a finite slope has been assigned, a function generator will
ramp the voltage.
"""

slope = self._slopes.get(chan, None)
if slope:
# We need .get and not cache/get_latest in case a ramp
# was interrupted
v_start = self.channels[chan-1].v.get()
duration = abs(v_set-v_start)/slope
LOG.info(f'Slope: {slope}, time: {duration}')
# SYNCing happens inside ramp_voltages
self.ramp_voltages([chan], [v_start], [v_set], duration)
else: # Should not be necessary to wav here.
if not slope:
# Should not be necessary to wav here.
self.write('wav {ch} 0 0 0;set {ch} {voltage:.6f}'
.format(ch=chan, voltage=v_set))
return
# We need .get and not cache/get_latest in case a ramp
# was interrupted
v_start = self.channels[chan-1].v.get()
v_span = v_set - v_start
v_amplitude = abs(v_span)
s_duration = v_amplitude / slope
LOG.info(f'Slope: {slope}, time: {s_duration}')
if v_amplitude <= 10:
# SYNCing happens inside ramp_voltages
self.ramp_voltages([chan], [v_start], [v_set], s_duration)
return
# Divide sweep into two parts
v_half_span = v_span / 2
s_half_duration = s_duration / 2
v_half_way = v_start + v_half_span
self.ramp_voltages([chan], [v_start], [v_half_way], s_half_duration)
LOG.warning('Trying to ramp more than 10 volts. '
'Waiting for first ramp to finish')
time.sleep(s_half_duration)
self.ramp_voltages([chan], [v_half_way], [v_set], s_half_duration)

def _set_mode(self, chan: int, new_mode: Mode) -> None:
"""
set_cmd for the QDAC's mode (combined voltage and current sense range).
It is not possible to switch from voltage range without setting the
the volage to zero first or set the global mode_force parameter True.
the voltage to zero first or set the global mode_force parameter True.
"""
def _clipto(value: float, min_: float, max_: float) -> float:
errmsg = ("Voltage is outside the bounds of the new voltage range"
Expand Down Expand Up @@ -786,6 +810,8 @@ def write(self, cmd: str) -> None:
self.visa_handle.write(cmd)
for _ in range(cmd.count(';')+1):
self._write_response = self.visa_handle.read()
if self._write_response.startswith('Error: '):
LOG.warning(self._write_response)

def read(self) -> str:
return self.visa_handle.read()
Expand All @@ -794,6 +820,26 @@ def _wait_and_clear(self, delay: float = 0.5) -> None:
time.sleep(delay)
self.visa_handle.clear()

def clear_read_queue(self) -> Sequence[str]:
"""
Flush the VISA message queue of the instrument
Waits 1 ms between each read.
Returns:
Sequence[str]: Messages lingering in queue
"""
lingering = list()
with self.timeout.set_to(0.001):
while True:
try:
message = self.visa_handle.read()
except pyvisa.VisaIOError:
break
else:
lingering.append(message)
return lingering

def connect_message(self,
idn_param: str = 'IDN',
begin_time: Optional[float] = None) -> None:
Expand All @@ -808,7 +854,7 @@ def connect_message(self,

def _get_firmware_version(self) -> float:
"""
Check if the "version" command reponds. If so we probbaly have a QDevil
Check if the "version" command reponds. If so we probably have a QDevil
QDAC, and the version number is returned. Otherwise 0.0 is returned.
"""
self.write('version')
Expand Down Expand Up @@ -1067,6 +1113,8 @@ def ramp_voltages_2d(
msg = ''
for i in range(no_channels):
amplitude = v_endlist[i]-v_startlist[i]
# TODO: if amplitute is too large, then split into two parts.
# if abs(amplitude) > 10: ...
ch = channellist[i]
fg = self._assigned_fgs[ch].fg
if trigger > 0: # Trigger 0 is not a trigger
Expand Down
4 changes: 1 addition & 3 deletions qcodes_contrib_drivers/tests/QDevil/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ Simulated instrument:
$ source venv/bin/activate
$ pytest qcodes_contrib_drivers/tests/QDevil/test_sim_qdac2_*.py

To silence warnings, use `-W ignore::DeprecationWarning`.

Real instrument:

$ source venv/bin/activate
Expand All @@ -29,4 +27,4 @@ Static types:
$ source venv/bin/activate
$ pip install --upgrade pip
$ pip install -e .[test]
$ pip install pyvisa-py==0.5.2
$ pip install pyvisa-py==0.5.2 jupyter pyserial

0 comments on commit 04cfd3d

Please sign in to comment.