{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# QCoDeS Example with Tektronix AWG70002A\n", "\n", "The Tektronix awg70002A can operate in two modes: function generator mode or AWG mode. This example notebook briefly covers both." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib notebook\n", "import matplotlib.pyplot as plt\n", "\n", "import numpy as np\n", "from qcodes.instrument_drivers.tektronix.AWG70002A import AWG70002A" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to: TEKTRONIX AWG70002A (serial:B020397, firmware:FV:5.3.0128.0) in 0.54s\n" ] } ], "source": [ "awg = AWG70002A('awg', 'TCPIP0::172.20.2.243::inst0::INSTR')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "awg:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "IDN :\t{'firmware': 'FV:5.3.0128.0', 'model': 'AWG70002A'...\n", "clock_external_frequency :\t6.25e+09 (Hz)\n", "clock_source :\tInternal \n", "current_directory :\t\"\\Users\\OEM\\Documents\" \n", "mode :\tAWG \n", "sample_rate :\t2.5e+10 (Sa/s)\n", "timeout :\t10 (s)\n", "awg_ch1:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "awg_amplitude :\t0.5 (V)\n", "fgen_amplitude :\t0.074 (V)\n", "fgen_dclevel :\t0 (V)\n", "fgen_frequency :\t1e+07 (Hz)\n", "fgen_offset :\t0.12 (V)\n", "fgen_period :\t1e-07 (s)\n", "fgen_phase :\t25 (degrees)\n", "fgen_signalpath :\tdirect \n", "fgen_symmetry :\t50 (%)\n", "fgen_type :\tEXPONENTIALDECAY \n", "marker1_high :\t0.1 (V)\n", "marker1_low :\t-0.4 (V)\n", "marker1_waitvalue :\tHIGH \n", "marker2_high :\t0.1 (V)\n", "marker2_low :\t-0.4 (V)\n", "marker2_waitvalue :\tHIGH \n", "resolution :\t8 \n", "state :\t1 \n", "awg_ch2:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "awg_amplitude :\t0.3 (V)\n", "fgen_amplitude :\t0.5 (V)\n", "fgen_dclevel :\t0 (V)\n", "fgen_frequency :\t1e+07 (Hz)\n", "fgen_offset :\t0 (V)\n", "fgen_period :\t1e-07 (s)\n", "fgen_phase :\t0 (degrees)\n", "fgen_signalpath :\tdirect \n", "fgen_symmetry :\t50 (%)\n", "fgen_type :\tTRIANGLE \n", "marker1_high :\t1.4 (V)\n", "marker1_low :\t0 (V)\n", "marker1_waitvalue :\tLOW \n", "marker2_high :\t1 (V)\n", "marker2_low :\t0 (V)\n", "marker2_waitvalue :\tLOW \n", "resolution :\t8 \n", "state :\t0 \n" ] } ], "source": [ "# Let's have a look at the available parameters\n", "\n", "awg.print_readable_snapshot(update=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Function Generator Style Operation" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Set the intrument mode to function generator\n", "awg.mode('FGEN')\n", "\n", "# Build some signal\n", "awg.ch1.fgen_type('EXPONENTIALDECAY')\n", "awg.ch1.fgen_frequency(10e6)\n", "awg.ch1.fgen_amplitude(0.074)\n", "awg.ch1.fgen_offset(0.12)\n", "awg.ch1.fgen_phase(25)\n", "\n", "# Switch channel 1 on\n", "awg.ch1.state(1)\n", "\n", "# Start outputting...\n", "awg.play()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# switch off the output eventually\n", "awg.stop()\n", "\n", "# and disable the channel\n", "awg.ch1.state(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## AWG Style Operation\n", "\n", "The instrument can be operated as an awg where the user uploads arrays describing the waveforms.\n", "\n", "Each channel operates in one of three resolution modes:\n", "\n", "* 8 bit signal + 2 markers\n", "* 9 bit signal + 1 marker\n", "* 10 bit signal with no markers\n", "\n", "Waveforms can be sent to the waveform list via `.wfmx` files. A `.wfmx` file can contain marker data. If the resolution of the instrument does not allow for markers, these are simply ignored." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Making and sending waveforms to the waveform list" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# set the instrument in awg mode\n", "awg.mode('AWG')\n", "# set the resolution to 8 bits plus two markers\n", "awg.ch1.resolution(8)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# clear the sequence list and waveform list (NOT ALWAYS A GOOD IDEA! BE CAREFUL!)\n", "awg.clearSequenceList()\n", "awg.clearWaveformList()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# Let us make a sine, upload it and play it\n", "\n", "N = 50000 # minimal length allowed is 2400 points\n", "\n", "m1 = np.concatenate((np.ones(int(N/2)), np.zeros(int(N/2))))\n", "m2 = np.concatenate((np.zeros(int(N/2)), np.ones(int(N/2))))\n", "\n", "ramp = 0.075*np.linspace(0, 1, N)\n", "\n", "mysine = 0.1*np.sin(10*2*np.pi*np.linspace(0, 1, N)) + ramp\n", "\n", "data = np.array([mysine, m1, m2])" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# The .wfmx file needs a name in the memory of the instrument\n", "# The name of the waveform in the waveform list is that same name\n", "# with no .wfmx extension\n", "filename = 'examplewaveform1.wfmx'" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# now compile the binary file\n", "wfmx_file = awg.makeWFMXFile(data, 0.350)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# and send it and load it into memory\n", "awg.sendWFMXFile(wfmx_file, filename)\n", "awg.loadWFMXFile(filename)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['examplewaveform1']" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The waveform is now in the waveform list\n", "awg.waveformList" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# now assign it to channel 1\n", "awg.ch1.setWaveform(filename.replace('.wfmx', ''))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Switch channel 1 on\n", "awg.ch1.state(1)\n", "\n", "# Start outputting...\n", "awg.play()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# switch off the output eventually\n", "awg.stop()\n", "\n", "# and disable the channel\n", "awg.ch1.state(0)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "awg.ch2.setWaveform(filename.replace('.wfmx', ''))" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": true }, "outputs": [], "source": [ "awg.ch2.state(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Making and sending sequences\n", "\n", "Sequences are much better off being generated using the broadbean module, but for now let's reduce the number of moving parts and compose a little sequence by hand." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# set the instrument in awg mode\n", "awg.mode('AWG')\n", "# set the resolution to 8 bits plus two markers\n", "awg.ch1.resolution(8)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "\n", "# Let's make a sequence where a sine plays on one channel while the other channel ramps\n", "# and then the roles reverse\n", "\n", "# As a preparation, let's set both channels to 300 mV peak-to-peak\n", "awg.ch1.awg_amplitude(0.3)\n", "awg.ch2.awg_amplitude(0.3)\n", "\n", "N = 20000 # minimally 2400\n", "\n", "SR = 1e9\n", "awg.sample_rate(SR) # set the sample rate on the instrument\n", "ramp_target = 0.1 # ramp target (V)\n", "\n", "time = np.linspace(0, N/SR, N)\n", "sinesignal = 0.15*np.sin(SR/N*2*np.pi*time)\n", "m1 = np.concatenate((np.ones(int(N/2)), np.zeros(int(N/2))))\n", "m2 = np.concatenate((np.zeros(int(N/2)), np.zeros(int(N/2))))\n", "rampsignal = np.linspace(0, ramp_target, N)\n", "\n", "# Then we compose and upload a .seqx file in 6 steps\n", "\n", "# Step 1: cast the waveform data into the .wfmx format\n", "# To make a .wfmx, we need to know the amplitude of the output channel\n", "ch1_amp = awg.ch1.awg_amplitude()\n", "ch2_amp = awg.ch2.awg_amplitude()\n", "\n", "#wfm_ch1_n1 = awg.makeWFMXFile(np.array([sinesignal, m1, m2]), ch1_amp)\n", "#wfm_ch1_n2 = awg.makeWFMXFile(np.array([rampsignal, m1, m2]), ch1_amp)\n", "#wfm_ch2_n1 = awg.makeWFMXFile(np.array([rampsignal, m1, m2]), ch2_amp)\n", "#wfm_ch2_n2 = awg.makeWFMXFile(np.array([sinesignal, m1, m2]), ch2_amp)\n", "\n", "\n", "wfm_ch1_n1 = np.array([sinesignal, m1, m2])\n", "wfm_ch1_n2 = np.array([rampsignal, m1, m2])\n", "wfm_ch2_n1 = np.array([rampsignal, m1, m2])\n", "wfm_ch2_n2 = np.array([sinesignal, m1, m2])\n", "\n", "# Step 2: decide on sequencing information\n", "# This information is provided as lists of the same length as the \n", "# sequence\n", "trig_waits = [0, 0] # 0: off, 1: trigA, 2: trigB, 3: EXT\n", "nreps = [2, 3] # 0 corresponds to infinite\n", "event_jumps = [0, 0] # 0: off, 1: trigA, 2: trigB, 3: EXT\n", "event_jump_to = [0, 0] # irrelevant if event-jump is 0, else the sequence pos. to jump to\n", "go_to = [0, 1] # 0 means next\n", "\n", "# Step 3: make the .seqx file\n", "# The sequence must be given a name\n", "\n", "seqname = 'tutorial_sequence'\n", "\n", "wfms = [[wfm_ch1_n1, wfm_ch1_n2], [wfm_ch2_n1, wfm_ch2_n2]]\n", "\n", "seqx = awg.makeSEQXFile(trig_waits,\n", " nreps,\n", " event_jumps,\n", " event_jump_to,\n", " go_to,\n", " wfms,\n", " [ch1_amp, ch2_amp],\n", " seqname)\n", "\n", "# Step 4: Transfer the seqx file\n", "awg.sendSEQXFile(seqx, 'thursday.seqx')\n", "\n", "# Step 5: Load the seqx file\n", "awg.loadSEQXFile('thursday.seqx')\n", "# Now the sequence should appear in the sequencelist, but it is not yet assigned to channels\n", "\n", "# Step 6: Assign tracks from the sequence to the channels\n", "# Unlike older/other AWG models, this can be done on a per-channel basis\n", "awg.ch1.setSequenceTrack(seqname, 1)\n", "awg.ch2.setSequenceTrack(seqname, 2)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# Now play it!\n", "awg.ch1.state(1)\n", "awg.ch2.state(1)\n", "awg.play()" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "awg.stop()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "# Finally irreversibly tear down the instrument\n", "awg.close()" ] } ], "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.6.6" }, "nbsphinx": { "execute": "never" } }, "nbformat": 4, "nbformat_minor": 2 }