diff --git a/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb b/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb
new file mode 100644
index 00000000000..1e97d3a0821
--- /dev/null
+++ b/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb
@@ -0,0 +1,303 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Benchmark of Keysight 34465A\n",
+ "\n",
+ "We benchmark the acquisition of N voltages from a QDac on a Keysight DMM. Two acquisition modes are tested; the \"classical\" set voltage/get voltage and a set voltage / send software trigger method.\n",
+ "\n",
+ "The former method is cast as a standard QCoDeS measurement, whereas the latter is just the raw commands. If anything, this should add a bit of extra overhead to the first method.\n",
+ "\n",
+ "The QDac sweeps a voltage from 0 V to 1 V.\n",
+ "\n",
+ "Conclusion: there is **no** speed-up."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "import qcodes as qc\n",
+ "import numpy as np\n",
+ "import time\n",
+ "from qcodes.instrument_drivers.Keysight.Keysight_34465A import Keysight_34465A\n",
+ "from qcodes.instrument_drivers.QDev.QDac import QDac"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Connected to: Keysight Technologies 34465A (serial:MY54505281, firmware:A.02.14-02.40-02.14-00.49-02-01) in 7.14s\n"
+ ]
+ }
+ ],
+ "source": [
+ "dmm = Keysight_34465A('dmm', 'TCPIP0::K-000000-00000.local::hislip0::INSTR')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "qdac = QDac('qdac', 'ASRL7::INSTR')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Pre-benchmark setting"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ap_time = 1e-3\n",
+ "dmm.NPLC(0.06) # aperture time of 1 ms\n",
+ "dmm.range(1) # Voltage range of 1 V\n",
+ "qdac.ch01_v(0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## N = 1000, set-get"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "# prepare the DMM for get-set mode\n",
+ "dmm.trigger_source('IMM')\n",
+ "dmm.sample_count(1)\n",
+ "dmm.trigger_count(1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Started at 2017-09-08 11:33:51\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#013_N_1000_setget_11-33-51'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:34:23\n",
+ "Started at 2017-09-08 11:34:23\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#014_N_1000_setget_11-34-23'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:34:55\n",
+ "Started at 2017-09-08 11:34:55\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#015_N_1000_setget_11-34-55'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:35:27\n",
+ "Started at 2017-09-08 11:35:27\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#016_N_1000_setget_11-35-27'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:35:59\n",
+ "Started at 2017-09-08 11:35:59\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#017_N_1000_setget_11-35-59'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:36:32\n",
+ "Started at 2017-09-08 11:36:32\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#018_N_1000_setget_11-36-32'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:37:04\n",
+ "Started at 2017-09-08 11:37:04\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#019_N_1000_setget_11-37-04'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:37:36\n",
+ "Started at 2017-09-08 11:37:36\n",
+ "DataSet:\n",
+ " location = 'data/2017-09-08/#020_N_1000_setget_11-37-36'\n",
+ " | | | \n",
+ " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n",
+ " Measured | dmm_volt | volt | (1000,)\n",
+ "Finished at 2017-09-08 11:38:08\n",
+ "32.2 s ± 110 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "\n",
+ "N = 1000\n",
+ "\n",
+ "# remember to turn off the display for better speed\n",
+ "dmm.display_text('Running set-get for {} points'.format(N))\n",
+ "\n",
+ "loop = qc.Loop(qdac.ch01_v.sweep(0, 1, num=N)).each(dmm.volt)\n",
+ "data = loop.get_data_set(name='N_{}_setget'.format(N))\n",
+ "_ = loop.run() # run the loop\n",
+ "\n",
+ "dmm.display_clear()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## N = 1000, set-software triggered"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def software_triggered_readings(N: int) -> np.array:\n",
+ " \"\"\"\n",
+ " Try to get N measurement points\n",
+ " \"\"\"\n",
+ " \n",
+ " dmm.display_text('Sending {} software triggers'.format(N))\n",
+ " \n",
+ " dmm.trigger_source('BUS')\n",
+ " dmm.sample_count(1) # samples per trigger\n",
+ " dmm.trigger_count(N) # number of triggers to wait for\n",
+ " dmm.init_measurement()\n",
+ " \n",
+ " qdac_setpoints = np.linspace(0, 1, N)\n",
+ " \n",
+ " for n in range(N):\n",
+ " qdac.ch01_v(qdac_setpoints[n])\n",
+ " dmm.write('*TRG')\n",
+ " time.sleep(dmm.sample_timer_minimum()) # Wait to avoid losing triggers\n",
+ " \n",
+ " # even if we are losing triggers, can ABORt the measurement\n",
+ " # and then fetch whatever data the DMM holds\n",
+ " dmm.abort_measurement() \n",
+ " raw_vals = dmm.ask('FETCH?')\n",
+ " dmm.display_clear()\n",
+ "\n",
+ " numvals = np.array(list(map(float, raw_vals.split(','))))\n",
+ " \n",
+ " print('Requested {} samples, got {}.'.format(N, len(numvals)))\n",
+ " \n",
+ " return numvals"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "Requested 1000 samples, got 1000.\n",
+ "32.2 s ± 387 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%timeit\n",
+ "\n",
+ "data = software_triggered_readings(1000)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Results summary\n",
+ "\n",
+ "**N = 1000**\n",
+ "\n",
+ "Standard set-get: 32.2 s\n",
+ "\n",
+ "Software triggered: 32.2 s"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "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.5.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py
index 7fa991f746b..95562699cc3 100644
--- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py
+++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py
@@ -185,6 +185,21 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False,
self.NPLC_list = PLCs[self.model]
self._apt_times = apt_times[self.model]
+ def errorparser(rawmssg: str) -> (int, str):
+ """
+ Parses the error message.
+
+ Args:
+ rawmssg: The raw return value of 'SYSTem:ERRor?'
+
+ Returns:
+ The error code and the error message.
+ """
+ code = int(rawmssg.split(',')[0])
+ mssg = rawmssg.split(',')[1].strip().replace('"', '')
+
+ return code, mssg
+
####################################
# PARAMETERS
@@ -306,6 +321,13 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False,
get_parser=float,
unit='s')
+ # SYSTEM
+ self.add_parameter('error',
+ label='Error message',
+ get_cmd='SYSTem:ERRor?',
+ get_parser=errorparser
+ )
+
# The array parameter
self.add_parameter('data_buffer',
parameter_class=ArrayMeasurement)
@@ -335,6 +357,7 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False,
self.add_function('init_measurement', call_cmd='INIT')
self.add_function('reset', call_cmd='*RST')
self.add_function('display_clear', call_cmd=('DISPLay:TEXT:CLEar'))
+ self.add_function('abort_measurement', call_cmd='ABORt')
if not silent:
self.connect_message()
@@ -404,3 +427,27 @@ def _set_resolution(self, value):
# NPLC settings change with resolution
self.NPLC.get()
+
+ def flush_error_queue(self, verbose: bool=True) -> None:
+ """
+ Clear the instrument error queue.
+
+ Args:
+ verbose: If true, the error messages are printed.
+ Default: True.
+ """
+
+ log.debug('Flushing error queue...')
+
+ err_code, err_message = self.error()
+ log.debug(' {}, {}'.format(err_code, err_message))
+ if verbose:
+ print(err_code, err_message)
+
+ while err_code != 0:
+ err_code, err_message = self.error()
+ log.debug(' {}, {}'.format(err_code, err_message))
+ if verbose:
+ print(err_code, err_message)
+
+ log.debug('...flushing complete')