countRate.c -- How to Maximize Count Rate
/* 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.
*/
/*
This program will maximize (25MHz) count rate by disabling the encoder filter
or minimize(12.5MHz) count rate by enabling the encoder filter on an RMB-10V2.
By default, the encoder filter is enabled. Setting the FilterDisable bit in the
feedbackQuadrature configuration register will allow a maximum of 25MHz.
To modify count rate on a different motor number, use '-motor #' option. It is
defaulted on motor 0.
To modify count rate on all motors that are supported by the node, use
'-all (true or false)' option. It is defaulted at -all false.
To either maximize or minimize count rate, use '-countrate (min or max)'
option.
To specify either primary or secondary encoder use the
'-encoder (primary or secondary)'
option. It is defaulted on primary enconder on motor 0.
To specify which node to modify, use '-node #'. It is defaulted on '-node 0'.
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.
The msgCHECK(...) macros used in the following sample code are intended
to convey our strong belief that ALL error return codes should be checked.
Actual application code should use specific error handling techniques (other
than msgCHECKs) best suited to your internal error recovery methods.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"
#define SQNODE_NUMBER (0)
#define MOTOR_NUMBER (0)
#define PRIMARY_ENCODER (0)
#define SECONDARY_ENCODER (1)
/* Parse command line */
long parseCommandLine(int argc,
char *argv[],
MPIControlType *controlType,
MPIControlAddress *controlAddress,
long *sqNodeNumber,
long *motorNumber,
long *allAxis,
long *encoderOption,
long *disableDigitalFilter)
{
long argIndex;
char *filterInput = NULL;
char *encOpt = NULL;
char *all = NULL;
char *lower = NULL;
/* Application-specific command line arguments */
Arg argList[] =
{
{ "-node", ArgTypeLONG, sqNodeNumber, },
{ "-motor", ArgTypeLONG, motorNumber, },
{ "-all", ArgTypeTEXT, &all, },
{ "-countrate", ArgTypeTEXT, &filterInput, },
{ "-encoder", ArgTypeTEXT, &encOpt, },
{ 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;
}
}
/* Set enable/disable digital filter from user input */
if(filterInput != NULL)
{
for(lower = filterInput; *lower != '\0'; lower++)
{
*lower = tolower(*lower);
}
if( strcmp(filterInput, "min") == 0 )
{
*disableDigitalFilter = FALSE;
}
else if( strcmp(filterInput, "max") == 0 )
{
*disableDigitalFilter = TRUE;
}
else
{
*disableDigitalFilter = -1;
}
}
/* Set encoder option for primary or secondary */
if(encOpt != NULL)
{
for(lower = encOpt; *lower != '\0'; lower++)
{
*lower = tolower(*lower);
}
if( strcmp(encOpt, "primary") == 0 )
{
*encoderOption = PRIMARY_ENCODER;
}
else if( strcmp(encOpt, "secondary") == 0 )
{
*encoderOption = SECONDARY_ENCODER;
}
else
{
*encoderOption = -1;
}
}
/* Disable or enable on either all axis or a specified axis only */
if(all != NULL)
{
for(lower = all; *lower != '\0'; lower++)
{
*lower = tolower(*lower);
}
if( strcmp(all, "true") == 0 )
{
*allAxis = TRUE;
}
else if( strcmp(all, "false") == 0 )
{
*allAxis = FALSE;
}
else
{
*allAxis = -1;
}
}
/* Check for unknown/invalid command line arguments */
if ((argIndex < argc) ||
(*sqNodeNumber < 0) ||
(*motorNumber < 0) ||
(*encoderOption != PRIMARY_ENCODER &&
*encoderOption != SECONDARY_ENCODER) ||
(*allAxis != TRUE && *allAxis != FALSE) ||
(*disableDigitalFilter != TRUE && *disableDigitalFilter != FALSE))
{
fprintf(stderr,"usage: %s %s\n"
"\t\t [-node #(0..%d)]\n"
/*RMB-10V2s support 4 motors*/
"\t\t [-motor #(0..3)]\n"
"\t\t [-all 'true' or 'false']\n"
"\t\t [-countrate 'max' or 'min']\n"
"\t\t [-encoder 'primary' or 'secondary']\n",
argv[0],
ArgUSAGE,
MEISynqNetMaxNODE_COUNT);
exit(MPIMessageARG_INVALID);
}
return 0;
}
/* Create and initialize MPI objects */
void programInit(MPIControl *control,
MPIControlType controlType,
MPIControlAddress *controlAddress,
MEISqNode *sqNode,
long sqNodeNumber)
{
long returnValue;
/* Create motion controller object */
*control =
mpiControlCreate(controlType, controlAddress);
msgCHECK(mpiControlValidate(*control));
/* Initialize motion controller */
returnValue =
mpiControlInit(*control);
msgCHECK(returnValue);
/* Create sqNode object */
*sqNode =
meiSqNodeCreate(*control, sqNodeNumber);
msgCHECK(meiSqNodeValidate(*sqNode));
}
/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl *control,
MEISqNode *sqNode)
{
long returnValue;
/* Delete sqNode object */
returnValue =
meiSqNodeDelete(*sqNode);
msgCHECK(returnValue);
*sqNode = MPIHandleVOID;
/* Delete motion controller object */
returnValue =
mpiControlDelete(*control);
msgCHECK(returnValue);
*control = MPIHandleVOID;
}
/* Return the Feedback Quadrature Address that relates to the motorNumber */
unsigned long getFeedbackQuadratureAddress(long motorNumber,
long encoderOption)
{
unsigned long fqAddress = 0;
/* Note that RMB 10v supports 4 axis only */
if(motorNumber == 0)
{
/* if primary encoder */
if(encoderOption == 0)
{
fqAddress = 0x00020000;
}
/* if secondary encoder */
else
{
fqAddress = 0x00028000;
}
}
else if (motorNumber == 1)
{
/* if primary encoder */
if(encoderOption == 0)
{
fqAddress = 0x01020000;
}
/* if secondary encoder */
else
{
fqAddress = 0x01028000;
}
}
else if (motorNumber == 2)
{
/* if primary encoder */
if(encoderOption == 0)
{
fqAddress = 0x02020000;
}
/* if secondary encoder */
else
{
fqAddress = 0x02028000;
}
}
else if (motorNumber == 3)
{
/* if primary encoder */
if(encoderOption == 0)
{
fqAddress = 0x03020000;
}
/* if secondary encoder */
else
{
fqAddress = 0x03028000;
}
}
return fqAddress;
}
/* Get data that will be written to either enable or disable digital filter */
unsigned long getResponseData(long disableDigitalFilter,
unsigned long responseData)
{
/* Turn digital Filter Off to maximize count rate */
if(disableDigitalFilter == TRUE)
{
responseData |= 0x2;
}
/* Turn digital Filter On to minimize count rate*/
else
{
responseData &= ~(0x2);
}
return responseData;
}
/* Enable or disable digital filter on the specified motor on the RMB-10V2 */
void setDigitalFilter(MEISqNode sqNode,
long motorNumber,
long encoderOption,
long disableDigitalFilter)
{
MEISqNodeCommand command;
MEISqNodeResponse response;
long returnValue;
/* Setting up read command to be sent to the node */
/* Get the relating feedback quadrature address of a motor */
command.address = getFeedbackQuadratureAddress(motorNumber,
encoderOption);
command.header.channel = MEISqNodeChannelNODE;
command.header.memory = MEISqNodeMemoryDATA;
command.header.size = MEISqNodeDataSize32BIT;
command.header.type = MEISqNodeCmdTypeREAD;
/* Send read command and get a response */
returnValue =
meiSqNodeCommand(sqNode,
&command,
&response);
msgCHECK(returnValue);
/* Display data being read from the node */
printf("Motor %d, Response from reading: 0x%x from 0x%x\n",
motorNumber,
response.data,
command.address);
/* Modify command setup for writing */
command.data = getResponseData(disableDigitalFilter,
response.data);
command.header.type = MEISqNodeCmdTypeWRITE;
/* Send write command */
returnValue =
meiSqNodeCommand(sqNode,
&command,
&response);
msgCHECK(returnValue);
/* Display data being written */
printf("Motor %d, Writing : 0x%x to 0x%x\n",
motorNumber,
command.data,
command.address);
/* Modify command setup for reading */
command.header.type = MEISqNodeCmdTypeREAD;
/* Send read command and get response */
returnValue =
meiSqNodeCommand(sqNode,
&command,
&response);
msgCHECK(returnValue);
/* Display data being read from the node */
printf("Motor %d, Response from reading: 0x%x from 0x%x\n\n",
motorNumber,
response.data,
command.address);
}
/* Verify that the Node is an RMB-10V2 */
long verifyNodeIsRMB (MEISqNode sqNode)
{
MEISqNodeInfo info;
long returnValue;
/* Print node information, expecting an RMB-10V */
returnValue = meiSqNodeInfo(sqNode, &info);
msgCHECK(returnValue);
/*printf("\n\nNode name: %s with %ld motors\n\n",
info.id.nodeName, info.motorCount); */
/* Check if node name is in fact RMB-10V2 */
if(strncmp(info.id.nodeName, "MEI RMB-10V2", 12) == 0)
{
returnValue = MPIMessageOK;
}
else
{
fprintf(stderr, "MEI RMB-10V2 is not located\n");
returnValue = -1;
}
return returnValue;
}
int main(int argc,
char *argv[])
{
MPIControl control;
MPIControlType controlType;
MPIControlAddress controlAddress;
MEISqNode sqNode;
MEISqNodeInfo info;
long sqNodeNumber = SQNODE_NUMBER;
long motorNumber = MOTOR_NUMBER;
long disableDigitalFilter = TRUE;
long encoderOption = PRIMARY_ENCODER;
long allAxis = FALSE;
long index;
long returnValue;
/* Parse command line */
parseCommandLine(argc,
argv,
&controlType,
&controlAddress,
&sqNodeNumber,
&motorNumber,
&allAxis,
&encoderOption,
&disableDigitalFilter);
/* Create and initialize MPI objects */
programInit(&control,
controlType,
&controlAddress,
&sqNode,
sqNodeNumber);
/* Check if the node specified is an MEI RMB-10V2 */
returnValue =
verifyNodeIsRMB(sqNode);
/* Disable or Enable Digital Filter on the specified motor or all */
if(returnValue == MPIMessageOK)
{
/* Get node information */
returnValue = meiSqNodeInfo(sqNode, &info);
msgCHECK(returnValue);
/* If all motors */
if(allAxis)
{
for(index = 0; index < info.motorCount; index++)
{
setDigitalFilter(sqNode,
index,
encoderOption,
disableDigitalFilter);
}
}
/* If a motor number is specified */
else
{
/* Check if motor number is valid */
if(motorNumber < info.motorCount)
{
setDigitalFilter(sqNode,
motorNumber,
encoderOption,
disableDigitalFilter);
}
/* If motor number not valid, print error message */
else
{
printf("\nCheck motor number requested. "
"Motor number %d is not supported.\n"
"%s supports motor number 0 to %d only. \n",
motorNumber, info.id.nodeName, info.motorCount-1);
}
}
}
/* Perform certain cleanup actions and delete MPI objects */
programCleanup(&control,
&sqNode);
return MPIMessageOK;
}
|