scstep.c -- Single Axis Sinusoidal Commutation Sample Configuration Program
/* ScStep.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.
*/
/*
: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 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 StepSCMain
argMainRENAME(main, StepSC)
#endif
#define AXIS_CNT (1)
/* Command line arguments and defaults */
long axisNumber = 0;
long motionNumber = 0;
Arg argList[] = {
{ "-axis", ArgTypeLONG, &axisNumber, },
{ "-motion", ArgTypeLONG, &motionNumber, },
{ NULL, ArgTypeINVALID, NULL, }
};
/* option to reverse encoder phasing */
#undef ReverseEncPhasing
/* Option to reverse DAC phasing */
#undef ReverseDACPhasing
int
main(int argc,
char *argv[])
{
MPIControl control; /* motion controller handle */
MPIAxis axis; /* axis handles */
MPIFilter filter; /* filter handles */
MPIMotor motor; /* motor handles */
MPIControlConfig controlConfig; /* motion controller configuration */
MPIAxisConfig axisConfig; /* axis configuration */
MPIFilterGain gain;
MPIMotorConfig motorConfig;
MEIMotorConfig motorConfigXmp;
MEIFilterGainPID *pid;
MEIXmpCommutationBlock *commutation;
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 OpenDAC_Level = (float)3277.0; /* Open Loop DAC Level where 32767. = 10V) */
float N_CYCLES = (float)3.0; /* number of elec. cycles per motor rev. */
#if defined(ReverseDACPhasing)
long dacCount;
long dacNumber[MPIMotorDacCountMAX];
long number;
#endif
float inPositionLimit = (float)1.0e10;
long argIndex, i;
/* 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) ||
(axisNumber >= MEIXmpMAX_Axes + AXIS_CNT) ||
(motionNumber >= MEIXmpMAX_MSs)) {
meiPlatformConsole("usage: %s %s\n"
"\t\t[-axis # (0 .. %d)]\n"
"\t\t[-motion # (0 .. %d)]\n",
argv[0],
ArgUSAGE,
MEIXmpMAX_Axes - AXIS_CNT,
MEIXmpMAX_MSs - 1);
exit(MPIMessageARG_INVALID);
}
/* Create device driver motion controller object */
control =
mpiControlCreate(controlType,
&controlAddress);
msgCHECK(mpiControlValidate(control));
/* Initialize motion controller */
returnValue = mpiControlInit(control);
msgCHECK(returnValue);
/*
Configure motion controller
Set Sample Rate = 2 kHz
Configure for commutation B phase DACs and ADCs
*/
returnValue =
mpiControlConfigGet(control,
&controlConfig,
NULL);
msgCHECK(returnValue);
controlConfig.sampleRate = 2000;
/*
When supporting commutation,
Cmd and Aux DACs must be enabled.
Enabling the same number of Cmd and Aux DACs as there are motors.
*/
controlConfig.cmdDacCount = controlConfig.motorCount;
controlConfig.auxDacCount = controlConfig.motorCount;
/* Configure required number of A/D */
controlConfig.adcCount = 8;
returnValue =
mpiControlConfigSet(control,
&controlConfig,
NULL);
msgCHECK(returnValue);
/* Create axis, filter and motor controller objects */
axis =
mpiAxisCreate(control,
axisNumber);
msgCHECK(mpiAxisValidate(axis));
filter =
mpiFilterCreate(control,
axisNumber);
msgCHECK(mpiFilterValidate(filter));
motor =
mpiMotorCreate(control,
axisNumber);
msgCHECK(mpiMotorValidate(motor));
/* Disable the amplifier */
returnValue =
mpiMotorAmpEnableSet(motor,
FALSE);
msgCHECK(returnValue);
/* Configure axis */
returnValue =
mpiAxisConfigGet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
/* Set inPositionLimit */
axisConfig.inPosition.tolerance.positionFine = inPositionLimit;
returnValue =
mpiAxisConfigSet(axis,
&axisConfig,
NULL);
msgCHECK(returnValue);
/* Configure Motor */
returnValue =
mpiMotorConfigGet(motor,
&motorConfig,
&motorConfigXmp);
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;
/* Disable home event */
motorConfig.event[MPIEventTypeHOME].action = MPIActionNONE;
/* Disable amp fault event */
motorConfig.event[MPIEventTypeAMP_FAULT].action = MPIActionNONE;
/* Disable neg. HW limit event */
motorConfig.event[MPIEventTypeLIMIT_HW_NEG].action = MPIActionNONE;
/* Disable pos. HW limit event */
motorConfig.event[MPIEventTypeLIMIT_HW_POS].action = MPIActionNONE;
/*
Set encoder phase:
0 - for normal
1 - for reversed
*/
#ifdef ReverseEncPhasing
motorConfig.encoderPhase = 1;
#else
motorConfig.encoderPhase = 0;
#endif
/* Setup commutation */
commutation = &motorConfigXmp.Commutation;
/* Motor Controller commutation parameters */
commutation->Mode = MEIXmpCommModeOPEN_LOOP;
commutation->Length = nEncCountPerCycle;
commutation->Scale = (float)MEIXmpCOMM_TABLE_SIZE * N_CYCLES /
(float)commutation->Length;
commutation->PhaseDelta = MEIXmpCOMM_120DEGREES;
commutation->OutputLevel = (float)0.0; /* level will be ramped after enable */
commutation->Offset = (long)0;
#if defined(ReverseDACPhasing)
motorConfigXmp.Dac.Phase = MEIXmpDACPhaseINVERTED;
#else
motorConfigXmp.Dac.Phase = MEIXmpDACPhaseNORMAL;
#endif
/* Set configuration */
returnValue =
mpiMotorConfigSet(motor,
&motorConfig,
&motorConfigXmp);
msgCHECK(returnValue);
/* Get current configuration */
returnValue =
mpiFilterGainGet(filter,
MEIFilterGainIndexDEFAULT,
&gain);
msgCHECK(returnValue);
pid = (MEIFilterGainPID *)&gain;
/* Filter Controller control parameters */
pid->gain.proportional = (float)100.;
pid->gain.integral = (float)0.0;
pid->gain.derivative = (float)400.;
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);
/*
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);
/* Enable the amplifier */
returnValue =
mpiMotorAmpEnableSet(motor,
TRUE);
msgCHECK(returnValue);
/*
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.
*/
returnValue =
mpiMotorConfigGet(motor,
&motorConfig,
&motorConfigXmp);
msgCHECK(returnValue);
for(i= 1; i <= 100; i++){
commutation->OutputLevel = (float)(i)*((OpenDAC_Level)/((float)100.0));
/* Set configuration */
returnValue =
mpiMotorConfigSet(motor,
&motorConfig,
&motorConfigXmp);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
meiPlatformSleep(1000);
/* Motor outbound move */
for(i= 1; i <= 100; i++){
commutation->Offset = (long)(i*2.56);
/* Set configuration */
returnValue =
mpiMotorConfigSet(motor,
&motorConfig,
&motorConfigXmp);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
meiPlatformSleep(1000);
/* Motor return move */
for(i= 1; i <= 100; i++){
commutation->Offset = (long)(256 - (i*2.56));
/* Set configuration */
returnValue =
mpiMotorConfigSet(motor,
&motorConfig,
&motorConfigXmp);
msgCHECK(returnValue);
meiPlatformSleep(30);
}
meiPlatformSleep(1000);
/* Delete Objects */
returnValue = mpiMotionDelete(motion);
msgCHECK(returnValue);
returnValue = mpiMotorDelete(motor);
msgCHECK(returnValue);
returnValue = mpiFilterDelete(filter);
msgCHECK(returnValue);
returnValue = mpiAxisDelete(axis);
msgCHECK(returnValue);
returnValue = mpiControlDelete(control);
msgCHECK(returnValue);
return ((int)returnValue);
}