Main function

In this section, you'll learn how to apply all the code in this chapter to main.cpp. If everything is done correctly, you should be able to gear your axis properly. To help you review what you have learned, we add comments into the code to describe the meaning of the functions.

  1. In main.cpp, under Cam.h, add the following code:
  2. Copy
    #include "Gear.h"
  3. In int _tmain, under the code block if (!StartKingstar()), add the following code to get the number of devices on your EtherCAT network.
  4. Copy
        //Create an instance of the SubsystemStatus structure and get the state from it.
        SubsystemStatus Subsystem = { ecatOffline, ecatOffline, 0, 0, 0, {ecatOffline}, {ecatOffline}, {axisOffline} };
        GetStatus(&Subsystem, NULL);

        //Display the details of the EtherCAT network.
        RtPrintf("Number of Devices found: %d\n", Subsystem.SlaveCount);
        RtPrintf("Number of Axes found: %d\n", Subsystem.AxesCount);
        RtPrintf("Number of I/O found: %d\n", Subsystem.IOCount);
        RtPrintf("\n");
  5. Under RtPrintf("\n");, add the following code to gear an axis. To see the gearing result, we need to move the master axis. The slave's velocity is always following the master while it is geared. The slave's position is also following the master's position based on the gear ratio.
  6. We display the details of the servo drives so you know we use two different drives for gearing. We set the motion profiles, convert the units, and tune the PIDs. You can use the function from Chapter 4 to do this. Note that we use the bool variable Gear to toggle between Gear (SetAxisGear) and Gear-In-Position (SetAxisGearInPos). By default, the Gear code will be run.

    Copy
        //Declare indexes for axes and a gear state.
        int Master = 2;
        int Slave = 6;
        double setPosition = 0;
        KsCommandStatus gear = { 0 };

        //Display the information of devices.
        PrintDeviceInformation(Master);
        PrintDeviceInformation(Slave);

        //Set motion profiles.
        //You need to set motion profiles, or the minimum following error will be large.
        MotionProfile(Master);
        MotionProfile(Slave);

        //Convert the unit. In this tutorial we convert it to degrees.
        PositionUnitConversion(Master);
        PositionUnitConversion(Slave);

        //PID tuning.
        /*When you use velocity or torque modes, you must tune PID.
          In this tutorial we use modeMasterIntPos, which doesn't require PID,
          but you should offer PID values for your drive to get the best performance.*/
        UpdatePID(Master);
        UpdatePID(Slave);

        //Enable axes.
        EnableAxis(Master);
        EnableAxis(Slave);

        //Set a starting position for the master and slave axes.
        SetAxisPositionOffset(Master, setPosition, FALSE, mcImmediately);
        SetAxisPositionOffset(Slave, setPosition, FALSE, mcImmediately);
        printf("Master starting position:\n");
        GetAnAxisPosition(Master);
        printf("Slave starting position:\n");
        GetAnAxisPosition(Slave);

        BOOL Gear = TRUE;   //TRUE: Gear. FALSE: Gear in position.
        if (Gear)
        {
            RtPrintf("Make a velocity move to use Gear.\n\n");

            //Gear the axes.
            gear = AssignGearSlave(Master, Slave);
        }

        else
        {
            double MasterPosition = -80;
            double SlavePosition = -100;

            RtPrintf("Make a velocity move to use GearInPos.\n\n");
            
            //To use SetAxisGearInPos, we need to use MoveAxisVelocity to move the master a bit.
            MoveAxisVelocity(Master, 100, 1000, 1000, 10000, mcNegativeDirection, mcBuffered);

            Sleep(100);

            //Gear in position.
            gear = AssignGearInPosSlave(Master, Slave, MasterPosition, SlavePosition);
        }

        //Move the master and display its position and velocity.
        RtPrintf("Master axis:\n");

        /*Move the master again for the slave to follow its velocity.
          Remember not to set the master's velocity too high,
          or the slave may not be able to follow the master.*/
        MoveAxisVelocity(Master, 360, 3600, 3600, 360000, mcNegativeDirection, mcBuffered);
        Sleep(1000);

        //Display the master's position and velocity.
        RtPrintf("End position:\n");
        GetAnAxisPosition(Master);
        GetAnAxisVelocity(Master);
        RtPrintf("----------\n\n");

        //Display the slave's position and velocity.
        RtPrintf("Slave axis:\n");
        RtPrintf("End position:\n");
        GetAnAxisPosition(Slave);
        GetAnAxisVelocity(Slave);

        //Check whether the axes are synchronized.
        if (gear.InSync)
            RtPrintf("The master and slave axes are synchronized.\n\n");

        Halt(Master);

        //Detach the slave axis from the master.
        RemoveGearSlave(Slave);
        
        //Disable axes.
        DisableAxis(Master);
        DisableAxis(Slave);

Complete code

In conclusion, in main.cpp, your code should be as follows:

Copy
#include "RT_Project_01.h"
#include "SystemInitialization.h"
#include "IOModule.h"
#include "AxisConfiguration.h"
#include "SingleAxisMotion.h"
#include "Homing.h"
#include "Cam.h"
#include "Gear.h"

int _tmain(int argc, _TCHAR * argv[])
{
    //Start the KINGSTAR Subsystem.
    if (!StartKingstar())
    {
        RtPrintf("The KINGSTAR Subsystem is not started.\n");
        return -1;
    }

    else
        RtPrintf("The KINGSTAR Subsystem is started.\n");

    RtPrintf("\n");

    //Create an instance of the SubsystemStatus structure and get the state from it.
    SubsystemStatus Subsystem = { ecatOffline, ecatOffline, 0, 0, 0, {ecatOffline}, {ecatOffline}, {axisOffline} };
    GetStatus(&Subsystem, NULL);

    //Display the details of the EtherCAT network.
    RtPrintf("Number of Devices found: %d\n", Subsystem.SlaveCount);
    RtPrintf("Number of Axes found: %d\n", Subsystem.AxesCount);
    RtPrintf("Number of I/O found: %d\n", Subsystem.IOCount);
    RtPrintf("\n");

    //Declare indexes for axes and a gear state.
    int Master = 2;
    int Slave = 6;
    double setPosition = 0;
    KsCommandStatus gear = { 0 };

    //Display the information of devices.
    PrintDeviceInformation(Master);
    PrintDeviceInformation(Slave);

    //Set motion profiles.
    //You need to set motion profiles, or the minimum following error will be large.
    MotionProfile(Master);
    MotionProfile(Slave);

    //Convert the unit. In this tutorial we convert it to degrees.
    PositionUnitConversion(Master);
    PositionUnitConversion(Slave);

    //PID tuning.
    /*When you use velocity or torque modes, you must tune PID.
      In this tutorial we use modeMasterIntPos, which doesn't require PID,
      but you should offer PID values for your drive to get the best performance.*/
    UpdatePID(Master);
    UpdatePID(Slave);

    //Enable axes.
    EnableAxis(Master);
    EnableAxis(Slave);

    //Set a starting position for the master and slave axes.
    SetAxisPositionOffset(Master, setPosition, FALSE, mcImmediately);
    SetAxisPositionOffset(Slave, setPosition, FALSE, mcImmediately);
    printf("Master starting position:\n");
    GetAnAxisPosition(Master);
    printf("Slave starting position:\n");
    GetAnAxisPosition(Slave);

    BOOL Gear = TRUE;   //TRUE: Gear. FALSE: Gear in position.
    if (Gear)
    {
        RtPrintf("Make a velocity move to use Gear.\n\n");

        //Gear the axes.
        gear = AssignGearSlave(Master, Slave);
    }

    else
    {
        double MasterPosition = -80;
        double SlavePosition = -100;

        RtPrintf("Make a velocity move to use GearInPos.\n\n");
        
        //To use SetAxisGearInPos, we need to use MoveAxisVelocity to move the master a bit.
        MoveAxisVelocity(Master, 100, 1000, 1000, 10000, mcNegativeDirection, mcBuffered);

        Sleep(100);

        //Gear in position.
        gear = AssignGearInPosSlave(Master, Slave, MasterPosition, SlavePosition);
    }

    //Move the master and display its position and velocity.
    RtPrintf("Master axis:\n");

    /*Move the master again for the slave to follow its velocity.
      Remember not to set the master's velocity too high,
      or the slave may not be able to follow the master.*/
    MoveAxisVelocity(Master, 360, 3600, 3600, 360000, mcNegativeDirection, mcBuffered);
    Sleep(1000);

    //Display the master's position and velocity.
    RtPrintf("End position:\n");
    GetAnAxisPosition(Master);
    GetAnAxisVelocity(Master);
    RtPrintf("----------\n\n");

    //Display the slave's position and velocity.
    RtPrintf("Slave axis:\n");
    RtPrintf("End position:\n");
    GetAnAxisPosition(Slave);
    GetAnAxisVelocity(Slave);

    //Check whether the axes are synchronized.
    if (gear.InSync)
        RtPrintf("The master and slave axes are synchronized.\n\n");

    Halt(Master);

    //Detach the slave axis from the master.
    RemoveGearSlave(Slave);

    //Disable axes.
    DisableAxis(Master);
    DisableAxis(Slave);

    //Stop the KINGSTAR Subsystem.
    if (!StopKingstar())
    {
        RtPrintf("The KINGSTAR Subsystem is not stopped.\n");
        return -1;
    }

    else
        RtPrintf("The KINGSTAR Subsystem is stopped.\n");
  
    return 0;
}

NOTE:  To let you easily understand how to move an axis, we leave only necessary code in the main function. You can add more code depending on your needs.

NOTE:  You probably have noticed that some header files are not used because we didn't include their related functions in the main function. Feel free to comment out unused header files. In the tutorial, we preserve all the header files in case you want to use any of the functions you have learned.

 

Output:

SetAxisGear

Motion command: MoveAxisVelocity

Direction: negative