capture1.c -- Perform a velocity move and capture position based on Home or Index pulse.
/* capture1.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/capture1.c 10 7/18/01 9:32a Kevinh $"
#endif
#if defined(ARG_MAIN_RENAME)
#define main capture1Main
argMainRENAME(main, capture1)
#endif
/*
:Perform a velocity move and capture position based on Home or Index pulse.
This sample application demonstrates use of the Capture feature on the XMP.
First, a velocity move is commanded on an Axis. A capture is then configured
to trigger on either a Home sensor or index pulse.
Each motion block supports 10 capture registers. The default configuration
is two capture registers per motor -- while the last two (8,9) on each motion
block are reserved for the Auxiliary Encoder (not supported). The capture
registers are default mapped as follows... 0 & 1 for Motor0, 2 & 3 for Motor1,
10 & 11 for Motor4, etc. The first Capture for each motor latches the default
(primary) encoder input, and the second capture latches the AUX encoder
input. The equation used below calculates the Capture number for the primary
motor feedback given the default capture mapping.
captureNumber = ((motorNumber / MEIXmpMotorsPerBlock) * MEIXmpMaxLatches) +
((motorNumber % MEIXmpMotorsPerBlock) * CapturesPerMotor);
This program presumes the tuning parameters(PID, PIV, etc.) for your
stage(or tool, or machine) have already been set. That is, the tuning
parameters need to be established prior to running this program so the
stage can move in a stable manner. Please use the Tuning Guidelines if
these values haven't been determined.
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"
#define CapturesPerMotor (2) /* Default Capture configuration */
/* User Settings */
#define ACTIVE_FALLING_EDGE (0)
#define ACTIVE_RAISING_EDGE (1)
#define MOTORNUM (0) /* Number of motors */
/* Motion Parameters */
#define VELOCITY (5000.0) /* Move velocity */
#define ACCEL (10000.0) /* Move acceleration*/
/* Capture Parameters */
#define CAPTURE_EDGE (ACTIVE_FALLING_EDGE) /* Capture on falling edge */
/* CAPTURE_TRIGGER can be MEIMotorInputHOME or MEIMotorInputINDEX */
#define CAPTURE_TRIGGER (MEIMotorInputHOME) /* Capture on home pulse */
/* Perform basic command line parsing. (-control -server -port -trace) */
void basicParsing(int argc,
char *argv[],
MPIControlType *controlType,
MPIControlAddress *controlAddress)
{
long argIndex;
/* Parse command line for Control type and address */
argIndex = argControl(argc, argv, controlType, controlAddress);
/* Check for unknown/invalid command line arguments */
if (argIndex < argc) {
fprintf(stderr, "usage: %s %s\n", argv[0], ArgUSAGE);
exit(MPIMessageARG_INVALID);
}
}
/* Calculate default capture number for axisNumber */
long captureNumber(long motorNumber)
{
return ((motorNumber/MEIXmpMotorsPerBlock) * MEIXmpMaxLatches) +
((motorNumber % MEIXmpMotorsPerBlock) * CapturesPerMotor);
}
/* Create and initialize MPI objects */
void programInit(MPIControl *control,
MPIControlType controlType,
MPIControlAddress *controlAddress,
MPIMotion *motion,
long motionNumber,
MPIAxis *axis,
long axisNumber,
MPIMotor *motor,
long motorNumber,
MPICapture *capture,
long captureNumber)
{
long returnValue;
/* Create motion controller object */
*control =
mpiControlCreate(controlType,
controlAddress);
msgCHECK(mpiControlValidate(*control));
/* Initialize motion controller */
returnValue =
mpiControlInit(*control);
msgCHECK(returnValue);
/* Create axis object */
*axis =
mpiAxisCreate(*control,
axisNumber);
msgCHECK(mpiAxisValidate(*axis));
/* Create motion supervisor object with axis */
*motion =
mpiMotionCreate(*control,
motionNumber,
*axis);
msgCHECK(mpiMotionValidate(*motion));
/* Create motor object */
*motor =
mpiMotorCreate(*control,
motorNumber);
msgCHECK(mpiMotorValidate(*motor));
/* Create capture object */
*capture =
mpiCaptureCreate(*control,
captureNumber);
msgCHECK(mpiCaptureValidate(*capture));
}
/*
Configure capture object.
edge: 0 for falling edge, 1 for rising edge
*/
void configureCapture(MPICapture capture,
MEIMotorInput trigger,
long edge)
{
MPICaptureConfig captureConfig;
long returnValue;
/* Disable capture */
returnValue =
mpiCaptureArm(capture,
FALSE);
msgCHECK(returnValue);
/* Read caputre configuration */
returnValue =
mpiCaptureConfigGet(capture,
&captureConfig,
NULL);
msgCHECK(returnValue);
/* Set capture parameters */
captureConfig.trigger.mask = trigger;
captureConfig.trigger.pattern = edge ? trigger : 0;
/* Write capture configuration */
returnValue =
mpiCaptureConfigSet(capture,
&captureConfig,
NULL);
msgCHECK(returnValue);
}
/* Disable Home Event action */
void disableHomeEvent(MPIMotor motor,
MPICapture capture)
{
MPIMotorEventConfig eventConfig;
long returnValue;
returnValue =
mpiMotorEventConfigGet(motor,
MPIEventTypeHOME,
&eventConfig,
NULL);
msgCHECK(returnValue);
eventConfig.action = MPIActionNONE; /* No action */
eventConfig.trigger.polarity = TRUE; /* Active high */
returnValue =
mpiMotorEventConfigSet(motor,
MPIEventTypeHOME,
&eventConfig,
NULL);
msgCHECK(returnValue);
/* Arm the capture */
returnValue =
mpiCaptureArm(capture,
TRUE);
msgCHECK(returnValue);
}
/* Perform a Velocity move */
void velocityMove(MPITrajectory *trajectory,
MPIMotionParams *params,
MPIMotion *motion)
{
long returnValue;
/* Setup motion parameters */
trajectory->velocity = VELOCITY;
trajectory->acceleration = ACCEL;
trajectory->deceleration = ACCEL; /* Not used for velocity move */
trajectory->jerkPercent = 0.0; /* Not used for velocity move */
params->velocity.trajectory = trajectory;
/* Start a velocity move */
returnValue =
mpiMotionStart(*motion,
MPIMotionTypeVELOCITY,
params);
msgCHECK(returnValue);
}
/* Poll capture status and update display */
void pollForCaptureAndUpdateDisplay(MPICapture *capture,
MPIMotor *motor,
MEIMotorInput trigger)
{
MPICaptureStatus captureStatus;
MPIMotorIo io;
long caputuresCounted = 0;
long returnValue;
/* State Machine - Poll capture status, update display, etc. */
while (meiPlatformKey(MPIWaitPOLL) <= 0) {
returnValue =
mpiCaptureStatus(*capture,
&captureStatus,
NULL);
msgCHECK(returnValue);
/* Display Home and Capture state */
returnValue =
mpiMotorIoGet(*motor,
&io);
msgCHECK(returnValue);
printf("\rI/O state:%d CaptureState:%d ",
!(!(io.input & trigger)), /* input bit */
captureStatus.state); /* (1=ARMED, 2=CAPTURED) */
if (captureStatus.state == MPICaptureStateCAPTURED) {
caputuresCounted++;
printf("Latched Position = %.0lf # of captures = %d\n\n",
captureStatus.latch[0],
caputuresCounted);
/* Re-arm position capture */
returnValue =
mpiCaptureArm(*capture,
TRUE);
msgCHECK(returnValue);
}
}
}
/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl *control,
MPIMotion *motion,
MPIAxis *axis,
MPIMotor *motor,
MPICapture *capture)
{
long returnValue;
/* Delete capture object */
returnValue =
mpiCaptureDelete(*capture);
msgCHECK(returnValue);
/* Delete motor object */
returnValue =
mpiMotorDelete(*motor);
msgCHECK(returnValue);
/* Delete motion supervisor object */
returnValue =
mpiMotionDelete(*motion);
msgCHECK(returnValue);
/* Delete axis object */
returnValue =
mpiAxisDelete(*axis);
msgCHECK(returnValue);
/* Delete motion controller object */
returnValue =
mpiControlDelete(*control);
msgCHECK(returnValue);
}
int main(int argc,
char *argv[])
{
MPIControl control;
MPIControlType controlType;
MPIControlAddress controlAddress;
MPIMotion motion;
MPIAxis axis;
MPIMotor motor;
MPICapture capture;
MPITrajectory trajectory;
MPIMotionParams params;
long returnValue; /* Return value from library */
long motorNumber = MOTORNUM;
long motionNumber = motorNumber;
long axisNumber = motorNumber;
/* Perform basic command line parsing. (-control -server -port -trace) */
basicParsing(argc,
argv,
&controlType,
&controlAddress);
/* Create and initialize MPI objects */
programInit(&control,
controlType,
&controlAddress,
&motion,
motionNumber,
&axis,
axisNumber,
&motor,
motorNumber,
&capture,
captureNumber(motorNumber));
/* Configure capture */
configureCapture(capture,
CAPTURE_TRIGGER,
CAPTURE_EDGE);
/* Disable Home Event action */
disableHomeEvent(motor,
capture);
/* Perform a Velocity move */
velocityMove(&trajectory,
¶ms,
&motion);
printf("\n Moving.... Press any key to quit.\n\n");
/* Poll capture status and update display */
pollForCaptureAndUpdateDisplay(&capture,
&motor,
CAPTURE_TRIGGER);
printf("\nStopping.\n");
/* Stop motion on axis */
returnValue =
mpiMotionAction(motion,
MPIActionSTOP);
msgCHECK(returnValue);
/* Perform certain cleanup actions and delete MPI objects */
programCleanup(&control,
&motion,
&axis,
&motor,
&capture);
return ((int)returnValue);
}