Phasemeter Instrument

The Phasemeter instrument is used to measure the amplitude and change in phase of periodic input signals. Using the auto-acquire feature, it can automatically lock to input frequencies in the range of 2-200MHz and track phase with a bandwidth of 10kHz.

The Phasemeter is different from other instruments in that its data is not presented in the form of frames; instead, it is supplied as a stream of samples which may be logged to a file or streamed live to pymoku over the network. Each data sample is presented as a sequence of measurements of the form:

( fs, f, count, phase, I, Q )

Where:

  • fs: set-point frequency of the PLL (Hz)
  • f: measured frequency of the input signal (Hz)
  • count: the index of this measurement (n)
  • phase: the measured phase of the input signal (cycles)
  • I: in-phase amplitude component (V)
  • Q: quadrature amplitude component (V)

Note

For the output phase measure of a channel to be valid, it’s tracking loop (PLL) must be “locked” to the input signal. A channel’s PLL is considered to be “locked” if the ratio I/Q is large. That is, Q ~ 0. Note that the exact ratio depends upon the SNR of your signal.

For logging data to a file, the data_log type functions should be used (see the phasemeter_basic.py example below). For networking streaming, the stream_data type functions should be used (see the realtime_phasemeter.py example script).

Example Usage

For an in-depth walkthrough on using the pymoku Phasemeter Instrument, see the pymoku Phasemeter tutorial. The following example code and a wide range of other pymoku demo scripts can be found at the pymoku Github repository.

phasemeter_basic.py
#
# pymoku example: Phasemeter data logging
#
# This example demonstrates how you can configure the Phasemeter instrument
# and log single-channel phase and [I,Q] data to a CSV file for a 10
# second duration.
#
# (c) 2019 Liquid Instruments Pty. Ltd.
#
from pymoku import Moku
from pymoku.instruments import Phasemeter
import time

# 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:
	# Deploy the new Phasemeter instrument to the Moku:Lab
	# Also, try to synchronise the Moku:Lab to an external 10MHz reference
	i = m.deploy_instrument(Phasemeter, use_external=True)

	# Set the Channel 1 seed frequency to 10MHz and a sample rate of ~30Hz
	i.set_initfreq(1, 10e6)
	i.set_samplerate('slow')

	# Restart the frequency-tracking loop on Channel 1
	i.reacquire(ch=1)

	# Stop an existing log, if any, then start a new one. 10 seconds of both channels to the
	# SD Card (rather than internal storage). Using CSV format.
	i.stop_data_log()
	i.start_data_log(duration=10, use_sd=True, ch1=True, ch2=False, filetype='csv')

	# Track progress percentage of the data logging session
	progress = 0
	while progress < 100:
		# 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.progress_data_log()
		print("Progress {}%".format(progress))

	# Upload the log file to the local directory
	i.upload_data_log()
	print("Uploaded log file to local directory.")

	# Denote that we are done with the data logging session so resources may be cleand up
	i.stop_data_log()

except StreamException as e:
	print("Error occured: %s" % e)
finally:
	m.close()

The Phasemeter Class

class pymoku.instruments.Phasemeter

Phasemeter instrument object.

To run a new Phasemeter instrument, this should be instantiated and deployed via a connected Moku object using deploy_instrument. Alternatively, a pre-configured instrument object can be obtained by discovering an already running Phasemeter instrument on a Moku:Lab device via discover_instrument.

__init__()

Create a new Phasemeter instrument, ready to be attached to a Moku.

type = "phasemeter"

Name of this instrument.

auto_acquire(*args, **kwargs)

Restarts the frequency tracking loop and phase counter for the specified channel, or both if no channel is specified. The initial frequency of the channel’s tracking loop is automatically acquired, ignoring the manually set seed frequency by set_initfreq.

To acquire using the manually set seed frequency, see reacquire.

Parameters:ch (int; {1,2}) – Channel number, or None for both
Raises:ValueError – If the channel number is invalid.
commit()

Apply all modified settings.

Note

If the autocommit feature has been turned off, this function can be used to manually apply any instrument settings to the Moku device. These instrument settings are those configured by calling all set_ and gen_ type functions. Manually calling this function allows you to atomically apply many instrument settings at once.

data_log_filename()

Returns the current base filename of the logging session.

The base filename doesn’t include the file extension as multiple files might be recorded simultaneously with different extensions.

Return type:str
Returns:The file name of the current, or most recent, log file.
gen_off(*args, **kwargs)

Turn Waveform Generator output(s) off.

The channel will be turned on when configuring the waveform type but can be turned off using this function. If ch is None (the default), both channels will be turned off, otherwise just the one specified by the argument.

Parameters:ch (int; {1,2} or None) – Channel to turn off or None for all channels
Raises:ValueOutOfRangeException – if the channel number is invalid
gen_sinewave(*args, **kwargs)

Generate a sinewave signal on the specified output channel

Parameters:
  • ch (int; {1,2}) – Channel number
  • amplitude (float; V) – Signal peak-to-peak amplitude
  • frequency (float; Hz) – Frequency
  • phase (float; degrees) – Phase
  • phase_locked (boolean) – Locks the phase of the generated sinewave to the measured phase of the input signal
Raises:
get_bandwidth(ch)

Get the bandwidth of the phasemeter.

Parameters:ch (int; {1,2}) – Analog channel number to get bandwidth of.
Return type:float; Hz
Returns:Bandwidth
Raises:ValueError – If the channel number is invalid.
get_frontend(channel)

Get the analog frontend configuration.

Parameters:channel (int; {1,2}) – Channel for which the relay settings are being retrieved
Returns:Array of bool with the front end configuration of channels - [0] 50 Ohm - [1] 10xAttenuation - [2] AC Coupling
get_initfreq(ch)

Reads the seed frequency register of the phase tracking loop Valid if auto acquire has not been used.

Parameters:ch (int; {1,2}) – Channel number to read the initial frequency of.
Return type:float; Hz
Returns:Seed frequency
Raises:ValueError – If the channel number is invalid.
get_samplerate()

Get the samplerate of the Phasemeter

Return type:float; smp/s
Returns:Samplerate
get_stream_data(n=0, timeout=None)

Get any new instrument samples that have arrived on the network.

This returns a tuple containing two arrays (one per channel) of up to ‘n’ samples of instrument data. If a channel is disabled, the corresponding array is empty. If there were less than ‘n’ samples remaining for the session, then the arrays will contain this remaining amount of samples.

Parameters:
  • n (int) – Number of samples to get off the network. Set this to ‘0’ to get all currently available samples, or ‘-1’ to wait on all samples of the currently running streaming session to be received.
  • timeout (float) – Timeout in seconds
Return type:

tuple

Returns:

([CH1_DATA], [CH2_DATA])

Raises:
get_timestep()

Returns the expected time between streamed samples.

This returns the inverse figure to get_samplerate. This form is more useful for constructing time axes to support, for example, get_stream_data.

Return type:float
Returns:Time between data samples in seconds.
progress_data_log()

Estimates progress of a logging session started by a start_data_log call.

Return type:float
Returns:[0.0-100.0] representing 0 - 100% completion of the current logging session.Note that 100% is only returned when the session has completed, the progress may pause at 99% for a time as internal buffers are flushed.
Raises:StreamException: if an error occurred with the current logging session.
reacquire(*args, **kwargs)

Restarts the frequency tracking loop and phase counter for the specified channel, or both if no channel is specified. The starting frequency of the channel’s tracking loop is set to the seed frequency as set by calling set_initfreq.

To automatically acquire a seed frequency, see auto_acquire.

Parameters:ch (int; {1,2}) – Channel number, or None for both
Raises:ValueError – If the channel number is invalid.
set_bandwidth(*args, **kwargs)

Set the bandwidth of the phasemeter.

The phasemeter can measure deviations in phase and frequency up to the set bandwidth.

Parameters:
  • ch (int; {1,2}) – Analog channel number to set bandwidth of.
  • n – Desired bandwidth (will be rounded up to to the nearest multiple 10kHz / 2^N with N = [0,10])
Raises:
  • ValueError – If the channel number is invalid.
  • ValueOutOfRangeException – if the bandwidth is not positive-definite or the channel number is invalid
set_defaults(*args, **kwargs)

Can be extended in implementations to set initial state

set_frontend(channel, fiftyr=True, atten=False, ac=False)

Configures gain, coupling and termination for each channel.

Parameters:
  • channel (int; {1,2}) – Channel to which the settings should be applied
  • fiftyr (bool) – 50Ohm termination; default is 1MOhm.
  • atten (bool) – Turn on 10x attenuation. Changes the dynamic range between 1Vpp and 10Vpp.
  • ac (bool) – AC-couple; default DC.
set_initfreq(*args, **kwargs)

Manually set the initial frequency of the designated channel

Parameters:
  • ch (int; {1,2}) – Channel number to set the initial frequency of.
  • f (int; 2e6 < f < 200e6) – Initial locking frequency of the designated channel
Raises:
  • ValueError – If the channel number is invalid.
  • ValueOutOfRangeException – If the frequency parameter is out of range.
set_samplerate(*args, **kwargs)

Set the sample rate of the Phasemeter.

Options are {‘veryslow’,’slow’,’medium’,’fast’,’veryfast’,’ultrafast’} corresponding to 30.5176 smp/s, 122.0703 smp/s, 1.9531 ksmp/s, 15.625 ksmp/s, 125 ksps/s.

Parameters:samplerate (string, {'veryslow','slow','medium','fast','veryfast','ultrafast'}) – Desired sample rate
Raises:ValueError – If samplerate parameter is invalid.
start_data_log(duration=10, ch1=True, ch2=True, use_sd=True, filetype='csv')

Start logging instrument data to a file.

Progress of the data log may be checked calling progress_data_log.

All outstanding settings must have been committed before starting the data log. This will always be true if pymoku.autocommit=True, the default.

Note

The Moku’s internal filesystem is volatile and will be wiped when the Moku is turned off. If you want your data logs to persist either save to SD card or move them to a permanent storage location prior to powering your Moku off.

Parameters:
  • duration (float) – Log duration in seconds
  • ch1 (bool) – Enable streaming on Channel 1
  • ch2 (bool) – Enable streaming on Channel 2
  • use_sd (bool) – Whether to log to the SD card, else the internal Moku filesystem.
  • filetype (string) – Log file type, one of {‘csv’,’bin’,’mat’,’npy’} for CSV, Binary, MATLAB or NPY (Numpy Data) respectively.
Raises:
start_stream_data(duration=10, ch1=True, ch2=True)

Start streaming instrument data over the network.

Samples being streamed can be retrieved by calls to get_stream_data.

All outstanding settings must have been committed before starting the stream. This will always be true if pymoku.autocommit=True, the default.

Parameters:
  • duration (float) – Log duration in seconds
  • ch1 (bool) – Enable streaming on Channel 1
  • ch2 (bool) – Enable streaming on Channel 2
Raises:
stop_data_log()

Stops the current instrument data logging session.

This must be called exactly once for every start_data_log call, even if the log terminated itself due to timeout. Calling this function doesn’t just stop the session (if it isn’t already stopped), but also resets error and transfer state, ready to start a new logging session.

stop_stream_data()

Stops instrument data being streamed over the network.

Should be called exactly once for every start_stream_data call, even if the streaming session stopped itself due to timeout. Calling this function not only causes the stream to stop, but also resets error and transfer state, ready to start a new streaming session.

upload_data_log()

Load most recently recorded data file from the Moku to the local PC.

Raises: