Digital cyclic switch
To set digital cyclic switches, you need to define how switches are triggered and select the output to be controlled by switches. In this section, you'll learn how to use SetAxisCyclicSwitch to set digital cyclic switches and use them to control digital outputs' value.
Process of using digital cyclic switch
The following process shows how digital cam switches are set:
McCamSwitch and McOutput -> SetAxisCyclicSwitch -> MoveAxis -> ReadOutputBit
Structures
McCamSwitch: defines a digital cyclic switch.
McOutput: selects which digital output will be controlled.
Functions
SetAxisCyclicSwitch: uses an axis' position to control a switch that triggers a digital output repeatedly. When an axis reaches a certain position, a switch is turned on or off. A switch can be controlled by a forward and backward movement of an axis.
ReadOutputBit: reads a bit from a digital output of a real or simulated I/O module.
Code
We divide the digital cyclic switch code into steps to explain. In the last part, we combine all the code for you to see the completed one.
In DigitalSwitch.cpp
, add the following code:
- Use McCamSwitch and McOutput to configure the settings of digital cyclic switches. There is no priority among them. In this guide, we configure switches first, in which you set a track to contain a switch, and use axis' positions or duration to determine where and how long a switch is on. The positions are set by FirstOnPosition and LastOnPosition. The duration is set by FirstOnPosition and Duration.
- In this guide, we defines two switches. One is triggered by distance and the other by time. We declare two variables.
Value
is for ReadOutputBit to use andSwitches
is to choose which switch we want to use. - Selects which digital output will be controlled by the track.
- Use SetAxisCyclicSwitch to set digital cyclic switches. When
Switches
is equal to zero, it uses the distance switch; whenSwitches
is equal to another value, it uses the time switch. By default, we use the distance switch. - Move an axis to trigger the distance switch. We use MoveAxisAbsolute to move it and read the axis' position to make sure the axis reaches the target. Notice that the target position is 1500, which is in the switch-on range – we set FirstOnPosition and LastOnPosition to 300 and 600 respectively, and set StartPosition to 1000. It means the switch will be triggered between 1300 and 1600 in the first cycle.
- Use ReadOutputBit to read the digital output controlled by the track.
- Next, we trigger the switch in the second cycle. The second cycle's switch-on range is 2300 – 2600. Our target position is 2500.
- Finally, we trigger the switch in the third cycle. The third cycle's switch-on range is 3300 to 3600. Our target position is 3500.
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");
}
Since we use GetAnAxisPosition in Chapter 5: Single-Axis Motion > Get and Set values, you need to include SingleAxisMotion.h
.
/*-----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);
NOTE: If there is fourth cycle, the range will be 4300 – 4600. Since StartPosition is 1000 and Duration is 3500, the cycle ends at 4500.
/*-----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);
}
Complete code
The complete code should be as follows:
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
3000, //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
3000, //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);
}
Output:
Triggered by distance:
Triggered by time: