seq2.c -- Perform a repeated multi-axis motion command sequence,
wait for an I/O bit
/* seq2.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.
*/
#if defined(MEI_RCS)
static const char MEIAppRCS[] =
"RCSHeader";
#endif
/*
:Perform a repeated multi-axis motion command sequence, wait for an I/O bit
This sample program creates a program sequencer that will generate a multi-axis
motion beween two points. The program sequencer waits for the motion to
complete in between moves. After commanding the two motions the program
sequencer waits for a transceiver I/O bit to change state (defined by
TRANSCEIVER_ID and TRIGGER_STATE at the top of the program). Then the sequence
loops back to the beginning of the motion command sequence, and repeats the
motion until the user presses a key. The program execution is handled entirely
on the controller, with no host computer intervention. The motion can be
viewed by the Motion Console and Motion Scope utilities.
The XMP program sequencer controls the execution of a single command or a
series of commands on the XMP controller. The program sequencer provides the
ability to execute programs directly on the XMP controller without host
intervention. Examples of individual commands that can be executed by the
program sequencer are motion, looping, conditional branching, computation,
reading and writing of memory, time delays, waiting for conditions, setting
inputs/outputs, and generation of events. This rich command set provides
capability similar to, and beyond, that provided by Programmable Logic
Controller (PLC) programs.
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.
*/
#include <stdlib.h>
#include <stdio.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"
#define MOTION_COUNT (2)
#define AXIS_COUNT (2)
/* Define the transceiver to wait for in between motion sequences */
#define TRANSCEIVER_ID (MPIMotorGeneralIo0) /* index to bit #0 */
#define TRANSCEIVER_MASK (0x1) /* mask for bit #0 */
/* Define the trigger value for the transceiver,
MPICommandOperatorBIT_SET or MPICommandOperatorBIT_CLEAR
*/
#define TRIGGER_STATE (MPICommandOperatorBIT_SET)
/* Command line arguments and defaults */
long axisNumber[AXIS_COUNT] = { 0, 1, };
long motionNumber = 0;
long motorNumber = 0;
long sequenceNumber = 0;
long sequenceSize = -1;
MPIMotionType motionType = MPIMotionTypeTRAPEZOIDAL;
Arg argList[] = {
{ "-axis", ArgTypeLONG, &axisNumber[0], },
{ "-motion", ArgTypeLONG, &motionNumber, },
{ "-motor", ArgTypeLONG, &motorNumber, },
{ "-sequence", ArgTypeLONG, &sequenceNumber, },
{ "-size", ArgTypeLONG, &sequenceSize, },
{ "-type", ArgTypeLONG, &motionType, },
{ NULL, ArgTypeINVALID, NULL, }
};
double position[MOTION_COUNT][AXIS_COUNT] = {
{ 20000.0, 0.0, },
{ 0.0, 20000.0, },
};
MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
{ /* velocity accel decel jerkPercent */
{ 10000.0, 100000.0, 100000.0, 50.0, },
{ 10000.0, 100000.0, 100000.0, 50.0, },
},
{ /* velocity accel decel jerkPercent */
{ 10000.0, 100000.0, 100000.0, 50.0, },
{ 10000.0, 100000.0, 100000.0, 50.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], },
};
/* 3 => START + MOTION_DONE + I/O 1 => BRANCH */
MPICommand CommandTable[(MOTION_COUNT * 3) + 1];
#define COMMAND_COUNT (sizeof(CommandTable) / sizeof(MPICommand))
int
main(int argc,
char *argv[])
{
MPIControl control; /* motion controller handle */
MPIMotion motion; /* motion handle */
MPIAxis axis[AXIS_COUNT]; /* axis handles */
MPIMotor motor; /* motor handle */
MPISequence sequence; /* sequence handle */
MPICommandParams commandParams; /* command parameters */
MPIControlConfig controlConfig;
long returnValue; /* return value from library */
long commandIndex; /* CommandTable[] index */
long index;
MPIControlType controlType;
MPIControlAddress controlAddress;
long argIndex;
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[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
(motionNumber >= MEIXmpMAX_MSs) ||
(motorNumber >= MEIXmpMAX_Motors) ||
(sequenceNumber >= MEIXmpMAX_PSs) ||
(motionType < MPIMotionTypeFIRST) ||
(motionType >= MEIMotionTypeLAST)) {
meiPlatformConsole("usage: %s %s\n"
"\t\t[-axis # (0 .. %d)]\n"
"\t\t[-motion # (0 .. %d)]\n"
"\t\t[-motor # (0 .. %d)]\n"
"\t\t[-sequence # (0 .. %d)]\n"
"\t\t[-size # (%d)]\n"
"\t\t[-type # (0 .. %d)]\n",
argv[0],
ArgUSAGE,
MEIXmpMAX_Axes - AXIS_COUNT,
MEIXmpMAX_MSs - 1,
MEIXmpMAX_Motors - 1,
MEIXmpMAX_PSs - 1,
sequenceSize,
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;
}
}
axisNumber[1] = axisNumber[0] + 1;
/* Create motion controller object */
control =
mpiControlCreate(controlType,
&controlAddress);
msgCHECK(mpiControlValidate(control));
/* Initialize motion controller */
returnValue = mpiControlInit(control);
msgCHECK(returnValue);
/* Enable a sequence engine on the controller */
returnValue =
mpiControlConfigGet(control,
&controlConfig,
NULL);
msgCHECK(returnValue);
if (controlConfig.sequenceCount <= sequenceNumber) {
controlConfig.sequenceCount = (sequenceNumber + 1);
}
returnValue =
mpiControlConfigSet(control,
&controlConfig,
NULL);
msgCHECK(returnValue);
/* Create motion object for MS number */
motion =
mpiMotionCreate(control,
motionNumber,
MPIHandleVOID);
msgCHECK(mpiMotionValidate(motion));
/* Create axis object for X_AXIS */
axis[0] =
mpiAxisCreate(control,
axisNumber[0]);
msgCHECK(mpiAxisValidate(axis[0]));
/* Create axis object for Y_AXIS */
axis[1] =
mpiAxisCreate(control,
axisNumber[1]);
msgCHECK(mpiAxisValidate(axis[1]));
/* Create motion axis list */
returnValue =
mpiMotionAxisListSet(motion,
AXIS_COUNT,
axis);
msgCHECK(returnValue);
/* Create motor object */
motor =
mpiMotorCreate(control,
motorNumber);
msgCHECK(mpiMotorValidate(motor));
/* Create Sequence */
sequence =
mpiSequenceCreate(control,
sequenceNumber,
sequenceSize);
msgCHECK(mpiSequenceValidate(sequence));
/* CommandTable[commandIndex] */
commandIndex = 0;
/* Create motion Commands */
for (index = 0; index < MOTION_COUNT; index++) {
MPIMotionParams *motionParams;
/* mpiMotionStart(motion, type, params); */
commandParams.motion.motionCommand = MPICommandMotionSTART;
commandParams.motion.motion = motion;
commandParams.motion.type = motionType;
motionParams = &commandParams.motion.params;
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;
}
}
/* Create Command */
CommandTable[commandIndex] =
mpiCommandCreate(MPICommandTypeMOTION,
&commandParams,
(commandIndex == 0) ? "First" : NULL);
msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));
commandIndex++;
commandParams.waitEvent.handle = motion;
commandParams.waitEvent.oper = MPICommandOperatorBIT_SET;
mpiEventMaskCLEAR(commandParams.waitEvent.mask);
mpiEventMaskSET(commandParams.waitEvent.mask, MPIEventTypeMOTION_DONE);
/* Create Command */
CommandTable[commandIndex] =
mpiCommandCreate(MPICommandTypeWAIT_EVENT,
&commandParams,
NULL);
msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));
commandIndex++;
/* Wait for General purpose motor I/O bit */
commandParams.waitIO.type = MPIIoTypeMOTOR_GENERAL;
commandParams.waitIO.source.motor = motor;
commandParams.waitIO.oper = TRIGGER_STATE;
commandParams.waitIO.mask = TRANSCEIVER_MASK;
/* Create Command */
CommandTable[commandIndex] =
mpiCommandCreate(MPICommandTypeWAIT_IO,
&commandParams,
NULL);
msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));
commandIndex++;
}
/* Branch to the first command of the sequence */
commandParams.branch.label = "First"; /* First command */
commandParams.branch.expr.oper = MPICommandOperatorALWAYS;
/* Create Command */
CommandTable[commandIndex] =
mpiCommandCreate(MPICommandTypeBRANCH,
&commandParams,
NULL);
msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));
commandIndex++;
/* Create sequence command list */
returnValue =
mpiSequenceCommandListSet(sequence,
commandIndex,
CommandTable);
msgCHECK(returnValue);
/* Start sequence */
returnValue =
mpiSequenceStart(sequence,
MPIHandleVOID);
if (returnValue != MPIMessageOK) {
fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
argv[0],
returnValue,
mpiMessage(returnValue, NULL));
exit(2);
}
meiPlatformConsole("Press any key to stop sequence\n");
meiPlatformKey(MPIWaitFOREVER);
/* Stop sequence */
returnValue = mpiSequenceStop(sequence);
msgCHECK(returnValue);
returnValue = mpiSequenceDelete(sequence);
msgCHECK(returnValue);
returnValue = mpiMotionDelete(motion);
msgCHECK(returnValue);
for (index = 0; index < AXIS_COUNT; index++) {
returnValue = mpiAxisDelete(axis[index]);
msgCHECK(returnValue);
}
returnValue = mpiMotorDelete(motor);
msgCHECK(returnValue);
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
return ((int)returnValue);
}
|