The previous entry in this series went over the Mover function block. Movers already give us a lot of options for how to control our XTS system, but typically we don’t want to control movers based on which index in the array they are, we want to control them based on where they are along the track. That’s what stations are for.
This blog will go over the Station function block that comes with the base starter project. We will see how to configure the stations properly and what methods we have at our disposal to use with our system. This blog will continue to use the Beckhoff XTS_Base GitHub and the large XTS starter kit.
Beckhoff XTS Series
Stations
Stations are defined positions along the XTS track where movers will stop until commanded to do something else. This allows for a mover to reach the station, have some actions performed on it while stationary, then to be sent elsewhere on the track.
Declaring Stations
In MAIN, in the variable declaration we already have an array of stations declared with the line
Station : ARRAY[0..GVL.NUM_STATIONS - 1] OF Station;
If you want to add more stations, you can change the value of NUM_STATIONS
in the GVL
file. There’s advantages and disadvantages to having your stations in an array. The advantages are that they’re all stored in one place, the name is consistent across various stations, and it’s easy to iterate through all the stations if needed. Additionally, adding stations between two existing stations is as easy as shifting the other stations in the array up an index. The disadvantage is that the station names are not going to be as descriptive as they could be if they were individually named. For this blog, we’re going to continue using the array of stations.
Configuring Stations
The existing starter project already has 5 stations configured, shown below:
The position definition for these stations is in the MS_INTIIALIZING_OBJECTIVES section of the MAIN state machine, which is at line 109.
Station[0].Position := 5;
Station[1].Position := 750;
Station[2].Position := 1200;
Station[3].Position := 1300;
Station[4].Position := 1400;
We can see that the stations are given positions (in mm) around the track that line up with the picture above. Changing these positions will change where along the track the stations exist.
We also need to make sure to call the CyclicLogic method of the station object. This is already done for us in line 414.
FOR i := 0 TO GVL.NUM_STATIONS - 1 DO
Station[i].Cyclic();
END_FOR
One other thing these stations are already configured to do is to unregister movers on stopping or disabling. This will make sure that no movers are “trapped” at stations when the system starts back up. This is done in lines 327 and 362 by calling the UnregisterAll method for each station.
FOR i := 0 TO GVL.NUM_STATIONS - 1 DO
Station[i].UnregisterAll();
END_FOR
Station Logic
The existing starter project already has some stations logic. The logic for these stations is in the MS_RUN section of the MAIN state machine, which starts at line 212. There’s a couple methods and properties about the station objects that are useful to describe to interpret this code.
MoverInPosition
MoverInPosition is a property of the station object. This property is true if a mover has arrived at the station. This is important to check before trying to do anything with a station’s mover because if there is no mover in the station, the code will try to command an invalid mover reference.
CurrentMover
CurrentMover is a property of the station object. This property is a reference to the mover that is currently at the station. This allows commands to the movers to go through the stations so logic can be configured on a station level rather than on a mover level.
With these methods and properties, we can better understand what the existing stations are doing.
// Station 0 Logic
IF Station[0].MoverInPosition THEN
StationTimer[0](IN := TRUE, PT := T#1000MS);
IF StationTimer[0].Q THEN
Station[0].CurrentMover.SetVelocity(mediumVelocity);
Station[0].CurrentMover.MoveToStation(Station[1]);
END_IF
ELSE
StationTimer[0](IN := FALSE);
END_IF
Station 0 is straightforward. Once a mover arrives, the logic waits for 1 second before setting the velocity to medium velocity and sending the mover to station 1.
// Station 1 Logic
IF Station[1].MoverInPosition THEN
StationTimer[1](IN := TRUE, PT := T#250MS);
IF StationTimer[1].Q THEN
Station[1].CurrentMover.SetVelocity(mediumVelocity);
Station[1].CurrentMover.MoveToStation(Station[nextStation]);
nextStation := nextStation - 1;
IF nextStation = 1 THEN
nextStation := 4;
END_IF
END_IF
ELSE
StationTimer[1](IN := FALSE);
END_IF
Station 1 has some similar logic. It only waits for 250 milliseconds and then rotates through sending to station 4, then station 3, then station 2, then back to station 4. This is a great example of how you can use the XTS system to multi-task with processes that have higher cycle times.
// Group of Stations 2, 3, and 4 Logic
IF Station[2].MoverInPosition AND Station[3].MoverInPosition AND Station[4].MoverInPosition THEN
StationTimer[2](IN := TRUE, PT := T#750MS);
IF StationTimer[2].Q THEN
StationTimer[2](IN := FALSE);
Station[2].CurrentMover.MoveVelocity(500);
Station[3].CurrentMover.MoveVelocity(500);
Station[4].CurrentMover.MoveVelocity(500);
END_IF
END_IF
Stations 2 through 4 have their logic combined since they’re intended to be parallel processes. Once a mover has arrived in each of the three stations, the logic waits for 750 milliseconds before commanding all three movers to move at 500mm/s.
If we’re commanding these movers to move at 500mm/s until they receive another command, how will they ever stop? The first answer is that they have collision avoidance, so the movers will stop if they would run into a mover ahead of them. The second answer is that we have position triggers further along the track to give them new commands. In the next blog in this series, we will go over position triggers.
If you’d like help with the next steps for your XTS system, DMC is proud to be a Beckhoff System Integrator and has worked on multiple XTS projects and applications. Learn more about our Beckhoff partnership and contact us for your next project.
Ready to take your Automation project to the next level? Contact us today to learn more about our solutions and how we can help you achieve your goals.