APIs, concepts, guides, and more
IO: User Limits

Learn how to use User Limits in C#.

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.


In this page:


šŸ“œ User Limit: Digital Input One Condition

Learn how to configure a User Limits 📖 triggered by a single digital input. When the input matches the specified value, the configured output is activated.
Trigger: Digital Input Conditions: 1

/* This sample demonstrates how to configure a user limit triggered by a single digital input.
When the input matches the specified value, the configured output is activated.
Uses simulated IO with user buffer memory for demonstration purposes.
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: Digital Input One Condition");
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.UserLimitCountSet(1); // set the amount of user limits to use
controller.InterruptEnableSet(true); // enable user limit interrupts
// create simulated io using user buffer memory
ulong userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0);
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, bitNumber: 0);
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, bitNumber: 1);
Helpers.CheckErrors(output0);
// configure user limit condition
controller.UserLimitConditionSet(
number: 0,
conditionNumber: 0,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: input0.AddressGet(),
userLimitMask: (uint)input0.MaskGet(),
limitValueUInt32: (uint)input0.MaskGet());
// configure user limit settings
controller.UserLimitConfigSet(
number: 0,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION,
action: RSIAction.RSIActionNONE,
actionAxis: 0,
duration: 0);
// configure user limit output
controller.UserLimitOutputSet(
number: 0,
andMask: (uint)output0.MaskGet(),
orMask: (uint)output0.MaskGet(),
outputPtr: output0.AddressGet(),
enabled: true);
Console.WriteLine("Waiting for input trigger...");
// verify output is initially off
if (output0.Get())
throw new Exception("ERROR: Output should not be triggered yet");
// set input high (bit 0) - condition met
controller.MemorySet(input0.AddressGet(), 0b0001); // bit 0 is high
// wait for user limit interrupt to confirm trigger
if (controller.InterruptWait(1000) != RSIEventType.RSIEventTypeUSER_LIMIT)
throw new Exception("ERROR: User limit did not trigger when input was high");
// verify output was activated
if (!output0.Get())
throw new Exception("ERROR: Output should be high after user limit triggered");
Console.WriteLine("āœ“ User limit triggered successfully - input high, output activated");
// cleanup
output0.Set(false);
controller.UserLimitDisable(0);
controller.UserLimitCountSet(0);
Console.WriteLine("\nUser limit digital input one condition complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}
static void CheckErrors(RapidCodeObject rsiObject)
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
Definition _helpers.cs:15
Helpers class provides static methods for common tasks in RMP applications.
Definition _helpers.cs:5
uint64_t AddressGet()
Get the Host Address for the I/O point.
void Set(bool state)
Set the state of a Digital Output.
static IOPoint * CreateDigitalInput(Axis *axis, RSIMotorDedicatedIn motorDedicatedInNumber)
Create a Digital Input from an Axis' Dedicated Input bits.
static IOPoint * CreateDigitalOutput(Axis *axis, RSIMotorDedicatedOut motorDedicatedOutNumber)
Create a Digital Output from an Axis' Dedicated Output bits.
bool Get()
Get the state of Digital Input or Output.
int32_t MaskGet()
Get the bit mask for the I/O point.
Represents one specific point: Digital Output, Digital Input, Analog Output, or Analog Input....
Definition rsi.h:11550
static MotionController * Get()
Get an already running RMP EtherCAT controller.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:800
RSIControllerAddressType
Used to get firmware address used in User Limits, Recorders, etc.
Definition rsienums.h:405
RSIEventType
Event Types or Status Bits.
Definition rsienums.h:966
RSIUserLimitLogic
Logic options for User Limits.
Definition rsienums.h:646
RSIAction
Action to perform on an Axis.
Definition rsienums.h:1115
RSIUserLimitTriggerType
Trigger types for UserLimits.
Definition rsienums.h:633


šŸ“œ User Limit: Digital Input Two Condition

Learn how to configure a User Limits 📖 triggered by two digital inputs with AND logic. Both inputs must be high for the output to activate.
Trigger: Digital Input Conditions: 2

/* This sample demonstrates how to configure a user limit triggered by two digital inputs.
Uses AND logic - both inputs must be high for the output to activate.
The RMP controller's User Limits compare two different input bits to specific values (high=1 or low=0).
When both conditions match (using AND logic), the specified output bit is activated (turns high).
In this example:
- Two conditions are configured via UserLimitConditionSet() to monitor two separate inputs
- Both inputs must turn high (1) to trigger the user limit
- When triggered, UserLimitOutputSet() activates the output to high (1)
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: Digital Input Two Condition");
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.UserLimitCountSet(1); // set the amount of user limits to use
controller.InterruptEnableSet(true); // enable user limit interrupts
// create simulated io using user buffer memory
ulong userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0);
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, bitNumber: 0);
IOPoint input1 = IOPoint.CreateDigitalInput(controller, userBufferAddress, bitNumber: 1);
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, bitNumber: 2);
Helpers.CheckErrors(output0);
// configure first input condition (condition 0)
controller.UserLimitConditionSet(
number: 0,
conditionNumber: 0,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: input0.AddressGet(),
userLimitMask: (uint)input0.MaskGet(),
limitValueUInt32: (uint)input0.MaskGet());
// configure second input condition (condition 1)
controller.UserLimitConditionSet(
number: 0,
conditionNumber: 1,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: input1.AddressGet(),
userLimitMask: (uint)input1.MaskGet(),
limitValueUInt32: (uint)input1.MaskGet());
// configure user limit settings (AND logic for both conditions)
controller.UserLimitConfigSet(
number: 0,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeCONDITION_AND,
action: RSIAction.RSIActionNONE,
actionAxis: 0,
duration: 0);
// configure user limit output
controller.UserLimitOutputSet(
number: 0,
andMask: (uint)output0.MaskGet(),
orMask: (uint)output0.MaskGet(),
outputPtr: output0.AddressGet(),
enabled: true);
Console.WriteLine("Waiting for both inputs to trigger...");
// verify output is initially off
if (output0.Get())
throw new Exception("ERROR: Output should not be triggered yet");
// set first input high (bit 0 only) - AND condition not met
controller.MemorySet(input0.AddressGet(), 0b0001); // only bit 0 is high
if (output0.Get())
throw new Exception("ERROR: Output should not trigger with only one input");
// set BOTH inputs high (bits 0 and 1) - AND condition met
controller.MemorySet(input1.AddressGet(), 0b0011); // both bit 0 AND bit 1 are high
// wait for user limit interrupt to confirm trigger
if (controller.InterruptWait(1000) != RSIEventType.RSIEventTypeUSER_LIMIT)
throw new Exception("ERROR: User limit did not trigger when both inputs were high");
// verify output was activated
if (!output0.Get())
throw new Exception("ERROR: Output should be high after user limit triggered");
Console.WriteLine("āœ“ User limit triggered successfully - both inputs high, output activated");
// cleanup
controller.UserLimitDisable(0);
output0.Set(false);
Console.WriteLine("\nUser limit digital input two condition complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}


šŸ“œ User Limit: EStop and Store Position

Learn how to configure a User Limits 📖 that triggers an E-Stop when a digital input goes high. The axis command position is stored when the user limit triggers.
Trigger: Digital Input Conditions: 1 Event: EStop

/* This sample demonstrates how to configure a user limit that triggers an E-Stop when a digital input goes high.
The axis command position is stored when the user limit triggers.
Example uses Beckhoff IO Terminals (EL1088 for inputs).
Check your digital IO signal indexes in RapidSetup -> Tools -> NetworkIO.
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: EStop and Store Position");
// set sample config params
const int AXIS_INDEX = 0;
const int INPUT_INDEX = 0;
const int CONDITION = 0;
const int USER_DATA_INDEX = 0;
const double DURATION = 0.125; // time delay before action executes (seconds)
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.UserLimitCountSet(1);
controller.InterruptEnableSet(true);
// create simulated io using user buffer memory
ulong userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0);
IOPoint input0 = IOPoint.CreateDigitalInput(controller, userBufferAddress, INPUT_INDEX);
// get axis
Axis axis = controller.AxisGet(Constants.AXIS_0_INDEX);
// start velocity motion
axis.AmpEnableSet(true);
axis.MoveVelocity(velocity: 10.0, accel: 20.0);
// configure user limit condition
controller.UserLimitConditionSet(
number: 0,
conditionNumber: CONDITION,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: input0.AddressGet(),
userLimitMask: (uint)input0.MaskGet(),
limitValueUInt32: 1);
// configure user limit settings (e-stop action)
controller.UserLimitConfigSet(
number: 0,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION,
action: RSIAction.RSIActionE_STOP_ABORT,
actionAxis: AXIS_INDEX,
duration: DURATION);
// configure user data to store axis command position
controller.UserLimitInterruptUserDataAddressSet(
number: 0,
userDataIndex: USER_DATA_INDEX,
address: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION));
Console.WriteLine("Axis moving... waiting for input trigger to E-Stop");
// wait for user limit to trigger
while (controller.InterruptWait(250) != RSIEventType.RSIEventTypeUSER_LIMIT)
{
// simulate input trigger
controller.MemorySet(input0.AddressGet(), 1);
}
// wait for motion to stop
// get the stored position data
int triggeredUserLimit = controller.InterruptSourceNumberGet() - 1; // account for extra user limit per axis
double interruptPosition = controller.InterruptUserDataDoubleGet(USER_DATA_INDEX);
double positionInUserUnits = interruptPosition / axis.UserUnitsGet();
Console.WriteLine($"āœ“ User limit triggered - E-Stop executed");
Console.WriteLine($" Triggered User Limit: {triggeredUserLimit}");
Console.WriteLine($" Position at trigger: {positionInUserUnits} (user units)");
// cleanup
axis.Abort();
controller.UserLimitDisable(0);
controller.UserLimitCountSet(0);
Console.WriteLine("\nUser limit E-Stop store position complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}
Constants used in the C# sample apps.
Definition _constants.cs:3
const int AXIS_0_INDEX
Default: 0.
Definition _constants.cs:11
static void PhantomAxisReset(Axis phantomAxis)
Configures a phantom axis on the controller.
Definition _helpers.cs:144
uint64_t AddressGet(RSIAxisAddressType addressType)
Get the an address for some location on the Axis.
double UserUnitsGet()
Get the number of counts per User Unit.
void MoveVelocity(double velocity)
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5863
void Abort()
Abort an axis.
int32_t MotionDoneWait()
Waits for a move to complete.
int32_t AmpEnableSet(bool enable, int32_t ampActiveTimeoutMilliseconds=AmpEnableTimeoutMillisecondsDefault, bool overrideRestrictedState=false)
Enable all amplifiers.
RSIAxisAddressType
Used to get firmware address used in User Limits, Recorders, etc.
Definition rsienums.h:434


šŸ“œ User Limit: Feed Rate Change at Position

Learn how to configure a User Limits 📖 to change the feed rate when the axis reaches a specified position.
Trigger: Position Conditions: 1 Event: FeedRate

/* This sample demonstrates how to configure a user limit to change the feed rate when the axis reaches a specified position.
The user limit triggers when the command position exceeds the trigger value.
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: Feed Rate Change at Position");
// set sample config params
const int CONDITION = 0;
const double POSITION_TRIGGER_VALUE = 5.0;
const double DEFAULT_FEED_RATE = 1.0;
const double DESIRED_FEED_RATE = 2.0;
const int DURATION = 0;
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.UserLimitCountSet(1);
controller.InterruptEnableSet(true);
// get axis
Axis axis = controller.AxisGet(Constants.AXIS_0_INDEX);
// set initial feed rate
axis.FeedRateSet(DEFAULT_FEED_RATE);
Console.WriteLine($"Initial Feed Rate: {axis.FeedRateGet()}");
// configure user limit condition (trigger when position > POSITION_TRIGGER_VALUE)
controller.UserLimitConditionSet(
number: 0,
conditionNumber: CONDITION,
logic: RSIUserLimitLogic.RSIUserLimitLogicGT,
addressOfDouble: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION),
limitValueDouble: POSITION_TRIGGER_VALUE);
// configure user limit settings
controller.UserLimitConfigSet(
number: 0,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION,
action: RSIAction.RSIActionNONE,
actionAxis: axis.NumberGet(),
duration: DURATION);
// configure user limit output to change feed rate
controller.UserLimitOutputSet(
number: 0,
limitValueDouble: DESIRED_FEED_RATE,
outputPtr: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeTARGET_FEEDRATE),
enabled: true);
Console.WriteLine($"Moving to position {POSITION_TRIGGER_VALUE + 1}...");
Console.WriteLine($"Feed rate will change to {DESIRED_FEED_RATE} when position > {POSITION_TRIGGER_VALUE}");
// start motion past the trigger position
axis.AmpEnableSet(true);
axis.MoveSCurve(POSITION_TRIGGER_VALUE + 1);
// verify feed rate changed
double finalFeedRate = axis.FeedRateGet();
Console.WriteLine($"Final Feed Rate: {finalFeedRate}");
if (finalFeedRate == DESIRED_FEED_RATE)
Console.WriteLine("āœ“ User limit triggered - feed rate changed successfully");
else
Console.WriteLine($"āœ— Feed rate did not change (expected: {DESIRED_FEED_RATE}, actual: {finalFeedRate})");
// cleanup
controller.UserLimitDisable(0);
controller.UserLimitCountSet(0);
Console.WriteLine("\nUser limit feed rate change complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}
static void AbortMotionObject(RapidCodeMotion motionObject)
Aborts motion on the given RapidCodeMotion object (Axis or MultiAxis), waits for motion to stop,...
Definition _helpers.cs:186
void MoveSCurve(double position, double vel, double accel, double decel, double jerkPct)
double FeedRateGet()
Get the axis feed rate.
void FeedRateSet(double rate)
Set the feed rate for an Axis.
int32_t NumberGet()
Get the axis number.


šŸ“œ User Limit: Position Abort

Learn how to configure a User Limits 📖 to abort motion when a specified position is reached.
Trigger: Position Conditions: 1 Event: Abort

/* This sample demonstrates how to configure a user limit to abort motion when a specified position is reached.
The user limit triggers when the command position exceeds the trigger value and executes an abort action.
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: Position Abort");
// set sample config params
const int USER_LIMIT_NUMBER = 0;
const double TRIGGER_POSITION = 5.0;
const double MOVE_POSITION = 10.0; // must be past the trigger position
const int OUTPUT_INDEX = 1;
const int WAIT_FOR_TRIGGER_MILLISECONDS = 1000;
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.UserLimitCountSet(1);
controller.InterruptEnableSet(true);
// create simulated output
ulong userBufferAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, 0);
IOPoint output0 = IOPoint.CreateDigitalOutput(controller, userBufferAddress, OUTPUT_INDEX);
output0.Set(false); // start with output off
// get axis
Axis axis = controller.AxisGet(Constants.AXIS_0_INDEX);
// configure user limit condition (trigger when position > TRIGGER_POSITION)
controller.UserLimitConditionSet(
number: USER_LIMIT_NUMBER,
conditionNumber: 0,
logic: RSIUserLimitLogic.RSIUserLimitLogicGT,
addressOfDouble: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION), // for real axis use actual position
limitValueDouble: TRIGGER_POSITION);
// configure user limit settings (abort action)
controller.UserLimitConfigSet(
number: USER_LIMIT_NUMBER,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION,
action: RSIAction.RSIActionABORT,
actionAxis: axis.NumberGet(),
duration: 0);
// configure user limit output
controller.UserLimitOutputSet(
number: USER_LIMIT_NUMBER,
andMask: (uint)output0.MaskGet(),
orMask: (uint)output0.MaskGet(),
outputPtr: output0.AddressGet(),
enabled: true);
Console.WriteLine($"Moving to position {MOVE_POSITION}...");
Console.WriteLine($"User limit will trigger abort at position {TRIGGER_POSITION}");
if (output0.Get())
Console.WriteLine("ERROR: Output should not be triggered yet");
// start motion
axis.AmpEnableSet(true);
axis.MoveSCurve(MOVE_POSITION);
// wait for user limit interrupt
RSIEventType interruptType = controller.InterruptWait(WAIT_FOR_TRIGGER_MILLISECONDS);
if (interruptType == RSIEventType.RSIEventTypeUSER_LIMIT)
{
// note: object number for user_limit interrupts is unscaled, add axis count since there's one user limit per axis
int interruptSource = controller.InterruptSourceNumberGet();
int expectedSource = USER_LIMIT_NUMBER + 1; // account for extra user limit per axis
if (interruptSource == expectedSource)
{
Console.WriteLine($"āœ“ User limit triggered - abort executed");
Console.WriteLine($" Interrupt source: {interruptSource}");
if (output0.Get())
Console.WriteLine(" Output activated successfully");
else
Console.WriteLine(" WARNING: Output was not activated");
}
else
{
Console.WriteLine($"āœ— Got USER_LIMIT interrupt but wrong source (expected: {expectedSource}, actual: {interruptSource})");
}
}
else
{
Console.WriteLine($"āœ— Expected USER_LIMIT interrupt but got {interruptType}");
}
// cleanup
output0.Set(false);
controller.UserLimitDisable(USER_LIMIT_NUMBER);
controller.UserLimitCountSet(0);
Console.WriteLine("\nUser limit position abort complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}


šŸ“œ User Limit: Command Position Direct Set

Learn how to use two User Limits 📖 in sequence for advanced control. First user limit triggers on digital input and executes triggered modify to decelerate. Second user limit triggers when first completes and axis is idle.
Trigger: Custom Conditions: Multiple

/* This sample demonstrates using two user limits in sequence.
First user limit: triggers on digital input, executes triggered modify to decelerate, stores position.
Second user limit: triggers when first completes and axis is idle, directly sets command position.
This is an advanced example of coordinating multiple user limits.
*/
using RSI.RapidCode; // RSI.RapidCode.dotNET;
Console.WriteLine("šŸ“œ User Limit: Command Position Direct Set");
// set sample config params
const int AXIS_COUNT = 1;
const int USER_LIMIT_FIRST = 0;
const int USER_LIMIT_SECOND = 1;
const int USER_LIMIT_COUNT = 2;
const int DURATION = 0;
const bool ONE_SHOT = true; // user limit triggers only once
// user limit interrupt constants
const int COMMAND_POSITION_INDEX = 0;
const int ACTUAL_POSITION_INDEX = 1;
// get rmp objects
try
{
Helpers.CheckErrors(controller);
// configure user limits
controller.AxisCountSet(AXIS_COUNT);
controller.UserLimitCountSet(USER_LIMIT_COUNT);
// get axis
Axis axis = controller.AxisGet(Constants.AXIS_0_INDEX);
// set the triggered modify values to stop very quickly
/*
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ FIRST USER LIMIT │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
*/
// condition 0: trigger on digital input
controller.UserLimitConditionSet(
number: USER_LIMIT_FIRST,
conditionNumber: 0,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeDIGITAL_INPUTS),
userLimitMask: 0x400000,
limitValueUInt32: 0x400000);
// configuration: cause a triggered_modify action on the axis
controller.UserLimitConfigSet(
number: USER_LIMIT_FIRST,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION,
action: RSIAction.RSIActionTRIGGERED_MODIFY,
actionAxis: axis.NumberGet(),
duration: DURATION,
singleShot: ONE_SHOT);
/*
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ SECOND USER LIMIT │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
*/
// condition 0: wait for first user limit to trigger
controller.UserLimitConditionSet(
number: USER_LIMIT_SECOND,
conditionNumber: 0,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfUInt32: controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSERLIMIT_STATUS, USER_LIMIT_FIRST),
userLimitMask: 1,
limitValueUInt32: 1);
// condition 1: AND wait for axis command velocity = 0.0
controller.UserLimitConditionSet(
number: USER_LIMIT_SECOND,
conditionNumber: 1,
logic: RSIUserLimitLogic.RSIUserLimitLogicEQ,
addressOfDouble: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_VELOCITY),
limitValueDouble: 0.0);
// configuration: no action, just monitoring
controller.UserLimitConfigSet(
number: USER_LIMIT_SECOND,
triggerType: RSIUserLimitTriggerType.RSIUserLimitTriggerTypeCONDITION_AND,
action: RSIAction.RSIActionNONE,
actionAxis: 0,
duration: 0,
singleShot: ONE_SHOT);
// start motion
axis.ClearFaults();
axis.AmpEnableSet(true);
axis.MoveVelocity(velocity: 10, accel: 100);
Console.WriteLine("Axis moving... waiting for user limit triggers");
// configure and enable interrupts
ConfigureUserLimitInterrupts(controller, axis, USER_LIMIT_FIRST);
ConfigureUserLimitInterrupts(controller, axis, USER_LIMIT_SECOND);
controller.InterruptEnableSet(true);
// wait for and display interrupts
WaitForInterrupts(controller);
// cleanup
axis.Abort();
controller.UserLimitDisable(USER_LIMIT_FIRST);
controller.UserLimitDisable(USER_LIMIT_SECOND);
Console.WriteLine("\nUser limit command position direct set complete.");
}
// handle errors as needed
finally
{
controller.Delete(); // dispose
}
// configure interrupt user data addresses for a user limit
void ConfigureUserLimitInterrupts(MotionController controller, Axis axis, int userLimitIndex)
{
number: userLimitIndex,
userDataIndex: COMMAND_POSITION_INDEX,
address: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION));
controller.UserLimitInterruptUserDataAddressSet(
number: userLimitIndex,
userDataIndex: ACTUAL_POSITION_INDEX,
address: axis.AddressGet(RSIAxisAddressType.RSIAxisAddressTypeACTUAL_POSITION));
}
// wait for and display user limit interrupts
void WaitForInterrupts(MotionController controller)
{
bool done = false;
int timeout_milliseconds = 100;
int interruptCount = 0;
while (!done)
{
RSIEventType eventType = controller.InterruptWait(timeout_milliseconds);
if (eventType != RSIEventType.RSIEventTypeTIMEOUT)
{
interruptCount++;
Console.WriteLine($"\nInterrupt {interruptCount}: {eventType} at sample {controller.InterruptSampleTimeGet()}");
}
switch (eventType)
{
case RSIEventType.RSIEventTypeUSER_LIMIT:
int userLimitNum = controller.InterruptSourceNumberGet();
double cmdPos = controller.InterruptUserDataDoubleGet(COMMAND_POSITION_INDEX);
double actPos = controller.InterruptUserDataDoubleGet(ACTUAL_POSITION_INDEX);
Console.WriteLine($" UserLimit: {userLimitNum}");
Console.WriteLine($" Command Position: {cmdPos}");
Console.WriteLine($" Actual Position: {actPos}");
break;
case RSIEventType.RSIEventTypeTIMEOUT:
done = true;
Console.WriteLine($"\nāœ“ Completed - received {interruptCount} interrupts");
break;
default:
break;
}
}
}
void TriggeredModifyDecelerationSet(double decel)
Set the deceleration rate for an Triggered Modify Event.
void TriggeredModifyJerkPercentSet(double jerkPct)
Set the jerk percent for an Triggered Modify Event.
void UserLimitInterruptUserDataAddressSet(int32_t number, uint32_t userDataIndex, uint64_t address)
Set the User Data address based on a User Limit trigger.
void ClearFaults()
Clear all faults for an Axis or MultiAxis.