The RMP Motion Controller APIs
User Limits

UserLimit directly sets a command position sample application. More...

Warning
This is a sample program to assist in the integration of the RMP motion controller with your application. It may not contain all of the logic and safety features that your application requires. We recommend that you wire an external hardware emergency stop (e-stop) button for safety when using our code sample apps. Doing so will help ensure the safety of you and those around you and will prevent potential injury or damage.

The sample apps assume that the system (network, axes, I/O) are configured prior to running the code featured in the sample app. See the Configuration page for more information.


📜 User Limit   Trigger: Digital Input Conditions: 1
This sample code is done in AKD Drive with one Actual axis. There are a lots of available/free firmware address. Some are suggested in comment. Avaiable/free firmware addess can be found using vm3 as long as there is no label on address, it can be used.

// Constants
const int INPUT_INDEX = 0; // This is the index of the digital input you will use to trigger the user limit.
const int OUTPUT_INDEX = 1; // This is the index of the digital output that will go active when the user limit triggers.
controller.AxisCountSet(1); // The number of user limits must not be greater than the number of axis and must be set before the number of user limits
controller.UserLimitCountSet(1); // Set the amount of UserLimits that you want to use. (every connected axis will automatically get 1 user limit)
controller.InterruptEnableSet(true); // Enable User Limit Interrupts. (When a user limit input comparison is met, and interrupt is triggered)
UInt64 userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0); // Grabing an memory address to store a simulated IO point.
//Instead of using physical IO we will use simulated IO using a memory address as simulated IO. See the IO sample apps to see how to use a physical IO instead.
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, INPUT_INDEX); // Create a simulated IOpoint using userBuffer memory.
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, OUTPUT_INDEX); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
//-------- PARAMETERS FOR UserLimitConditionSet --------
int userLimitNumber = 0; // Specify which user limit to use.
int condition = 0; // Specify which condition to use (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
RSIUserLimitLogic logic = RSIUserLimitLogic.RSIUserLimitLogicEQ; // Logic for input value comparison.
UInt64 inputAddress = input0.AddressGet(); // Use IOPoint or manually set using controller.NetworkInputAddressGet(INPUT_INDEX); for Beckhoff 10 was the index of 1st input. (To check your IO indexes go to RapidSetup -.
uint test = (uint)input0.MaskGet();
uint inputMask = (uint)input0.MaskGet(); // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
uint limtValue = (uint)input0.MaskGet(); // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
// [1] Configure the input's trigger condition.
controller.UserLimitConditionSet(userLimitNumber,// (User Limit Index) - Specify which user limit to use
condition, // (Condition Number) - Specify how many inputs you want to compare.
logic, // (Comparison Logic) - Specify the how the input value(s) will be compared
inputAddress, // (Input Address) - Specify the address of the input that will be compared.
inputMask, // (Input Mask) - Specify the bits in an address which need to be used when comparing inputs.
limtValue); // (Limit Value) - Specify the value to be compared with.
//-------- PARAMETERS FOR UserLimitConfigSet --------
RSIUserLimitTriggerType triggerType = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION;
RSIAction action = RSIAction.RSIActionNONE;
int axisNumber = 0;
int duration = 0;
// [2] Configure and Enable the user limit.
controller.UserLimitConfigSet(userLimitNumber,// (User Limit Index) - Specify which user limit to use.
triggerType, // (Trigger Type) - Specify how your condition should be evalutated.
action, // (User Limit Action) - Specify the action you want to cause on the axis when the user limit triggers.
axisNumber, // (Current Axis) - Specify the axis that the action (defined above) will occur on.
duration); // (Output Timer) - Specify the time delay before the action is executed after the User Limit has triggered.
//-------- PARAMETERS FOR UserLimitOutputSet --------
uint andMask = (uint)output0.MaskGet(); // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
uint orMask = (uint)output0.MaskGet(); // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
UInt64 outputAddress = output0.AddressGet(); //Alternatively set manually using: controller.NetworkOutputAddressGet(OUTPUT_INDEX);
bool enableOutput = true;
// [3] Configure what the output will be. (Call this method after UserLimitConfigSet if you want an output to be triggered) (The output will only be triggered if the input conditions are TRUE.)
controller.UserLimitOutputSet(userLimitNumber,// (User Limit Index) - Specify which user limit to use.
andMask, // (Logic AND Mask) - Specify the value that the digital output will be AND-ed with.
orMask, // (Logic OR Mask) - Specify the value that the digital output will be OR-ed with.
outputAddress, // (Output Address) - Specify the digital output address.
enableOutput); // (Enable Output Set) - If TRUE, the output AND-ing and OR-ing will be executed when the User Limit triggers.
while (controller.InterruptWait(250) != RSIEventType.RSIEventTypeUSER_LIMIT) // Loop will execute every 250 ms
{
Assert.False(output0.Get(), "We expect the output to NOT be triggered");
controller.MemorySet(input0.AddressGet(), 1);
}
Assert.True(output0.Get(), "We expect the output to be triggered");
controller.UserLimitDisable(userLimitNumber); // Disable User Limit.
output0.Set(false); // Disable User Limit.

Learn more in topic page.


📜 User Limit   Trigger: Digital Input Conditions: 2
This sample code shows how to configure the RMP controller's User Limits to compare an two different input bits to a specific signal (high signal (1) OR low signal (0)). If the (2 conditions) patterns match, then the specified output bit is activated (turns high).
In this example we configure a user limit to trigger when both our INPUTS turns high(1). Once the INPUTS turn high(1) then our user limit will set the OUTPUT to high(1). The INPUTS are specified in two different UserLimitConditionSet() The OUTPUT is specified in UserLimitOutputSet()
In this example Beckhoff IO Terminals (Model EL1088 for Inputs and Model EL2008 for outputs) were used to control the Digital IO signals.
Make sure to check the correct digital IO signal indexes of your system in: RapidSetup -.Tools -.NetworkIO

// Constants
const int INPUT_INDEX0 = 0; // This is the index of the digital input you will use to trigger the user limit.
const int INPUT_INDEX1 = 1; // This is the index of the digital input you will use to trigger the user limit.
const int OUTPUT_INDEX = 2; // This is the index of the digital output that will go active when the user limit triggers.
controller.AxisCountSet(1); // The number of user limits must not be greater than the number of axis and must be set before the number of user limits
controller.UserLimitCountSet(1); // Set the amount of UserLimits that you want to use. (every connected axis will automatically get 1 user limit)
controller.InterruptEnableSet(true); // Enable User Limit Interrupts. (When a user limit input comparison is met, and interrupt is triggered)
//-------- PARAMETERS FOR 1st and 2nd UserLimitConditionSet --------
int userLimitNumber = 0; // Specify which user limit to use.
RSIUserLimitLogic logic = RSIUserLimitLogic.RSIUserLimitLogicEQ; // Logic for input value comparison.
UInt64 userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0); // Grabing an memory address to store a simulated IO point.
//Instead of using physical IO we will use simulated IO using a memory address as simulated IO. See the IO sample apps to see how to use a physical IO instead.
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, INPUT_INDEX0); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
IOPoint input1 = IOPoint.CreateDigitalInput(controller, userBufferAddress, INPUT_INDEX1); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, OUTPUT_INDEX); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
int condition0 = 0; // Specify which condition to use (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
UInt64 input0Address = input0.AddressGet(); // 10 was the index of my 1st input. (To check your IO indexes go to RapidSetup -.
uint input0Mask = (uint)input0.MaskGet();
uint limitValue0 = (uint)input0.MaskGet();
int condition1 = 1; // Specify which condition to use (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
UInt64 input1Address = input1.AddressGet(); // 11 was the index of my 2nd input. (To check your IO indexes go to RapidSetup -.
uint input1Mask = (uint)input1.MaskGet();
uint limitValue1 = (uint)input1.MaskGet();
// [1] Configure the 1st input's trigger condition. (condition 1)
controller.UserLimitConditionSet(userLimitNumber, // (User Limit Index) - Specify which user limit to use
condition0, // (Condition Number) - Specify how many inputs you want to compare.
logic, // (Comparison Logic) - Specify the how the input value(s) will be compared
input0Address, // (Input Address) - Specify the address of the input that will be compared.
input0Mask, // (Input Mask) - Specify the bits in an address which need to be used when comparing inputs.
limitValue0); // (Limit Value) - Specify the value to be compared with.
// [2] Configure the 2nd input's trigger condition. (condition 2)
controller.UserLimitConditionSet(userLimitNumber, // (User Limit Index) - Specify which user limit to use
condition1, // (Condition Number) - Specify how many inputs you want to compare.
logic, // (Comparison Logic) - Specify the how the input value(s) will be compared
input1Address, // (Input Address) - Specify the address of the input that will be compared.
input1Mask, // (Input Mask) - Specify the bits in an address which need to be used when comparing inputs.
limitValue1); // (Limit Value) - Specify the value to be compared with.
//-------- PARAMETERS FOR UserLimitConfigSet --------
RSIUserLimitTriggerType triggerType = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeCONDITION_AND;
RSIAction action = RSIAction.RSIActionNONE;
int axis = 0;
int duration = 0;
// [3] Configure and Enable the user limit.
controller.UserLimitConfigSet(userLimitNumber, // (User Limit Index) - Specify which user limit to use.
triggerType, // (Trigger Type) - Specify how your condition should be evalutated.
action, // (User Limit Action) - Specify the action you want to cause on the axis when the user limit triggers.
axis, // (Current Axis) - Specify the axis that the action (defined above) will occur on.
duration); // (Output Timer) - Specify the time delay before the action is executed after the User Limit has triggered.
//-------- PARAMETERS FOR UserLimitOutputSet --------
uint andMask = (uint)output0.MaskGet();
uint orMask = (uint)output0.MaskGet();
UInt64 outputAddress = output0.AddressGet();
bool enableOutput = true;
// [4] Configure what the output will be. (Call this method after UserLimitConfigSet if you want an output to be triggered) (The output will only be triggered if the input conditions are TRUE.)
controller.UserLimitOutputSet(userLimitNumber, // (User Limit Index) - Specify which user limit to use.
andMask, // (Logic AND Mask) - Specify the value that the digital output will be AND-ed with.
orMask, // (Logic OR Mask) - Specify the value that the digital output will be OR-ed with.
outputAddress, // (Output Address) - Specify the digital output address.
enableOutput); // (Enable Output Set) - If TRUE, the output AND-ing and OR-ing will be executed when the User Limit triggers.
while (controller.InterruptWait(250) != RSIEventType.RSIEventTypeUSER_LIMIT) // Wait for user limit to trigger. Loop will execute every 250 ms
{
Assert.False(output0.Get(), "We expect the output to NOT be triggered");
controller.MemorySet(input0.AddressGet(), 1); // Set bit 0 high.
Assert.False(output0.Get(), "We expect the output to NOT be triggered");
controller.MemorySet(input0.AddressGet(), 2); // Set bit 1 high.
Assert.False(output0.Get(), "We expect the output to NOT be triggered");
//---TRIGGER---
controller.MemorySet(input0.AddressGet(), 3); // Set bits 0 and 1 high.
}

Learn more in topic page.


📜 User Limit   Trigger: Digital Input Conditions: 1 Event: EStop
This sample code shows how to configure a RMP controller's User Limit to compare an input bit to a specific signal (high signal (1) OR low signal (0)).
If the (1 condition) pattern matches, then the specified input bit has been activated (turned high) and a User limit Event will trigger. In this example we configure a user limit to trigger when our INPUT turns high(1). Once the INPUT turns high(1) then our user limit will command an E-Stop action on the Axis and store the Axis Command Position. The INPUT is specified in UserLimitConditionSet() The User Limit configuration is done on UserLimitConfigSet() The specified address to record on User Limit Event is specified in UserLimitInterruptUserDataAddressSet() The Data from the speficified addres is retrieved by calling InterruptUserDataGet() In this example Beckhoff IO Terminals (Model EL1088 for Inputs) were used to control the Digital IO signals. Make sure to check the correct digital IO signal indexes of your system in: RapidSetup -. Tools -. NetworkIO

// Constants
const int AXIS_INDEX = 0; // This is the index of the axis you will use to command motion.
const int INPUT_INDEX = 0;
const int AXIS_COUNT = 1; // Axes on the network.
const int USER_LIMIT = 0; // Specify which user limit to use.
const int CONDITION = 0; // Specify which condition to use. (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
const RSIUserLimitLogic LOGIC = RSIUserLimitLogic.RSIUserLimitLogicEQ; // Logic for input value comparison.
const int LIMIT_VALUE = 1; // The value to be compared which needs to be set here.
const RSIUserLimitTriggerType TRIGGER_TYPE = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION; // Choose the how the condition (s) should be evaluated.
const RSIAction ACTION = RSIAction.RSIActionE_STOP_ABORT; // Choose the action you want to cause when the User Limit triggers.
const double DURATION = 0.125; // Enter the time delay before the action is executed after the User Limit has triggered.
const int USER_DATA_INDEX = 0;
// Some Necessary Pre User Limit Configuration
controller.AxisCountSet(1);
controller.UserLimitCountSet(1); // Set the amount of UserLimits that you want to use.
controller.InterruptEnableSet(true); // Enable User Limit Interrupts. (When a user limit input comparison is met, and interrupt is triggered)
UInt64 userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0); // Grabing an memory address to store a simulated IO point.
//Instead of using physical IO we will use simulated IO using a memory address as simulated IO. See the IO sample apps to see how to use a physical IO instead.
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, INPUT_INDEX); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
axis = CreateAndReadyAxis(Constants.AXIS_NUMBER); // Initialize your axis object.
axis.MoveVelocity(10.0, 20.0); // Command a velocity move (Velocity=1.0, Acceleration=10.0).
// USER LIMIT CONDITION
controller.UserLimitConditionSet(USER_LIMIT, CONDITION, LOGIC, input0.AddressGet(), (uint)input0.MaskGet(), LIMIT_VALUE); // Set your User Limit Condition (1st step to setting up your user limit)
// USER LIMIT CONFIGURATION
controller.UserLimitConfigSet(USER_LIMIT, TRIGGER_TYPE, ACTION, AXIS_INDEX, DURATION); // Set your User Limit Configuration. (2nd step to setting up your user limit)
// USER LIMIT USER DATA SET
controller.UserLimitInterruptUserDataAddressSet(USER_LIMIT, // Specify the user limit you want to add User Data for.
USER_DATA_INDEX, // Specify what user data index you would like to use. (must be a value from 0 to 4)
axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION)); // Specify the address of the data value you want to store in your User Data so that you can retrieve it later after the UserLimit limit triggers.
// WAIT FOR DIGITAL INPUT TO TRIGGER USER LIMIT EVENT.
while (controller.InterruptWait(250) != RSIEventType.RSIEventTypeUSER_LIMIT) // Wait until your user limit triggers.
{
controller.MemorySet(input0.AddressGet(), 1);
}
int triggeredUserLimit = controller.InterruptSourceNumberGet() - AXIS_COUNT; // Check that the correct user limit has triggered. (an extra user limit is allocated for each axis)
double interruptPosition = controller.InterruptUserDataDoubleGet(USER_DATA_INDEX); // Get the data stored in the interrupt's user data you configured.
Console.WriteLine("TRIGGERED - User Limit Interrupt Position = " + interruptPosition / axis.UserUnitsGet()); // Get the position of the axis when it user limit event triggered.
controller.UserLimitDisable(USER_LIMIT);

Learn more in topic page.


📜 User Limit   Trigger: Position Conditions: 1 Event: FeedRate
Configure a UserLimit to change the FeedRate when the axis has reached a specified position.

// Constants
const int USER_LIMIT = 0; // Specify which user limit to use.
const int USER_LIMIT_COUNT = 1;
const int AXIS_COUNT = 1;
const int CONDITION = 0; // Specify which condition to use. (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
const RSIUserLimitLogic LOGIC = RSIUserLimitLogic.RSIUserLimitLogicGT; // Logic for input value comparison.
const double POSITION_TRIGGER_VALUE = 5; // The value to be compared which needs to be set here.
const RSIUserLimitTriggerType TRIGGER_TYPE = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION; // Choose the how the condition (s) should be evaluated.
const RSIAction ACTION = RSIAction.RSIActionNONE; // Choose the action you want to cause when the User Limit triggers.
const int DURATION = 0; // Enter the time delay before the action is executed after the User Limit has triggered.
const double DEFAULT_FEED_RATE = 1.0;
const double DESIRED_FEED_RATE = 2.0;
// Other Global Variables
UInt64 feedRateAddress;
// Some Necessary Pre User Limit Configuration
controller.AxisCountSet(AXIS_COUNT); // The number of user limits must not be greater than the number of axis and must be set before the number of user limits
controller.UserLimitCountSet(USER_LIMIT_COUNT); // Set the amount of UserLimits that you want to use.
axis = CreateAndReadyAxis(Constants.AXIS_NUMBER); // Initialize your axis object.
axis.FeedRateSet(DEFAULT_FEED_RATE); // Restore FeedRate to default value.
// USER LIMIT CONDITION
// We will use command position because we are working with a phantom axis. Actual position can be used for real axis.
controller.UserLimitConditionSet(USER_LIMIT, CONDITION, LOGIC, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION), POSITION_TRIGGER_VALUE); // Set your User Limit Condition (1st step to setting up your user limit)
// USER LIMIT CONFIGURATION
controller.UserLimitConfigSet(USER_LIMIT, TRIGGER_TYPE, ACTION, axis.NumberGet(), DURATION); // Set your User Limit Configuration. (2nd step to setting up your user limit)
// USER LIMIT OUTPUT
feedRateAddress = axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeTARGET_FEEDRATE);
controller.UserLimitOutputSet(USER_LIMIT, DESIRED_FEED_RATE, feedRateAddress, true);

Learn more in topic page.


📜 User Limit   Trigger: Position Conditions: 1 Event: Abort
Configure a User Limit to call abort when a specified position is reached.

// Constants
const int AXIS_COUNT = 1;
const int USER_LIMIT_COUNT = 1;
const int USER_LIMIT_NUMBER = 0;
const double TRIGGER_POSITION = 0.05; // Specify the position where the user limit will trigger.
const double MOVE_POSITION = 1.0; // We'll move to this position, which must be past the trigger position.
const int OUTPUT_INDEX = 1; // This is the index of the digital output that will go active when the user limit triggers.
const int WAIT_FOR_TRIGGER_MILLISECONDS = 100; // we'll wait for the UserLimit interrupt for this long before giving up.
// Some Necessary Pre User Limit Configuration
controller.AxisCountSet(AXIS_COUNT); // The number of user limits must not be greater than the number of axis and must be set before the number of user limits
controller.UserLimitCountSet(USER_LIMIT_COUNT); // Set the amount of UserLimits that you want to use. (every connected axis will automatically get 1 user limit)
controller.InterruptEnableSet(true); // Enable User Limit Interrupts. (When a user limit input comparison is met, and interrupt is triggered)
UInt64 userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0); // Grabbing a memory address to make a simulated IO point.
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, OUTPUT_INDEX); // Create IOPoint object. Can be used to automatically get the address of a specified node and input index
output0.Set(false); // be sure we are starting with a value of 0 aka off
axis = CreateAndReadyAxis(Constants.AXIS_NUMBER); // Initialize your axis object.
//-------- PARAMETERS FOR UserLimitConditionSet -------- // Specify which user limit to use.
int condition = 0; // Specify which condition to use (0 or 1) ("0" to compare 1 input || "1" to compare 2 inputs)
double limitValue = TRIGGER_POSITION; // The limit value will be in counts so we multiply our desired position by USER_UNITS
controller.UserLimitConditionSet(USER_LIMIT_NUMBER, // (User Limit Index) - Specify which user limit to use
condition, // (Condition Number) - Specify how many inputs you want to compare.
RSIUserLimitLogic.RSIUserLimitLogicGT, // (Comparison Logic) - Specify the how the input value(s) will be compared
axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION),// (Input Address) - Specify the address of the input that will be compared. // FOR A REAL AXIS USE ACTUAL POSITION
limitValue); // (Limit Value) - Specify the value to be compared with.
//-------- PARAMETERS FOR UserLimitConfigSet --------
RSIUserLimitTriggerType triggerType = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION;
RSIAction action = RSIAction.RSIActionABORT; // Abort move when user limit triggers.
int duration = 0;
// [2] Configure and Enable the user limit.
controller.UserLimitConfigSet(USER_LIMIT_NUMBER, // (User Limit Index) - Specify which user limit to use.
triggerType, // (Trigger Type) - Specify how your condition should be evalutated.
action, // (User Limit Action) - Specify the action you want to cause on the axis when the user limit triggers.
axis.NumberGet(), // (Current Axis) - Specify the axis that the action (defined above) will occur on.
duration); // (Output Timer) - Specify the time delay before the action is executed after the User Limit has triggered.
//-------- PARAMETERS FOR UserLimitOutputSet --------
uint andMask = (uint)output0.MaskGet(); // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
uint orMask = (uint)output0.MaskGet(); ; // Get the appropriate mask from your IOpoint. OR use 0x00010000 for AKD General IO, 1 for Beckhoff IO Terminals
UInt64 outputAddress = output0.AddressGet(); //Alternatively set manually using: controller.NetworkOutputAddressGet(OUTPUT_INDEX);
bool enableOutput = true;
// [3] Configure what the output will be. (Call this method after UserLimitConfigSet if you want an output to be triggered) (The output will only be triggered if the input conditions are TRUE.)
controller.UserLimitOutputSet(USER_LIMIT_NUMBER, // (User Limit Index) - Specify which user limit to use.
andMask, // (Logic AND Mask) - Specify the value that the digital output will be AND-ed with.
orMask, // (Logic OR Mask) - Specify the value that the digital output will be OR-ed with.
outputAddress, // (Output Address) - Specify the digital output address.
enableOutput); // (Enable Output Set) - If TRUE, the output AND-ing and OR-ing will be executed when the User Limit triggers.
Assert.False(output0.Get(), "We expect the output to NOT be triggered");
// TRIGGER
axis.MoveSCurve(MOVE_POSITION); // Command simple motion past the trigger position.
RSIEventType interruptType = controller.InterruptWait(WAIT_FOR_TRIGGER_MILLISECONDS);
if (interruptType == RSIEventType.RSIEventTypeUSER_LIMIT)
{
// note - the object number returned for USER_LIMIT interrupts is raw an unscaled and we must add the controller's AxisCount since internally
// there is one UserLimit allocated per Axis
Assert.That(controller.InterruptSourceNumberGet(), Is.EqualTo(USER_LIMIT_NUMBER + AXIS_COUNT), "We got a USER_LIMIT interrupt but it was the wrong one.");
Assert.True(output0.Get(), "We expect the output to be turned on when the user limit triggers.");
}
else
{
Assert.Fail("We expected a USER_LIMIT interrupt when the trigger position was exceeded but instead got " + interruptType.ToString());
}
axis.AmpEnableSet(false); // Disable the motor.
controller.UserLimitDisable(USER_LIMIT_NUMBER); // Disable User Limit.
output0.Set(false); // Set output low so program can run again

Learn more in topic page.


📜 Two User Limits   Custom
Configure two UserLimits. The first will trigger on a digital input and copy the Axis Actual Position to the UserBuffer and decelerate to zero velocity with TRIGGERED_MODIFY. The second UserLimit will trigger after the first UserLimit triggers and the Axis gets to IDLE stae and it will directly set the command position of an Axis from the position stored in the UserBuffer.

// Constants
const int AXIS_COUNT = 1;
const int USER_LIMIT_FIRST = 0; // Specify which user limit to use.
const int USER_LIMIT_SECOND = 1;
const int USER_LIMIT_COUNT = 2;
const RSIUserLimitLogic LOGIC = RSIUserLimitLogic.RSIUserLimitLogicEQ; // Logic for input value comparison.
const RSIUserLimitTriggerType TRIGGER_TYPE = RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION; // Choose the how the condition (s) should be evaluated.
const RSIAction ACTION = RSIAction.RSIActionTRIGGERED_MODIFY; // Choose the action you want to cause when the User Limit triggers.
const int DURATION = 0; // Enter the time delay before the action is executed after the User Limit has triggered.
const bool ONE_SHOT = true; // if true, User Limit will only trigger ONCE
// User Limit Interrupt constants
const int COMMAND_POSITION_INDEX = 0;
const int ACTUAL_POSITION_INDEX = 1;
const int TC_COMMAND_POSITION_INDEX = 2;
const int TC_ACTUAL_POSITION_INDEX = 3;
public void UserLimitCommandPositionDirectSet()
{
// Some Necessary Pre User Limit Configuration
controller.AxisCountSet(AXIS_COUNT);
controller.UserLimitCountSet(USER_LIMIT_COUNT); // Set the amount of UserLimits that you want to use.
axis = CreateAndReadyAxis(Constants.AXIS_NUMBER); // Initialize your axis object.
// set the triggered modify values to stop very quickly
axis.TriggeredModifyDecelerationSet(Constants.DECELERATION);
axis.TriggeredModifyJerkPercentSet(Constants.JERK_PERCENT);
// USER LIMIT CONDITION 0 (trigger on digital input)
controller.UserLimitConditionSet(USER_LIMIT_FIRST, 0, LOGIC, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeDIGITAL_INPUTS), 0x400000, 0x400000); // Set your User Limit Condition (1st step to setting up your user limit)
// controller.UserLimitOutputSet(USER_LIMIT_FIRST, RSIDataType.RSIDataTypeDOUBLE, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeTC_ACTUAL_POSITION), controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER), true);
controller.UserLimitConfigSet(USER_LIMIT_FIRST, TRIGGER_TYPE, ACTION, axis.NumberGet(), DURATION, ONE_SHOT); // Set your User Limit Configuration. (2nd step to setting up your user limit)
// CONDITION 0 (wait for first user limit to trigger)
controller.UserLimitConditionSet(USER_LIMIT_SECOND, 0, RSIUserLimitLogic.RSIUserLimitLogicEQ, controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSERLIMIT_STATUS, USER_LIMIT_FIRST), 1, 1);
// CONDITION 1 (AND wait for Axis command velcity = 0.0)
controller.UserLimitConditionSet(USER_LIMIT_SECOND, 1, RSIUserLimitLogic.RSIUserLimitLogicEQ, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_VELOCITY), 0.0);
// OUTPUT (copy value from UserBuffer to TC.CommandPosition when trigered)
//controller.UserLimitOutputSet(USER_LIMIT_SECOND, RSIDataType.RSIDataTypeDOUBLE, controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER), axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeTC_COMMAND_POSITION), true);
controller.UserLimitConfigSet(USER_LIMIT_SECOND, RSIUserLimitTriggerType.RSIUserLimitTriggerTypeCONDITION_AND, RSIAction.RSIActionNONE, 0, 0, ONE_SHOT);
// get the Axis moving
axis.ClearFaults();
axis.AmpEnableSet(true);
axis.MoveVelocity(Constants.VELOCITY, Constants.ACCELERATION);
// configure and enable interrupts
ConfigureUserLimitInterrupts(USER_LIMIT_FIRST);
ConfigureUserLimitInterrupts(USER_LIMIT_SECOND);
controller.InterruptEnableSet(true);
// wait for (and print) interrupts
WaitForInterrupts();
}
public void ConfigureUserLimitInterrupts(int userLimitIndex)
{
controller.UserLimitInterruptUserDataAddressSet(userLimitIndex, COMMAND_POSITION_INDEX, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION));
controller.UserLimitInterruptUserDataAddressSet(userLimitIndex, ACTUAL_POSITION_INDEX, axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeACTUAL_POSITION));
}
public void WaitForInterrupts()
{
bool done = false;
int timeout_millseconds = 10;
while (!done)
{
RSIEventType eventType = controller.InterruptWait(timeout_millseconds);
Console.WriteLine("IRQ: " + eventType.ToString() + " at sample " + controller.InterruptSampleTimeGet());
switch (eventType)
{
case RSIEventType.RSIEventTypeUSER_LIMIT:
Console.WriteLine("UserLimit " + controller.InterruptSourceNumberGet());
Console.WriteLine("CmdPos: " + controller.InterruptUserDataDoubleGet(COMMAND_POSITION_INDEX));
Console.WriteLine("ActPos: " + controller.InterruptUserDataDoubleGet(ACTUAL_POSITION_INDEX));
Console.WriteLine("TC.CmdPos: " + controller.InterruptUserDataDoubleGet(TC_COMMAND_POSITION_INDEX));
Console.WriteLine("TC.ActPos: " + controller.InterruptUserDataDoubleGet(TC_ACTUAL_POSITION_INDEX));
break;
case RSIEventType.RSIEventTypeTIMEOUT:
done = true;
break;
default:
break;
}
}
}

Learn more in topic page.

RSI::RapidCode::MotionController::UserLimitCountSet
void UserLimitCountSet(int32_t userLimitCount)
Set the number of processed UserLimits in the MotionController.
RSI::RapidCode::RapidCodeInterrupt::InterruptSourceNumberGet
int32_t InterruptSourceNumberGet()
Get the number (or index) of the object (Axis, Motor, etc) that generated the interrupt.
RSI::RapidCode::RapidCodeInterrupt::InterruptUserDataDoubleGet
double InterruptUserDataDoubleGet(uint32_t userDataIndex)
Get the user data associated with the interrupt, as a 64-bit double.
RSI::RapidCode::MotionController::UserLimitInterruptUserDataAddressSet
void UserLimitInterruptUserDataAddressSet(int32_t number, uint32_t userDataIndex, uint64_t address)
Set the User Data address based on a User Limit trigger.
RSI::RapidCode::MotionController::AxisCountSet
void AxisCountSet(int32_t axisCount)
Set the number of allocated and processed axes in the controller.
RSI::RapidCode::MotionController::UserLimitOutputSet
void UserLimitOutputSet(int32_t number, uint32_t andMask, uint32_t orMask, uint64_t outputPtr, bool enabled)
Configure a User Limit Output block.
RSI::RapidCode::RSIEventType
RSIEventType
Event Types or Status Bits.
Definition: rsienums.h:893
RSI::RapidCode::MotionController::UserLimitDisable
void UserLimitDisable(int32_t number)
Disable the processing of a User Limit.
RSI::RapidCode::MotionController::InterruptEnableSet
void InterruptEnableSet(bool enable)
Control interrupts for this class.
RSI::RapidCode::RSIUserLimitLogic
RSIUserLimitLogic
Logic options for User Limits.
Definition: rsienums.h:627
RSI::RapidCode::MotionController::MemorySet
void MemorySet(uint64_t address, int32_t data)
Write a value to controller memory.
RSI::RapidCode::MotionController::UserLimitConfigSet
void UserLimitConfigSet(int32_t number, RSIUserLimitTriggerType triggerType, RSIAction action, int32_t actionAxis, double duration, bool singleShot)
Configure a User Limit.
RSI::RapidCode::MotionController::AddressGet
uint64_t AddressGet(RSIControllerAddressType type)
Get the an address for some location on the MotionController.
RSI::RapidCode::RapidCodeInterrupt::InterruptWait
RSIEventType InterruptWait(int32_t milliseconds)
Suspend the current thread until an interrupt arrives from the controller.
RSI::RapidCode::MotionController::UserLimitConditionSet
void UserLimitConditionSet(int32_t number, int32_t conditionNumber, RSIUserLimitLogic logic, uint64_t addressOfUInt32, uint32_t userLimitMask, uint32_t limitValueUInt32)
Set the conditions for a User Limit with a 32-bit integer trigger value.
RSI::RapidCode::RapidCodeInterrupt::InterruptSampleTimeGet
int32_t InterruptSampleTimeGet()
Get the sample timer value when the last interrupt was generated.
RSI::RapidCode::RSIUserLimitTriggerType
RSIUserLimitTriggerType
Trigger types for UserLimits.
Definition: rsienums.h:614
RSI::RapidCode::RSIControllerAddressType
RSIControllerAddressType
Used to get firmware address used in User Limits, Sequencers, etc.
Definition: rsienums.h:411
RSI::RapidCode::RSIAction
RSIAction
Action to perform on an Axis.
Definition: rsienums.h:1033
HelperFunctions.CheckErrors
static void CheckErrors(RapidCodeObject rsiObject)
Check if the RapidCode Object has any errors.
Definition: HelperFunctions.cs:64
RSI::RapidCode::RSIAxisAddressType
RSIAxisAddressType
Used to get firmware address used in User Limits, Sequencers, etc.
Definition: rsienums.h:426
HelperFunctions
Helper Functions for checking logged creation errors, starting the network, etc.
Definition: HelperFunctions.cs:50
RSI::RapidCode::IOPoint::CreateDigitalOutput
static IOPoint * CreateDigitalOutput(Axis *axis, RSIMotorDedicatedOut motorDedicatedOutNumber)
Create a Digital Output from an Axis' Dedicated Output bits.