Moku pro data logger indefinitely wait for trigger

Moku Pro

MokuOS: 4.2.2

Hardware version: 3.0

Firmware: 644.0

Python: 3.11.15

I have a Moku pro and I tried to write a python API to repetitively trigger the data logger for automated measurement. Within multi-instrument mode, I set up a trigger source using a signal generator. I then route that signal to the data logger, and use a loop to rearm the session after each trigger has been received.

But sometimes I run into errors where the data logger freezes and indefinitely stays in the waiting for trigger stage. I confirmed that the trigger signal is firing correctly when this happens. I was wondering if there is a problem with my python control code, or perhaps I’m running into a software bug.

A screenshot of the multi-instrument set up is shown below, and I have attached the python script that I was using. Any help would be appreciated, thanks in advance!

“”"

Setup, 3 MIM slots:

Slot 1 – Waveform Generator (WFG)

OutB: periodic square-wave trigger (Internal burst mode),

also routed out to physical Output 1

Slot 2 – Lock-in Amplifier (LIA)

InputA ← physical Input 1 ← [loop cable] ← physical Output 1

(kept in the chain in case its own internal

clock/processing contributes to the bug)

OutA → Slot3InA (demodulated output, recorded)

Slot 3 – Datalogger (DL)

InputA ← Slot2OutA (recorded data)

InputB ← Slot1OutB (hardware trigger source, internal)

Routing:

Slot1OutB → Slot3InB (trigger, internal)

Slot1OutB → Output1 (trigger, physical monitor/loopback)

Input1 → Slot2InA (physical Input 1 → LIA in)

Slot2OutA → Slot3InA (data)

Goal: WFG OutB fires a trigger pulse every BURST_PERIOD seconds via its

‘Internal’ burst mode. Each loop iteration arms the Datalogger and waits

for logging_progress()[‘complete’] to go True. l connection.

“”"

import time

from moku.instruments import (

WaveformGenerator,

LockInAmp,

Datalogger,

MultiInstrument,

)

# ─── Configuration ──────────────────────────────────────────────────────────

IP_ADDRESS = ‘…’

# Datalogger

SAMPLE_RATE = 100 # Sa/s

DURATION = 0.2 # seconds per triggered session

NUM_SESSIONS = None # None = run until Ctrl-C (recommended for bug hunting)

# Waveform Generator

WFG_TRIGGER_FREQUENCY = 1000 # Hz — shape of the pulse itself

WFG_TRIGGER_AMPLITUDE = 2.0 # Vpp (swings -1V to +1V)

WFG_TRIGGER_OFFSET = 0.0 # V

WFG_TRIGGER_DUTY = 50 # %

WFG_TRIGGER_BURST_CYCLES = 1

BURST_PERIOD = 3 # seconds between trigger events

# Lock-in Amplifier

LIA_FREQUENCY = 1e6 # Hz — internal demod reference (no live input signal)

LIA_CORNER_FREQ = 100e3

LIA_FILTER_SLOPE = ‘Slope6dB’

LIA_MAIN_OUTPUT = ‘R’

# Datalogger trigger — comfortably within the -1V..+1V swing of the WFG

# trigger signal, not a marginal/near-peak value.

TRIGGER_LEVEL = 0.5

# ─── Connect and configure ───────────────────────────────────────────────────

print(‘Connecting to Moku Pro …’)

moku = MultiInstrument(IP_ADDRESS, platform_id=4, force_connect=True)

wfg = moku.set_instrument(1, WaveformGenerator)

lia = moku.set_instrument(2, LockInAmp)

dl = moku.set_instrument(3, Datalogger)

moku.set_connections(connections=[

dict(source=‘Slot1OutB’, destination=‘Slot3InB’), # trigger → DL (internal)

dict(source=‘Slot1OutB’, destination=‘Output1’), # trigger → physical Output 1

dict(source=‘Input1’, destination=‘Slot2InA’), # physical Input 1 → LIA in

dict(source=‘Slot2OutA’, destination=‘Slot3InA’), # LIA out → DL data channel

])

print(‘Instruments deployed and connected.’)

# ── Front-end configuration ─────────────────────────────────────────────────

moku.set_frontend(channel=1, impedance=‘1MOhm’, coupling=‘DC’, bandwidth=‘300MHz’, attenuation=‘0dB’)

moku.set_output(channel=1, output_gain=‘0dB’) # 2 Vpp — trigger monitor out

print(‘Front-end (AFE) settings applied.’)

# OutA not used — off.

wfg.generate_waveform(channel=1, type=‘Off’)

wfg.generate_waveform(

channel=2,

type=‘Square’,

frequency=WFG_TRIGGER_FREQUENCY,

amplitude=WFG_TRIGGER_AMPLITUDE,

offset=WFG_TRIGGER_OFFSET,

duty=WFG_TRIGGER_DUTY,

)

wfg.set_burst_mode(

channel=2,

source=‘Internal’,

mode=‘NCycle’,

burst_cycles=WFG_TRIGGER_BURST_CYCLES,

burst_period=BURST_PERIOD,

)

print(f’WFG: OutA = off | OutB = burst trigger, period {BURST_PERIOD}s’)

lia.set_demodulation(mode=‘Internal’, frequency=LIA_FREQUENCY)

lia.set_filter(corner_frequency=LIA_CORNER_FREQ, slope=LIA_FILTER_SLOPE)

lia.set_outputs(main=LIA_MAIN_OUTPUT, aux=‘None’)

print(f’LIA: {LIA_FREQUENCY:.0f} Hz demod, corner {LIA_CORNER_FREQ:.0f} Hz ({LIA_FILTER_SLOPE})')

dl.set_acquisition_mode(mode=‘Precision’)

dl.enable_input(channel=1, enable=True) # InputA — recorded LIA data

dl.enable_input(channel=2, enable=True) # InputB — hardware trigger source

print(‘Datalogger configured.\n’)

# ─── Triggered logging loop ───────────────────────────────────────────────────

try:

dl.stop_logging()

except Exception:

pass

def arm():

return dl.start_logging(

duration=DURATION,

sample_rate=SAMPLE_RATE,

trigger_source=‘InputB’,

trigger_level=TRIGGER_LEVEL,

)

session = 0

try:

log_info = arm()

session = 1

print(f’[{session:04d}] Armed — {log_info[“file_name”]}')

while NUM_SESSIONS is None or session < NUM_SESSIONS:

start_wait = time.time()

while True:

progress = dl.logging_progress()

if progress.get(‘complete’):

break

elapsed = time.time() - start_wait

print(f’\r[{session:04d}] Waiting for trigger … {elapsed:5.1f}s’, end=‘’, flush=True)

time.sleep(0.05)

print(f’\r[{session:04d}] Done — {progress[“file_name”]} ’

f’({progress[“samples_logged”]} samples) ')

session += 1

log_info = arm()

print(f’[{session:04d}] Armed — {log_info[“file_name”]}')

except KeyboardInterrupt:

print(f’\nStopped by user after {session} attempted sessions.')

finally:

try:

moku.relinquish_ownership()

except Exception:

pass

print(‘Disconnected.’)

Hello @Tina ,

Thank you for reaching out to Liquid Instruments! I tested your Python script and saw the same behavior you had reported. It seems that the data logger freezes after a number of iterations, and the only way to recover it is to stop the log and rearm. I was able to modify your script (attached as a .m file) and added a timeout check. If the data logger doesn’t receive a trigger within a certain amount of time (8 seconds in the modified script) then the data logger is stopped and rearmed which will allow data to be collected again. I have reported this issue to my development team and will update this thread when a fix is released. I hope this helps!

-Dylan

datalogger_rearm_fix.m (3.9 KB)

Hi Dylan,

Thanks for looking into this! Please let me know once a fixed is released.