This page was generated from docs/examples/driver_examples/Qcodes example with Rohde Schwarz ZNB.ipynb. Interactive online version: Binder badge.

QCoDeS Example with Rohde Schwarz ZNB20/8

[1]:
%matplotlib nbagg
import matplotlib.pyplot as plt
import numpy as np
import qcodes as qc
[2]:
import qcodes.instrument_drivers.rohde_schwarz.ZNB as ZNB
from qcodes.instrument_drivers.rohde_schwarz.ZNB import ZNBChannel
[3]:
from qcodes import initialise_database, load_or_create_experiment, Measurement
from qcodes.dataset.plotting import plot_by_id
initialise_database()
load_or_create_experiment(experiment_name='test_with_znb8',
                          sample_name="no sample")
[3]:
test_with_znb8#no sample#4@C:\Users\jenielse\source\repos\qcodes_generate_test_db\qcplotbenchmark.db
----------------------------------------------------------------------------------------------------

The driver supports three ways of interacting with the instrument. We go through all of them here in order.

Remotely setup VNA channels

By default the VNA driver will clear any traces and channels defined on the VNA and create a new channel for each of the S parameters available on the VNA. I.e. S11, S12, S21 and S22 for a 2 port VNA. In this mode the VNA also starts up with RF power turned off.

[4]:
vna = ZNB.ZNB('VNA', 'TCPIP0::192.168.15.104::inst0::INSTR')
station = qc.Station(vna)
Connected to: Rohde-Schwarz ZNB8-4Port (serial:1311601044103158, firmware:2.86) in 0.72s

To use the VNA we likely want to turn on RF Power, which is off by default for safty in this driver. The driver default to low power but for safety lets set it to -50 dBm. The rf can be turned on and off globally and the power adjusted individually for each channel.

[5]:
vna.channels.power(-50)
vna.rf_on()

As we have turned on rf power it’s likely that the display output is out of scale so lets force a autoscale for all channels

[6]:
vna.channels.autoscale()

The QCoDes driver for the Rohde Schwarz ZNB(8/20) is setup with num_ports*num_ports channels each containing one trace and reprecenting the standard S parameters (S11, S12, S21, S22 etc). For each S parameter you can define a frequency sweep and the power of the rf source i.e if we want to sweep from 100 KHz to 6 MHz in 100 steps measureing S11:

[7]:
vna.channels.S11.start(100e3)
vna.channels.S11.stop(6e6)
vna.channels.S11.npts(100)

With a power of -30 dBm

[8]:
vna.channels.S11.power(-30)

Now we can meassure a frequency trace, first remembering to turn on the rf source. By default this produces a dB magnitude scan.

[9]:
vna.rf_on()
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace.get()
    datasaver.add_result((vna.channels.S11.trace, get_v))
Starting experimental run with id: 62
[10]:
ax, cbax = plot_by_id(datasaver.run_id)

We can also define a frequency trace by setting the span and center frequency. Here as a 200 KHz windows centered around 1 MHZ

[11]:
vna.channels.S11.span(200e3)
vna.channels.S11.center(1e6)
vna.channels.S11.npts(100)
[12]:
vna.rf_on()
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace.get()
    datasaver.add_result((vna.channels.S11.trace, get_v))
ax, cbax = plot_by_id(datasaver.run_id)
Starting experimental run with id: 63

We can also measure the linear magniture.

[13]:
vna.rf_on()
vna.channels.S11.format('Linear Magnitude')
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace.get()
    datasaver.add_result((vna.channels.S11.trace, get_v))
ax, cbax = plot_by_id(datasaver.run_id)
Starting experimental run with id: 64

Or the real part

[14]:
vna.rf_on()
vna.channels.S11.format('Real')
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace.get()
    datasaver.add_result((vna.channels.S11.trace, get_v))
ax, cbax = plot_by_id(datasaver.run_id)
Starting experimental run with id: 65

Or imaginary

[15]:
vna.rf_on()
vna.channels.S11.format('Imaginary')
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace.get()
    datasaver.add_result((vna.channels.S11.trace, get_v))
ax, cbax = plot_by_id(datasaver.run_id)
Starting experimental run with id: 66

However, the QCoDeS dataset does not currently support complex number so if you want to capture both the magnitude and phase you should use trace_mag_phase which returns magnitude and phase as two arrays

[16]:
# First set format back for consistency
vna.channels.S11.format('dB')
[17]:
vna.rf_on()
meas = Measurement()
meas.register_parameter(vna.channels.S11.trace_mag_phase)
with meas.run() as datasaver:
    get_v = vna.channels.S11.trace_mag_phase.get()
    datasaver.add_result((vna.channels.S11.trace_mag_phase, get_v))
ax, cbax = plot_by_id(datasaver.run_id)
Starting experimental run with id: 67

A number of methods exists to help setup the VNA

We can display all 4/16 … S parameters in a split view on the VNA display.

[18]:
vna.display_sij_split()

Or we can display all parameters in one view.

[19]:
vna.display_single_window()

Or a grid of our own choice

[20]:
vna.display_grid(2,1)
[21]:
vna.display_sij_split()

It is possible to switch the display of traces on and off

[22]:
vna.update_display_off()
[23]:
vna.update_display_on()

Control if data should be captured continiously when not capturing traces

[24]:
vna.cont_meas_off()
[25]:
vna.cont_meas_on()

And switch the rf output on and off

[26]:
vna.rf_on()
[27]:
vna.rf_off()

Doing a 2D sweep is supported too

[28]:
vna.rf_on()
vna.channels.S11.start(100e3)
vna.channels.S11.stop(200e3)
vna.channels.S11.npts(100)
vna.channels.S11.avg(10)
[29]:
meas = Measurement()
meas.register_parameter(vna.channels.S11.power)
meas.register_parameter(vna.channels.S11.trace, setpoints=(vna.channels.S11.power,))
with meas.run() as datasaver:
    for power in range(-50, -30, 1):
        vna.channels.S11.power.set(power)
        get_v = vna.channels.S11.trace.get()
        datasaver.add_result((vna.channels.S11.power, power),
                             (vna.channels.S11.trace, get_v))
Starting experimental run with id: 68
[30]:
ax, cbax = plot_by_id(datasaver.run_id)

We can also capture db Traces for all channels in one QCoDeS measurement. Notice how start/stop number of points and number of averages can be set globally for all channels.

[31]:
vna.channels.start(9e3)
vna.channels.stop(8.5e9)
vna.channels.npts(100)
vna.channels.avg(100)
[32]:
vna.rf_on()
meas = Measurement()
meas.register_parameter(vna.channels.trace)
with meas.run() as datasaver:
    get_v = vna.channels.trace.get()
    datasaver.add_result((vna.channels.trace, get_v))
Starting experimental run with id: 69
[34]:
ax, cbax = plot_by_id(datasaver.run_id)