Search code examples
labviewzaber

Unexpected responses from Zaber devices in LabVIEW


When using Zaber's LabVIEW driver to control their devices, it sometimes returns strange responses to commands. For example, sending the Move Absolute command might return a Set Target Speed response or a Manual Move Tracking response, instead of the expected Move Absolute response. What causes that, and how can it be avoided?


Solution

  • The Cause

    The most common cause of this problem is that you used the Write Command VI to send a command, but never read the response. That response sits in the serial port's receive buffer until you read it. If you later use the Request Command VI, it will write the new command and then read the response from the old command that's still sitting in the buffer.

    That can confuse your code if you're using the response data values to perform a calculation, but it can be even worse when you are requesting a movement command. The way that the Request Command VI knows when the movement has finished is that the device sends back a response. If there's already a response in the buffer, then it looks like the movement finished immediately. Your VI will look as if it's skipping movement commands.

    Here's an incorrect example that shows how the problem can happen. The Move Relative command will not finish before the Move To Stored Position command is sent. All three of the following examples can be downloaded from our web site.

    Wiring diagram of responses handled incorrectly

    Another way to cause this kind of problem is to send a command to multiple devices using device number zero and only read the first response. (Each device will send its own response.) You can also cause problems if you use the manual control knob or a joystick while a VI is running. That movement will generate a bunch of responses when your VI wasn't sending anything.

    Solution 1: Request Command VI

    The simplest solution is just to make sure that you read every response to every command. If you use the Request Command VI for each command, it will handle most situations properly.

    Here's a corrected version of the previous example that now uses the Request Command VI.

    Wiring diagram of responses handled correctly

    If you send a command to all devices using device number zero, then you'll have to adjust the response count so it knows how many responses to wait for.

    In more complicated scenarios like moving two devices at the same time, you can use the Write Command VI in combination with the Blocking Read Response VI to make sure that you receive all the responses. See the simultaneous requests example for more details.

    This solution won't help if you are using the manual control knob or a joystick while the VI is running.

    Solution 2: Clearing the Buffer

    Maybe you've got a complicated VI that already has a bunch of writes and you don't want to clean them all up, or maybe you want to use the manual control knob or a joystick while the VI is running. Perhaps the response pattern isn't completely predictable for some other reason. If you can't avoid getting extra responses in the buffer, you can clean them out when the craziness is over. Just use the Read Response VI (not the blocking one) and keep reading as long as it finds responses.

    Here's the same example that now clears out the buffer. It pauses for ten seconds so you can use the manual control knob to generate some extra responses.

    Wiring diagram of responses cleared from the buffer

    One trick with this solution is knowing when the craziness has ended. Ideally, the devices should not be moving, and you should wait at least 20 milliseconds before you start clearing out the buffer. That gives time for the devices to process the last command and send a response. If the devices are still moving, then you'll get an extra response when they finally finish.

    Solution 3: State Machine

    If your VI is really complicated or unpredictable, the state machine pattern can be a robust approach. Instead of closely tying each request with its response, the VI keeps track of a global state, and deals with each response separately. See Zaber's Write Commands and Read Responses VI for another example.

    This approach is also useful if you have parallel loops sending commands. You can't have two loops reading from the serial port at the same time.