motGate1.c -- Load and trigger a point to point motion using a control
Gate.
/* motGate1.c */
/* Copyright(c) 1991-2006 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.
*/
/*
:Load and trigger a point to point motion using a control Gate.
This sample program demonstrates how to use the motion HOLD attribute and
a control Gate, to pre-load a single axis trapezoidal profile motion.
The XMP-Series controller supports a motion HOLD attribute, which is useful
for pre-loading and triggering motion profiles. One or more motion supervisors
can be started from the same HOLD conditions. When multiple motion supervisors
are triggered by the same HOLD conditions, the individual motion profiles will
start in the same DSP sample period. The HOLD can be set/cleared with a host
function call, an XMP-Series controller internal variable or a Motor I/O
state change.
The MEIMotionAttrHold{...} structure is used to configure the HOLD conditions:
typedef struct MEIMotionAttrHold {
MEIMotionAttrHoldType type;
MEIMotionAttrHoldSource source;
float timeout;
} MEIMotionAttrHold;
The HOLD "type" can be one of the following:
MEIMotionHoldTypeGATE - host software controlled.
MEIMotionHoldTypeINPUT - XMP controller internal variable.
MEIMotionHoldTypeMOTOR - XMP controller motor I/O state change.
For each HOLD "type" the "source" union, MEIMotionAttrHoldSource{...},
configures the HOLD conditions:
MEIMotionHoldTypeGATE:
long gate - number between 0 to 31.
The motion is held until the "gate" is cleared. The function
meiControlGateSet(...) is used to set/clear a gate. When the closed
parameter is TRUE, the gate is set, and motion is held. When the
closed parameter is FALSE, the gate is cleared, and motion starts.
MEIMotionHoldTypeINPUT
long *input - address of XMP memory location.
long mask - bit mask, bitwise ANDed with the input value.
long pattern - HOLD is released when masked value matches pattern.
The motion is held until the value of the internal XMP memory location
(pointed to by *input) bitwise ANDed with the mask matches the pattern.
MEIMotionHoldTypeMOTOR
long number - motor "n", XMP's dedicated inputs (Motor[n].IO.DedicaedIN.IO)
long mask - bit mask, bitwise ANDed with the dedicated inputs.
long pattern - HOLD is released when masked inputs matches pattern.
The motion is held until the value of the dedicated input word
(Motor[n].IO.DedicaedIN.IO) bitwise ANDed with the mask matches the
pattern.
The HOLD "timeout" will cause the motion to start after the specified period
(in seconds) even if the hold criteria have not been met. To disable the
timeout feature, set the timeout value to zero.
The MPI expects an array of hold attributes specifying separate attributes
form each axis of a motion supervisor. All axes holding with the same hold
attributes (same gate, same input, mask, and pattern) will start motion in
the same sample even if the moves are specified using different motion
supervisors.
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"
#define MOTION_NUMBER (0)
#define AXIS_NUMBER (0)
#define GATE_NUMBER (0)
#define TIMEOUT (0) /* Wait forever */
#define GOAL_POSITION ( 10000.0)
#define VELOCITY ( 10000.0)
#define ACCELERATION (100000.0)
#define DECELERATION (100000.0)
#define JERK_PERCENT ( 100.0)
/* 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);
}
}
/* Create and initialize MPI objects */
void programInit(MPIControl *control,
MPIControlType controlType,
MPIControlAddress *controlAddress,
MPIMotion *motion,
long motionNumber,
MPIAxis *axis,
long axisNumber)
{
long returnValue;
/* Create control 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 object */
*motion =
mpiMotionCreate(*control,
motionNumber,
*axis);
msgCHECK(mpiMotionValidate(*motion));
}
/* Delete MPI objects */
void programCleanup(MPIControl *control,
MPIMotion *motion,
MPIAxis *axis)
{
long returnValue;
/* Delete motion supervisor object */
returnValue =
mpiMotionDelete(*motion);
msgCHECK(returnValue);
*motion = MPIHandleVOID;
/* Delete axis object */
returnValue =
mpiAxisDelete(*axis);
msgCHECK(returnValue);
*axis = MPIHandleVOID;
/* Delete control object */
returnValue =
mpiControlDelete(*control);
msgCHECK(returnValue);
*control = MPIHandleVOID;
}
int main(int argc,
char *argv[])
{
MPIControl control; /* motion controller object handle */
MPIMotion motion; /* motion object handle */
MPIAxis axis; /* axis object handle */
MPIControlType controlType;
MPIControlAddress controlAddress;
MPIMotionParams params; /* motion parameters */
MPITrajectory trajectory; /* motion trajectory */
MEIMotionAttributes attributes; /* motion attributes */
MEIMotionAttrHold hold; /* hold attribute configuration */
long gateNumber = GATE_NUMBER;
float gateTimeout = (float)TIMEOUT;
double position; /* final target position */
long returnValue; /* return value from library */
/* Perform basic command line parsing. (-control -server -port -trace) */
basicParsing(argc, argv, &controlType, &controlAddress);
/* Create and initialize MPI objects */
programInit(&control,
controlType,
&controlAddress,
&motion,
MOTION_NUMBER,
&axis,
AXIS_NUMBER);
/* Set up motion parameters */
position = GOAL_POSITION; /* counts */
trajectory.velocity = VELOCITY; /* counts per sec */
trajectory.acceleration = ACCELERATION; /* counts per sec * sec */
trajectory.deceleration = DECELERATION; /* counts per sec * sec */
trajectory.jerkPercent = JERK_PERCENT;
params.sCurve.trajectory = &trajectory;
params.sCurve.position = &position;
/* Configure Motion Attributes */
hold.type = MEIMotionAttrHoldTypeGATE; /* software motion Gate control */
hold.source.gate = gateNumber;
hold.timeout = gateTimeout;
attributes.hold = &hold;
params.external = &attributes;
printf("Setting the Control Gate to TRUE.\n");
/* Set a control gate to prevent the motion profile from executing */
returnValue =
meiControlGateSet(control,
gateNumber,
TRUE); /* set gate */
msgCHECK(returnValue);
printf("Loading the motion.\n");
/* Load motion profile with HOLD attribute */
returnValue =
mpiMotionStart(motion,
(MPIMotionType)
(MPIMotionTypeS_CURVE | MEIMotionAttrMaskHOLD),
¶ms);
msgCHECK(returnValue);
printf("Press any key to set the Control Gate to FALSE...\r");
/* Wait for user key */
meiPlatformKey(MPIWaitFOREVER);
printf("Setting the Control Gate to FALSE (executing the motion).\n");
/* Clear a control gate, executing the preloaded motion */
returnValue =
meiControlGateSet(control,
gateNumber,
FALSE); /* clear the gate */
msgCHECK(returnValue);
/* Delete MPI objects */
programCleanup(&control,
&motion,
&axis);
return ((int)returnValue);
}
|