User-Defined Scanning Path C/C++ Code

NI-Motion

User-Defined Scanning Path 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, 3);
   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);


   // 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
}