Issue saving high res buffer with Oscilloscope

Moku model: Moku:Pro
Operating system: macOS 12.6
Software version: 2.4.2
Firmware version: 569
Python Moku API version: 2.4

Bug or support request description:

Hi there,

I’m working the Python Moku API to set up a script to take and save data at various settings for a device, but am running into an issue with saving the high resolution data buffer. It seems that it works the first time, but subsequent tries raise an error:

MokuException: ['Error occurred while saving high resolution data frame']

The error seems to go away if I completely restart the Moku and then rerun the Python code (taking over control again). However, the same error returns after subsequent tries. Is this a known issue with the using the Oscilloscope instrument via the Python API? I’ve also noticed that the same line can sometimes return a timeout error.

Code:

from moku.instruments import Oscilloscope
import matplotlib.pyplot as plt
import os
import time
from datetime import datetime

import contextlib

@contextlib.contextmanager
def connect_instrum(MokuInstrument, ip_address, force_connect=False):

    MI = MokuInstrument(ip_address, force_connect=force_connect)
    try:
        yield MI
    except Exception as e:
        raise e
    finally:
        MI.relinquish_ownership()

moku_ip = '192.168.73.1'

with connect_instrum(Oscilloscope, moku_ip, force_connect=True) as i:
    i.set_defaults()

    # Trigger on input Channel 1, rising edge, 0V 
    i.set_trigger(
        type='Edge',
        source='Output1',
        level=0,
    )

    # View +-5usec, i.e. trigger in the centre
    i.set_timebase(-0.1, 0.1)

    # Generate an output square wave on Channel 1, 1Vpp, 1kHz, 0V offset
    i.generate_waveform(1, 'Square', amplitude=1, frequency=1e3, duty=50)
    # Set the data source of Channel 1 to the generated output sinewave
    i.set_source(1, 'Output1')

    # Set the data source of Channel 2 to be Input 1
    i.set_source(2, 'Input2')

    plt.grid(b=True)
    plt.ylim([-1, 1])

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

    # Configure labels for axes
    ax = plt.gca()

    time.sleep(3)
    data = i.get_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'])
    print(i.summary())
    
    response = i.save_high_res_buffer(comments="Test")
    file_name = response["file_name"]
    i.download(
        "ssd",
        file_name,
        os.path.abspath(f'./test{datetime.now().strftime("%Y%m%d_%H%M%S")}.li'),
    )

Error:

---------------------------------------------------------------------------
MokuException                             Traceback (most recent call last)
<ipython-input-14-952d6b0ded09> in <module>
     49 
---> 50     response = i.save_high_res_buffer(comments="Test")
     51     file_name = response["file_name"]
     52     i.download(

/opt/anaconda3/lib/python3.8/site-packages/moku/instruments/_oscilloscope.py in save_high_res_buffer(self, comments)
    487             comments=comments,
    488         )
--> 489         return self.session.post(self.operation_group, operation, params)
    490 
    491     def get_samplerate(self):

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in func_wrapper(self, *args, **kwargs)
     12     def func_wrapper(self, *args, **kwargs):
     13         response = func(self, *args, **kwargs)
---> 14         return self.resolve(response)
     15 
     16     return func_wrapper

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in resolve(self, response)
    148                     return data.data
    149                 elif data.success is False:
--> 150                     self.handle_error(data.code, data.messages)
    151             else:
    152                 self.handle_http_error(response)

/opt/anaconda3/lib/python3.8/site-packages/moku/session.py in handle_error(code, messages)
    112             raise exceptions.UnexpectedChangeError(messages)
    113         else:
--> 114             raise exceptions.MokuException(messages)
    115 
    116     @staticmethod

MokuException: ['Error occurred while saving high resolution data frame']

Looking around the forum a little bit, this could be a related issue to this one from about 8 months ago:

Have there been any updates on that issue? For now we will use the datalogger to take continuous data and trigger offline.

I was able to reproduce this issue on my end with the ‘Error occured while saving high resolution data frame’ message appearing. It seems like the easy fix is to remove the comments=‘Test’ for now, however I have submitted this as a bug to our software team. Thank you for pointing this out to us and let me know if this fixes the issue for you!

Hi @Sam.Speece,

Unfortunately, I still seem to get the error after removing that comment - I tried restarting the Moku and using it with a different device (the Mac app), but still have one successful data taking with the oscilloscope, before the subsequent runs raise the same error.

FYI, I’ve essentially taken the code I used from the API examples:

When you removed that comment, you could re-run the script over and over again to collect new data?

Quick update on some of the testing I’ve done and what I’ve found has worked.

I removed majority of the matplotlib lines to get minimum viable code that reproduces the issue and added back in the comments=‘Test’ bit too. It seems there is one line that causes the high res data download issue to appear infrequently (about 3 of every 5 runs ends in high res download error). I think I just got lucky previously when removing the comments=‘Test’ part and got it to run 3 times in a row without error.

In your original code, removing line 53 (calling get_data()) seems to resolve issues for me and I’ve gotten it to run successfully 10 consecutive times. There is likely some strange interaction with using both get_data() and save_high_res_data() in the same script that is causing issues.

Alternatively, if you still need to call get_data(), I have found that calling it after I call save_high_res_data() does not produce any errors.

Let me know if this one helps you any better.

Thanks for the update! I tried doing the same thing, and it definitely improved the success rate, but I still do get the same MokuException errors every couple of runs. One other thing that I was wondering could be part of success/failure rate it is how I’m connecting to the Moku. Right now, I’m connecting via WiFi. Are you using the same connection method?

I played around more with commenting out various lines and seeing what combination of lines raises the error. In my experience, it seems like the error was only raised in the scenario that both:

  1. I am generating some type of waveform through an output
  2. I am triggering on that output

If both were not true, then I didn’t get an error over 10 runs. If both were true, then I got, e.g., 6-8 errors out of 10 runs. In other words, in the code I’m using, if I set the trigger source to "Input2", there’s no error, but I have about a >50% chance of an error with the source set to "Output1".

Here’s the simplified code I’m using, which should be about the same as you described:

from moku.instruments import Oscilloscope
import os
import time
from datetime import datetime

import contextlib

@contextlib.contextmanager
def connect_instrum(MokuInstrument, ip_address, force_connect=False):

    MI = MokuInstrument(ip_address, force_connect=force_connect)
    try:
        yield MI
    except Exception as e:
        raise e
    finally:
        MI.relinquish_ownership()

moku_ip = '192.168.73.1'

with connect_instrum(Oscilloscope, moku_ip, force_connect=True) as i:
    i.set_defaults()

    i.set_trigger(
        type='Edge',
        source='Output1',
        level=0,
    )
    i.disable_input(3)
    i.disable_input(4)

    i.set_timebase(-0.1, 0.1)

    i.generate_waveform(1, 'Square', amplitude=1, frequency=1e3, duty=50)
    i.set_source(1, 'Output1')
    i.set_source(2, 'Input2')


    time.sleep(3) # wait for Moku to finish setting channels
    
    response = i.save_high_res_buffer()
    file_name = response["file_name"]
    i.download(
        "ssd",
        file_name,
        os.path.abspath(f'./test{datetime.now().strftime("%Y%m%d_%H%M%S")}.li'),
    )