Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
888 views
in Technique[技术] by (71.8m points)

arduino - Track position of Zaber device while moving

I am using a Zaber linear stage controlled by an Arduino using the Zaber shield. I try to do something similar to this question (Track position of a Zaber device as it moves), but using the Arduino language instead of Labview.

In the answer 3 options were provided: interpolate from the start and end points, poll the position using a timer, or turn on a device mode that reports the position every 250 ms.

The device mode does not seem to exist for my stage (X-LSQ-075B-E01) and I don't want to rely on interpolation. The stage is fitted with an encoder and I can easily get its readback for the exact position; I just don't know how to poll the stage while moving. I came up with the following code (a bit simplified), but it is relatively slow and only gives the readback from 1 stage (we are actually using 2) and sending the command to both does not really work.

#include <ZaberAscii.h>

ZaberShield shield(ZABERSHIELD_ADDRESS_AA);
ZaberAscii za(shield);

void setup() {
  shield.begin(115200);
  Serial.begin(115200);
  za.send(1, 1, "move rel", 20000);
  za.receive();

  while (za.isIdle(1) == false) {
    za.send(1, "get encoder.pos");
    ZaberAscii::reply reply = za.receive();
    if (!reply.isReply) {
      Serial.println("*** Received a non-reply message from device " + String(reply.deviceNumber) + ".");
    }
    else if (reply.isRejected) {
      Serial.println("*** A command was rejected by device " + String(reply.deviceNumber) + ".");
    }
    else {
      Serial.println( String(reply.deviceNumber) + ": " + String(reply.responseData));
    }
    delay(5);
  }

  za.pollUntilIdle(1);
  Serial.println("1 finished");
  za.send(2, 1, "move rel", 20000);

  while (za.isIdle(2) == false) {
    za.send(2, "get encoder.pos");
    Serial.println("Device 2 not idle");
    ZaberAscii::reply reply = za.receive();
    if (!reply.isReply) {
      Serial.println("*** Received a non-reply message from device " + String(reply.deviceNumber) + ".");
    }
    else if (reply.isRejected) {
      Serial.println("*** A command was rejected by device " + String(reply.deviceNumber) + ".");
    }
    else {
      Serial.println( String(reply.deviceNumber) + ": " + String(reply.responseData));
    }
    //delay(10);
  }
  Serial.println("2 finished");
}

void loop() {}
question from:https://stackoverflow.com/questions/66045903/track-position-of-zaber-device-while-moving

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To have it work on both devices, you would need to send both movement commands before starting the while loop, and then for the while loop you would want the condition to repeat until both axes are idle. Within the while loop you would read the position of both axes.

On the timing, can you say approximately what frequency you're getting now? The timing per communication is typically about 5-10ms. With the current functions, the isIdle() call takes it's own command, so I'd expect the above loop to be about 20-40ms. You could cut it in half by pulling the .IsBusy information from the 'get encoder.pos' reply.

Mike McDonald [email protected]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...