How to change the phase of the demodulation signal in Pymoku Lock-In Amplifier

Moku:Lab Lock-In Amplifier uses dual-phase demodulation to determine the X and Y components of a signal. The phase of the demodulation signal can be shifted in Pymoku by adjusting the demodulation signal properties.

This example demonstrates how the demodulation signal can be adjusted.

from pymoku import Moku
from pymoku.instruments import LockInAmp
import statistics
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

# Connect to your Moku by its device name
# Alternatively, use Moku.get_by_serial('#####') or Moku('192.168.###.###')
m = Moku.get_by_name('Moku')

try:
# Locks to external reference 10 MHz clock
i = m.deploy_or_connect(LockInAmp,set_default=True, use_external=True)

# Output a 1MHz sine wave but demodulate at a harmonic (2MHz)
i.set_demodulation('internal', 1e6)
# i.set_lo_output(1.0, 1e6, 0)
i.set_filter(100, 2)

# Output the 'X' (I) signal and the local-oscillator sine wave on the two
# DAC channels. Configure a PID controller on the main 'X' output with
# a proportional gain of 10x, integrator cross-over of 10Hz and integrator
# saturation at 100x
i.set_outputs('X', 'sine')
# i.set_pid_by_frequency('main', kp=10, i_xover=10, si=100)

# Monitor the I and Q signals from the mixer, before filtering
i.set_monitor('A', 'in1')
i.set_monitor('B', 'main')

# Trigger on Monitor 'B' ('Q' signal), rising edge, 0V with 0.1V hysteresis
i.set_trigger('B', 'rising', 0)

# View +- 0.1 second, i.e. trigger in the centre
i.set_timebase(-2e-6, 2e-6)

# 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_realtime_data()

# Set up the plotting parameters
plt.ion()
plt.show()
plt.grid(b=True)
plt.ylim([-0.1, 0.1])
plt.xlim([data.time[0], data.time[-1]])

line1, = plt.plot([])
line2, = plt.plot([])

# Configure labels for axes
ax = plt.gca()
ax.xaxis.set_major_formatter(FuncFormatter(data.get_xaxis_fmt))
ax.yaxis.set_major_formatter(FuncFormatter(data.get_yaxis_fmt))
ax.fmt_xdata = data.get_xcoord_fmt
ax.fmt_ydata = data.get_ycoord_fmt

plt.pause(1)

# This loops through a phase range of 0 to 350 degrees with a step size of 10
for a in range(0, 350, 10):

# Set a demodulation phase
i.phase_demod = a
i.commit()

# get a frame of data
data = i.get_realtime_data()

# print out the demodulation phase and mean value of the output
print(f'New Phase?{i.phase_demod}')
print(f'Mean {statistics.mean(data.ch2)}')
# Update the Plotting
line1.set_ydata(data.ch1)
line2.set_ydata(data.ch2)
line1.set_xdata(data.time)
line2.set_xdata(data.time)
plt.pause(1)


finally:
# Close the connection to the Moku device
# This ensures network resources and released correctly
m.close()