Use digital cam switch

To set digital cam switches, you need to define how switches are triggered and select the outputs to be controlled by switches. In this section, you'll learn how to use SetAxisCamSwitch to set digital cam switches and use them to control digital outputs' value.

Process for using digital cam switch

The following process shows how digital cam switches are set:

McCamSwitch, McTrack, and McOutput -> SetAxisCamSwitch -> MoveAxis -> ReadOutputBit

Structures

McCamSwitch: defines a digital cam switch.

McTrack: time compensation and hysteresis to be applied to a switch on a track.

McOutput: selects which digital output will be controlled.

Functions

SetAxisCamSwitch: uses an axis' position to control a switch that controls a digital output. When the axis reaches a certain position, the 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 cam switch code into steps to explain. In the last part, we combine all the code for you to see the completed one.

In DigitalCamSwitch.cpp, add the following code:

  1. Use McCamSwitch, McTrack, and McOutput to configure the settings of digital cam switches. There is no priority among them. In this guide, we configure switches first, in which you set tracks to contain switches, and use axis' positions or duration to determine where and how long a switch is on. Each track can have up to eight switches. The positions are set by FirstOnPosition and LastOnPosition. The duration is set by FirstOnPosition and Duration.
  2. Use SetAxisCamSwitch to set digital cam switches.
  3. Copy
        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
        ));
  4. Move an axis to trigger the first switch. We use MoveAxisAbsolute to move it and read the axis' position to make sure the axis reaches the target. Since we use GetAnAxisPosition in Chapter 5: Single-Axis Motion > Get and Set values, you need to include SingleAxisMotion.h.
  5. Copy
        /*-----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 status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2700,
            1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
        if (status.Error)
            RtPrintf("MoveAxisAbsolute failed: %d\n", status.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 first digital output controlled by the first track.
  7. Copy
        ReadOutputBit(2, 0, &Value);

        RtPrintf("Read the output bit corresponding to Track Zero, 1st switch: %d\n\n", Value);
  8. Next, we are triggering the second switch. This switch is a bit different because its AxisDirection is negative. To trigger it, you have to move the axis past LastOnPosition, and then move it back to the range between FirstOnPosition and LastOnPosition, so the switch can be triggered when axis is moving in the negative direction.
  9. Copy
        /*-----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");

        status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3600, 1000,
            10000, 10000, 1000000, mcPositiveDirection, mcAborting));
        if (status.Error)
            RtPrintf("MoveAxisAbsolute failed: %d\n", status.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.*/
        status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2500, 1000,
            10000, 10000, 1000000, mcNegativeDirection, mcAborting));
        if (status.Error)
            RtPrintf("MoveAxisAbsolute failed: %d\n", status.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);

  10. Move the axis to trigger the third switch. The third allows positive and negative directions, so all we need to do is to move the axis into the specified range.
  11. Copy
        /*-----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");

        status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 5000, 1000,
            10000, 10000, 1000000, mcPositiveDirection, mcAborting));
        if (status.Error)
            RtPrintf("MoveAxisAbsolute failed: %d\n", status.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);

  12. The fourth switch is controlled by time. We move the axis to FirstPosition to trigger it. Notice that this switch is connected to the second output, so you need to read the second output's bit.
  13. Copy
        /*-----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");

        status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3000, 1000,
            10000, 10000, 1000000, mcNegativeDirection, mcAborting));
        if (status.Error)
            RtPrintf("MoveAxisAbsolute failed: %d\n", status.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, 1st switch: %d\n\n", Value);
    }

Complete code

The complete code should be like this:

Copy
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.
    //The index of the track a switch belongs to.
    //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.
    //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   }
    };

    //Each track controls one output and can contain multiple switches.
    //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.
    //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 status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2700,
        1000, 10000, 10000, 1000000, mcPositiveDirection, mcAborting));
    if (status.Error)
        RtPrintf("MoveAxisAbsolute failed: %d\n", status.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");

    status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3600, 1000,
        10000, 10000, 1000000, mcPositiveDirection, mcAborting));
    if (status.Error)
        RtPrintf("MoveAxisAbsolute failed: %d\n", status.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.*/
    status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 2500, 1000,
        10000, 10000, 1000000, mcNegativeDirection, mcAborting));
    if (status.Error)
        RtPrintf("MoveAxisAbsolute failed: %d\n", status.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");

    status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 5000, 1000,
        10000, 10000, 1000000, mcPositiveDirection, mcAborting));
    if (status.Error)
        RtPrintf("MoveAxisAbsolute failed: %d\n", status.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");

    status = WaitForCommand(30, TRUE, MoveAxisAbsolute(Index, 3000, 1000,
        10000, 10000, 1000000, mcNegativeDirection, mcAborting));
    if (status.Error)
        RtPrintf("MoveAxisAbsolute failed: %d\n", status.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, 1st switch: %d\n\n", Value);
}