stepcfg2.c -- Configure an 8 axis XMP to support 8 Servos and 8 Steppers
/* stepCfg2.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/stepcfg2.c 8 7/23/01 2:36p Kevinh $";
#endif
/*
:Configure an 8 axis XMP to support 8 Servos and 8 Steppers
The XMP controller has the capability to control 8 servo axes as well
as 8 stepper axes on a single controller. The XMP uses the Xcvr
IO for axes 0 - 7 for stepper outputs on axes 8 - 15. This is obtained
by redirecting the stepper controller pointer from Xcvr hardware that
would be present on a 16 axis controller to Xcvr's 0 - 7.
Certain limitations apply:
-No Steppers can be configured on the first 8 axes.
-The 2nd 8 axes will not have any IO (User, Home, PosLimits, AmpEnables, etc).
-No encoder loopback is availiable on the Stepper axes.
-The IN_FINE position criteria must be increased for motion done to return.
The following code performs the necessary configurations to run a Step/Dir
stepper on Motor 8 using Xcvr0 A & B. Define CONFIG_ONLY to configure the
XMP, but not perform any motion.
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 stepCfg2Main
argMainRENAME(main, stepCfg2)
#endif
#define AXIS_COUNT (16)
#define FILTER_COUNT (16)
#define MS_COUNT (16)
#define MOTOR_COUNT (16)
/* Command line arguments and defaults */
long axisNumber[AXIS_COUNT] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long filterNumber[FILTER_COUNT] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long motorNumber[MOTOR_COUNT] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long motionNumber = -1; /* Use next availiable MS */
long width = 255;
Arg argList[] = {
{ NULL, ArgTypeINVALID, NULL, }
};
/* LOOPBACK_CONFIG : TRUE = count step pulses in encoder register, FALSE = no loopback */
#define LOOPBACK_CONFIG TRUE
/* output pulse width (seconds) */
#define PULSE_WIDTH_VALUE (2.55e-5)
#undef CW_CCW_STEPPERS
#if defined CW_CCW_STEPPERS
#define IO_CONFIG_A (MEIMotorTransceiverConfigCW)
#define IO_CONFIG_B (MEIMotorTransceiverConfigCCW)
#else
#define IO_CONFIG_A (MEIMotorTransceiverConfigSTEP)
#define IO_CONFIG_B (MEIMotorTransceiverConfigDIR)
#endif
#define TRANSCEIVER_ID_A (MEIXmpMotorIOBitXCVR_A)
#define TRANSCEIVER_ID_B (MEIXmpMotorIOBitXCVR_B)
#define INVERT_BIT (FALSE)
int
main(int argc,
char *argv[])
{
MPIControl control;
MPIControlConfig config;
MPIControlType controlType;
MPIControlAddress controlAddress;
MPIFilter filter;
MPIAxis axis;
MPIAxisConfig axisConfig; /* Axis configuration */
MPIMotion motion;
MPIMotor motorZero;
MPIMotor motorEight;
MPIMotorConfig motorZeroConfig;
MPIMotorConfig motorEightConfig;
MEIMotorConfig motorZeroConfigXmp;
MEIMotorConfig motorEightConfigXmp;
MPIMotionParams params; /* motion parameters */
MPITrajectory trajectory; /* motion trajectory */
double position; /* final target position */
long argIndex;
long returnValue;
long motionDone = FALSE;
long stepperNumber;
/* 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",
argv[0],
ArgUSAGE);
exit(MPIMessageARG_INVALID);
}
/* Obtain a Control handle */
control =
mpiControlCreate(controlType,
&controlAddress);
msgCHECK(mpiControlValidate(control));
/* Initialize the controller */
returnValue = mpiControlInit(control);
msgCHECK(returnValue);
/* Get controller status */
returnValue =
mpiControlConfigGet(control,
&config,
NULL);
msgCHECK(returnValue);
/* Configure controller for 16 Axes, Filters, and Motors */
config.axisCount = AXIS_COUNT;
config.filterCount = FILTER_COUNT;
config.motionCount = MS_COUNT;
config.motorCount = MOTOR_COUNT;
/* Set controller configuration */
returnValue =
mpiControlConfigSet(control,
&config,
NULL);
msgCHECK(returnValue);
/* Display controller configuration */
printf("Controller:\n"
"\taxisCount %d\n"
"\tadcCount %d\n"
"\t cmdDacCount %d\n"
"\tfilterCount %d\n"
"\tmotionCount %d\n"
"\tmotorCount %d\n"
"\tsequenceCount %d\n"
"\tsampleRate %d\n",
config.axisCount,
config.adcCount,
config.cmdDacCount,
config.filterCount,
config.motionCount,
config.motorCount,
config.sequenceCount,
config.sampleRate);
/* Create filter object */
filter =
mpiFilterCreate(control,
filterNumber[8]);
msgCHECK(mpiFilterValidate(filter));
/* Configure Filter for Step algorithm */
if (returnValue == MPIMessageOK) {
MEIFilterConfig filterConfigXmp;
returnValue =
mpiFilterConfigGet(filter,
NULL,
&filterConfigXmp);
msgCHECK(returnValue);
filterConfigXmp.Algorithm = MEIXmpAlgorithmNONE;
returnValue =
mpiFilterConfigSet(filter,
NULL,
&filterConfigXmp);
msgCHECK(returnValue);
}
/* Create axis object*/
axis =
mpiAxisCreate(control,
axisNumber[8]); /* axis number */
msgCHECK(mpiAxisValidate(axis));
/* Configure axis */
returnValue =
mpiAxisConfigGet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
axisConfig.inPosition.tolerance.positionFine = (float)10E10;
returnValue =
mpiAxisConfigSet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
/* Create motion object, append axis */
motion =
mpiMotionCreate(control,
motionNumber, /* motion supervisor number */
axis); /* axis object handle */
msgCHECK(mpiMotionValidate(motion));
/* Set up motion parameters */
trajectory.velocity = 1000.0; /* counts per sec */
trajectory.acceleration = 10000.0; /* counts per sec * sec */
trajectory.deceleration = 10000.0;
position = 2000.0; /* target position (counts) */
params.trapezoidal.trajectory = &trajectory;
params.trapezoidal.position = &position;
/* Create Motor0 Object */
motorZero =
mpiMotorCreate(control,
0);
msgCHECK(mpiMotorValidate(motorZero));
/* Create Motor8 Object */
motorEight =
mpiMotorCreate(control,
8);
msgCHECK(mpiMotorValidate(motorEight));
/* Get Motor0's Configuration */
returnValue =
mpiMotorConfigGet(motorZero,
&motorZeroConfig,
&motorZeroConfigXmp);
msgCHECK(returnValue);
/* Configure Xcvr A/B for Step/Dir */
motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_A].Config = IO_CONFIG_A;
motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_B].Config = IO_CONFIG_B;
motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_A].Invert = INVERT_BIT;
motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_B].Invert = INVERT_BIT;
returnValue =
mpiMotorConfigSet(motorZero,
&motorZeroConfig,
&motorZeroConfigXmp);
msgCHECK(returnValue);
printf("StepControl Pointer for Motor 0: 0x%X\n", motorZeroConfigXmp.Commutation.StepControl);
/* Get MotorEight's Configuration */
returnValue =
mpiMotorConfigGet(motorEight,
&motorEightConfig,
&motorEightConfigXmp);
msgCHECK(returnValue);
motorEightConfigXmp.Stepper.PulseWidth = (float)PULSE_WIDTH_VALUE;
motorEightConfigXmp.Stepper.Loopback = LOOPBACK_CONFIG;
/* Set motorEight's Commutation.StepControl register equal to MotorZero's */
stepperNumber = motorNumber[0];
returnValue =
meiMotorConfigStepper(motorEight,
&motorEightConfigXmp,
stepperNumber); /* StepControl source location */
msgCHECK(returnValue);
/* Disable limit error */
motorEightConfig.event[MPIEventTypeLIMIT_ERROR].action = MPIActionNONE;
motorEightConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error = (float)10E10;
/* Disable home event */
motorEightConfig.event[MPIEventTypeHOME].action = MPIActionNONE;
/* Disable amp fault event */
motorEightConfig.event[MPIEventTypeAMP_FAULT].action = MPIActionNONE;
/* Disable neg. HW limit event */
motorEightConfig.event[MPIEventTypeLIMIT_HW_NEG].action = MPIActionNONE;
/* Disable pos. HW limit event */
motorEightConfig.event[MPIEventTypeLIMIT_HW_POS].action = MPIActionNONE;
/* Disable neg. SW limit event */
motorEightConfig.event[MPIEventTypeLIMIT_SW_NEG].action = MPIActionNONE;
/* Disable pos. SW limit event */
motorEightConfig.event[MPIEventTypeLIMIT_SW_POS].action = MPIActionNONE;
/* Disable Encoder Fault event */
motorEightConfig.event[MPIEventTypeENCODER_FAULT].action= MPIActionNONE;
/* Configure Motor 8 as Stepper */
motorEightConfig.type = MPIMotorTypeSTEPPER;
returnValue =
mpiMotorConfigSet(motorEight,
&motorEightConfig,
&motorEightConfigXmp);
msgCHECK(returnValue);
/* Write MS/Axis map to controller and clear any events */
returnValue =
mpiMotionAction(motion,
MPIActionRESET);
msgCHECK(mpiMotionValidate(motion));
/* Verify it worked */
returnValue =
mpiMotorConfigGet(motorEight,
&motorEightConfig,
&motorEightConfigXmp);
msgCHECK(returnValue);
printf("New StepControl Pointer for Motor 8: 0x%X\n", motorEightConfigXmp.Commutation.StepControl);
#ifndef CONFIG_ONLY
printf("Motor 8 configured for Stepper using Xcvr 0 & 1.\n"
"Starting move on Motor 8...\n");
returnValue =
mpiMotionStart(motion,
MPIMotionTypeTRAPEZOIDAL,
¶ms);
msgCHECK(returnValue);
/* Poll status until motion done */
motionDone = FALSE;
while (motionDone == FALSE) {
MPIStatus status;
returnValue =
mpiMotionStatus(motion,
&status,
NULL);
msgCHECK(returnValue);
switch (status.state) {
case MPIStateIDLE: {
motionDone = TRUE;
/* Wait for the motor to settle */
meiPlatformSleep(300); /* msec */
break;
}
case MPIStateERROR: {
motionDone = TRUE;
/* Clear any error condition(s) */
returnValue =
mpiMotionAction(motion,
MPIActionRESET);
msgCHECK(returnValue);
/* Wait for reset to take effect */
meiPlatformSleep(100); /* msec */
break;
}
default: {
break;
}
}
}
position = 0.0; /* target position (counts) */
params.trapezoidal.position = &position;
returnValue =
mpiMotionStart(motion,
MPIMotionTypeTRAPEZOIDAL,
¶ms);
msgCHECK(returnValue);
#endif /* CONFIG_ONLY */
/* Delete object handles */
returnValue = mpiMotorDelete(motorZero);
msgCHECK(returnValue);
returnValue = mpiMotorDelete(motorEight);
msgCHECK(returnValue);
returnValue = mpiFilterDelete(filter);
msgCHECK(returnValue);
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
return ((int)returnValue);
}