.

     

MPI Application Template
template.c
 

demandModeSwitch.c -- Use multiple filters and user limits for on-the-fly demand mode switching


/* demandModeSwitch.c */

/* Copyright(c) 1991-2007 by Motion Engineering, Inc.  All rights reserved.
 *
 * This software  contains proprietary and  confidential information  of
 * Motion Engineering Inc., and its suppliers.  Except as may be set forth
 * in the license agreement under which  this software is supplied, use,
 * disclosure, or  reproduction is prohibited without the prior express
 * written consent of Motion Engineering, Inc.
 */

/*

:Use multiple filters and user limits for on-the-fly demand mode switching.

This sample application demonstrates how to use multiple filters on a single 
 motor for multiple demand modes. One filter will be used for Torque Mode and
 the other for Velocity Mode. This application also demonstrates how to use
 User Limits to do on-the-fly demand mode switching.

This program remaps the input pointers used by the demandChannels for the 
 specified MOTOR to data in the specified VELOCITY_FILTER. This program is 
 not responsible for determining which Filters are used and which Motors are 
 used, or how many motors or filters are active in the firmware. 

In this example, motor MOTOR_NUMBER has its demand channels remapped to get 
 velocity and torque information from Filter VELOCITY_FILTER_NUMBER.  This 
 example does not check to see if filter VELOCITY_FILTER_NUMBER is being 
 processed. The definition of MOTOR_NUMBER and VELOCITY_FILTER_NUMBER is up to
 the user.  It is also up to the user to make sure that the chosen MOTOR_NUMBER
 and VELOCITY_FILTER_NUMBER represent objects that are being processed by the 
 firmware. 

This code assumes that motion supervisor 0 is mapped to axis 0, filter 0, and 
 motor 0, and that filter 1 is unused and unmapped. To change which objects
 are used, change the defines below.

This application commands moves to three points: a high starting position, 
 zero, and the starting position again. From the starting position, the motor
 is commanded in Velocity Mode. When it passes below a position threshold 
 (see defines below), it switches to Torque Mode. When it comes back above
 a second threshold, it switches back to Velocity Mode. When these positions
 are passed, a user-defined location in the User Buffer is written to, 
 allowing visualization of the mode change with Motion Scope. The code also
 configures the Motion Done events to include Move IDs, allow the application
 to determine when the final move has completed.

This code was original developed for and tested on a Kollmorgan S200 drive. 

Warning!  This is a sample program to assist in the integration of an
 MEI motion controller with your application.  It may not contain all
 of the logic and safety features that your application requires.
 
The msgCHECK(...) macros used in the following sample code are intended
 to convey our strong belief that ALL error return codes should be checked.
 Actual application code should use specific error handling techniques (other
 than msgCHECKs) best suited to your internal error recovery methods.
 
*/

#include <stdlib.h>
#include <stdio.h>

#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    modeSwitch
argMainRENAME(main, modeSwitch)
#endif

/* Motion used to command motion */
#define MOTION_NUMBER         (0) 

/* Axis used for feedback */
#define AXIS_NUMBER           (0) 

/* Motor whose demand structure will be modified */
#define MOTOR_NUMBER       (0)   

/* Filter that will be used for Velocity Mode */
#define VELOCITY_FILTER_NUMBER   (1)   

/* Filter that motor will be switched back to */
#define ORIGINAL_FILTER_NUMBER   (0)   


/* USER_LIMIT0 will trigger below this position */
#define POSITION_LIMIT0       (2000000)   

/* USER_LIMIT1 will trigger above this position */
#define POSITION_LIMIT1       (1000000)   

/* This location in the User Buffer will be written when user events trigger */
#define USER_BUFFER_INDEX     (0)


/* Positions for motion */

#define  POS0              (1E7)
#define  VEL0              (1E8)
#define ACC0               (1E8)
#define DEC0               (1E8)
#define JERK0              (66)
#define DELAY0             (1)

#define  POS1              (0)
#define  VEL1              (VEL0/2)
#define ACC1               (1E8)
#define DEC1               (1E8)
#define JERK1              (66)
#define  DELAY1               (1)

#define  POS2              (1E7)
#define  VEL2              (VEL0)
#define ACC2               (ACC1)
#define DEC2               (ACC1)
#define JERK2              (66)
#define DELAY2             (2)

typedef struct MotionProfile{
   double         position;
   MPITrajectory  trajectory;
   double         delay;
} MotionProfile;

MotionProfile Profile[] = {
   { POS0, {VEL0, ACC0, DEC0, JERK0}, DELAY0 },
   { POS1, {VEL1, ACC1, DEC1, JERK1}, DELAY1 },
   { POS2, {VEL2, ACC2, DEC2, JERK2}, DELAY2 },

};

#define  NUMBER_OF_PROFILES   (sizeof(Profile)/sizeof(MotionProfile))


/* Parse command line */
long parseCommandLine(int                argc,
                      char               *argv[],
                      MPIControlType     *controlType,
                      MPIControlAddress  *controlAddress,
                      long               *axisNumber,
                      long               *motionNumber)
{
    long    argIndex;

    /* Application-specific command line arguments */
    Arg argList[] =
    {
        {   "-axis",    ArgTypeLONG,    &(*axisNumber),    },
        {   "-motion",  ArgTypeLONG,    &(*motionNumber),  },
        {   NULL,       ArgTypeINVALID, NULL,           }
    };

    /* Parse command line for Control type and address */
    argIndex =
        argControl(argc,
                   argv,
                   controlType,
                   controlAddress);

    /* Parse command line for application-specific arguments */
    while (argIndex < argc)
    {
        long    argIndexNew;

        argIndexNew = argSet(argList, argIndex, argc, argv);

        if (argIndexNew <= argIndex)
        {
            argIndex = argIndexNew;
            break;
        }
        else
        {
            argIndex = argIndexNew;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if (argIndex < argc)
    {
        meiPlatformConsole("usage: %s %s\n"
                     "\t      [-axis # (0 .. %d)]\n"
                     "\t      [-motion # (0 .. %d)]\n",
                     argv[0],
                     ArgUSAGE,
                     MEIXmpMAX_Axes,
                     MEIXmpMAX_MSs);
        exit(MPIMessageARG_INVALID);
    }

    return 0;
}


/* Create and initialize MPI objects */
void programInit(MPIControl         *control,
		MPIControlType      controlType,
		MPIControlAddress  *controlAddress,
		MPIMotor         *motor,
		long          motorNumber,
		MPIFilter        *velocityFilter,
		long          velFilterNumber,
		MPIFilter        *originalFilter,
		long          origFilterNumber,
		MPIAxis            *axis,
		long                axisNumber,
		MPIMotion          *motion,
		long                motionNumber,
		MPIEventMgr        *eventMgr,
		MPINotify          *notify,
		Service            *service)
{
    MPIEventMask    eventMask;
    long            returnValue;

    /* Create motion controller object */
    *control =
        mpiControlCreate(controlType, controlAddress);
    msgCHECK(mpiControlValidate(*control));

    /* Initialize motion controller */
    returnValue =
        mpiControlInit(*control);
    msgCHECK(returnValue);

   /* Create motor object */
   *motor =
      mpiMotorCreate(*control, motorNumber);
   msgCHECK(mpiMotorValidate(*motor));

   /* Create filter objects */
   *velocityFilter =
      mpiFilterCreate(*control, velFilterNumber);
   msgCHECK(mpiFilterValidate(*velocityFilter));

   *originalFilter =
      mpiFilterCreate(*control, origFilterNumber);
   msgCHECK(mpiFilterValidate(*originalFilter));

    /* Create axis object */
    *axis =
        mpiAxisCreate(*control, axisNumber);
    msgCHECK(mpiAxisValidate(*axis));

    /* Create motion supervisor object with axis */
    *motion =
        mpiMotionCreate(*control, motionNumber, *axis);
    msgCHECK(mpiMotionValidate(*motion));

    /* Map axis to motion supervisor on XMP */
    returnValue =
        mpiMotionAction(*motion, MEIActionMAP);
    msgCHECK(returnValue);

    /* Create event manager object */
    *eventMgr =
        mpiEventMgrCreate(*control);
    msgCHECK(mpiEventMgrValidate(*eventMgr));

    /* Request notification of ALL events from motion */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    meiEventMaskALL(eventMask);

    /* Calling mpiMotionEventNotifySet(...) so that events will be reported */
    returnValue =
        mpiMotionEventNotifySet(*motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

    /* Create event notification object for NULL (all objects) */
    *notify =
        mpiNotifyCreate(eventMask, NULL);
    msgCHECK(mpiNotifyValidate(*notify));

    /* Append notify to event manager */
    returnValue =
        mpiEventMgrNotifyAppend(*eventMgr, *notify);
    msgCHECK(returnValue);

    /* Create service thread */
    *service =
        serviceCreate(*eventMgr,
                      -1,   /* default (max) priority */
                      -1);  /* -1 => enable interrupts */
    if (*service == NULL)
    {
        msgCHECK(MPIMessageHANDLE_INVALID);
    }
}


/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl  *control,
		MPIMotor *motor,
		MPIFilter   *velocityFilter,
		MPIFilter   *originalFilter,
		MPIAxis     *axis,
		MPIMotion   *motion,
		MPIEventMgr *eventMgr,
		MPINotify   *notify,
		Service     *service)
{
    long            returnValue;

    /* Delete service object */
    returnValue =
        serviceDelete(*service);
    msgCHECK(returnValue);

    /* Delete event manager object */
    returnValue =
        mpiEventMgrDelete(*eventMgr);
    msgCHECK(returnValue);
    *eventMgr = MPIHandleVOID;

    /* Delete event notification object */
    returnValue =
        mpiNotifyDelete(*notify);
    msgCHECK(returnValue);
    *notify = MPIHandleVOID;

    /* Delete motion supervisor object */
    returnValue =
        mpiMotionDelete(*motion);
    msgCHECK(returnValue);
    *motion = MPIHandleVOID;

    /* Delete axis object */
    returnValue =
        mpiAxisDelete(*axis);
    msgCHECK(returnValue);
    *axis = MPIHandleVOID;

   /* Delete filter handles */
    returnValue =
        mpiFilterDelete(*velocityFilter);
    msgCHECK(returnValue);
   *velocityFilter = MPIHandleVOID;

    returnValue =
        mpiFilterDelete(*originalFilter);
    msgCHECK(returnValue);
   *originalFilter = MPIHandleVOID;


   /* Delete motor handle */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(returnValue);
    *motor = MPIHandleVOID;

    /* Delete motion controller object */
    returnValue =
        mpiControlDelete(*control);
    msgCHECK(returnValue);
    *control = MPIHandleVOID;
}


/* Wait for and display motion done and user limit events,
   and switch demand modes when the appropriate user limits
   are hit.
 */
void displayEventsUntilMotionDone(MPINotify notify,
                          MPIMotor motor,
                          long lastMotionID)
{
    MPIEventStatus  eventStatus;
    long            returnValue;

    MEIEventStatusInfo  *info;
   info = (MEIEventStatusInfo *)eventStatus.info;

    while (TRUE)
    {
        /* Wait for events */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

      if (eventStatus.type == MEIEventTypeLIMIT_USER0)
        {
            meiPlatformConsole("User Limit 0 event received: "
                        "switching to torque mode\n");
         /* Switch to torque mode here */
         msgCHECK(meiMotorDemandModeSet(motor, MEIMotorDemandModeTORQUE));
        }

      if (eventStatus.type == MEIEventTypeLIMIT_USER1)
        {
            meiPlatformConsole("User Limit 1 event received: "
                        "switching to velocity mode\n");
         /* Switch to velocity mode here */
         msgCHECK(meiMotorDemandModeSet(motor, MEIMotorDemandModeVELOCITY));
        }


        if (eventStatus.type == MPIEventTypeMOTION_DONE)
        {
            meiPlatformConsole("Motion Done event received from motion %d\n",
                        info->data.word[1]);
         if (info->data.word[1] == lastMotionID) {
            break;
         }
        }
    }
}

/* Configure user limits for actual position comparison
   and writing to the user buffer.
*/
long userLimitPositionEvent(MPIMotor         motor,
			long          axisNumber,
			MEIEventType     eventType,
			MEIXmpLimitType     limitType,
			long          position,
			long           userBufferIndex,
			long          outputData)
{
	MPIControl       control;
	MEIPlatform       platform;
	MEIXmpData       *firmware;
	MEIXmpBufferData *buffer;
	MEIMotorEventConfig motorEventConfig;
	MPIEventMask        resetMask;
	MEIXmpLimitType      limitTypeVel;
	long           *actPositionPtr;
	long           *outputAddr;
	long           returnValue = MPIMessageOK;
	
	mpiEventMaskCLEAR(resetMask);
	mpiEventMaskSET(resetMask, eventType);


    /* Determine control handle, then get pointer to XMP firmware */
    control = mpiMotorControl(motor);
   msgCHECK(mpiControlValidate(control));
   platform = meiControlPlatform(control);

    returnValue =
        mpiControlMemory(control,
                         (void **)&firmware,
                         (void **)&buffer);
   msgCHECK(returnValue);

   returnValue =
      mpiMotorEventConfigGet(motor,
                               eventType,
                               NULL,
                               &motorEventConfig);
   msgCHECK(returnValue);

   /* Velocity < 0 or Velocity > 0 */
   if(limitType == MEIXmpLimitTypeGE){
      limitTypeVel = MEIXmpLimitTypeFGE;
   }else{
      limitTypeVel = MEIXmpLimitTypeFLT;
   }

	actPositionPtr = (long*) &firmware->Axis[axisNumber].ActPosition;
	returnValue = meiPlatformHostAddress64To32(platform,
							&actPositionPtr,
							1);   /* low word */
	msgCHECK(returnValue);
	
	motorEventConfig.Condition[0].Type          = limitType;
	motorEventConfig.Condition[0].SourceAddress = actPositionPtr;
	motorEventConfig.Condition[0].Mask          = 0xffffffff;  /* AND mask */
	motorEventConfig.Condition[0].LimitValue.g32.l = position;
	
	motorEventConfig.Condition[1].Type          = limitTypeVel;
	motorEventConfig.Condition[1].SourceAddress =
	&firmware->Axis[axisNumber].CommandVelocity;
	motorEventConfig.Condition[1].Mask          = 0xffffffff;
	motorEventConfig.Condition[1].LimitValue.g32.f  = 0;
	
	motorEventConfig.Status = MEIXmpStatusLIMIT;
	
	/* Determine logic result from Condition[0] and Condition[1] */
	motorEventConfig.Logic  = MEIXmpLogicAND;
	
	/* Write output data to User Buffer */
	outputAddr = &buffer->UserBuffer.Data[userBufferIndex];
	motorEventConfig.Output.OutputPtr = outputAddr;
	motorEventConfig.Output.AndMask   = 0;
	motorEventConfig.Output.OrMask    = outputData;
	motorEventConfig.Output.Enabled   = TRUE;

    returnValue =
        mpiMotorEventConfigSet(motor,
                               eventType,
                               NULL,
                               &motorEventConfig);
    msgCHECK(returnValue);

    /* Reset event in case conditions have already been satisfied */
   returnValue =
      mpiMotorEventReset(motor,
                           resetMask);
    msgCHECK(returnValue);

   return returnValue;
}

/* Setup second filter for velocity mode moves with the specified motor and axis*/
long remapVelocityDemandInput(MPIMotor motor,
                       MPIFilter filter,
                       MPIAxis axis)
{
   long returnValue;
   MPIControl control;
   MEIPlatform platform;
   MEIXmpMotor *motorPtr;
   MEIXmpMotorControl motorControl;
   MEIXmpFilter *filterPtr;
   MEIXmpAxis *axisPtr;

   control = mpiMotorControl(motor);
   returnValue = mpiControlValidate(control);

   if (returnValue == MPIMessageOK) {
      platform = meiControlPlatform(control);
      returnValue = meiPlatformValidate(platform);
   }

   if (returnValue == MPIMessageOK) {
      returnValue = mpiMotorMemory(motor,
                           &motorPtr);
   }

   if (returnValue == MPIMessageOK) {
      returnValue = mpiFilterMemory(filter,
                           &filterPtr);
   }

   if (returnValue == MPIMessageOK) {
      returnValue = mpiAxisMemory(axis,
                           &axisPtr);

   }

   /* Get motorControl struct */
   if (returnValue == MPIMessageOK) {
      returnValue = mpiMotorMemoryGet(motor,
                              &motorControl,
                              &motorPtr->IO.Control,
                              sizeof(motorControl));
   }

   /* Verify that we're in Velocity Mode */
   if (returnValue == MPIMessageOK) {
      if (motorControl.ModeControlData[MEIXmpMotorModeSelectVELOCITY].Mode ==
            MEIXmpMotorControlModeVELOCITY) {

         /* Demand Channels 2 and 3 are used for Velocity Mode.
            Channel 2 is used for the torque demand which comes 
            from the filter's feedforward term.
         */
         long *inputPtrTorque, *inputPtrVelocity;
         MEIXmpMotorControlModeData velData =
            motorControl.ModeControlData[MEIXmpMotorModeSelectVELOCITY];

         inputPtrTorque = (long*)&filterPtr->Data.FFOutput;
         if (returnValue == MPIMessageOK) {
            returnValue = meiPlatformMemoryToFirmware(platform,
                                          inputPtrTorque,
                                          &inputPtrTorque);
            if (returnValue == MPIMessageOK) {
               returnValue =
                  mpiMotorMemorySet(motor,
                                &motorPtr->IO.DemandChannel[2].Input,
                                &inputPtrTorque,
                                sizeof(inputPtrTorque));
            }
         }


         /* Channel 3 is used for the velocity demand which comes from the
            filter's PID, so we'll use the post filter output.
         */
         if (returnValue == MPIMessageOK) {
            inputPtrVelocity = (long*)&filterPtr->Data.PostFilterOutput;
            returnValue = meiPlatformMemoryToFirmware(platform,
                                          inputPtrVelocity,
                                          &inputPtrVelocity);
            if (returnValue == MPIMessageOK) {
               returnValue =
                  mpiMotorMemorySet(motor,
                                &motorPtr->IO.DemandChannel[3].Input,
                                &inputPtrVelocity,
                                sizeof(inputPtrVelocity));
            }
         }

         /* Grab the filter's gain index and integrator disable settings
            and put them into the motor's demand mode configuration for
            velocity mode.
          */
         if (returnValue == MPIMessageOK) {
            long *gainIndex = &filterPtr->GainIndex;
            long *nodeIntegratorDisable =
               &filterPtr->NodeIntegratorDisable;

            returnValue = meiPlatformMemoryToFirmware(platform,
                                          gainIndex,
                                          &gainIndex);

            if (returnValue == MPIMessageOK) {
               returnValue =
                  meiPlatformMemoryToFirmware(platform,
                                       nodeIntegratorDisable,
                                       &nodeIntegratorDisable);
            }

            if (returnValue == MPIMessageOK) {
               MEIXmpMotorControlModeData *modePtr =
                  motorPtr->IO.Control.ModeControlData;
               modePtr = &modePtr[MEIXmpMotorModeSelectVELOCITY];

               velData.GainIndex = gainIndex;
               velData.NodeIntegratorDisable =
                  nodeIntegratorDisable;

               returnValue =
                  mpiMotorMemorySet(motor,
                                &modePtr->GainIndex,
                                &velData.GainIndex,
                                sizeof(gainIndex));

               if (returnValue == MPIMessageOK) {
                  returnValue =
                     mpiMotorMemorySet(motor,
                                   &modePtr->NodeIntegratorDisable,
                                   &velData.NodeIntegratorDisable,
                                   sizeof(nodeIntegratorDisable));
               }
            }

            /*  Map the axis to the filter's input so we get feedback */
            if (returnValue == MPIMessageOK) {
               long* inputPtrAxis = (long*) axisPtr;

               returnValue = meiPlatformMemoryToFirmware(platform,
                                               inputPtrAxis,
                                               &inputPtrAxis);

               if (returnValue == MPIMessageOK) {
                  returnValue =
                     mpiFilterMemorySet(filter,
                                    &filterPtr->Axis[0].Ptr,
                                    &inputPtrAxis,
                                    sizeof(inputPtrAxis));
               }

               if (returnValue == MPIMessageOK) {
                  returnValue =
                     mpiFilterMemorySet(filter,
                                    &filterPtr->Axis[1].Ptr,
                                    &inputPtrAxis,
                                    sizeof(inputPtrAxis));
               }

            }
         }
      }
      else {
         returnValue = MPIMessageARG_INVALID;
      }
   }

   return (returnValue);
}

/* Configure motion done events to record the move ID so we know when
   the final move in the profile is finished.
*/
void configMotionDoneNotification(MPIMotor motor,
                          MPIAxis axis,
                          MPIMotion motion)
{
	long           returnValue;
	MPIEventMask      eventMask;
	MEIEventNotifyData  motionData;
	MEIXmpAxis          *xmpAxis;


   meiPlatformConsole("Configuring Motion Done event notification\n");

   /* Set up event notification to record move ID */
   returnValue = mpiAxisMemory(axis, &xmpAxis);
   msgCHECK(returnValue);

   returnValue =
        mpiMotorEventNotifyGet(motor,
                               &eventMask,
                               NULL);
    msgCHECK(returnValue);

   returnValue =
        mpiMotorEventNotifySet(motor,
                               eventMask,
                               NULL);

   returnValue =
        mpiAxisEventNotifyGet(axis,
                              &eventMask,
                              &motionData);
    msgCHECK(returnValue);

   motionData.address[1] = (void *)(&xmpAxis->MoveID);

   returnValue =
        mpiAxisEventNotifySet(axis,
                              eventMask,
                              &motionData);
    msgCHECK(returnValue);

   returnValue =
        mpiMotionEventNotifyGet(motion,
                                &eventMask,
                                &motionData);
    msgCHECK(returnValue);

   motionData.address[1] = (void *)(&xmpAxis->MoveID);

   returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                &motionData);
    msgCHECK(returnValue);


}

/* Set user limit events */
void configUserLimitNotification(MPIMotor motor,
                         MPIAxis axis,

                         long positionLimit0,
                         long positionLimit1,
                         long userBufferIndex)
{
   long axisNumber;
   long returnValue;

   meiPlatformConsole("Configuring User Limit event notification\n");

   returnValue =
      mpiAxisNumber(axis,
                 &axisNumber);
   msgCHECK(returnValue);

   userLimitPositionEvent(motor,
                     axisNumber,
                     MEIEventTypeLIMIT_USER0,
                     MEIXmpLimitTypeLT,
                     positionLimit0,
                     userBufferIndex,
                     1);

   userLimitPositionEvent(motor,
                     axisNumber,
                     MEIEventTypeLIMIT_USER1,
                     MEIXmpLimitTypeGE,
                     positionLimit1,
                     userBufferIndex,
                     0);

}


/* Remap filters for velocity mode, start move, wait for events, and restore */
void commandMoves(MPIControl  control,
		MPIMotor     motor,
		MPIFilter    velocityFilter,
		MPIFilter    originalFilter,
		MPIAxis      axis,
		MPIMotion    motion,
		MotionProfile  *profile,
		long         numberOfProfiles,
		MPINotify      notify)
{
   MPIMotionParams      params;
   long           index;
   long           returnValue;

   /* Add secondary filter for Velocity Mode */
   meiPlatformConsole("Switching to Velocity Mode\n");

   returnValue = meiMotorDemandModeSet(motor, MEIMotorDemandModeVELOCITY);
   msgCHECK(returnValue);

   meiPlatformConsole("Remapping filter for Velocity Mode\n");

   returnValue = remapVelocityDemandInput(motor,velocityFilter,axis);
   msgCHECK(returnValue);


   /* Start motion */
   meiPlatformConsole("Starting motion\n");

   for(index = 0; index < numberOfProfiles; index++) {
      params.sCurve.position   = &profile[index].position;
      params.sCurve.trajectory = &profile[index].trajectory;
      params.attributes.delay = &profile[index].delay;
      params.attributes.id = index;

      returnValue =
         mpiMotionStart(motion,
                     MPIMotionTypeS_CURVE | MPIMotionAttrMaskAPPEND |
                     MPIMotionAttrMaskDELAY | MPIMotionAttrMaskID,
                     &params);

      meiPlatformConsole("mpiMotionStart #%d returns 0x%x: %s\n",
                     index,
                     returnValue,
                     mpiMessage(returnValue, NULL));
   }


   /* Wait for the final motion done event */
   meiPlatformConsole("Waiting for events\n");

    displayEventsUntilMotionDone(notify, motor, numberOfProfiles - 1);

   meiPlatformConsole("Finished waiting for events\n");


   /* Remap Velocity Mode demand back to original filter */
   meiPlatformConsole("Remapping original filter for Velocity Mode\n");

   returnValue = remapVelocityDemandInput(motor,originalFilter,axis);
   msgCHECK(returnValue);


   /* Switch back to Torque Mode */
   meiPlatformConsole("Switching back to Torque Mode\n");

   returnValue = meiMotorDemandModeSet(motor, MEIMotorDemandModeTORQUE);
   msgCHECK(returnValue);

}


/* Main routine */
int main(int     argc,
         char   *argv[])
{
	MPIControl          control;
	MPIControlType      controlType;
	MPIControlAddress   controlAddress;
	MPIMotor				motor;
	MPIFilter         	velocityFilter;
	MPIFilter         	originalFilter;
	MPIAxis             axis;
	MPIMotion           motion;
	MPIEventMgr         eventMgr;
	MPINotify           notify;
	Service             service          = MPIHandleVOID;
	long                motorNumber     = MOTOR_NUMBER;
	long                velFilterNumber    = VELOCITY_FILTER_NUMBER;
	long                origFilterNumber = ORIGINAL_FILTER_NUMBER;
	long                axisNumber       = AXIS_NUMBER;
	long                motionNumber     = MOTION_NUMBER;


    /* Parse command line */
    parseCommandLine(argc,
                     argv,
                     &controlType,
                     &controlAddress,
                     &axisNumber,
                     &motionNumber);

    /* Create and initialize MPI objects */
    programInit(&control,
		controlType,
		&controlAddress,
		&motor,
		motorNumber,
		&velocityFilter,
		velFilterNumber,
		&originalFilter,
		origFilterNumber,
		&axis,
		axisNumber,
		&motion,
		motionNumber,
		&eventMgr,
		&notify,
		&service);

   /* Configure motion done event */
   configMotionDoneNotification(motor,
                         axis,
                         motion);

   /* Configure user limit events */
   configUserLimitNotification(motor,
                        axis,
                        POSITION_LIMIT0,
                        POSITION_LIMIT1,
                        USER_BUFFER_INDEX);

    /* Remap filters for velocity mode, start move, 
      wait for events, and restore 
   */
   commandMoves(control,
             motor,
             velocityFilter,
             originalFilter,
             axis,
             motion,
             Profile,
             NUMBER_OF_PROFILES,
             notify);

    /* Perform certain cleanup actions and delete MPI objects */
    programCleanup(&control,
		&motor,
		&velocityFilter,
		&originalFilter,
		&axis,
		&motion,
		&eventMgr,
		&notify,
		&service);

    return MPIMessageOK;
}
 
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2009 Motion Engineering