event3.c -- Perform a repeated single-axis motion using command-line-specified axis (default 0).
/* event3.c */
/* Copyright(c) 1991-2002 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.
*/
#if defined(MEI_RCS)
static const char MEIAppRCS[] =
"$Header: /MainTree/XMPLib/XMP/app/event3.c 13 7/23/01 2:36p Kevinh $";
#endif
/*
:Perform a repeated single-axis motion using command-line-specified axis (default 0).
Wait for events to be distributed by the event manager in a separate service thread.
Check status after motion complete, warn of inPosition not set.
Warning! This is a sample program to assist in the integration of the
XMP motion controller with your application. It may not contain all
of the logic and safety features that your application requires.
*/
#include <stdlib.h>
#include <stdio.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"
#if defined(ARG_MAIN_RENAME)
#define main event3Main
argMainRENAME(main, event3)
#endif
#define MOTION_COUNT (2)
#define AXIS_COUNT (1)
/* Command line arguments and defaults */
long axisNumber = 0;
long motionNumber = 0;
MPIMotionType motionType = MPIMotionTypeTRAPEZOIDAL;
Arg argList[] = {
{ "-axis", ArgTypeLONG, &axisNumber, },
{ "-motion", ArgTypeLONG, &motionNumber, },
{ "-type", ArgTypeLONG, &motionType, },
{ NULL, ArgTypeINVALID, NULL, }
};
double position[MOTION_COUNT][AXIS_COUNT] = {
{ 20000.0, },
{ 0.0, },
};
MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
{ /* velocity accel decel */
{ 10000.0, 100000.0, 100000.0, },
},
{ /* velocity accel decel */
{ 10000.0, 100000.0, 100000.0, },
},
};
/* motion parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
{ &trajectory[0][0], &position[0][0], },
{ &trajectory[1][0], &position[1][0], },
};
MPIMotionTrapezoidal trapezoidal[MOTION_COUNT] = {
{ &trajectory[0][0], &position[0][0], },
{ &trajectory[1][0], &position[1][0], },
};
MPIMotionVelocity velocity[MOTION_COUNT] = {
{ &trajectory[0][0], },
{ &trajectory[1][0], },
};
long
motionDone(MPIMotion motion,
MPIStatus *status);
int
main(int argc,
char *argv[])
{
MPIControl control; /* motion controller handle */
MPIAxis axisList[AXIS_COUNT]; /* axis handle(s) */
MPIMotion motion; /* motion handle */
MPINotify notify; /* event notification object */
MPIEventMgr eventMgr; /* event manager handle */
MPIEventMask eventMask;
MPIControlType controlType;
MPIControlAddress controlAddress;
Service service;
long returnValue; /* return value from library */
long index;
long argIndex;
/* 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) ||
(axisNumber >= MEIXmpMAX_Axes) ||
(motionNumber >= MEIXmpMAX_MSs) ||
(motionType < MPIMotionTypeFIRST) ||
(motionType >= MEIMotionTypeLAST)) {
meiPlatformConsole("usage: %s %s\n"
"\t\t[-axis # (0 .. %d)]\n"
"\t\t[-motion # (0 .. %d)]\n"
"\t\t[-type # (0 .. %d)]\n",
argv[0],
ArgUSAGE,
MEIXmpMAX_Axes - 1,
MEIXmpMAX_MSs - 1,
MEIMotionTypeLAST - 1);
exit(MPIMessageARG_INVALID);
}
switch (motionType) {
case MPIMotionTypeS_CURVE:
case MPIMotionTypeTRAPEZOIDAL:
case MPIMotionTypeVELOCITY: {
break;
}
default: {
meiPlatformConsole("%s: %d: motion type not available\n",
argv[0],
motionType);
exit(MPIMessageUNSUPPORTED);
break;
}
}
/* Create motion controller object */
control =
mpiControlCreate(controlType,
&controlAddress);
msgCHECK(mpiControlValidate(control));
/* Initialize motion controller */
returnValue = mpiControlInit(control);
msgCHECK(returnValue);
/* Create axis object using axisNumber on controller*/
axisList[0] =
mpiAxisCreate(control,
axisNumber);
msgCHECK(mpiAxisValidate(axisList[0]));
/* Create motion supervisor object using MS number */
motion =
mpiMotionCreate(control,
motionNumber,
MPIHandleVOID);
msgCHECK(mpiMotionValidate(motion));
/* Create 1-axis motion coordinate system */
returnValue =
mpiMotionAxisListSet(motion,
AXIS_COUNT,
axisList);
msgCHECK(returnValue);
/* Request notification of all events from motion */
mpiEventMaskCLEAR(eventMask);
mpiEventMaskALL(eventMask);
returnValue =
mpiMotionEventNotifySet(motion,
eventMask,
NULL);
msgCHECK(returnValue);
/* Create event notification object for motion */
notify =
mpiNotifyCreate(eventMask,
motion);
msgCHECK(mpiNotifyValidate(notify));
/* Create event manager object */
eventMgr = mpiEventMgrCreate(control);
msgCHECK(mpiEventMgrValidate(eventMgr));
/* Add notify to event manager's list */
returnValue =
mpiEventMgrNotifyAppend(eventMgr,
notify);
msgCHECK(returnValue);
/* Create service thread */
service =
serviceCreate(eventMgr,
-1, /* default (max) priority */
-1); /* -1 => enable interrupts */
meiASSERT(service != NULL);
/* Loop repeatedly */
index = 0;
while ((returnValue == MPIMessageOK) &&
(meiPlatformKey(MPIWaitPOLL) <= 0)) {
MPIMotionParams motionParams;
switch (motionType) {
case MPIMotionTypeS_CURVE: {
motionParams.sCurve = sCurve[index];
break;
}
case MPIMotionTypeTRAPEZOIDAL: {
motionParams.trapezoidal = trapezoidal[index];
break;
}
case MPIMotionTypeVELOCITY: {
motionParams.velocity = velocity[index];
break;
}
default: {
meiASSERT(FALSE);
break;
}
}
/* Start motion */
returnValue =
mpiMotionStart(motion,
motionType,
&motionParams);
fprintf(stderr,
"mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
motion,
motionType,
&motionParams,
returnValue,
mpiMessage(returnValue, NULL));
switch (returnValue) {
case MPIMotionMessageERROR: {
returnValue =
mpiMotionAction(motion,
MPIActionRESET);
fprintf(stderr,
"mpiMotionAction(0x%x, RESET) returns 0x%x\n",
motion,
returnValue);
msgCHECK(returnValue);
/* FALL THROUGH */
}
case MPIMotionMessageNOT_READY: {
returnValue = MPIMessageOK;
continue;
}
case MPIMotionMessageMOVING: {
returnValue = MPIMessageOK;
break;
}
case MPIMessageOK:
default: {
break;
}
}
/* Collect motion events */
while (returnValue == MPIMessageOK) {
MPIEventStatus eventStatus;
/* Wait for motion event */
returnValue =
mpiNotifyEventWait(notify,
&eventStatus,
MPIWaitFOREVER);
fprintf(stderr,
"mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
"\teventStatus: type %d source 0x%x info 0x%x\n",
notify,
&eventStatus,
MPIWaitFOREVER,
returnValue,
eventStatus.type,
eventStatus.source,
eventStatus.info[0]);
if (returnValue == MPIMessageOK) {
if (eventStatus.type == MPIEventTypeMOTION_DONE) {
break;
}
}
else {
break;
}
}
if (returnValue == MPIMessageOK) {
MPIStatus status;
returnValue =
motionDone(motion,
&status);
if ((returnValue == MPIMessageOK) &&
(status.state == MPIStateERROR)) {
if ((status.action == MPIActionABORT) ||
(status.action == MPIActionE_STOP_ABORT)) {
double position[AXIS_COUNT];
returnValue =
mpiMotionPositionGet(motion,
position, /* actual */
NULL); /* command */
msgCHECK(returnValue);
returnValue =
mpiMotionPositionSet(motion,
NULL, /* actual */
position); /* command */
msgCHECK(returnValue);
}
returnValue =
mpiMotionAction(motion,
MPIActionRESET);
fprintf(stderr,
"mpiMotionAction(0x%x, RESET) returns 0x%x\n",
motion,
returnValue);
msgCHECK(returnValue);
}
}
putchar('\n');
if (++index >= MOTION_COUNT) {
index = 0;
}
}
fprintf(stderr,
"%s exiting: returnValue 0x%x: %s\n",
argv[0],
returnValue,
mpiMessage(returnValue, NULL));
returnValue = mpiMotionDelete(motion);
msgCHECK(returnValue);
for (index = 0; index < AXIS_COUNT; index++) {
returnValue = mpiAxisDelete(axisList[index]);
msgCHECK(returnValue);
}
returnValue = serviceDelete(service);
msgCHECK(returnValue);
returnValue = mpiEventMgrDelete(eventMgr);
msgCHECK(returnValue);
returnValue = mpiNotifyDelete(notify);
msgCHECK(returnValue);
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
return ((int)returnValue);
}
long motionDone(MPIMotion motion,
MPIStatus *status)
{
long returnValue;
double actual[AXIS_COUNT];
double command[AXIS_COUNT];
returnValue =
mpiMotionStatus(motion,
status,
NULL);
msgCHECK(returnValue);
printf("MotionDone: status: state %d action %d eventMask 0x%x\n"
"\tatTarget %d settled %d %s\n",
status->state,
status->action,
status->eventMask,
status->atTarget,
status->settled,
(status->settled == FALSE)
? "=== NOT SETTLED ==="
: "");
returnValue =
mpiMotionPositionGet(motion,
actual,
command);
msgCHECK(returnValue);
if (returnValue == MPIMessageOK) {
long index;
/* Display axis positions */
for (index = 0; index < AXIS_COUNT; index++) {
printf("\taxis[%d] position: command %11.3lf\tactual %11.3lf\n",
index,
command[index],
actual[index]);
}
}
return (returnValue);
}