Execute motion on an Axis or MultiAxis triggered by real-time conditions such as I/O values, axis positions, or software triggers.
🔹 What is Motion Hold?
Motion Hold is a feature available to any motion on an Axis or MultiAxis. The feature allows the user to command (and therefore load) a motion that should not execute immediately. The motion will be triggered by some real-time condition monitored by the RMP firmware.
There are three main types of Motion Hold:
- I/O triggered motion - A motion holds its execution until an I/O value reaches the desired state.
- Position triggered motion - A motion holds its execution until an Axis position is exceeded.
- Software triggered motion - A motion holds its execution until a bit is set in the RMP’s firmware memory.
🔹 Why use Motion Hold?
Motion Hold is especially useful when a motion needs to have a very tight synchronization with some other process – when the synchronization must be accurate to less than one millisecond. A Windows app cannot offer this level of synchronization so it must be configured into the RMP for processing in the real-time firmware for sub-millisecond response to start motion.
Some examples of when Motion Hold might be used for various types:
- Note
- EXAMPLE 1 - IO Triggered Motion \ An Axis may need to perform its motion precisely when a digital input bit changes state.
-
EXAMPLE 2 - Position Triggered Motion \ An Axis may need to wait for some other Axis to move into a safe position before it can start its motion.
-
EXAMPLE 3 - Software Triggered Motion \ An Axis object (Or two axes) that has independent motion but must be started synchronously (can also be accomplished using MultiAxis). The Windows application will set a bit in RMP firmware memory which will trigger both Axis objects to start within the same RMP sample period.
📜 Sample Code
IO Triggered Motion
An Axis may need to perform its motion precisely when a digital input bit changes state. This sample code is done in AKD Drive with Digital IO Inputs switches. A digital input switch triggers to release the HOLD set on the specified Motion. This functionality is available for all Drives but some changes to the sample app may be required.
- C#
const int DIGITAL_INPUTS_PDO_INDEX = 3;
Position Triggered Motion
An Axis may need to wait for some other Axis to move into a safe position before it can start its motion. This sample code is done in AKD Drive with one Actual Axis and one Phantom Axis. It can be applied to two Phantom Axis or two Actual Axis with the slight changes of code which is guided in comment.
- C#
const double TRIGGER_POS = 1;
const int MOVING_AXIS_TARGET = 10;
const int HOLDINGAXIS_TARGET = 2;
Axis holdingAxis = controller.
AxisGet(Constants.HOLDING_AXIS_INDEX);
Axis movingAxis = controller.
AxisGet(Constants.MOVING_AXIS_INDEX);
Software Triggered Motion
An Axis object (Or two axes) that has independent motion but must be started synchronously (can also be accomplished using MultiAxis). The Windows application will set a bit in RMP firmware memory which will trigger both Axis objects to start within the same RMP sample period. 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. Available/free firmware addresses can be found using vm3 as long as there is no label on address, it can be used.
- C#
int WAIT_TIME = 10;
int MOVE_DIST = 2;
if (controller.
MemoryGet(SOFTWARE_ADDRESS) != 0x0)
{
}
System.Threading.Thread.Sleep(WAIT_TIME);
System.Threading.Thread.Sleep(WAIT_TIME);
- C++
const int AXIS_COUNT = 1;
const int AXIS_NUMBER = 0;
const double USER_UNITS = 1048576;
const int USER_BUFFER_INDEX = 0;
const double MOTION_DISTANCE = 0.25;
const std::chrono::duration HOLD_TIME = std::chrono::milliseconds(2000);
USE_HARDWARE = false;
const char rmpPath[] = "C:\\RSI\\X.X.X\\";
if (USE_HARDWARE)
{
}
else
{
}
try
{
uint64_t userBufferAddress = controller->
AddressGet(RSIControllerAddressType::RSIControllerAddressTypeUSER_BUFFER, USER_BUFFER_INDEX);
if (controller->
MemoryGet(userBufferAddress) != 0x0)
{
controller->
MemorySet(userBufferAddress, 0x0);
}
printf("\nCommanding Motion...\n");
printf("\nSetting Motion Hold...\n");
printf("Commanding Motion...\n");
std::this_thread::sleep_for(HOLD_TIME);
printf("Releasing Motion Hold...\n");
controller->
MemorySet(userBufferAddress, 0x1);
controller->
MemorySet(userBufferAddress, 0x0);
printf("\nClearing Motion Hold...\n");
printf("Commanding Motion...\n");
}
{
printf("%s\n", err.text);
return -1;
}
return 0;