# Examples for Python
# Arbitrary Waveform Generator
# arbitrarywavegen_basic.py
This example demonstrates how you can generate and output arbitrary waveforms using Moku AWG
#
# moku example: Arbitrary waveform generator
#
# This example demonstrates how you can generate and output arbitrary
# waveforms using Moku AWG
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
import numpy as np
from moku.instruments import ArbitraryWaveformGenerator
# Generate a signal that the Arbitrary Waveform Generator should generate on the output
t = np.linspace(0, 1, 100) # Evaluate our waveform at 100 points
# Simple square wave (can also use scipy.signal)
sq_wave = np.array([-1.0 if x < 0.5 else 1.0 for x in t])
# More interesting waveform. Note that we have to normalize this waveform
# to the range [-1, 1]
not_sq = np.zeros(len(t))
for h in np.arange(1, 15, 2):
not_sq += (4 / (np.pi * h)) * np.cos(2 * np.pi * h * t)
not_sq = not_sq / max(abs(not_sq))
# Connect to your Moku by its ip address ArbitraryWaveformGenerator('192.168.###.###')
# or by its serial ArbitraryWaveformGenerator(serial=123)
i = ArbitraryWaveformGenerator('192.168.###.###', force_connect=False)
try:
# Load and configure the waveform.
i.generate_waveform(channel=1, sample_rate='Auto',
lut_data=list(sq_wave), frequency=10e3,
amplitude=1)
i.generate_waveform(channel=2, sample_rate='Auto', lut_data=list(not_sq),
frequency=10e3, amplitude=1)
# Set channel 1 to pulse mode
# 2 dead cycles at 0Vpp
i.pulse_modulate(channel=1, dead_cycles=2, dead_voltage=0)
# Set Channel 2 to burst mode
# Burst mode triggering from Input 1 at 0.1 V
# 3 cycles of the waveform will be generated every time it is triggered
i.burst_modulate(channel=2, trigger_source='Input1', trigger_mode='NCycle', burst_cycles=3, trigger_level=0.1)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Cloud Compile
# cloud_compile_adder.py
This example demonstrates how you can configure Cloud Compile, using Multi-Instrument mode to run the Adder example (opens new window)
#
# moku example: Adder Cloud Compile
#
# This example demonstrates how you can configure Cloud Compile, using
# Multi-Instrument mode, to add and subtract two input signals together and
# output the result to the Oscilloscope.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import MultiInstrument, CloudCompile, Oscilloscope
# Connect to your Moku by its ip address using
# MultiInstrument('192.168.###.###')
# or by its serial number using MultiInstrument(serial=123)
m = MultiInstrument('192.168.###.###', platform_id=2)
try:
# Set the instruments and upload Cloud Compile bitstreams from your device
# to your Moku
bitstream = "path/to/project/adder/bitstreams.tar.gz"
mcc = m.set_instrument(1, CloudCompile, bitstream=bitstream)
osc = m.set_instrument(2, Oscilloscope)
# Configure the connections
connections = [dict(source="Slot1OutA", destination="Slot2InA"),
dict(source="Slot1OutB", destination="Slot2InB"),
dict(source="Slot2OutA", destination="Slot1InA"),
dict(source="Slot2OutB", destination="Slot1InB")]
m.set_connections(connections=connections)
# Configure the Oscilloscope to generate a ramp wave and square wave with
# equal frequencies, then sync the phases
osc.generate_waveform(1, 'Square', amplitude=1, frequency=1e3, duty=50)
osc.generate_waveform(2, 'Ramp', amplitude=1, frequency=1e3, symmetry=50)
osc.sync_output_phase()
# Set the time span to cover four cycles of the waveforms
osc.set_timebase(-2e-3, 2e-3)
# Retrieve data
data = osc.get_data()
# Set up the plotting parameters
plt.plot(data['time'], data['ch1'], label='Add')
plt.plot(data['time'], data['ch2'], label='Subtract')
# Configure labels for axes
plt.xlabel("Time [Second]")
plt.ylabel("Amplitude [Volt]")
plt.grid(visible=True)
plt.legend(loc=0)
plt.show()
except Exception as e:
print(f'Exception occurred: {e}')
finally:
m.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# cloud_compile_arithmetic.py
This example demonstrates how you can configure Cloud Compile, using Multi-Instrument mode to run the Arithmetic Unit example (opens new window)
#
# moku example: Arithmetic Cloud Compile
#
# This example demonstrates how you can configure Cloud Compile to chose to
# add, subtract or multiply two input signals using the control registers
# and output the result to the Oscilloscope.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import MultiInstrument, CloudCompile, Oscilloscope
# Connect to your Moku by its ip address using
# MultiInstrument('192.168.###.###')
# or by its serial number using MultiInstrument(serial=123)
m = MultiInstrument('192.168.###.###', platform_id=2)
try:
# Set the instruments and upload Cloud Compile bitstreams from your device
# to your Moku
bitstream = "path/to/project/arithmetic/bitstreams.tar.gz"
mcc = m.set_instrument(1, CloudCompile, bitstream=bitstream)
osc = m.set_instrument(2, Oscilloscope)
# Configure the connections
connections = [dict(source="Slot1OutA", destination="Slot2InA"),
dict(source="Slot2OutB", destination="Slot2InB"),
dict(source="Slot2OutA", destination="Slot1InA"),
dict(source="Slot2OutB", destination="Slot1InB")]
m.set_connections(connections=connections)
# Configure the Oscilloscope to generate a ramp wave and square wave with
# equal frequencies, then sync the phases
osc.generate_waveform(1, 'Square', amplitude=50e-3,
frequency=1e3, duty=50)
osc.generate_waveform(2, 'Ramp', amplitude=50e-3,
frequency=1e3, symmetry=50)
osc.sync_output_phase()
# Set the time span to cover four cycles of the waveforms
osc.set_timebase(-2e-3, 2e-3)
osc.set_trigger(type="Edge", edge="Rising", level=0,
mode="Normal", source="ChannelB")
# Set up the plotting figure
fig, axs = plt.subplots(3, sharex=True)
# Set Control Register 1 to choose to add (0b00), subtract (0b01) or
# multiply (0b10) the input signals
mcc.set_control(1, 0b00)
# Retrieve the data
data = osc.get_data(wait_reacquire=True)
# Plot the result and configure labels for the axes
axs[0].plot(data['time'], data['ch1'], color='r')
axs[0].grid(visible=True)
axs[0].set_title('Add - 0b00')
# Repeat these steps for each option
mcc.set_control(1, 0b01)
data = osc.get_data(wait_reacquire=True)
axs[1].plot(data['time'], data['ch1'], color='b')
axs[1].grid(visible=True)
axs[1].set_ylabel("Amplitude [Volt]")
axs[1].set_title('Subtract - 0b01')
mcc.set_control(1, 0b10)
data = osc.get_data(wait_reacquire=True)
axs[2].plot(data['time'], data['ch1'], color='y')
axs[2].grid(visible=True)
axs[2].set_title('Multiply - 0b10')
# Configure labels for axes
plt.xlabel("Time [Second]")
plt.tight_layout()
plt.show()
except Exception as e:
print(f'Exception occurred: {e}')
finally:
m.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Data Logger
# datalogger_basic.py
This example demonstrates use of the Datalogger instrument to log time-series voltage data to a file.
#
# moku example: Basic Datalogger
#
# This example demonstrates use of the Datalogger instrument to log time-series
# voltage data to a (Binary or CSV) file.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
import os
import time
from moku.instruments import Datalogger
# Connect to your Moku by its ip address using Datalogger('192.168.###.###')
# or by its serial number using Datalogger(serial=123)
i = Datalogger('192.168.###.###', force_connect=False)
try:
# Configure the frontend
i.set_frontend(channel=1, impedance='1MOhm', coupling="AC", range="10Vpp")
# Log 100 samples per second
i.set_samplerate(100)
i.set_acquisition_mode(mode='Precision')
# Generate Sine wave on Output1
i.generate_waveform(channel=1, type='Sine', amplitude=1,
frequency=10e3)
# Stop an existing log, if any, then start a new one. 10 seconds of both
# channels
logFile = i.start_logging(duration=10)
# Track progress percentage of the data logging session
complete = False
while complete is False:
# Wait for the logging session to progress by sleeping 0.5sec
time.sleep(0.5)
# Get current progress percentage and print it out
progress = i.logging_progress()
complete = progress['complete']
if 'time_remaining' in progress:
print(f"Remaining time {progress['time_remaining']} seconds")
# Download log from Moku, use liconverter to convert this .li file to .csv
i.download("persist", logFile['file_name'], os.path.join(os.getcwd(), logFile['file_name']))
print("Downloaded log file to local directory.")
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Data Streaming
# datalogger_streaming.py
This example demonstrates use of the Datalogger instrument to stream time-series voltage data.
#
# moku example: Basic Datalogger streaming
#
# This example demonstrates use of the Datalogger instrument to
# stream time-series voltage data and plot it using matplotlib
#
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import Datalogger
i = Datalogger('192.168.###.###', force_connect=False)
try:
# generate a waveform on output channel 1
i.generate_waveform(1, "Sine", frequency=100)
# disable Input2 as we want to stream data only from Input1
i.enable_input(2, enable=False)
# set the sample rate to 10KSa/s
i.set_samplerate(10e3)
# stream the data for 10 seconds..
i.start_streaming(10)
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
line1, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# get the chunk of streamed data
data = i.get_stream_data()
if data:
plt.xlim([data['time'][0], data['time'][-1]])
# Update the plot
line1.set_ydata(data['ch1'])
line1.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
i.stop_streaming()
print(e)
finally:
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# lock_in_amplifier_streaming.py
This example demonstrates use of the Lockin Amplifier instrument to demodulate Input signal with a reference signal from local oscillator and stream the generated waveform from auxiliary output
#
# moku example: Plotting Lock-in Amplifier
#
# This example demonstrates how you can configure the Lock-in
# Amplifier instrument to demodulate an input signal from Input 1
# with the reference signal from the Local Oscillator to extract the
# X component and generate a sine wave on the auxiliary output
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import LockInAmp
# Connect to your Moku by its ip address using
# LockInAmp('192.168.###.###')
# or by its serial number using LockInAmp(serial=123)
i = LockInAmp('192.168.xxx.xxx', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and
# 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm',
attenuation='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm',
attenuation='0dB')
# Configure the demodulation signal to Local oscillator
# with 1 MHz and 0 degrees phase shift
i.set_demodulation('Internal', frequency=1e6, phase=0)
# Set low pass filter to 1 kHz corner frequency with
# 6 dB/octave slope
i.set_filter(1e3, slope='Slope6dB')
# Configure output signals
# X component to Output 1
# Aux oscillator signal to Output 2 at 1 MHz 500 mVpp
i.set_outputs('X', 'Aux')
i.set_aux_output(1e6, 0.5)
# Set up signal monitoring
# Configure monitor points to Input 1 and main output
i.set_monitor(1, 'Input1')
i.set_monitor(2, 'MainOutput')
# Configure the trigger conditions
# Trigger on Probe A, rising edge, 0V
i.set_trigger(type='Edge', source='ProbeA', level=0)
# View +- 1 ms i.e. trigger in the centre
i.set_timebase(-1e-3, 1e-3)
i.start_streaming(duration=20, rate=100e3)
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_stream_data()
if data:
plt.xlim([data['time'][0], data['time'][-1]])
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
i.stop_streaming()
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# mim_dl_lia_streaming.py
This example demonstrates data streaming feature in Multi-instrument mode, deploying Datalogger in slot1 and Lockin Amplifier in slot2.
import matplotlib.pyplot as plt
from moku.instruments import Datalogger, LockInAmp, MultiInstrument
i = MultiInstrument('192.168.xxx.xxx', platform_id=2)
try:
dl = i.set_instrument(1, Datalogger)
lia = i.set_instrument(2, LockInAmp)
connections = [dict(source="Input1", destination="Slot1InA"),
dict(source="Slot1OutA", destination="Slot2InA"),
dict(source="Slot1OutA", destination="Slot2InB"),
dict(source="Slot2OutA", destination="Output1")]
i.set_connections(connections=connections)
dl.generate_waveform(1, "Sine", frequency=1000)
dl.start_streaming(10)
dl.stream_to_file()
lia.set_monitor(1, "Input1")
lia.start_streaming(10)
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = lia.get_stream_data()
# Update the plot
if data:
plt.xlim([data['time'][0], data['time'][-1]])
line1.set_ydata(data['ch1'])
line1.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
print(e)
finally:
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Digital Filter Box
This example demonstrates how you can configure the Digital Filter Box instrument to filter and display two signals.
#
# Python moku example: Plotting Digital Filter Box
#
# This example demonstrates how you can configure the Digital
# Filter Box instrument to filter and display two signals. Filter
# 1 takes its input from Input1 and applies a lowpass Butterworth
# filter. Filter 2 takes its input from Input1 + Input2 and applies
# a highpass Elliptic filter. The output of both filters are then
# displayed on the plot.
#
# (c) 2023 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku import MokuException
from moku.instruments import DigitalFilterBox
# Connect to your Moku by its ip address using
# DigitalFilterBox('192.168.###.###')
# or by its serial number using DigitalFilterBox(serial=123)
i = DigitalFilterBox('192.168.2.125', force_connect=True)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and
# default input range (400 mVpp range on Moku:Pro, 1 Vpp
# range on Moku:Lab, 10 Vpp range on Moku:Go)
i.set_frontend(1, coupling='DC', impedance='1MOhm',
attenuation='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm',
attenuation='0dB')
# Channel1 signal: Input 1
# Channel2 signal: Input 1 + Input 2
i.set_control_matrix(1, input_gain1=1, input_gain2=0)
i.set_control_matrix(2, input_gain1=1, input_gain2=1)
# Configure Digital Filter on Channel 1 and Channel 2
# Channel1 is a 8th-order Butterworth lowpass filter
# Channel2 is a 8th-order Elliptic highpass filter
# 3.906 MHz is for Moku:Go
# Please change sampling rate for other Moku devices.
i.set_filter(1, "3.906MHz", shape="Lowpass",
type="Butterworth", low_corner=1e3,
order=8)
i.set_filter(2, "3.906MHz", shape="Highpass",
type="Elliptic", high_corner=100e3,
order=8)
# Monitor ProbeA: Filter Channel1 output
# Monitor ProbeB: Filter Channel2 output
i.set_monitor(1, "Output1")
i.set_monitor(2, "Output2")
# Enable Digital Filter Box output ports
i.enable_output(1, signal=True, output=True)
i.enable_output(2, signal=True, output=True)
# View +- 0.5 ms i.e. trigger in the centre
i.set_timebase(-0.5e-3, 0.5e-3)
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-0.01, 0.01])
line1, = plt.plot([], label="Lowpass Filter Output")
line2, = plt.plot([], label="Highpass Filter Output")
# Configure labels for axes
ax = plt.gca()
ax.legend(handles=[line1, line2], loc=1)
plt.xlabel("Time [Second]")
plt.ylabel("Amplitude [Volt]")
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
if data:
plt.xlim([data['time'][0], data['time'][-1]])
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except MokuException as e:
print("Couldn't configure Moku. Please check your IP address and that you've updated the script parameters (such as sampling rate) to match your device.")
raise e
finally:
# Releasing ownership of the Moku allows other users to connect
# to it without forcing a takeover.
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Frequency Response Analyzer
# freq_response_analyzer_basic.py
This example demonstrates how you can generate output sweeps using the Frequency Response Analyzer instrument, and view one frame of the transfer function data.
#
# moku example: Basic Frequency Response Analyzer
#
# This example demonstrates how you can generate output sweeps using the
# Frequency Response Analyzer instrument, and view one frame of the transfer
# function data.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import FrequencyResponseAnalyzer
# Connect to your Moku by its ip address using FrequencyResponseAnalyzer('192.168.###.###')
# or by its serial number using FrequencyResponseAnalyzer(serial=123)
i = FrequencyResponseAnalyzer('192.168.###.###', force_connect=False)
try:
# Configure output sweep parameters (100Hz-20MHz)
i.set_sweep(start_frequency=20e6, stop_frequency=100, num_points=256,
averaging_time=1e-3, averaging_cycles=5, settling_cycles=5,
settling_time=1e-3)
# Configure output sweep amplitudes
# Channel 1 - 0.1Vpp
# Channel 1 - 0.1Vpp
i.set_output(1, 0.1)
i.set_output(2, 0.1)
# Start the sweep
i.start_sweep()
# Get a single sweep frame. This will block until the sweep is complete,
# beware if your range includes low frequencies!
frame = i.get_data(wait_complete=True)
# Print out the data for Channel 1
print(frame['ch1']['frequency'], frame['ch1']['magnitude'],
frame['ch1']['phase'])
# Print out the data for Channel 2
print(frame['ch2']['frequency'], frame['ch2']['magnitude'],
frame['ch2']['phase'])
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# freq_response_analyzer_plotting.py
This example demonstrates how you can generate output sweeps using the Frequency Response Analyzer instrument, and view transfer function data in real-time.
#
# moku example: Plotting Frequency Response Analyzer
#
# This example demonstrates how you can generate output sweeps using the
# Frequency Response Analyzer instrument, and view transfer function data
# in real-time.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import FrequencyResponseAnalyzer
# Connect to your Moku by its ip address using FrequencyResponseAnalyzer('192.168.###.###')
# or by its serial number using FrequencyResponseAnalyzer(serial=123)
i = FrequencyResponseAnalyzer('192.168.###.###', force_connect=False)
# Define output sweep parameters here for readability
f_start = 20e6 # Hz
f_end = 100 # Hz
sweep_length = 512
log_scale = True
amp_ch1 = 0.5 # Vpp
amp_ch2 = 0.5 # Vpp
averaging_time = 1e-6 # sec
settling_time = 1e-6 # sec
averaging_cycles = 1
settling_cycles = 1
try:
# Set the output sweep amplitudes
i.set_output(1, amp_ch1)
i.set_output(2, amp_ch2)
# Set the sweep configuration
i.set_sweep(start_frequency=f_start, stop_frequency=f_end,
num_points=sweep_length, averaging_time=averaging_time,
settling_time=settling_time, averaging_cycles=averaging_cycles,
settling_cycles=settling_cycles)
# Start the output sweep in loop mode
i.start_sweep()
# Set up the amplitude plot
plt.subplot(211)
if log_scale:
# Plot log x-axis if frequency sweep scale is logarithmic
line1, = plt.semilogx([])
line2, = plt.semilogx([])
else:
line1, = plt.plot([])
line2, = plt.plot([])
ax_1 = plt.gca()
ax_1.set_xlabel('Frequency (Hz)')
ax_1.set_ylabel('Magnitude (dB)')
# Set up the phase plot
plt.subplot(212)
if log_scale:
line3, = plt.semilogx([])
line4, = plt.semilogx([])
else:
line3, = plt.plot([])
line4, = plt.plot([])
ax_2 = plt.gca()
ax_2.set_xlabel('Frequency (Hz)')
ax_2.set_ylabel('Phase (Cycles)')
plt.ion()
plt.show()
plt.grid(visible=True)
# Retrieves and plot new data
while True:
frame = i.get_data()
ch1Data = frame['ch1']
ch2Data = frame['ch2']
# Set the frame data for each channel plot
plt.subplot(211)
ch1MagnitudeData = ch1Data['magnitude']
ch2MagnitudeData = ch2Data['magnitude']
line1.set_ydata(ch1MagnitudeData)
line2.set_ydata(ch2MagnitudeData)
line1.set_xdata(ch1Data['frequency'])
line2.set_xdata(ch2Data['frequency'])
# Phase
plt.subplot(212)
ch1PhaseData = ch1Data['phase']
ch2PhaseData = ch2Data['phase']
line3.set_ydata(ch1PhaseData)
line4.set_ydata(ch2PhaseData)
line3.set_xdata(ch1Data['frequency'])
line4.set_xdata(ch2Data['frequency'])
# Ensure the frequency axis is a tight fit
ax_1.set_xlim(min(ch1Data['frequency']), max(ch2Data['frequency']))
ax_2.set_xlim(min(ch1Data['frequency']), max(ch2Data['frequency']))
ax_1.relim()
ax_1.autoscale_view()
ax_2.relim()
ax_2.autoscale_view()
# Redraw the lines
plt.draw()
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Laser Lock Box
# laser_lock_box_basic.py
This example demonstrates how you can configure the Laser Lock Box Instrument and monitor the signals at Input 1 and Input 2.
#
# moku example: Basic Laser Lock Box
#
# This example demonstrates how you can configure the Laser Lock Box
# Instrument and monitor the signals at Input 1 and Input 2.
# (c) 2022 Liquid Instruments Pty. Ltd.
#
from moku.instruments import LaserLockBox
# Connect to your Moku by its ip address using LaserLockBox('192.168.###.###')
# or by its serial number using LaserLockBox(serial=123)
i = LaserLockBox('192.168.xxx.xxx', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', gain='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm', gain='-20dB')
# Configure the scan oscillator to a 10 Hz 500 mVpp positive ramp
# signal from Output 1
i.set_scan_oscillator(enable=True, shape='PositiveRamp',
frequency=10, amplitude=0.5, output='Output1')
# Configure the demodulation signal to Local oscillator with 1 MHz and
# 0 degrees phase shift
i.set_demodulation('Internal', frequency=1e6, phase=0)
# Configure a 4th order low pass filter with 100 kHz corner frequency
i.set_filter(shape='Lowpass', low_corner=100e3, order=4)
# Set the fast PID controller to -10 dB proportional gain and
# integrator crossover frequency at 3 kHz
i.set_pid_by_frequency(1, -10, int_crossover=3e3)
# Set the slow PID controller to -10 dB proportional gain and
# integrator crossover frequency at 50 Hz
i.set_pid_by_frequency(2, -10, int_crossover=50)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# laser_lock_box_plotting.py
This example demonstrates how you can configure the Laser Lock Box Instrument and monitor the signals at Input 1 and Input 2.
#
# moku example: Plotting Laser Lock Box
#
# This example demonstrates how you can configure the Laser Lock Box
# Instrument and monitor the signals at Input 1 and Input 2.
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import LaserLockBox
# Connect to your Moku by its ip address using LaserLockBox('192.168.###.###')
# or by its serial number using LaserLockBox(serial=123)
i = LaserLockBox('192.168.xxx.xxx', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', gain='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm', gain='-20dB')
# Configure the scan oscillator to a 10 Hz 500 mVpp positive ramp
# signal from Output 1
i.set_scan_oscillator(enable=True, shape='PositiveRamp',
frequency=10, amplitude=0.5, output='Output1')
# Configure the demodulation signal to Local oscillator with 1 MHz and
# 0 degrees phase shift
i.set_demodulation('Internal', frequency=1e6, phase=0)
# Configure a 4th order low pass filter with 100 kHz corner frequency
i.set_filter(shape='Lowpass', low_corner=100e3, order=4)
# Set the fast PID controller to -10 dB proportional gain and
# integrator crossover frequency at 3 kHz
i.set_pid_by_frequency(1, -10, int_crossover=3e3)
# Set the slow PID controller to -10 dB proportional gain and
# integrator crossover frequency at 50 Hz
i.set_pid_by_frequency(2, -10, int_crossover=50)
# Enable the output channels
i.set_output(1, True, True)
i.set_output(2, True, True)
# Set up signal monitoring
# Configure monitor points to Input 1 and Input2
i.set_monitor(1, 'Input1')
i.set_monitor(2, 'Input2')
# Configure the trigger conditions
# Trigger on Probe A, rising edge, 0V
i.set_trigger(type='Edge', source='ProbeA', level=0)
# View +- 1 ms i.e. trigger in the centre
i.set_timebase(-1e-3, 1e-3)
# Get initial data frame to set up plotting parameters. This can be done
# once if we know that the axes aren't going to change (otherwise we'd do
# this in the loop)
data = i.get_data()
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
plt.xlim([data['time'][0], data['time'][-1]])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Lock-in Amplifier
# lock_in_amplifier_basic.py
This example demonstrates how you can configure the Lock-in Amplifier instrument to demodulate an input signal from Input 1 with the reference signal from the Local Oscillator to extract the X component and generate a sine wave on the auxiliary output
#
# moku example: Basic Lock-in Amplifier
#
# This example demonstrates how you can configure the Lock-in Amplifier
# instrument to demodulate an input signal from Input 1 with the reference
# signal from the Local Oscillator to extract the X component and generate
# a sine wave on the auxiliary output
# (c) 2022 Liquid Instruments Pty. Ltd.
#
from moku.instruments import LockInAmp
# Connect to your Moku by its ip address using LockInAmp('192.168.###.###')
# or by its serial number using LockInAmp(serial=123)
i = LockInAmp('192.168.xxx.xxx', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', attenuation='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm', attenuation='0dB')
# Configure the demodulation signal to Local oscillator with 1 MHz and
# 0 degrees phase shift
i.set_demodulation('Internal', frequency=1e6, phase=0)
# Set low pass filter to 1 kHz corner frequency with 6 dB/octave slope
i.set_filter(1e3, slope='Slope6dB')
# Configure output signals
# X component to Output 1
# Aux oscillator signal to Output 2 at 1 MHz 500 mVpp
i.set_outputs('X', 'Aux')
i.set_aux_output(1e6, 0.5)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# lock_in_amplifier_plotting.py
This example demonstrates how you can configure the Lock-in Amplifier instrument to demodulate an input signal from Input 1 with the reference signal from the Local Oscillator to extract the X component and generate a sine wave on the auxiliary output
#
# moku example: Plotting Lock-in Amplifier
#
# This example demonstrates how you can configure the Lock-in Amplifier
# instrument to demodulate an input signal from Input 1 with the reference
# signal from the Local Oscillator to extract the X component and generate
# a sine wave on the auxiliary output
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import LockInAmp
# Connect to your Moku by its ip address using LockInAmp('192.168.###.###')
# or by its serial number using LockInAmp(serial=123)
i = LockInAmp('192.168.xxx.xxx', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', attenuation='0dB')
i.set_frontend(2, coupling='DC', impedance='1MOhm', attenuation='-20dB')
# Configure the demodulation signal to Local oscillator with 1 MHz and
# 0 degrees phase shift
i.set_demodulation('Internal', frequency=1e6, phase=0)
# Set low pass filter to 1 kHz corner frequency with 6 dB/octave slope
i.set_filter(1e3, slope='Slope6dB')
# Configure output signals
# X component to Output 1
# Aux oscillator signal to Output 2 at 1 MHz 500 mVpp
i.set_outputs('X', 'Aux')
i.set_aux_output(1e6, 0.5)
# Set up signal monitoring
# Configure monitor points to Input 1 and main output
i.set_monitor(1, 'Input1')
i.set_monitor(2, 'MainOutput')
# Configure the trigger conditions
# Trigger on Probe A, rising edge, 0V
i.set_trigger(type='Edge', source='ProbeA', level=0)
# View +- 1 ms i.e. trigger in the centre
i.set_timebase(-1e-3, 1e-3)
# Get initial data frame to set up plotting parameters. This can be done
# once if we know that the axes aren't going to change (otherwise we'd do
# this in the loop)
data = i.get_data()
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
plt.xlim([data['time'][0], data['time'][-1]])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Logic Analyzer
# logic_analyzer_plotting.py
This example demonstrates how you can configure the Logic Analyzer instrument to retrieve a single frame of data for all 16 channels
#
# moku example: Basic Logic Analyzer
#
# This example demonstrates how to use Pattern Generator in
# Logic Analyzer and generate and observe patterns on DIO pins.
#
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import LogicAnalyzer
# Connect to your Moku by its ip address using
# LogicAnalyzer('192.168.###.###')
# or by its serial number using LogicAnalyzer(serial=123)
i = LogicAnalyzer('192.168.###.###')
try:
patterns = [{"pin": 1, "pattern": [1] * 1024}, # logic high
{"pin": 2, "pattern": [0] * 1024}, # logic low
{"pin": 3, "pattern": [0, 1] * 512},
{"pin": 4, "pattern": [1, 0] * 512}]
i.set_pattern_generator(1, patterns=patterns, divider=8)
i.set_pin_mode(pin=1, state="PG1")
i.set_pin_mode(pin=2, state="PG1")
i.set_pin_mode(pin=3, state="PG1")
i.set_pin_mode(pin=4, state="PG1")
data = i.get_data(wait_reacquire=True, include_pins=[1, 2, 3, 4])
pin1, = plt.step(data["time"], data["pin1"])
pin2, = plt.step(data["time"], [i + 2 for i in data["pin2"]])
pin3, = plt.step(data["time"], [i + 4 for i in data["pin3"]])
pin4, = plt.step(data["time"], [i + 6 for i in data["pin4"]])
plt.ion()
plt.show()
plt.grid(True)
plt.ylim([-1, 8])
plt.yticks([0, 2, 4, 6], labels=["Pin1", "Pin2", "Pin3", "Pin4"])
while True:
data = i.get_data(wait_reacquire=True,
include_pins=[1, 2, 3, 4])
pin1.set_xdata(data["time"])
pin2.set_xdata(data["time"])
pin3.set_xdata(data["time"])
pin4.set_xdata(data["time"])
pin1.set_ydata(data["pin1"])
pin2.set_ydata([i + 2 for i in data["pin2"]])
pin3.set_ydata([i + 4 for i in data["pin3"]])
pin4.set_ydata([i + 6 for i in data["pin4"]])
plt.pause(0.001)
except Exception as e:
raise e
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Multi-instrument Mode
# mim_wg_osc.py
Multi-instrument Mode on Moku:Go (two-slot), deploying the Waveform Generator and Oscilloscope at once. This example is easily ported to Moku:Pro by changing the "platform_id" to one supported by that hardware.
import matplotlib.pyplot as plt
from moku.instruments import MultiInstrument
from moku.instruments import Oscilloscope, WaveformGenerator
m = MultiInstrument('192.168.###.###', platform_id=2)
try:
wg = m.set_instrument(1, WaveformGenerator)
osc = m.set_instrument(2, Oscilloscope)
connections = [dict(source="Input1", destination="Slot1InA"),
dict(source="Slot1OutA", destination="Slot2InA"),
dict(source="Slot1OutA", destination="Slot2InB"),
dict(source="Slot2OutA", destination="Output1")]
print(m.set_connections(connections=connections))
wg.generate_waveform(1, "Sine")
osc.set_timebase(-5e-3, 5e-3)
data = osc.get_data()
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
plt.xlim([data['time'][0], data['time'][-1]])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = osc.get_data()
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
raise e
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
m.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# mim_wg_sa.py
Multi-instrument Mode on Moku:Go (two slot), deploying the Waveform Generator and Spectrum Analyzer at once. This example is easily ported to Moku:Pro by changing the "platform_id" to one supported by that hardware.
import matplotlib.pyplot as plt
from moku.instruments import MultiInstrument
from moku.instruments import SpectrumAnalyzer, WaveformGenerator
m = MultiInstrument("192.168.###.###", platform_id=2)
try:
w = m.set_instrument(1, WaveformGenerator)
s = m.set_instrument(2, SpectrumAnalyzer)
connections = [dict(source="Input1", destination="Slot1InA"),
dict(source="Slot1OutA", destination="Slot2InA")]
print(m.set_connections(connections=connections))
w.generate_waveform(1, "Sine", frequency=10e5)
s.set_span(frequency1=0, frequency2=10e5)
s.set_rbw('Auto')
line1, = plt.plot([])
plt.ion()
plt.show()
plt.grid(visible=True)
plt.autoscale(axis='x', tight=True)
# Get an initial frame of data to set any frame-specific plot parameters
frame = s.get_data()
# Format the x-axis as a frequency scale
ax = plt.gca()
# Get and update the plot with new data
while True:
frame = s.get_data()
# Set the frame data for each channel plot
line1.set_ydata(frame['ch1'])
# Frequency axis shouldn't change, but to be sure
line1.set_xdata(frame['frequency'])
# Ensure the frequency axis is a tight fit
ax.relim()
ax.autoscale_view()
# Redraw the lines
plt.draw()
plt.pause(0.001)
except Exception as e:
raise e
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
m.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Oscilloscope
# oscilloscope_basic.py
This script demonstrates how to use the Oscilloscope instrument to retrieve a single frame of dual-channel voltage data.
#
# moku example: Basic Oscilloscope
#
# This script demonstrates how to use the Oscilloscope instrument
# to retrieve a single frame of dual-channel voltage data.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import Oscilloscope
# Connect to your Moku by its ip address using Oscilloscope('192.168.###.###')
# or by its serial number using Oscilloscope(serial=123)
i = Oscilloscope('192.168.###.###', force_connect=False)
try:
# Set the span to from -1ms to 1ms i.e. trigger point centred
i.set_timebase(-1e-3, 1e-3)
# Get and print a single frame of data (time series
# of voltage per channel)
data = i.get_data()
print(data['ch1'], data['ch2'], data['time'])
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# oscilloscope_plotting.py
This example demonstrates how you can configure the Oscilloscope instrument, and view triggered time-voltage data frames in real-time.
#
# moku example: Plotting Oscilloscope
#
# This example demonstrates how you can configure the Oscilloscope instrument,
# and view triggered time-voltage data frames in real-time.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import Oscilloscope
# Connect to your Moku by its ip address using Oscilloscope('192.168.###.###')
# or by its serial number using Oscilloscope(serial=123)
i = Oscilloscope('192.168.###.###', force_connect=False)
try:
# Trigger on input Channel 1, rising edge, 0V
i.set_trigger(type='Edge', source='Input1', level=0)
# View +-5usec, i.e. trigger in the centre
i.set_timebase(-5e-6, 5e-6)
# Generate an output sine wave on Channel 1, 1Vpp, 1MHz, 0V offset
i.generate_waveform(1, 'Sine', amplitude=1, frequency=1e6)
# Set the data source of Channel 1 to be Input 1
i.set_source(1, 'Input1')
# Set the data source of Channel 2 to the generated output sinewave
i.set_source(2, 'Input2')
# Get initial data frame to set up plotting parameters. This can be done
# once if we know that the axes aren't going to change (otherwise we'd do
# this in the loop)
data = i.get_data()
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
plt.xlim([data['time'][0], data['time'][-1]])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Phasemeter
# phasemeter_basic.py
This example demonstrates how you can configure the Phasemeter instrument to measure 4 independent signals.
#
# moku example: Basic Phasemeter
#
# This example demonstrates how you can configure the Phasemeter
# instrument to measure 4 independent signals.
# (c) 2022 Liquid Instruments Pty. Ltd.
#
from moku.instruments import Phasemeter
# Connect to your Moku by its ip address using Phasemeter('192.168.###.###')
# or by its serial number using Phasemeter(serial=123)
i = Phasemeter('192.168.###.###', force_connect=False)
try:
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 400 mVpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', range='400mVpp')
i.set_frontend(2, coupling='DC', impedance='1MOhm', range='400mVpp')
i.set_frontend(3, coupling='DC', impedance='1MOhm', range='400mVpp')
i.set_frontend(4, coupling='DC', impedance='1MOhm', range='400mVpp')
# Configure Output channel 1 to generate sine waves at 1 Vpp, 2 MHz
i.generate_output(1, 'Sine', amplitude=1, frequency=2e6)
# Configure Output channel 2 to be phase locked to Input 2 signal at an
# amplitude of 0.5 Vpp
i.generate_output(2, 'Sine', amplitude=0.5, phase_locked=True)
# Configure Output channel 3 and 4 to generate measured phase at a
# scaling of 1 V/cycle and 10 V/cycle respectively
i.generate_output(3, 'Phase', scaling=1)
i.generate_output(4, 'Phase', scaling=10)
# Set the acquisition speed to 596Hz for all channels
i.set_acquisition_speed('596Hz')
# Set all input channels to 2 MHz, bandwidth 100 Hz
i.set_pm_loop(1, auto_acquire=False, frequency=2e6, bandwidth='100Hz')
i.set_pm_loop(2, auto_acquire=False, frequency=2e6, bandwidth='100Hz')
i.set_pm_loop(3, auto_acquire=False, frequency=2e6, bandwidth='100Hz')
i.set_pm_loop(4, auto_acquire=False, frequency=2e6, bandwidth='100Hz')
# Get all the data available from the Moku
data = i.get_data()
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# PID Controller
# pidcontroller_basic.py
This script demonstrates how to configure one of the two PID Controllers in the PID Controller instrument. Configuration is done by specifying frequency response characteristics of the controller.
# moku example: Basic PID Controller
#
# This script demonstrates how to configure one of the two PID Controllers
# in the PID Controller instrument. Configuration is done by specifying
# frequency response characteristics of the controller.
#
# (c) 2022 Liquid Instruments Pty. Ltd.
#
from moku.instruments import PIDController
# Connect to your Moku by its ip address using PIDController('192.168.###.###')
# or by its serial number using PIDController(serial=123)
i = PIDController('192.168.###.###', force_connect=False)
try:
# Configures the control matrix:
# Channel 1: input 1 gain = 1 dB, input 2 gain = 0 dB
# Channel 2: input 2 gain = 0 dB, input 2 gain = 1 dB
i.set_control_matrix(channel=1, input_gain1=1, input_gain2=0)
i.set_control_matrix(channel=2, input_gain1=0, input_gain2=1)
# Configure PID Control loop 1 using frequency response characteristics
# P = -10dB
# I Crossover = 100Hz
# D Crossover = 10kHz
# I Saturation = 10dB
# D Saturation = 10dB
# Double-I = OFF
i.set_by_frequency(channel=1, prop_gain=-10, int_crossover=1e2,
diff_crossover=1e4, int_saturation=10,
diff_saturation=10)
# Configure PID Control loop 2 using gain
# Proportional gain = 10
# Differentiator gain = -5
# Differentiator gain corner = 5 kHz
i.set_by_gain(channel=2, overall_gain=0, prop_gain=10, diff_gain=-5,
diff_corner=5e3)
# Enable the outputs of the PID controller
i.enable_output(1, signal=True, output=True)
i.enable_output(2, signal=True, output=True)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# pidcontroller_plotting.py
This script demonstrates how to configure both PID Controllers in the PID Controller instrument. Configuration on the Channel 1 PID is done by specifying frequency response characteristics, while Channel 2 specifies the gain characteristics.
The output response of each PID Controller channel is plotted in real-time.
# moku example: PID Controller Plotting Example
#
# This script demonstrates how to configure both PID Controllers
# in the PID Controller instrument. Configuration on the Channel 1
# PID is done by specifying frequency response characteristics,
# while Channel 2 specifies the gain characteristics.
#
# The output response of each PID Controller channel is plotted
# in real-time.
#
# (c) 2022 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
from moku.instruments import PIDController
# Connect to your Moku by its ip address using PIDController('192.168.###.###')
# or by its serial number using PIDController(serial=123)
i = PIDController('192.168.###.###', force_connect=False)
try:
# Configures the control matrix:
# Channel 1: input 1 gain = 1 dB, input 2 gain = 0 dB
# Channel 2: input 2 gain = 0 dB, input 2 gain = 1 dB
i.set_control_matrix(channel=1, input_gain1=1, input_gain2=0)
i.set_control_matrix(channel=2, input_gain1=0, input_gain2=1)
# Configure the Channel 1 PID Controller using frequency response
# characteristics
# P = -10dB
# I Crossover = 100Hz
# D Crossover = 10kHz
# I Saturation = 10dB
# D Saturation = 10dB
# Double-I = OFF
# Note that gains must be converted from dB first
i.set_by_frequency(channel=1, prop_gain=-10, int_crossover=1e2,
diff_crossover=1e4, int_saturation=10,
diff_saturation=10)
# Configure the Channel 2 PID Controller using gain characteristics
# Overall Gain = 6dB
# I Gain = 20dB
i.set_by_gain(channel=2, overall_gain=6.0, prop_gain=20)
# Set the probes to monitor Output 1 and Output 2
i.set_monitor(1, 'Output1')
i.set_monitor(2, 'Output2')
# Set the timebase
i.set_timebase(-1e-3, 1e-3) # +- 1ms
i.set_trigger(type='Edge', source='ProbeA', level=0)
# Enable the output channels of the PID controller
i.enable_output(1, True, True)
i.enable_output(2, True, True)
# Get initial data frame to set up plotting parameters. This can be done
# once if we know that the axes aren't going to change (otherwise we'd do
# this in the loop)
data = i.get_data()
# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-1, 1])
plt.xlim([data['time'][0], data['time'][-1]])
line1, = plt.plot([])
line2, = plt.plot([])
# Configure labels for axes
ax = plt.gca()
# This loops continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
# Update the plot
line1.set_ydata(data['ch1'])
line2.set_ydata(data['ch2'])
line1.set_xdata(data['time'])
line2.set_xdata(data['time'])
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Programmable Power Supplies
# powersupply_basic.py
This example will demonstrate how to configure the power supply units of the Moku:Go.
#
# moku example: Basic Programmable Power Supply Unit
#
# This example will demonstrate how to configure the power supply
# units of the Moku:Go.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import Oscilloscope
# Connect to your Moku by its ip address using Oscilloscope('192.168.###.###')
# or by its serial number using Oscilloscope(serial=123)
# An instrument must be deployed to establish the connection with the
# Moku, in this example we will use the Oscilloscope.
i = Oscilloscope('192.168.xxx.xxx', force_connect=False)
try:
# Configure Power Supply Unit 1 to 2 V and 0.1 A
i.set_power_supply(1,enable=True,voltage=2, current=0.1)
# Read the current status of Power Supply Unit 1
print(i.get_power_supply(1))
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Spectrum Analyzer
# spectrumanalyzer_basic.py
This example demonstrates how you can use the Spectrum Analyzer instrument to to retrieve a single spectrum data frame over a set frequency span.
#
# moku example: Basic Spectrum Analyzer
#
# This example demonstrates how you can use the Spectrum Analyzer instrument to
# to retrieve a single spectrum data frame over a set frequency span.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import SpectrumAnalyzer
# Connect to your Moku by its ip address using SpectrumAnalyzer('192.168.###.###')
# or by its serial number using SpectrumAnalyzer(serial=123)
i = SpectrumAnalyzer('192.168.###.###', force_connect=False)
# Deploy the Spectrum Analyzer to your Moku
try:
# Configure the Spectrum Analyzer
i.set_span(0, 10e6)
i.set_rbw('Auto') # Auto-mode
# Get the scan results and print them out (power vs frequency,
# two channels)
data = i.get_data()
print(data['ch1'], data['ch2'], data['frequency'])
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# spectrumanalyzer_plotting.py
This example demonstrates how you can configure the Spectrum Analyzer instrument and plot its spectrum data in real-time.
#
# moku example: Plotting Spectrum Analyzer
#
# This example demonstrates how you can configure the Spectrum Analyzer
# instrument and plot its spectrum data in real-time.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
import logging
import matplotlib.pyplot as plt
from moku.instruments import SpectrumAnalyzer
logging.basicConfig(format='%(asctime)s:%(name)s:%(levelname)s::%(message)s')
logging.getLogger('moku_client').setLevel(logging.INFO)
# Connect to your Moku by its ip address using SpectrumAnalyzer('192.168.###.###')
# or by its serial number using SpectrumAnalyzer(serial=123)
i = SpectrumAnalyzer('192.168.###.###', force_connect=False)
try:
# Configure the Spectrum Analyzer
i.set_span(frequency1=0, frequency2=30e3)
i.disable_output(1)
i.set_rbw('Auto') # Auto-mode
# Configure ADC inputs
i.set_frontend(1, impedance='1MOhm', coupling='DC', range='10Vpp')
i.set_frontend(2, impedance='1MOhm', coupling='DC', range='10Vpp')
# Set up basic plot configurations
line1, = plt.plot([])
line2, = plt.plot([])
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([-120, 20])
plt.autoscale(axis='x', tight=True)
# Get an initial frame of data to set any frame-specific plot parameters
frame = i.get_data()
# Format the x-axis as a frequency scale
ax = plt.gca()
# Get and update the plot with new data
while True:
frame = i.get_data()
# Set the frame data for each channel plot
line1.set_ydata(frame['ch1'])
line2.set_ydata(frame['ch2'])
# Frequency axis shouldn't change, but to be sure
line1.set_xdata(frame['frequency'])
line2.set_xdata(frame['frequency'])
# Ensure the frequency axis is a tight fit
ax.relim()
ax.autoscale_view()
# Redraw the lines
plt.draw()
plt.pause(0.001)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Waveform Generator
# waveformgenerator_basic.py
This example demonstrates how you can use the Waveform Generator instrument to generate a sinewave on Channel 1 and a square wave on Channel 2.
#
# moku example: Waveform Generator Basic
#
# This example demonstrates how you can use the Waveform Generator
# instrument to generate a sinewave on Channel 1 and a squarewave on Channel 2.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import WaveformGenerator
# Connect to your Moku by its ip WaveformGenerator('192.168.###.###')
# or by its serial m = WaveformGenerator(serial=123)
i = WaveformGenerator('192.168.###.###', force_connect=False)
try:
# Generate a sine wave on channel 1, 0.5 Vpp, 5 kHz
# Generate a square wave on channel 2, 1 Vpp, 1 kHz, 50% duty cycle
i.generate_waveform(channel=1, type='Sine', amplitude=0.5, frequency=5e3)
i.generate_waveform(channel=2, type='Square', amplitude=1.0, frequency=1e3, duty=50)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# waveformgenerator_modulation.py
This example demonstrates how you can use the Waveform Generator instrument to generate an amplitude modulated sine wave on Channel 1, and a sweep modulated sine wave on Channel 2.
#
# moku example: Waveform Generator Modulation
#
# This example demonstrates how you can use the Waveform Generator instrument
# to generate an amplitude modulated sine wave on Channel 1, and a sweep
# modulated sine wave on Channel 2.
#
# (c) 2021 Liquid Instruments Pty. Ltd.
#
from moku.instruments import WaveformGenerator
# Connect to your Moku by its ip address using WaveformGenerator('192.168.###.###')
# or by its serial number using WaveformGenerator(serial=123)
i = WaveformGenerator('192.168.###.###', force_connect=False)
try:
# Generate a sine wave on channel 1, 0.5 Vpp, 5 kHz
# Generate a sine wave on channel 2, 1 Vpp, 1 MHz
i.generate_waveform(channel=1, type='Sine', amplitude=0.5, frequency=5e3)
i.generate_waveform(channel=2, type='Sine', amplitude=1.0, frequency=1e6)
# Configure amplitude modulation on channel 1.
# Use internal reference as modulation source, modulation depth 50%,
# modulated at a frequency of 1Hz
i.set_modulation(channel=1, type='Amplitude', source='Internal', depth=50,
frequency=1)
# Configure Channel 2 with sweep trigger modulation.
# Use Input 1 as trigger source, trigger level is 0.1 V.
# Start the sweep at waveform frequency 1 MHz and stop at 10 Hz, each sweep is 3 seconds.
i.set_sweep_mode(channel=2, source='Input1', stop_frequency=10.0,
sweep_time=3.0, trigger_level=0.1)
except Exception as e:
print(f'Exception occurred: {e}')
finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
i.relinquish_ownership()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
← sync_phase Overview →