The RMP Motion Controller APIs
StreamingMotionBufferManagement.cpp
#if !defined(__INTIME__)
#include "rsi.h" // Import our RapidCode Library.
#include <process.h>
using namespace RSI::RapidCode;
const int AXIS_COUNT = 2;
const int DESIRED_POINTS = 50; // We'd like to keep a buffer of 50 points.
const int SYNC_PERIOD = 10; // Every 10 samples.
int32_t lastSample = 0;
#pragma region Fixed Size Implementation
//Some applications might like to send block of say 10 points.
//This means they might end up with anywhere from DESIRED_POINTS to DESIRED_POINTS + (POINT_BLOCK_COUNT - 1) in points at the time of Motion Call.
//We want to adjust desired points and keep track of the extra for future calculations.
//You don't need to do it this way unless you've a reason to.
//If you are using fixed size blocks, you might just want to just use MotionIdGet() and ExecutingMotionIdGet() to determine the number of blocks to send.
const int POINT_BLOCK_COUNT = 10;
int32_t extraPointsSentToEvenOutBlock = 0;
int32_t AdjustPointsNeededToBlockCount(int32_t initialCount)
{
int32_t calculatedCount = 0;
int32_t adjustedInitialCount = initialCount - extraPointsSentToEvenOutBlock;
while ((adjustedInitialCount > 0) && (adjustedInitialCount > calculatedCount))
{
calculatedCount += POINT_BLOCK_COUNT;
}
//Adjust ExtraPointsSent so it can be used in future cycles.
extraPointsSentToEvenOutBlock += calculatedCount - initialCount;
return calculatedCount;
}
#pragma endregion
volatile int _continueMonitoring = true;
// In this example the expected passed Object is a Controller Object.
void monitoringThread(void* tmp)
{
MotionController* controller = (MotionController*)tmp;
//Configure Sync Interrupts here.
controller->SyncInterruptPeriodSet(SYNC_PERIOD);
controller->SyncInterruptEnableSet(true);
while (_continueMonitoring)
{
//SyncInterruptWait will wait until the next Interrupt generated by the controller.
//This is the best way to periodically trigger your application while getting useful information about jitter.
int32_t sampleRecieved = controller->SyncInterruptWait();
int32_t pointsNeeded = sampleRecieved - lastSample;
//Some applications may want to see specific block counts. You likely don't need to do this. See region (Fixed Size Implementation) Notes above.
pointsNeeded = AdjustPointsNeededToBlockCount(pointsNeeded);
//Note this application doesn't do the following as it is intended to help organization rather than preform motion. Please see other examples for that.
//Generate pointsNeeded Points.
//Potentially Command Move with generated Points -or- signal thread to do so -or- any number of things.
//Save sample for next calculation.
lastSample = sampleRecieved;
//One possible point lookup method might be to keep a rotating buffer of points which you use SampleRate Modulus BufferSize for setting/lookup.
//SampleRateGet() Modulus BufferSize would be your key for current point.
}
}
// Print out any errors on the associated Object.
void checkErrors(RapidCodeObject *object)
{
while (object->ErrorLogCountGet() > 0)
{
printf("Error Found: %s\n", object->ErrorLogGet()->text);
}
}
void streamingMotionBufferManagementMain()
{
// Initialize MotionController. An example path to RapidCode diretory provided.
// NOTE: Use CreateFromBoard(#) and skip NetworkStart() for SynqNet.
MotionController *controller = MotionController::CreateFromSoftware(/*rmpPath*/);;// .XX\\");
checkErrors(controller);
try
{
// Initialize the Network.
controller->NetworkStart();
checkErrors(controller);
//Create Monitoring Thread.
_beginthread(monitoringThread, 0, controller);
//Wait for some exit condition
bool exitCondition = false;
while (!exitCondition)
{
//In theory, you application will be doing a lot in here. Note this application has no way to trigger exitCondition and will run forever.
}
}
catch (RsiError const& err)
{
printf("\n%s\n", err.text);
}
controller->Delete(); // Delete the controller as the program exits to ensure memory is deallocated in the correct order.
//Exit Gracefully
_continueMonitoring = false;
//Wait an appropriate time to get from the top of the Monitoring Loop to the bottom of it.
}
#endif //!defined(__INTIME__)
RSI::RapidCode::RsiError
The RsiError object contains information about any RapidCode API object's error/exception.
Definition: rsi.h:93
RSI::RapidCode::MotionController::NetworkStart
void NetworkStart()
Start the network with RSINetworkStartupMethodNORMAL.
RSI::RapidCode::MotionController::Delete
void Delete(void)
Delete the MotionController and all its objects.
RSI::RapidCode::MotionController::CreateFromSoftware
static MotionController * CreateFromSoftware()
Initialize and start the RMP EtherCAT controller.
RSI::RapidCode
RSI::RapidCode::RapidCodeObject
The RapidCode base class. All non-error objects are derived from this class.
Definition: rsi.h:150
RSI::RapidCode::MotionController::SyncInterruptPeriodSet
void SyncInterruptPeriodSet(uint32_t samples)
Configure the period for the Sync Interrupt on the controller.
RSI::RapidCode::RapidCodeObject::ErrorLogGet
const RsiError *const ErrorLogGet()
Get the next RsiError in the log.
RSI::RapidCode::MotionController::SyncInterruptEnableSet
void SyncInterruptEnableSet(bool enable)
Configure Sync (periodic) interrupts for the controller.
RSI::RapidCode::MotionController
The MotionController object represents the RMP INtime soft motion controller.
Definition: rsi.h:747
RSI::RapidCode::RapidCodeObject::ErrorLogCountGet
int32_t ErrorLogCountGet()
Get the number of software errors in the error log.
RSI::RapidCode::MotionController::SyncInterruptWait
int32_t SyncInterruptWait()
Suspend the current thread until an interrupt arrives from the controller.