ScStep.c -- Single Axis Sinusoidal Commutation Sample Configuration
Program
/* ScStep.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.
*/
/*
:Single Axis Sinusoidal Commutation Sample Configuration Program
Axis 0 - Uses Stepper type initialization with a small
90 (elec.) degree move. Axis stays in open-loop mode
with amplifier enabled.
Note - #def provided to reverse encoder and DAC phasing.
Program disables HW Limits, Amp Fault, Home and
Error Limit.
Configure the XMP:
Axis 0 Filter 0 Motor 0
Note that the commutation configuration parameters will be different
for your application. Take particular care in setting the open-loop
continuous DAC OutputLevel as this must be a safe level for your specific
drive and motor combination. Please read the MEI Sinusoidal Commutation
Documentation.
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 AXIS_CNT (1)
/* Command line arguments and defaults */
long axisNumber = 0;
long motionNumber = 0;
/* Perform basic command line parsing. (-control -server -port -trace) */
void parseCommandLine(int argc,
char *argv[],
MPIControlType *controlType,
MPIControlAddress *controlAddress,
long *axisNumber,
long *motionNumber)
{
long argIndex;
Arg argList[] =
{
/* Determining motor number */
{ "-motor", ArgTypeLONG, axisNumber, },
/* Determining motion supervisor number */
{ "-motion", ArgTypeDOUBLE, motionNumber, },
/* End of argument list (null terminator) */
{ NULL, ArgTypeINVALID, NULL, }
};
/* 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"
"\t\t[-motor # (0 .. %d)]\n"
"\t\t[-motion # (0 .. %d)]\n",
argv[0],
ArgUSAGE,
MEIXmpMAX_Axes - 1,
MEIXmpMAX_MSs - 1);
exit(MPIMessageARG_INVALID);
}
}
void programInit(MPIControl *control,
MPIControlType controlType,
MPIControlAddress *controlAddress,
MPIMotion *motion,
MPIAxis *axis,
MPIFilter *filter,
MPIMotor *motor)
{
long returnValue;
/* Create motion controller object */
*control = mpiControlCreate(controlType,
controlAddress);
msgCHECK(mpiControlValidate(*control));
/* Initialize motion controller */
returnValue = mpiControlInit(*control);
msgCHECK(returnValue);
/*
Create a Motion Object and append an Axis
Note 1 - separate axis appends will be required for coordinated motion
Note 2 - Axis Map does not take effect until motion is commanded
*/
*motion = mpiMotionCreate(*control,
motionNumber,
*axis);
msgCHECK(mpiMotionValidate(*motion));
/* Clear out any previous errors */
returnValue = mpiMotionAction(*motion,
MPIActionRESET);
msgCHECK(returnValue);
/* Immediately send Map to controller */
returnValue = mpiMotionAction(*motion,
(MPIAction)MEIActionMAP);
msgCHECK(returnValue);
/* Create axis */
*axis = mpiAxisCreate(*control,
axisNumber);
msgCHECK(mpiAxisValidate(*axis));
/* Create filter */
*filter = mpiFilterCreate(*control,
axisNumber);
msgCHECK(mpiFilterValidate(*filter));
/* Create motor */
*motor = mpiMotorCreate(*control,
axisNumber);
msgCHECK(mpiMotorValidate(*motor));
}
void programCleanup(MPIControl control,
MPIMotion motion,
MPIAxis axis,
MPIFilter filter,
MPIMotor motor)
{
long returnValue;
/* Delete Objects */
returnValue = mpiMotorDelete(motor);
msgCHECK(returnValue);
returnValue = mpiFilterDelete(filter);
msgCHECK(returnValue);
returnValue = mpiAxisDelete(axis);
msgCHECK(returnValue);
returnValue = mpiMotionDelete(motion);
msgCHECK(returnValue);
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
}
float setFineTolerance(MPIAxis axis, float tolerance)
{
MPIAxisConfig axisConfig;
long returnValue;
float oldTolerance;
/* Configure axis */
returnValue = mpiAxisConfigGet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
oldTolerance = axisConfig.inPosition.tolerance.positionFine;
/* Set inPositionLimit */
axisConfig.inPosition.tolerance.positionFine = (float)tolerance;
returnValue = mpiAxisConfigSet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
return oldTolerance;
}
/*
DAC output will be ramped and stage will be pulled to a magnetic pole.
Next, delay for stage to settle. Implement outbound move,delay, then
proceed with inbound move and delay.
*/
void stepMove(MPIMotor motor, float OpenDACLevel)
{
MPIMotorConfig motorConfig;
MEIMotorConfig motorConfig2;
long returnValue;
long i;
returnValue = mpiMotorConfigGet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
for(i= 1; i <= 100; i++)
{
motorConfig2.Commutation.OutputLevel = (float)(i)*((OpenDACLevel)/((float)100.0));
/* Set configuration */
returnValue = mpiMotorConfigSet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
meiPlatformSleep(1000);
/* Motor outbound move */
for(i= 1; i <= 100; i++)
{
motorConfig2.Commutation.Offset = (long)(i*2.56);
/* Set configuration */
returnValue = mpiMotorConfigSet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
meiPlatformSleep(1000);
/* Motor return move */
for(i= 1; i <= 100; i++)
{
motorConfig2.Commutation.Offset = (long)(256 - (i*2.56));
/* Set configuration */
returnValue = mpiMotorConfigSet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
}
/* Be sure to replace with appropriate PID values */
void setFilterGains(MPIFilter filter)
{
MPIFilterGain gain;
MEIFilterGainPID *pid;
long returnValue;
/* Get current configuration */
returnValue = mpiFilterGainGet(filter,
MEIFilterGainIndexDEFAULT,
&gain);
msgCHECK(returnValue);
pid = (MEIFilterGainPID *)&gain;
/* Filter Controller control parameters */
pid->gain.proportional = (float)100.0;
pid->gain.integral = (float)0.0;
pid->gain.derivative = (float)400.0;
pid->feedForward.velocity = (float)0.0;
pid->feedForward.acceleration = (float)0.0;
pid->feedForward.friction = (float)0.0;
pid->integrationMax.moving = (float)0.0;
pid->integrationMax.rest = (float)0.0;
pid->output.limit = (float)32767.0;
pid->output.offset = (float)0.0;
/* Set filter configuration */
returnValue = mpiFilterGainSet(filter,
MEIFilterGainIndexDEFAULT,
&gain);
msgCHECK(returnValue);
}
void configureMotor(MPIMotor motor,
long nEncCountPerCycle,
float OpenDACLevel,
float nCycles)
{
MEIXmpCommutationBlock *commutation;
MPIMotorConfig motorConfig;
MEIMotorConfig motorConfig2;
long returnValue;
/* Configure Motor */
returnValue = mpiMotorConfigGet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
/*
Disable limit error, home, amp fault & H/W Limits
Set encoder phase
*/
/* Disable limit error */
motorConfig.event[MPIEventTypeLIMIT_ERROR].action = MPIActionNONE;
motorConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error = (float)50000;
/* Setup commutation */
commutation = &motorConfig2.Commutation;
/* Motor Controller commutation parameters */
commutation->Mode = MEIXmpCommModeOPEN_LOOP;
commutation->Length = nEncCountPerCycle;
commutation->Scale = (float)MEIXmpCOMM_TABLE_SIZE * nCycles /
(float)commutation->Length;
commutation->PhaseDelta = MEIXmpCOMM_120DEGREES;
commutation->OutputLevel = 0.0;
commutation->Offset = (long)0;
/* Set up motor to use both Demands (two phases of the three in a motor) */
motorConfig2.demandMode = MEIMotorDemandModeANALOG_DUAL_DAC;
/* Set configuration */
returnValue = mpiMotorConfigSet(motor,
&motorConfig,
&motorConfig2);
msgCHECK(returnValue);
}
int main(int argc, char *argv[])
{
MPIControl control; /* motion controller handle */
MPIAxis axis; /* axis handles */
MPIFilter filter; /* filter handles */
MPIMotor motor; /* motor handles */
MPIMotion motion; /* Coordinated motion object handles */
MPIControlType controlType;
MPIControlAddress controlAddress;
long returnValue; /* return value from library */
long nEncCountPerCycle = 4096; /* number of encoder counts per motor revolution */
float OpenDACLevel = (float)3277.0; /* Open Loop DAC Level where 32767. = 10V) */
float nCycles = (float)3.0; /* number of elec. cycles per motor rev. */
float inPositionLimit = (float)1.0e10;
float oldFineTolerance;
/* Perform basic command line parsing. (-control -server -port -trace) */
parseCommandLine(argc,
argv,
&controlType,
&controlAddress,
&axisNumber,
&motionNumber);
programInit(&control,
controlType,
&controlAddress,
&motion,
&axis,
&filter,
&motor);
/* Disable the amplifier */
returnValue = mpiMotorAmpEnableSet(motor,
FALSE);
msgCHECK(returnValue);
/* Set tolerance wide so dither does not trigger a following error */
oldFineTolerance = setFineTolerance(axis, inPositionLimit);
/* Set up commutation */
configureMotor(motor,
nEncCountPerCycle,
OpenDACLevel,
nCycles);
/* Set PID values for tuning */
setFilterGains(filter);
/* Enable the amplifier */
returnValue = mpiMotorAmpEnableSet(motor,
TRUE);
msgCHECK(returnValue);
/* */
stepMove(motor, OpenDACLevel);
meiPlatformSleep(1000);
/* Perform certain cleanup actions and delete MPI objects */
programCleanup(control,
motion,
axis,
filter,
motor);
return ((int)returnValue);
}
|