2

我使用Zaber 控制台编写了一个脚本来控制一个循环执行多个步骤的 Zaber 设备。如何在循环中间暂停它并恢复它而不必回到开始?

4

1 回答 1

1

我可以想到四个选项来支持这一点。

  1. 让您的脚本在启动时以某种方式检测当前状态,并确定它应该从例程的哪个部分开始。根据您的例行程序,您可能能够读取当前位置以判断您处于哪一步。如果没有,您也可以使用用户内存或将当前状态写入文本文件。其中一个示例脚本显示了如何写入文本文件
  2. 除了主脚本之外,还要编写暂停脚本和恢复脚本。主脚本注意到来自其他两个脚本的响应。我将在下面包含一个示例。
  3. 无需单独的脚本来暂停和恢复,而是使用Zaber 操纵杆并对按钮进行编程以发送暂停和恢复命令。下面的示例也将涵盖这一点。
  4. 将您的脚本转换为在BackgroundWorker中运行主例程的插件。然后您可以在控件类中保持状态,并添加一个暂停/恢复按钮。

这是一个使用单独的脚本来暂停和恢复您的例程的示例。它还介绍了如何使用操纵杆按钮。

原始程序

首先,我创建了这个简单的例程。

/* C# example of how to pause and resume a Zaber Console script.
 * This script is the original routine without the pause and resume logic.
 * It moves to position zero, then makes four moves of 10000 microsteps each 
 * and goes back to zero. This loops forever.
 */
#template(simple)

while (true)
{
    for (var i = 0; i < 5; i++)
    {
        var position = i*10000;
        Output.WriteLine("moving to {0}", position);
        Conversation.Request(Command.MoveAbsolute, position);
    }
}

暂停

这是暂停例程的脚本。

/* C# example of how to pause and resume a Zaber Console script.
 * This script pauses the main routine by sending a Stop command. Running this 
 * script twice will stop the routine.
 */
#template(simple)

Conversation.Request(Command.Stop);

stop 命令将导致主脚本出错,但我们将更改主脚本以捕获该错误并添加暂停/恢复逻辑。

简历

这是恢复例程的脚本。

/* C# example of how to pause and resume a Zaber Console script.
 * This script resumes the main routine by sending an EchoData command with a
 * magic number.
 */
#template(simple)

const int RESUME_NUMBER = 42;// Matches the main routine.
Conversation.Request(Command.EchoData, RESUME_NUMBER);

常规加暂停逻辑

暂停和恢复脚本非常简单;真正的工作是让主脚本监听来自停止命令的错误和恢复的幻数。这是添加了所有内容的新版本的例程。在主脚本编辑器窗口中运行此脚本,并从主窗口脚本选项卡的网格中运行另外两个。

/* C# example of how to pause and resume a Zaber Console script.
 * This script is the main routine that moves to position zero, then makes four
 * moves of 10000 microsteps each and goes back to zero. This loops forever.
 * To pause the routine, run the Pause.cs script. To resume the routine, run
 * the Resume.cs script. Running the pause script twice will stop the routine.
 */
#template(methods)

/* We switched to the methods template so we can put the move with pause and
 * resume into a helper method.
 */
public override void Run()
{
    while ( ! IsCanceled)
    {
        for (var i = 0; i < 5 && ! IsCanceled; i++)
        {
            var position = i*10000;
            MoveTo(position);
        }
    }
}

/* This wraps the pause and resume logic around a simple MoveAbsolute command.
 * If your resume logic is more complicated, you can put more commands inside 
 * the try/catch block, or use the return value of this function to tell the
 * main routine what to do next.
 * When this method returns, either the move has successfully completed, or
 * IsCanceled is true.
 */
private void MoveTo(int position)
{
    bool isComplete = false;
    while ( ! isComplete && ! IsCanceled)
    {
        try
        {
            Output.WriteLine("moving to {0}", position);
            Conversation.Request(Command.MoveAbsolute, position);
            isComplete = true;
        }
        catch (RequestReplacedException ex)
        {
            Pause();
        }
        catch (RequestCollectionException ex)
        {
            /* If you are running against device number zero
             * or some other alias, you get a slightly
             * different exception.
             */
            Pause();
        }
    }
}

/* Just wait for responses from your device. If a response is an EchoData 
 * command with the magic number, then this method will return. If the response
 * is a Stop command, then IsCanceled is set to true and this method will 
 * return. All other responses are ignored.
 */
private void Pause()
{
    Output.WriteLine("paused");

    /* Let the device finish processing the current stop command before
     * you start listening, otherwise you sometimes see the stop command
         * again.
         */
    Sleep(100); 

    const int RESUME_NUMBER = 42;// Matches the resume script.
    var listener = new DeviceListener(Conversation.Device);
    bool isPaused = ! IsCanceled;// Don't pause if already canceled.
    while (isPaused)
    {
        var response = listener.NextResponse();// wait
        if (response.Command == Command.EchoData && 
            response.Data == RESUME_NUMBER)
        {
            isPaused = false;
            Output.WriteLine("resumed");
        }
        else if (response.Command == Command.Stop)
        {
            isPaused = false;
            IsCanceled = true;
            Output.WriteLine("stopped");
        }
    }
}

操纵杆

如果你有一个 Zaber 操纵杆,点击几个操纵杆按钮比在 Zaber 控制台中运行暂停和恢复脚本更方便。操纵杆上按钮 1 的默认命令是停止,因此您已经处理好暂停。如果您对其他按钮之一进行编程以发送 Echo Data 42,则可以恢复您的脚本。上面的最终脚本将运行带有暂停和恢复逻辑的例程,无论您是使用单独的脚本发送暂停和恢复命令还是使用操纵杆按钮发送它们。

于 2012-08-20T19:38:15.583 回答