Digital switch complete code
This page contains the complete code of Digital Switch.
In DigitalSwitch.cpp
, your digital switch code should be as follows:
Copy
#include "RT_Project_01.h"
#include "SingleAxisMotion.h"
#include "GroupMotion.h"
#include "DigitalSwitch.h"
#include <vector>
using namespace std;
VOID DigitalCamSwitch(int Index)
{
RtPrintf("Enable digital cam switches using an axis' position.\n\n");
BOOL Value = FALSE;
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero: %d\n\n", Value);
//Defines each switch. Each track can have up to eight switches.
//TrackNumber: the index of the track a switch belongs to.
//FirstOnPosition: the position at which the switch is enabled.
//LastOnPosition: the position at which the switch is disabled for distance switches.
//AxisDirection: the direction in which the switch is triggered. 0: Both, 1: Positive, 2: Negative.
//CamSwitchMode: the switch mode. 0: Distance, 1: Time.
//Duration: the duration in seconds the switch stays enabled. For time switches.
//The first three switches correspond to Output[0], the last corresponds to Output[1].
McCamSwitch Switches[4] =
{
//TrackNumber FirstOnPosition LastOnPosition AxisDirection CamSwitchMode Duration
{ 0, 2000, 3000, 1, 0, 0 },
{ 0, 2500, 3000, 2, 0, 0 },
{ 0, 4000, 6000, 0, 0, 0 },
{ 1, 3000, 0, 0, 1, 1.35 }
};
//On compensation is a delay in seconds before the output is turned on when a switch becomes active.
//Off compensation is a delay in seconds before the outout is turned off when a switch becomes inactive.
//Hysteresis adds a minimum distance in between switches to prevent an output from switching on and off.
McTrack Tracks[2] =
{
//OnCompensation OffCompensation Hysteresis
{ -0.125, 0.25, 0 },
{ 0, 0, 0 }
};
//Defines the output for each track.
//Each track controls one output.
//The type selects between axes and I/O modules. TRUE: Axis, FALSE: I/O module.
//The index of the axis or I/O module.
//The offset of the output bit in the output buffer of a device.
McOutput Outputs[2] =
{
//Axis Index Offset
{ FALSE, 2, 0 },
{ FALSE, 3, 0 }
};
KsCommandStatus camSwitch = WaitForCommand(5, FALSE, SetAxisCamSwitch(
Index, //Index
4, //SwitchLength
Switches, //Switches
2, //TrackLength
Outputs, //Outputs
Tracks, //Tracks
3, //EnableMask, enabling Track Zero and One
mcSetValue //ValueSource
));
/*-----Trigger the first switch-----*/
RtPrintf("-----Trigger the first switch-----\n\n");
//Move an axis to trigger a switch.
RtPrintf("Make an absolute move.\n\n");
//Start an absolute move.
KsCommandStatus absolute = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2700,
1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 1st switch: %d\n\n", Value);
/*-----Trigger the second switch-----*/
RtPrintf("-----Trigger the second switch-----\n\n");
/*Reset Value to zero to check whether the value become one when 2nd switch is triggered.
If we don't reset it, we won't know the "1" in value is from the 1st or 2nd switch.*/
Value = 0;
RtPrintf("Reset output bit to %d.\n\n", Value);
//Move the axis to the position 3600.
RtPrintf("Make absolute moves.\n\n");
absolute = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3600, 1000,
10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
//Move the axis to the position 2800.
/*We do this because the AxisDirection of the 2nd switch is negative.
The axis needs to past LastOnPosition first, and then move back to the
switch-on range so the switch can be triggered.*/
absolute = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2800, 1000,
10000, 10000, 1000000, mcNegativeDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 2nd switch: %d\n\n", Value);
/*-----Trigger the third switch-----*/
RtPrintf("-----Trigger the third switch-----\n\n");
Value = 0;
RtPrintf("Reset output bit to %d.\n\n", Value);
//Move the axis to the position 5000.
RtPrintf("Make an absolute move.\n\n");
absolute = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 5000, 1000,
10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 3rd switch: %d\n\n", Value);
/*-----Trigger the fourth switch-----*/
RtPrintf("-----Trigger the fourth switch-----\n\n");
Value = 0;
RtPrintf("Reset output bit to %d.\n\n", Value);
//Move the axis to the position 3000.
RtPrintf("Make an absolute move.\n\n");
absolute = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3000, 1000,
10000, 10000, 1000000, mcNegativeDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(3, 0, &Value);
RtPrintf("Read the output bit corresponding to Track One, 4th switch: %d\n\n", Value);
}
VOID GroupCamSwitch(int Group)
{
RtPrintf("Enable group digital cam switches using a group's distance.\n\n");
/*Value is used to check whether a switch has been triggered. By default,
it is FALSE (zero).*/
BOOL Value = FALSE;
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero: %d\n\n", Value);
//Defines each switch. Each track can have up to eight switches.
//TrackNumber: the index of the track a switch belongs to.
/*FirstOnPosition: the distance between the original starting position and FirstOnPosition
in a path motion command, must be nonnegative.*/
/*LastOnPosition: the distance between the original starting position and LastOnPosition
in a path motion command, must be positive and greater than FirstOnPosition.*/
//AxisDirection: not used, because FirstOnPosition and LastOnPosition are distance.
//CamSwitchMode: the switch mode. 0: Distance, 1: Time.
//Duration: the duration in seconds the switch stays enabled. For time switches.
//The first three switches correspond to Output[0], the last corresponds to Output[1].
McCamSwitch Switches[3] =
{
//TrackNumber FirstOnPosition LastOnPosition AxisDirection CamSwitchMode Duration
{ 0, 2000, 3000, 0, 0, 0 },
{ 0, 1000, 1500, 0, 0, 0 },
{ 1, 4000, 6000, 0, 1, 3 },
};
//On compensation is a delay in seconds before the output is turned on when a switch becomes active.
//Off compensation is a delay in seconds before the outout is turned off when a switch becomes inactive.
//Hysteresis adds a minimum distance in between switches to prevent an output from switching on and off.
McTrack Tracks[2] =
{
//OnCompensation OffCompensation Hysteresis
{ 0, 0, 0 },
{ 0, 0, 0 }
};
//Defines the output for each track.
//Each track controls one output.
//The type selects between axes and I/O modules. TRUE: Axis, FALSE: I/O module.
//The index of the axis or I/O module.
//The offset of the output bit in the output buffer of a device.
McOutput Outputs[2] =
{
//Axis Index Offset
{ FALSE, 2, 0 },
{ FALSE, 3, 0 }
};
const int LENGTH = 3; //The length of the Position array.
//First switch on: (1046.8, 1151.6, 1256.2) off: (1570.2, 1727.4, 1884.3)
//Second switch on: (523.4, 575.8, 628.1) off: (785.1, 863.65, 942.16)
//Third switch on: (2093.6, 2303.2, 2512.4) off: (3140.4, 3454.8, 3768.6)
//Unit vector: (0.5234, 0.5758, 0.6281)
double EndPositions[LENGTH] = { 5000, 5500, 6000 };
//Move an axis to trigger a switch.
RtPrintf("Make a linear absolute move.\n\n");
KsCommandStatus absolute = MoveLinearAbsolute(Group, LENGTH,
EndPositions, 500, 5000, 5000, 500000, mcAxisCoordSystem,
mcAborting, mcNone, NULL);
if (absolute.Error)
RtPrintf("MoveLinearAbsolute failed: %d\n", absolute.ErrorId);
KsCommandStatus groupCamSwitch = SetGroupPathCamSwitch(
Group, //Index
absolute, //MotionCommand
3, //SwitchLength
Switches, //Switches
2, //TrackLength
Outputs, //Outputs
Tracks, //Tracks
3 //EnableMask, enabling Track Zero and One
);
/*-----Calculate where the switches will be triggered-----*/
RtPrintf("Calculate where the switches will be triggered.\n\n");
double axisDistance[3] = { 0 };
double startPosition[3] = { 0 };
double currentPosition[3] = { 0 };
double Square[3] = { 0 };
//Calculate the square of each EndPosition.
Square[0] = pow(EndPositions[0], 2);
Square[1] = pow(EndPositions[1], 2);
Square[2] = pow(EndPositions[2], 2);
//Calculate the square root of the sum of each EndPositions' square number.
double sqrtRoot = sqrt(Square[0] + Square[1] + Square[2]);
printf("Square root: %f\n\n", sqrtRoot);
//Calculate the unit vector for each axis.
double unitVector[3] = { 0 };
unitVector[0] = EndPositions[0] / sqrtRoot;
unitVector[1] = EndPositions[1] / sqrtRoot;
unitVector[2] = EndPositions[2] / sqrtRoot;
//Display each unit vector.
/*After we get unit vectors, we need to calculate how many units an axis should
move to trigger a switch. The equations are as follows:
unitVector * FirstOnPosition = A
unitVector * LastOnPosition = B
The range between A and B is where a switch is triggered.*/
printf("unitVector[0]: %f\n", unitVector[0]);
printf("unitVector[1]: %f\n", unitVector[1]);
printf("unitVector[2]: %f\n\n", unitVector[2]);
for (int i = 0; i < 3; i++)
{
printf("unitVector[%d] * Switches[%d].FirstOnPosition: %f\n", i, i, unitVector[i] * Switches[i].FirstOnPosition);
printf("unitVector[%d] * Switches[%d].LastOnPosition: %f\n", i, i, unitVector[i] * Switches[i].LastOnPosition);
}
RtPrintf("\n");
/*-----Trigger the switches-----*/
RtPrintf("Trigger the switches.\n\n");
//Use vector to declare a dynamic array that creates a range-based for loop.
vector<int> Loop = { 1, 0, 2 };
/*Count is a flag used to check whether a switch's output has been read and displayed.
If it has, the count value will be incremented. This flag can ensure RtPrintf is executed
only once when it displays the output of the switch.*/
int Count = 0;
while (!absolute.Done)
{
//Get the state of MoveLinearAbsolute and pass it to absolute.
absolute = GetCommandStatus(absolute);
//Get the set position of a group.
GetGroupPosition(Group, mcAxisCoordSystem, mcSetValue, LENGTH, currentPosition);
//Calculate how far three axes move.
axisDistance[0] = currentPosition[0] - startPosition[0];
axisDistance[1] = currentPosition[1] - startPosition[1];
axisDistance[2] = currentPosition[2] - startPosition[2];
/*Use for loop to check whether the switches are triggered.
The switches are triggered in this sequence: 2->1->3.*/
for (auto i : Loop)
{
/*Value is used to check whether a switch has been triggered. If it has,
Value will be changed to one and displayed, and then be reset for the
next switch.*/
Value = 0;
//Check whether the axes trigger their own switches.
if (axisDistance[i] >= (unitVector[i] * Switches[i].FirstOnPosition) &&
axisDistance[i] <= (unitVector[i] * Switches[i].LastOnPosition))
{
/*Use switch-case statement to test whether a switch has been triggered.
If it has, display its output value once.*/
switch (i)
{
//Check whether the second switch is triggered.
case 1:
if (Count >= 1)
continue;
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 2nd switch: %d\n", Value);
Count++;
break;
//Check whether the first switch is triggered.
case 0:
if (Count >= 2)
continue;
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 1st switch: %d\n", Value);
Count++;
break;
//Check whether the third switch is triggered.
case 2:
if (Count >= 3)
continue;
ReadOutputBit(3, 0, &Value);
RtPrintf("Read the output bit corresponding to Track One, 1st switch: %d\n\n", Value);
Count++;
break;
default:
RtPrintf("Out of range.\n\n");
}
}
}
}
//Wait 1 millisecond to make sure everything is done.
//On the computers that have better performance, this command can be skipped.
Sleep(1);
//Get the state of SetGroupPathCamSwitch and pass it to groupCamSwitch.
groupCamSwitch = GetCommandStatus(groupCamSwitch);
//Display the Done state of MoveLinearAbsolute and SetGroupPathCamSwitch.
RtPrintf("MoveLinearAbsolute.Done: %d\n", absolute.Done);
RtPrintf("SetGroupPathCamSwitch.Done: %d\n\n", groupCamSwitch.Done);
//Display end positions of all axes.
RtPrintf("End position:\n");
GetAGroupPosition(Group);
}
VOID DigitalCyclicSwitch(int Index)
{
RtPrintf("Enable a cyclic switch using an axis' position.\n\n");
BOOL Value = FALSE;
BOOL Switches = 0;
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero: %d\n\n", Value);
//The position at which the switch is enabled.
//The position at which the switch is disabled for distance switches.
//The direction in which the switch is triggered. 0: Both, 1: Positive, 2: Negative.
//The switch mode. 0: Distance, 1: Time.
//The duration in seconds the switch stays enabled. For time switches.
//TrackNumber: must be zero.
/*FirstOnPosition: must be nonnegative. It is the distance relative to each cycle's
starting position.*/
/*LastOnPosition: must be positive and greater than FirstOnPosition. It is the distance
relative to each cycle's starting position.*/
//Duration: must be positive.
//Trigger the switch by distance.
McCamSwitch cyclicSwitch1 =
{
//TrackNumber FirstOnPosition LastOnPosition AxisDirection CamSwitchMode Duration
0, 300, 600, 1, 0, 0
};
//Trigger the switch by time.
McCamSwitch cyclicSwitch2 =
{
//TrackNumber FirstOnPosition LastOnPosition AxisDirection CamSwitchMode Duration
0, 400, 700, 1, 1, 0.5
};
//Defines the output for the track.
//The type selects between axes and I/O modules. TRUE: Axis, FALSE: I/O module.
//The index of the axis or I/O module.
//The offset of the output bit in the output buffer of a device.
McOutput Output =
{
//Axis Index Offset
FALSE, 2, 0
};
if (Switches == 0)
{
//Trigger the switch by distance.
KsCommandStatus digitalCyclicSwitch = WaitForCommand(5, FALSE, SetAxisCyclicSwitch(
Index, //Index
Output, //Output
100, //StartPosition
cyclicSwitch1, //CyclicSwitch
mcDistance, //IntervalType
1000, //Intreval
mcDistance, //Durationtype
3500, //Duration
mcSetValue //ValueSource
));
RtPrintf("Trigger the switch by distance.\n\n");
}
else
{
//Trigger the switch by time.
KsCommandStatus digitalCyclicSwitch = WaitForCommand(5, FALSE, SetAxisCyclicSwitch(
Index, //Index
Output, //Output
1000, //StartPosition
cyclicSwitch2, //CyclicSwitch
mcTime, //IntervalType
1, //Intreval
mcDistance, //Durationtype
3500, //Duration
mcSetValue //ValueSource
));
RtPrintf("Trigger the switch by time.\n\n");
}
/*-----Trigger the switch in the first cycle-----*/
RtPrintf("-----Trigger the switch in the first cycle-----\n\n");
//Move an axis to trigger a switch.
RtPrintf("Make an absolute move.\n\n");
//Start an absolute move.
KsCommandStatus absolute = WaitForCommand(10, TRUE, MoveAxisAbsolute(Index, 1500,
1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 1st cycle: %d\n\n", Value);
/*-----Trigger the switch in the second cycle-----*/
RtPrintf("-----Trigger the switch in the second cycle-----\n\n");
Value = 0;
RtPrintf("Reset output bit to %d.\n\n", Value);
absolute = WaitForCommand(5, TRUE, MoveAxisAbsolute(Index, 2500,
1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 2nd cycle: %d\n\n", Value);
/*-----Trigger the switch in the third cycle-----*/
RtPrintf("-----Trigger the switch in the third cycle-----\n\n");
Value = 0;
RtPrintf("Reset output bit to %d.\n\n", Value);
absolute = WaitForCommand(5, TRUE, MoveAxisAbsolute(Index, 3500,
1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
if (absolute.Error)
RtPrintf("MoveAxisAbsolute failed: %d\n", absolute.ErrorId);
//Wait a few cycles to get the correct end positions.
Sleep(5);
RtPrintf("End position:\n");
GetAnAxisPosition(Index);
ReadOutputBit(2, 0, &Value);
RtPrintf("Read the output bit corresponding to Track Zero, 3rd cycle: %d\n\n", Value);
}