Keysight M3202A AWG¶
The Keysight M3202A is a 1 GSa/a arbitrary waveform generator.
An instance of M3202A represents a module with 4 output channels. The channels of one module share the uploaded waveforms and trigers.
This example loads loads waveforms in AWGs in slots 2 and 3 of chassis 0.
[ ]:
import logging
import numpy as np
try:
import keysightSD1
except:
# add the path where the keysight library probably resides and try again
import sys
sys.path.append(r'C:\Program Files (x86)\Keysight\SD1\Libraries\Python')
import keysightSD1
import qcodes
from qcodes_contrib_drivers.drivers.Keysight.M3202A import M3202A
import qcodes.logger as logger
from qcodes.logger import start_all_logging
start_all_logging()
# logger.get_file_handler().setLevel(logging.DEBUG)
[ ]:
# try to close station from previous run.
try:
station.close_all_registered_instruments()
except: pass
[ ]:
# Demonstration of some errors
try:
wrong_chassis = M3202A("wrong chassis", chassis = 5, slot = 16)
except Exception as e:
print('Expected failure:', e)
try:
empty_slot = M3202A("empty_slot", chassis = 0, slot = 16)
except Exception as e:
print('Expected failure:', e)
try:
not_M3202A = M3202A("Digitizer", chassis = 0, slot = 5)
except Exception as e:
print('Expected failure:', e)
[ ]:
awg1 = M3202A("AWG1", chassis = 0, slot = 2)
awg2 = M3202A("AWG2", chassis = 0, slot = 3)
station = qcodes.Station()
station.add_component(awg1)
station.add_component(awg2)
[ ]:
# utility functions to create waveforms
def get_divider(prescaler):
if prescaler == 0:
divider = 1
elif prescaler == 1:
divider = 5
else:
divider = prescaler * 10
return divider
def create_sawtooth(period, repetition, prescaler):
divider = get_divider(prescaler)
n_pts = period // divider
w = np.linspace(-1, 1, n_pts)
w = np.tile(w, repetition)
if len(w) < 2000:
raise Exception('not enough data')
return w
def create_sine(period, repetition, prescaler):
divider = get_divider(prescaler)
n_pts = repetition * period // divider
phi = np.linspace(0, np.pi*2*repetition, n_pts)
w = np.sin(phi)
if len(w) < 2000:
raise Exception('not enough data')
return w
[ ]:
# setup output channels
pxi1 = keysightSD1.SD_TriggerExternalSources.TRIGGER_PXI1
trigger_mode = keysightSD1.SD_TriggerBehaviors.TRIGGER_FALL
for awg in [awg1, awg2]:
for ch in range(1,5):
awg.set_channel_offset(0.0, ch)
awg.set_channel_amplitude(1.0, ch)
awg.set_channel_wave_shape(keysightSD1.SD_Waveshapes.AOU_AWG, ch)
awg.awg_queue_config(ch, keysightSD1.SD_QueueMode.CYCLIC)
awg.awg_config_external_trigger(ch, pxi1, trigger_mode)
awg2.amplitude_channel_1.set(0.5)
awg2.offset_channel_2.set(0.5)
Generate and enqueue waveforms¶
Signal duration 20 us: * “AWG1.1”: 20x sawtooth (followed by zeros) * “AWG1.2”: 20 steps (followed by zeros) * “AWG2.3”: 2 us zero, 4 us sine, 2 us zero, 12 us sine * “AWG2.4”: 4 us sine, 4 us zero, 8 us sine, 4 us zero
[ ]:
prescaler_1GSa = 0
prescaler_200MSa = 1
prescaler_50MSa = 2
# 2000 zero's for end
zeros = np.zeros(2000)
# sawtooth period = 1 us: 2 period in 1 sample
sawtooth_2us = 0.5 * create_sawtooth(1000, 2, prescaler_1GSa)
# 20 steps use prescaler to reduce total number of samples. 200MSa/s => 4000 pts; 200 per step
steps = np.concatenate([0.02*i*np.ones(200) for i in range(20)])
# sine wave 2 MHz, 4 periods
sine = 0.6 * create_sine(500, 4, prescaler_1GSa)
# start all uploads
zeros_awg1 = awg1.upload_waveform(zeros)
sawtooth_2us_awg1 = awg1.upload_waveform(sawtooth_2us)
steps_awg1 = awg1.upload_waveform(steps)
zeros_awg2 = awg2.upload_waveform(zeros)
sine_awg2 = awg2.upload_waveform(sine)
# enqueue wave references
delay = 0
ext_trigger = keysightSD1.SD_TriggerModes.EXTTRIG
auto_trigger = keysightSD1.SD_TriggerModes.AUTOTRIG
awg1.awg_queue_waveform(1, sawtooth_2us_awg1, ext_trigger, delay, 10, prescaler_1GSa)
awg1.awg_queue_waveform(1, zeros_awg1, auto_trigger, delay, 1, prescaler_1GSa)
awg1.awg_queue_waveform(2, steps_awg1, ext_trigger, delay, 1, prescaler_200MSa)
awg1.awg_queue_waveform(2, zeros_awg1, auto_trigger, delay, 1, prescaler_1GSa)
awg2.awg_queue_waveform(3, zeros_awg2, ext_trigger, delay, 1, prescaler_1GSa)
awg2.awg_queue_waveform(3, sine_awg2, auto_trigger, delay, 2, prescaler_1GSa)
awg2.awg_queue_waveform(3, zeros_awg2, auto_trigger, delay, 1, prescaler_1GSa)
awg2.awg_queue_waveform(3, sine_awg2, auto_trigger, delay, 6, prescaler_1GSa)
awg2.awg_queue_waveform(4, sine_awg2, ext_trigger, delay, 2, prescaler_1GSa)
awg2.awg_queue_waveform(4, zeros_awg2, auto_trigger, delay, 2, prescaler_1GSa)
awg2.awg_queue_waveform(4, sine_awg2, auto_trigger, delay, 4, prescaler_1GSa)
awg2.awg_queue_waveform(4, zeros_awg2, auto_trigger, delay, 2, prescaler_1GSa)
# start AWGs. They will wait for external trigger.
awg1.awg_start_multiple(0b0011)
awg2.awg_start_multiple(0b1100)
Trigger AWGs¶
[ ]:
# start AWGs via PXI
# Note: PXI trigger can be set via any module
awg1.set_pxi_trigger(0, pxi1)
awg1.set_pxi_trigger(1, pxi1)