Error with enable_rollmode, enable_output and get_data

Hello,
I have noticed an interesting error with our Moku:Go using the Python API

Model: Moku:Go
Operating system: windows
software: 3.2.0
fireware: 591

I can replicate the bug with the following code.
I open the PID controller and enable_rollmode. If I then disable, and re-enable, the PID outputs (pid.enable_output(1, signal=True, output=False)pid.enable_output(1, signal=True, output=True) and then call pid.get_data() the Moku hangs and times out. However, this error does not happen if I do not initially enable_rollmode OR if I disable and then re-enable roll mode before calling get_data.

import sys
import time
from loguru import logger
from moku.__init__ import MokuException
from moku.instruments import MultiInstrument, LockInAmp, PIDController

ID = "[fe80::7269:79ff:feb9:4aea%252547]"

logger.remove()
logger.add(sys.stderr, level="INFO")


def try_get_data(pid):
    try:
        _ = pid.get_data(timeout=5)
    except MokuException:
        logger.error("Error in get_data.")
    else:
        logger.debug("No error")


def just_pid():
    logger.info("Running just PID")
    pid = PIDController(ID, force_connect=True, platform_id=2)
    pid.enable_rollmode(True)
    time.sleep(0.1)

    logger.info("Getting data base test")
    try_get_data(pid)

    pid.enable_output(1, signal=True, output=False)
    time.sleep(0.1)
    pid.enable_output(1, signal=True, output=True)
    # Uncommentting these line resolves the error
    # pid.enable_rollmode(False)
    # time.sleep(0.1)
    # pid.enable_rollmode(True)
    time.sleep(0.1)

    logger.info("Getting data after toggling output")
    try_get_data(pid)

    pid.set_defaults()
    time.sleep(3)

    logger.info("Getting data after resetting defaults")
    try_get_data(pid)


if __name__ == "__main__":
    just_pid()

Running this code gives the following log

2024-04-23 10:59:04.381 | INFO     | __main__:just_pid:23 - Running just PID
2024-04-23 10:59:10.440 | INFO     | __main__:just_pid:28 - Getting data base test
2024-04-23 10:59:12.732 | INFO     | __main__:just_pid:40 - Getting data after toggling output
2024-04-23 10:59:18.161 | ERROR    | __main__:try_get_data:17 - Error in get_data.
2024-04-23 10:59:21.644 | INFO     | __main__:just_pid:46 - Getting data after resetting defaults

the full traceback,
MokuException Traceback (most recent call last)
c:\Users\James\Documents\polarisation and phase feedback\tests\moku_bug_simple.py in
49
50 if name == “main”:
—> 51 just_pid()

c:\Users\James\Documents\polarisation and phase feedback\tests\moku_bug_simple.py in just_pid()
39
40 logger.info(“Getting data after toggling output”)
—> 41 try_get_data(pid)
42
43 pid.set_defaults()

c:\Users\James\Documents\polarisation and phase feedback\tests\moku_bug_simple.py in try_get_data(pid)
13 def try_get_data(pid):
14 # try:
—> 15 _ = pid.get_data(timeout=5)
16 # except MokuException:
17 # logger.error(“Error in get_data.”)

~\anaconda3\lib\site-packages\moku\instruments_pidcontroller.py in get_data(self, timeout, wait_reacquire, wait_complete)
753 wait_complete=wait_complete
754 )
→ 755 return self.session.post(
756 f"slot{self.slot}/{self.operation_group}",
757 operation,

~\anaconda3\lib\site-packages\moku\session.py in func_wrapper(self, *args, **kwargs)
16 def func_wrapper(self, *args, **kwargs):
17 response = func(self, *args, **kwargs)
—> 18 return self.resolve(response)
19
20 return func_wrapper

~\anaconda3\lib\site-packages\moku\session.py in resolve(self, response)
163 return data.data
164 elif data.success is False:
→ 165 self._handle_error(data.code, data.messages)
166 else:
167 print(response.dict)

~\anaconda3\lib\site-packages\moku\session.py in _handle_error(code, messages)
124 raise exceptions.UnexpectedChangeError(messages)
125 else:
→ 126 raise exceptions.MokuException(messages)
127
128 @staticmethod

MokuException: [‘Timeout before fetching the new frame’]

Hi @JamesStuart ,

Thank you very much for posting here!

I changed line 15 as following, and the error seems resolved

_ = pid.get_data(wait_reacquire=True)

Would you please give it a try? Please let me know how it goes. Thank you very much!

Best regards,
Hank

Hello,
_ = pid.get_data(wait_reacquire=True) works, however I find that data = pid.get_data(wait_reacquire=True) causes the amount of data returned to change shot-to-shot and wait_complete is not available in roll mode.

I cant get around this by calling data = pid.get_data(wait_reacquire=True) once after toggling the enable_output and then continuing to use wait_reacquire = False, but I wonder if there is a cleaner solution?