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:

  1. 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.
  2. Use SetAxisCyclicSwitch to set digital cyclic switches. When Switches is equal to zero, it uses the distance switch; when Switches is equal to another value, it uses the time switch. By default, we use the distance switch.
  3. Copy
        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");
        }
  4. 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.
  5. Since we use GetAnAxisPosition in Chapter 5: Single-Axis Motion > Get and Set values, you need to include SingleAxisMotion.h.

    Copy
        /*-----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);
  6. Use ReadOutputBit to read the digital output controlled by the track.
  7. Copy
        ReadOutputBit(2, 0, &Value);

        RtPrintf("Read the output bit corresponding to Track Zero, 1st cycle: %d\n\n", Value);
  8. Next, we trigger the switch in the second cycle. The second cycle's switch-on range is 2300 – 2600. Our target position is 2500.
  9. Copy
        /*-----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);

  10. 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.
  11. 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.

    Copy
        /*-----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:

Copy
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: