Contoured Move C/C++ Code
The following example code is not necessarily complete, and may not compile if copied exactly. Refer to the examples folder on the NI-Motion CD for files that are complete and compile as is.
// Main function
void main(void)
{
u8 boardID; // Board identification number
u8 vectorSpace; // Vector space number
u16 csr = 0; // Communication status register
u16 axisStatus; // Axis status
u16 status; // Temporary copy of status
u16 moveComplete; // Move complete status
i32 i;
i32 points[1994] = NIMC_SPIRAL_ARRAY; // Array of 2D points to move
u32 numPoints = 1994; // Total number of points to contour through
i32 bufferSize = 1000; // The size of the buffer to allocate on the motion controller
f64 actualInterval; // The interval the controller can really contour at
i32* downloadData = NULL; // The temporary array that is created to download the points to the controller
u32 currentDataPoint = 0; // Indicates the next point in the points array that is to be downloaded
i32 backlog; // Indicates the available space to download more points
u16 bufferState; // Indicates the state of the onboard buffer
u32 pointsDone; // Indicates the number of points that have been consumed
u32 dataCopied = 0; // Keeps tack of the points copied
// Variables for modal error handling
u16 commandID; // The commandID of the function
u16 resourceID; // The resource ID
i32 errorCode; // Error code
///////////////////////////////
// Set the board ID
boardID = 1;
// Set the axis number
vectorSpace = NIMC_VECTOR_SPACE1;
////////////////////////////////
// Configure a 2D Vector Space comprising of axes 1 and 2
err = flex_config_vect_spc(boardID, vectorSpace, 1, 2, 0);
CheckError;
// Set the operation mode to absolute position
err = flex_set_op_mode(boardID, vectorSpace, NIMC_ABSOLUTE_CONTOURING);
CheckError;
// Configure buffer on motion controller memory (RAM)
// Note requested time interval is hardcoded to 10 milliseconds
err = flex_configure_buffer(boardID, 1 /*buffer number*/, vectorSpace, NIMC_POSITION_DATA, bufferSize, numPoints, NIMC_TRUE, 10, &actualInterval);
CheckError;
// Send the first 1000 points of the data
downloadData = malloc(sizeof(i32)*bufferSize);
for(i=0;i<bufferSize;i++){
downloadData[i] = points[i];
currentDataPoint++;
}
err = flex_write_buffer(boardID, 1/*buffer number*/, bufferSize, 0, downloadData, 0xFF);
free(downloadData);
downloadData = NULL;
CheckError;
// Start Motion
err = flex_start(boardID, vectorSpace, 0);
CheckError;
for(;;){
axisStatus = 0;
// Check for available space and download remaining points every 50 milliseconds
Sleep(50);
// Check to see if we have more points to download
if(currentDataPoint < numPoints){
err = flex_check_buffer_rtn(boardID, 1/*buffer number*/, &backlog, &bufferState, &pointsDone);
CheckError;
if(backlog >= 300){
downloadData = malloc(sizeof(i32)*backlog);
dataCopied = 0;
for(i=0;i<backlog;i++){
if(currentDataPoint > numPoints) break;
downloadData[i] = points[currentDataPoint];
currentDataPoint++;
dataCopied++;
}
err = flex_write_buffer (boardID, 1 /*buffer number*/, dataCopied, 0, downloadData, 0xFF);
free(downloadData);
downloadData = NULL;
CheckError;
}
}
// Check the move complete status
err = flex_check_move_complete_status(boardID, vectorSpace, 0, &moveComplete);
CheckError;
if(moveComplete) break;
// Check for axis off status/following error or any modal errors
// Read the communication status register and check the modal errors
err = flex_read_csr_rtn(boardID, &csr);
CheckError;
// Check the modal errors
if (csr & NIMC_MODAL_ERROR_MSG){
err = csr & NIMC_MODAL_ERROR_MSG;
CheckError;
}
// Check the motor off status on all the axes or axis
err = flex_read_axis_status_rtn(boardID, 1, &status);
CheckError;
axisStatus |= status;
err = flex_read_axis_status_rtn(boardID, 2, &status);
CheckError;
axisStatus |= status;
if( (axisStatus & NIMC_FOLLOWING_ERROR_BIT) || (axisStatus & NIMC_AXIS_OFF_BIT) ){
break; // Break out of the for loop as an axis was killed
}
}
// Set the mode back to absolute mode to get the controller out of contouring
// mode
err = flex_set_op_mode(boardID, vectorSpace, NIMC_ABSOLUTE_POSITION);
CheckError;
// Free the buffer allocated on the controller memory
err = flex_clear_buffer(boardID, 1/*buffer number*/);
CheckError;
return; // Exit the Application
/////////////////////////////////////////////////////////////////////////
// Error Handling
//
nimcHandleError; //NIMCCATCHTHIS:
// Check to see if there were any Modal Errors
if (csr & NIMC_MODAL_ERROR_MSG){
do{
// Get the command ID, resource and the error code of the modal
// error from the error stack on the board
flex_read_error_msg_rtn(boardID,&commandID,&resourceID,&errorCode);
nimcDisplayError(errorCode,commandID,resourceID);
// Read the Communication Status Register
flex_read_csr_rtn(boardID,&csr);
}while(csr & NIMC_MODAL_ERROR_MSG);
}
else // Display regular error
nimcDisplayError(err,0,0);
return; // Exit the Application
}