-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #300 from simonzihlmann/feat_Tektronix_FCA3110
Tektronix FCA3100 counter driver
- Loading branch information
Showing
2 changed files
with
333 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from qcodes_contrib_drivers.drivers.Tektronix.FCA3100 import FCA3100" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Connected to: TEKTRONIX FCA3000 (serial:579249, firmware:V1.32 26 May 2022 09:54) in 0.13s\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"counter = FCA3100('counter', 'USB0::0x0699::0x3000::579249::INSTR', timeout=10)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# overview over all parameters" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"counter:\n", | ||
"\tparameter value\n", | ||
"--------------------------------------------------------------------------------\n", | ||
"IDN :\t{'vendor': 'TEKTRONIX', 'model': 'FCA3000', 'serial': '57924...\n", | ||
"counter_axis :\t[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.] (#)\n", | ||
"samples_number :\t11 \n", | ||
"threshold_A :\t0 (V)\n", | ||
"threshold_B :\t0.036 (V)\n", | ||
"time_array :\tNot available (s)\n", | ||
"timeout :\t10 (s)\n", | ||
"timestats :\tNot available (('s', 's', 's', 's'))\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"counter.print_readable_snapshot(update=True)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Usage of the two main parameters" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's get an example of the time statistics parameter (will return mean, stdev, min and max of a statistics containing samples_number number of samples)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"(0.01862650541, 7.4022264e-05, 0.01851450451, 0.01873824896)" | ||
] | ||
}, | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"counter.timestats()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's get an example of the time array parameter (will return an array of timestamps of length samples_number)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"array([0.01856394, 0.01875304, 0.01868165, 0.01846251, 0.01853304,\n", | ||
" 0.01867947, 0.01863655, 0.0185761 , 0.01863821, 0.01867253,\n", | ||
" 0.01866243])" | ||
] | ||
}, | ||
"execution_count": 10, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"counter.time_array()" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.11.7" | ||
}, | ||
"nbsphinx": { | ||
"execute": "never" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
182 changes: 182 additions & 0 deletions
182
src/qcodes_contrib_drivers/drivers/Tektronix/FCA3100.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
import logging | ||
import numpy as np | ||
from typing import Any, Tuple | ||
from qcodes.instrument import VisaInstrument | ||
from qcodes.parameters import MultiParameter, Parameter, ParameterWithSetpoints | ||
from qcodes.validators import Arrays, Ints | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
class TimeStatistics(MultiParameter): | ||
""" | ||
Returns the statistical values of a timing statistics. | ||
""" | ||
def __init__(self, | ||
name:str, | ||
instrument:"FCA3100", | ||
**kwargs: Any | ||
) -> None: | ||
""" | ||
Statistical values of a timing statistics. | ||
Args: | ||
name: name of the timing statistics | ||
instrument: Instrument to which the timing statistic is bound to. | ||
""" | ||
|
||
super().__init__(name=name, | ||
instrument=instrument, | ||
names=( | ||
f"{instrument.short_name}_{name}_mean", | ||
f"{instrument.short_name}_{name}_stddev", | ||
f"{instrument.short_name}_{name}_minval", | ||
f"{instrument.short_name}_{name}_maxval"), | ||
shapes=((), (),(),()), | ||
labels=( | ||
f"{instrument.short_name} {name} mean time", | ||
f"{instrument.short_name} {name} standard deviation", | ||
f"{instrument.short_name} {name} min value", | ||
f"{instrument.short_name} {name} max value"), | ||
units=('s', 's', 's', 's'), | ||
setpoints=((), (), (), ()), | ||
**kwargs) | ||
|
||
def get_raw(self) -> Tuple[float, float, float, float]: | ||
""" | ||
Gets data from the instrument | ||
Returns: | ||
Tuple: Statistical values of the time statistic | ||
""" | ||
assert isinstance(self.instrument, FCA3100) | ||
self.instrument.write('CALCulate:AVERage:STAT 1') | ||
self.instrument.write('INIT') # start measurement | ||
self.instrument.ask('*OPC?') # wait for it to complete | ||
reply = self.instrument.ask("CALCulate:AVERage:ALL?") | ||
mean, stddev, minval, maxval, _ = reply.split(",") | ||
|
||
return float(mean), float(stddev), float(minval), float(maxval) | ||
|
||
class CompleteTimeStatistics(ParameterWithSetpoints): | ||
def __init__(self, | ||
name:str, | ||
instrument:"FCA3100", | ||
**kwargs: Any | ||
) -> None: | ||
""" | ||
Parameter for a complete time statistics containing all measured switching times. | ||
Args: | ||
name: name of the complete time statistics | ||
instrument: Instrument to which the complete time statistic is bound to. | ||
""" | ||
super().__init__(name=name, | ||
instrument=instrument, | ||
label='Times till switching', | ||
unit='s', | ||
docstring='Arrays of switching times', | ||
**kwargs) | ||
|
||
def get_raw(self) -> np.ndarray: | ||
""" | ||
Gets the data from the instrument. | ||
Returns: | ||
np.ndarray: Array of swithing times | ||
""" | ||
assert isinstance(self.instrument, FCA3100) | ||
self.instrument.write('CALCulate:AVERage:STATe 0') | ||
self.instrument.write('ARM:COUN {}'.format(self.instrument.samples_number.get_latest())) | ||
data_str=self.instrument.ask("READ:ARRay? {}".format(self.instrument.samples_number.get_latest())) | ||
data = np.array(data_str.rstrip().split(",")).astype("float64") | ||
return data | ||
|
||
class GeneratedSetPoints(Parameter): | ||
""" | ||
A parameter that generates a setpoint array from start, stop and num points | ||
parameters. | ||
""" | ||
def __init__(self, numpointsparam, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self._numpointsparam = numpointsparam | ||
|
||
def get_raw(self): | ||
return np.arange(self._numpointsparam()) | ||
|
||
|
||
class FCA3100(VisaInstrument): | ||
""" | ||
This is the qcodes driver for the FCA3100 counter | ||
""" | ||
|
||
def __init__(self, | ||
name: str, | ||
address: str, | ||
terminator : str="\n", | ||
timeout : int=10, | ||
**kwargs) -> None: | ||
""" | ||
Qcodes driver for the Textronix FCA3100 frequency counter. | ||
Args: | ||
name: Name of the instrument | ||
address: Address of the instrument | ||
terminator (optional): Terminator character of | ||
the string reply. Defaults to "\\n". | ||
timeout (optional): VISA timeout is set purposely | ||
to a long time to allow long measurements. Defaults to 10. | ||
""" | ||
|
||
super().__init__(name = name, | ||
address = address, | ||
terminator = terminator, | ||
timeout = timeout, | ||
device_clear = False, | ||
**kwargs) | ||
|
||
self.write('INIT:CONT 0') | ||
|
||
self.add_parameter(name='timestats', | ||
parameter_class=TimeStatistics) | ||
|
||
self.add_parameter(name='samples_number', | ||
label='samples_number', | ||
get_cmd='CALCulate:AVERage:COUNt?', | ||
set_cmd='CALCulate:AVERage:COUNt {}', | ||
get_parser=float, | ||
vals=Ints(2, int(2e9)), | ||
docstring='Number of samples in the current statistics sampling' | ||
) | ||
|
||
self.add_parameter('counter_axis', | ||
unit='#', | ||
label='Counter Axis', | ||
parameter_class=GeneratedSetPoints, | ||
numpointsparam=self.samples_number, | ||
vals=Arrays(shape=(self.samples_number.get_latest,))) | ||
|
||
self.add_parameter(name='threshold_A', | ||
label='threshold_A', | ||
get_cmd='INPut1:LEVel?', | ||
set_cmd='INPut1:LEVel {}', | ||
get_parser=float, | ||
unit='V', | ||
docstring='Absolute voltage trigger threshold channel A' | ||
) | ||
|
||
self.add_parameter(name='threshold_B', | ||
label='threshold_B', | ||
get_cmd='INPut2:LEVel?', | ||
set_cmd='INPut2:LEVel {}', | ||
get_parser=float, | ||
unit='V', | ||
docstring='Absolute voltage trigger threshold channel B' | ||
) | ||
|
||
self.add_parameter(name='time_array', | ||
parameter_class=CompleteTimeStatistics, | ||
setpoints=(self.counter_axis,), | ||
vals=Arrays(shape=(self.samples_number.get_latest,)) | ||
) | ||
|
||
self.connect_message() |