.

     

MPI Application Template
template.c
 

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)
    {
        mpiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                     MPIXmpMAX_Axes - 1,
                            MPIXmpMAX_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)MPIActionMAP);
    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;
   MPIMotorConfig 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);

        mpiPlatformSleep(30);
    }

    mpiPlatformSleep(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);

        mpiPlatformSleep(30);
    }

    mpiPlatformSleep(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);

        mpiPlatformSleep(30);
    }
}

/* Be sure to replace with appropriate PID values */
void setFilterGains(MPIFilter filter)
{
   MPIFilterGain gain;
   MPIFilterGainPID *pid;
   long returnValue;

    /* Get current configuration */
    returnValue = mpiFilterGainGet(filter,
      MPIFilterGainIndexDEFAULT,
      &gain);
    msgCHECK(returnValue);

    pid = (MPIFilterGainPID *)&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,
      MPIFilterGainIndexDEFAULT,
      &gain);
    msgCHECK(returnValue);
}

void configureMotor(MPIMotor motor,
               long nEncCountPerCycle,
               float OpenDACLevel,
               float nCycles)
{
    MPIXmpCommutationBlock  *commutation;
    MPIMotorConfig      motorConfig;
    MPIMotorConfig      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        = MPIXmpCommModeOPEN_LOOP;
    commutation->Length      = nEncCountPerCycle;
    commutation->Scale       = (float)MPIXmpCOMM_TABLE_SIZE * nCycles /
                               (float)commutation->Length;
    commutation->PhaseDelta  = MPIXmpCOMM_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 = MPIMotorDemandModeANALOG_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);

    mpiPlatformSleep(1000);

   /* Perform certain cleanup actions and delete MPI objects */
    programCleanup(control,
      motion,
      axis,
      filter,
      motor);

    return ((int)returnValue);
}


      
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2009 Motion Engineering