# 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
# digital_filter_box_plotting.py
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
# Neural Network
# neuralnetwork_simplesine.py
This script demonstrates how to use the Neural Network instrument to generate a ramp wave and process it through the uploaded neural network, finally viewing the output in the oscilloscope. This uses the network generated in the Simple Sine wave example (opens new window)
#
# moku example: Neural Network
#
# This script demonstrates how to use the Neural Network instrument to generate
# a ramp wave and process it through the uploaded neural network, finally
# viewing the output in the oscilloscope. This uses the network generated
# in the Simple Sine wave example.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
import matplotlib.pyplot as plt
from moku.instruments import MultiInstrument
from moku.instruments import WaveformGenerator, NeuralNetwork, Oscilloscope
m = MultiInstrument('10.1.XXX.XXX', platform_id=4)
try:
# Set up MiM configuration
wg = m.set_instrument(1, WaveformGenerator)
nn = m.set_instrument(2, NeuralNetwork)
osc = m.set_instrument(3, Oscilloscope)
connections = [dict(source="Slot1OutA", destination="Slot2InA"),
dict(source="Slot1OutA", destination="Slot2InB"),
dict(source="Slot1OutB", destination="Slot2InC"),
dict(source="Slot1OutB", destination="Slot2InD"),
dict(source="Slot2OutA", destination="Slot3InA")]
print(m.set_connections(connections=connections))
# Generate ramp wave in Waveform Generator
wg.generate_waveform(channel=1, type='Ramp', amplitude=0.25, frequency=5e3, symmetry=100)
print(wg.summary())
# Load network into Neural Network and set inputs and outputs
nn.set_input(strict=False, channel=1, low_level=-1, high_level=1)
nn.set_input_sample_rate(sample_rate=305000)
nn.upload_network("/path/to/simple_sine_model.linn")
nn.set_output(strict=False, channel=1, enabled=True, low_level=-1, high_level=1)
print(nn.summary())
# Set up Oscilloscope for plotting
osc.set_timebase(-5e-3, 5e-3)
data = osc.get_data()
print(osc.summary())
# 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]])
line, = 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
line.set_ydata(data['ch1'])
line.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 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
# phasemeter_plotting.py
This example demonstrates how you can configure the Phasemeter instrument to measure 2 independent signals and display the results in real-time.
#
# moku example: Plotting Phasemeter
#
# This example demonstrates how you can configure the Phasemeter instrument
# and collect live samples from it's output.
# The signal amplitude is calculated using these samples, and plotted for
# real-time viewing.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
from moku.instruments import Phasemeter
import matplotlib.pyplot as plt
from time import time
import numpy as np
# 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=True)
try:
# Set samplerate to 37 Hz/s
i.set_acquisition_speed(speed="37Hz")
# Set Channel 1 and 2 to DC coupled, 1 MOhm impedance, and 4Vpp range
i.set_frontend(1, coupling="DC", impedance="1MOhm", range="4Vpp")
i.set_frontend(2, coupling="DC", impedance="1MOhm", range="4Vpp")
# Configure output channel 1 to generate sine waves at 0.5Vpp, 5 MHz
i.generate_output(1, "Sine", amplitude=0.5, frequency=5e6)
# Configure output channel 2 to generate sine waves at 1Vpp, 10 MHz
i.generate_output(2, "Sine", amplitude=1, frequency=10e6)
# Get auto acquired frequency for channel 1 and 2
i.get_auto_acquired_frequency(channel=1)
i.get_auto_acquired_frequency(channel=2)
# Get initial data frame to set plot bounds
data = i.get_data()
# Set plot bounds
plt.ion()
plt.show()
plt.grid(True)
plt.ylabel("Amplitude (Vrms)")
plt.xlabel("Time (s)")
plt.xlim((-20, 0))
(line1,) = plt.plot([])
(line2,) = plt.plot([])
timestamps = []
ydata1 = []
ydata2 = []
# Configure labels for axes
ax = plt.gca()
# This loop continuously updates the plot with new data
while True:
# Get new data
data = i.get_data()
# Update the x- to mimic the Moku App traces
# Append the current timestamp then normalize by the current time
# so that now is t = 0s
t_now = time()
timestamps += [t_now]
xdata = np.array(timestamps) - t_now
# Update the plot
ydata1 += [data["ch1"]["amplitude"]]
ydata2 += [data["ch2"]["amplitude"]]
line1.set_ydata(ydata1)
line2.set_ydata(ydata2)
line1.set_xdata(xdata)
line2.set_xdata(xdata)
ax.relim()
ax.autoscale_view()
plt.pause(0.001)
plt.draw()
# Ensure data is maintained to a reasonable length of 1000 points
# This will cover more than the 20 second x-axis limit
timestamps = timestamps[-1000:]
ydata1 = ydata1[-1000:]
ydata2 = ydata2[-1000:]
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
93
94
# phasemeter_streaming.py
This example demonstrates how you can configure the Phasemeter instrument to measure a signal, stream and display the results.
#
# moku example: Phasemeter networking streaming
#
# This example starts a 30-second network stream of Channel 1 Phasemeter data
# and processes it live. The contents of each data sample are printed out,
# along with the signal amplitude which may be calculated as A = sqrt(I^2 + Q^2).
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
from moku.instruments import Phasemeter
import numpy as np
import matplotlib.pyplot as plt
# 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 samplerate to 150 Hz/s
i.set_acquisition_speed(speed='150Hz')
# Set channel 1 to DC coupled, 1 MOhm impedance, and 4Vpp range
i.set_frontend(1, coupling='DC', impedance='1MOhm', range='4Vpp')
# Set auto acquired frequency for channel 1
i.set_pm_loop(channel=1, auto_acquire=True, bandwidth='1kHz')
# Get auto acquired frequency for channel 1
i.get_auto_acquired_frequency(channel=1)
# Stop and existing streaming session and start a new one for 30s
i.stop_streaming()
i.start_streaming(duration=30)
# Set up the figure for plotting
plt.ion()
fig, axs = plt.subplots(3, 1, sharex=True)
plt.show()
for ax in axs:
ax.grid(True)
ax.set_xlim(0, 30)
(f_ax, a_ax, p_ax) = axs
f_ax.set_ylabel("Frequency (Hz)")
a_ax.set_ylabel("Amplitude (Vrms)")
p_ax.set_ylabel("Phase (cyc)")
p_ax.set_xlabel("Time (s)")
(line1,) = f_ax.plot([])
(line2,) = f_ax.plot([])
(line3,) = a_ax.plot([])
(line4,) = p_ax.plot([])
f_ax.legend(labels=("Frequency", "Set Frequency"), loc=1)
time_span = []
frequency = []
set_freq_ = []
amplitude = []
phase_cyc = []
# This loop continuously updates the plot with new data
while True:
# Get stream data
data = i.get_stream_data()
# Update the plot
time_span += data['time']
frequency += data['ch1_frequency']
set_freq_ += data['ch1_set_frequency']
amplitude += list(np.sqrt(np.array(data['ch1_i'])**2+np.array(data['ch1_q'])**2))
phase_cyc += data['ch1_phase']
line1.set_data(time_span, frequency)
line2.set_data(time_span, set_freq_)
line3.set_data(time_span, amplitude)
line4.set_data(time_span, phase_cyc)
for ax in axs:
ax.relim()
ax.autoscale_view()
plt.pause(0.01)
except Exception as e:
print(f'Exception Occurred: {e}')
plt.pause(2)
finally:
# Close the connection to the Moku device
# This ensures network resources are released correctly
i.stop_streaming()
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
# 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
# Time and Frequency Analyzer
# timefrequencyanalyzer_basic.py
This example demonstrates how you can use the Time and Frequency Analyzer instrument to to retrieve and view the statistics of the intervals.
#
# moku example: Plotting Time and Frequency Analyzer
#
# This example demonstrates how you can configure the Time and Frequency Analyzer
# instrument, and view the statistics of the intervals.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
from pprint import pprint
from moku.instruments import TimeFrequencyAnalyzer
# Connect to your Moku by its ip address using TimeFrequencyAnalyzer('192.168.###.###')
# or by its serial number using TimeFrequencyAnalyzer(serial=123)
i = TimeFrequencyAnalyzer('192.168.###.###', force_connect=True)
try:
# Set the event detectors
# Set Event A to detect rising edge events on Input 1 at 0V
# Set Event B to detect rising edge events on Input 2 at 0V
i.set_event_detector(1, 'Input1', threshold=0, edge='Rising')
i.set_event_detector(2, 'Input2', threshold=0, edge='Rising')
# Set the interpolation to Linear
i.set_interpolation(mode='Linear')
# Set acquisition mode to a 100ms Window
i.set_acquisition_mode(mode='Windowed', window_length=100e-3)
# Set the interval analyzers
# Set Interval A to start at Event A and stop at Event A
# Set Interval B to start at Event B and stop at Event B
i.set_interval_analyzer(1, start_event_id=1, stop_event_id=1)
i.set_interval_analyzer(2, start_event_id=2, stop_event_id=2)
# Get data and explore statistics
data = i.get_data()
print('Interval 1:')
pprint(data['interval1']['statistics'])
print('Interval 2:')
pprint(data['interval2']['statistics'])
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
# timefrequencyanalyzer_plotting.py
This example demonstrates how you can configure the Time and Frequency Analyzer instrument and plot histogram data frames in real-time.
#
# moku example: Plotting Time and Frequency Analyzer
#
# This example demonstrates how you can configure the Time and Frequency Analyzer
# instrument, and view histogram data frames in real-time.
#
# (c) 2024 Liquid Instruments Pty. Ltd.
#
import matplotlib.pyplot as plt
import numpy as np
from moku.instruments import TimeFrequencyAnalyzer
# Connect to your Moku by its ip address using TimeFrequencyAnalyzer('192.168.###.###')
# or by its serial number using TimeFrequencyAnalyzer(serial=123)
i = TimeFrequencyAnalyzer('192.168.###.###', force_connect=True)
try:
# Set the event detectors
# Set Event A to detect rising edge events on Input 1 at 0V
# Set Event B to detect rising edge events on Input 2 at 0V
i.set_event_detector(1, 'Input1', threshold=0, edge='Rising')
i.set_event_detector(2, 'Input2', threshold=0, edge='Rising')
# Set the interpolation to Linear
i.set_interpolation(mode='Linear')
# Set acquisition mode to a 100ms Window
i.set_acquisition_mode(mode='Windowed', window_length=100e-3)
# Set the histogram to 8ns span centred around 2us
i.set_histogram(start_time=1.996e-6, stop_time=2.004e-6)
# Set the interval analyzers
# Set Interval A to start at Event A and stop at Event A
# Set Interval B to start at Event B and stop at Event B
i.set_interval_analyzer(1, start_event_id=1, stop_event_id=1)
i.set_interval_analyzer(2, start_event_id=2, stop_event_id=2)
# 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
t0 = data['interval1']['histogram']['t0']
dt = data['interval1']['histogram']['dt']
length = 1024
x = np.linspace(start=t0, stop=t0 + dt*1023, num=1024)
plt.ion()
plt.show()
plt.grid(visible=True)
plt.ylim([0, 600])
plt.xlim([1.996e-6, 2.004e-6])
line1 = plt.bar(x, height=data['interval1']['histogram']['data'], width=dt, align='edge', alpha=0.8)
line2 = plt.bar(x, height=data['interval2']['histogram']['data'], width=dt, align='edge', alpha=0.8)
# 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
height1 = data['interval1']['histogram']['data']
height2 = data['interval2']['histogram']['data']
for count1, rect1, count2, rect2 in zip(height1, line1.patches, height2, line2.patches):
rect1.set_height(count1)
rect2.set_height(count2)
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
# 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
# waveformgenerator_triggered.py
This example demonstrates how you can use the Waveform Generator instrument to generate a gated sine wave on Channel 1, and a swept frequency square wave on Channel 2.
#
# moku example: Waveform Generator Triggering
#
# This example demonstrates how you can use the Waveform Generator instrument
# to generate a gated sine wave on Channel 1, and a swept frequency square wave
# on Channel 2.
#
# (c) 2024 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:
# Set sine wave to channel 1 and square wave to channel 2
i.generate_waveform(channel=1, type='Sine',
amplitude=1, frequency=10)
i.generate_waveform(channel=2, type='Square',
amplitude=1, frequency=500, duty=50)
# Activate burst trigger for output 1 and sweep trigger for output 2
i.set_burst_mode(channel=1, source='Internal', mode='Gated',
burst_period=2, trigger_level=0.5, burst_duration=0.1)
i.set_sweep_mode(channel=2, source='Internal', stop_frequency=10,
sweep_time=2, 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 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
← sync_phase Overview →