APIs, concepts, guides, and more
Compensator

Use compensators to add delta offsets to an axis's position based on stored position data for compensating surface irregularities.

🔹 Introduction

A compensator can be used to add a delta offset on the position of one axis based on the position of one or two axis. An example use case would compensating the Z (vertical) axis for X-Y surface irregularities.

In order for your compensator to work you will need to externally collect data on the Z axis deltas for each of the data points in your table. These measurements could be taken manually or if your machine has a touch probe you could write a program to build your compensation table for you.

The compensator works by adding an offset to the position of an axis based on positions stored in a table. This offset is applied right before data is sent do the drive and does not change command position. How data will be retrieved from the table is defined by a min, max, and delta for each input axis.

🔹 Determining required configuration parameters

To configure a compensator, first define the X-Y area to be compensated (Xmin to Xmax, Ymin to Ymax). Then define the spacing of the data points points (delta) for the X and Y axes to determine the compensation table size.

Note
The delta must be a multiple of the difference between the min and the max.

The range in which the compensator will be applied is defined by the min and max. The delta defines the amount of travel between the next compensation value in the table. Linear interpolation is used between points. To determine the number of compensation points required you can use the following equations.

1D Compensation: Points = (positionMax-positionMin) / positionDelta + 1

2D Compensation: Points = PointsX * PointsY

For example:

Image

Axis Min Max Delta
X 0 200000 50000
Y 25000 225000 10000

X_Points = (200000-0)/50000 + 1 = 5\ Y_Points = (225000-25000)/10000 +1 = 21

CompensatorPoints = X_Points * Y_Points = 105

🔹 Pre-allocating memory

Once you know the number of compensators you plan to use and the number of points in the respective tables the functions CompensatorCountSet and CompensatorPointCountSet to reserve memory in the motion controller for the compensator. This must be done before initializing objects that use dynamic memory (Like axes). This will reserve the space in memory on the motion controller. To check the amount of memory available for the compensator and other RSI objects you can check ExternalMemorySizeGet.

🔹 Configure Your Compensator

Once you have started the network you can call CompensatorConfigSet(...) to configure and enable your compensator. To disable your compensator you can use CompensatorDisable(...). For a full list of available functions see our RapidCode API.

Warning
Compensators use counts NOT User Units
Note
Compensator does not affect your command position. The command and compensator output are combined right before getting sent to the drive. You can use CompensatorPositionGet() to see the result of your compensator(s). The compensator will change your actual position Make sure your position error limit is larger than the difference between your largest and smallest compensation table values.
Multiple compensators can be applied to an axis. Overlapping compensators will add to their result.

🔹 Example table

For example, if you were at X=100000 and Y=115000 The value of -1800 counts would be added to your Z target.

Image

Image

🔹 Single Axis Compensator

It is also possible to set up a compensator with the same input and output axis. Such compensators must be configured to use the input axis's command position as the actual position would cause a feedback loop.

An example use case for this feature would be correcting position errors caused by mechanical imperfections in an actuator.

Here is an example of how a commanded position vs a corrected position graph could look for a single axis compensator.

Image

📜 Sample Code

1D Compensator

  • C#

    // To use a compensator space in memory must be reserved before creating axis objects. For this sample app we will create two overlapping compensation tables.
    controller.CompensatorCountSet(2);
    // To know how much memory will be required for the compensator table you must first know your MIN, MAX, and DELTA. See our compensator topic page for more information.
    const int MIN = 0; // The smallest value in counts on the input axis where a table will be applied to the output axis.
    const int MAX = 200; // The largest value in counts on the input axis where a table will be applied to the output axis.
    const int DELTA = 10; // The number of encoder counts on the input axis between values in the table.
    const int POINTS = ((MAX - MIN) / DELTA) + 1; // The space required in memory for the table to be held. (21)
    // Compensator table values use Axis COUNTS NOT user units to be applied to the output axis.
    double[] TABLE0 = new double[POINTS] { 0, 1000, -5000, -10000, 10000, 5000, -5000, 2500, 0, 2500, 5000, 7500, 1000, 1250, 1000, 7500, 5000, 2500, 0, -2500, -1000 };
    double[] TABLE1 = new double[POINTS] { 0, 500, 0, 0, 0, 0, 0, 0, 0, 0, 1000, -5000, -1000, 1000, 5000, -5000, 2500, 0, -1000, 0, 0 };
    // Reserve space in memory for the compensator tables.
    controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE0.Length);
    controller.CompensatorPointCountSet(Constants.COMP_NUM_ONE, TABLE1.Length);
    controller.AxisCountSet(2);
    Axis moving_axis = CreateAndReadyAxis(Constants.MAIN_AXIS_NUMBER); // Helper function to setup an axis
    Axis follower_axis = CreateAndReadyAxis(Constants.DRIVEN_AXIS_NUMBER); // Helper function to setup an axis
    // NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
    if (controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO) == TABLE0.Length && POINTS == TABLE0.Length)
    {
    // Initalize the Compensator
    controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, moving_axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, MIN, MAX, DELTA, follower_axis, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE0);
    // You can also configure multiple overlaping compensation tables. Note the first compensator remains in SINGLE mode but the second is set to ADDITIVE
    controller.CompensatorConfigSet(Constants.COMP_NUM_ONE, moving_axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, MIN, MAX, DELTA, follower_axis, RSICompensatorOutputType.RSICompensatorOutputTypeADDITIVE, TABLE1);
    }

2D Compensator

  • C#

    // Constants
    const int X_MIN = 0;
    const int X_MAX = 500;
    const int X_DELTA = 100;
    const int Y_MIN = 0;
    const int Y_MAX = 500;
    const int Y_DELTA = 100;
    const int COMPENSATOR_X_POINTS = ((X_MAX - X_MIN) / X_DELTA) + 1;
    const int COMPENSATOR_Y_POINTS = ((Y_MAX - Y_MIN) / Y_DELTA) + 1;
    const int POINTS = (COMPENSATOR_X_POINTS) * (COMPENSATOR_Y_POINTS);
    // Compensator uses Axis COUNTS NOT user units
    double[] TABLE = new double[POINTS] {
    0, 0, 0, 0, 0, 0,
    100, 200, -200, 10, 300, 0,
    100, 200, -500, 400, 500, 0,
    0, 0, 0, 0, 0, 0,
    -300, 300, -300, -300, -300, 0,
    0, 0, 0, 0, 0, 0,
    };
    // To use a compensator space in memory must be reserved before creating axis objects. For this sample app we will create two overlapping compensation tables.
    controller.CompensatorCountSet(1);
    controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE.Length);
    // Initialize Axes. (Use RapidSetup Tool to see what is your axis number)
    controller.AxisCountSet(3);
    Axis x = CreateAndReadyAxis(Constants.X_AXIS_NUMBER);
    Axis y = CreateAndReadyAxis(Constants.Y_AXIS_NUMBER);
    Axis z = CreateAndReadyAxis(Constants.Z_AXIS_NUMBER);
    z.ErrorLimitTriggerValueSet(1); // Specify the position error limit trigger. (Learn more about this on our support page)
    // Initalize the Compensator
    controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, x, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, X_MIN, X_MAX, X_DELTA, y, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, Y_MIN, Y_MAX, Y_DELTA, z, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE);

Single Axis Compensator

  • C#

    // Constants
    const int MIN = 10;
    const int MAX = 210;
    const int DELTA = 10;
    const int POINTS = ((MAX - MIN) / DELTA) + 1; //21
    // Compensator uses Axis COUNTS NOT user units
    double[] TABLE = new double[POINTS] { 0, 2, -3, -5, -3, 2, -3, 0, 2, -3, -5, -3, 2, -3, 0, 2, -3, -5, -3, 2, -3 };
    // Setup memory space for the compensator
    controller.CompensatorCountSet(1);
    controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE.Length);
    // Initialize Axes. (Use RapidSetup Tool to see what is your axis number)
    controller.AxisCountSet(1);
    Axis axis = CreateAndReadyAxis(Constants.AXIS_NUMBER);
    // NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
    if (controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO) == TABLE.Length && POINTS == TABLE.Length)
    {
    controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_COMMAND_POSITION, MIN, MAX, DELTA, axis, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE);
    axis.MoveSCurve(DELTA * 2); // Note multiply by to to get to index because min=delta
    axis.MotionDoneWait();
    controller.SampleWait(Constants.SAMPLES);
    }