forked from epics_driver_modules/motorBase
New documents.
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
|
||||
<meta name="Author" content="sluiter">
|
||||
|
||||
<meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; U; SunOS 5.6 sun4u) [Netscape]">
|
||||
<title>Procedure for new motor record device drivers</title>
|
||||
<meta name="author" content="Ron Sluiter">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<center>
|
||||
<h1> Procedures for adding new motor controller support to motor record</h1>
|
||||
</center>
|
||||
|
||||
<ol>
|
||||
<li> Select a supported controller that most closely matches the characteristics
|
||||
of the new controller. If the new controller is simply a different model
|
||||
of a supported controller family (e.g. Oregon Micro Systems or Newport's Motion
|
||||
Master), then, of course, chose a model from the controller family that most
|
||||
closely matches the characteristics of the new controller. Otherwise,
|
||||
select a supported controller based on other characteristics, such as; communication
|
||||
interface (i.e., VME, RS232, GPIB), controller features (e.g., encoder support,
|
||||
DC servo support, etc.), etc. In what follows this will be called the
|
||||
<i>source</i> controller or <i>source</i> device driver.</li>
|
||||
|
||||
<ul>
|
||||
<li> When I added MM3000 device support I selected the MM4000 because it
|
||||
is simply a different Newport model.</li>
|
||||
<li> When I added IM483 device support I selected the MM4000 because it
|
||||
has a serial communication option.</li>
|
||||
|
||||
</ul>
|
||||
<li> Chose an appropriate device name for the new controller. Copy
|
||||
the <i>relevant </i>files from the selected source controller, to the new,
|
||||
<i>destination,</i> controller, giving the new files appropriate names
|
||||
using the new device name. (See motor_files.html for a list of all
|
||||
motor record source code files.)</li>
|
||||
|
||||
<ul>
|
||||
<li> When I added MM3000 device support I copied the following files:</li>
|
||||
|
||||
<ul>
|
||||
<li> devMM4000.c -> devMM3000.c</li>
|
||||
<li> drvMM4000.h -> drvMMCom.h</li>
|
||||
<li> drvMM4000.c -> drvMM3000.c</li>
|
||||
|
||||
</ul>
|
||||
<li> When I added IM483 device support I copied the following files:</li>
|
||||
|
||||
<ul>
|
||||
<li> devMM4000.c -> devIM483.c</li>
|
||||
<li> drvMMCom.h -> drvIM483.h</li>
|
||||
<li> drvMM4000.c -> drvIM483.c</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
<li> Modify all the new files by cleaning up the obvious header information
|
||||
(e.g. filename, usage, etc.). Delete the old <i>Modification Log </i>
|
||||
entries and add a single new entry that notes which source file you copied
|
||||
to start this file.</li>
|
||||
<li> Modify the new driver include file (e.g., drvOms.h, drvMMCom.h, drvIM483.h,
|
||||
etc.) first.</li>
|
||||
|
||||
<ul>
|
||||
<li> Fix the multiple inclusion protection; i.e.,</li>
|
||||
|
||||
<ul>
|
||||
<li> #ifndef INC<i>filename</i>h</li>
|
||||
<li> #define INC<i>filename</i>h 1</li>
|
||||
<li> #endif /* INC<i>filename</i>h */</li>
|
||||
|
||||
</ul>
|
||||
<li> Delete everything in the driver include file that is specific to the
|
||||
old controller. If a device specific data area is needed for this controller,
|
||||
then that structure definition should appear in this file (see the MMcontroller
|
||||
structure in drvMMCom.h or IM483controller structure in drvIM483.h).</li>
|
||||
|
||||
</ul>
|
||||
<li> Modify the device source code file (e.g., devOms.c, devMM4000.c, devIM483.c,
|
||||
etc.) next.</li>
|
||||
|
||||
<ul>
|
||||
<li> Do a global <i>find and replace</i> on the file; replacing the source
|
||||
root name with the destination root name; e.g., MM4000 to IM483.</li>
|
||||
<li> Find the <device>_build_trans() function. Unless the source
|
||||
controller you chose was from the same family of controllers, the command
|
||||
primitives for the new controller will not match those of the source controller.
|
||||
Hence, each of the <i>switch case </i>statements in <device>_build_trans()
|
||||
will have to be;</li>
|
||||
|
||||
<ol>
|
||||
<li> Evaluated, as to be whether or not the new controller can support the
|
||||
associated motor command.</li>
|
||||
<li> If the new controller supports the motor command, find the command
|
||||
primitive for the motor command and modify the <i>switch case </i>code to
|
||||
output the correct command primitive.</li>
|
||||
|
||||
</ol>
|
||||
<li> Check that the command line terminator function argument located
|
||||
in the <device>_end_trans() function is correct.</li>
|
||||
<li>Determine whether or not the destination motor controller supports
|
||||
multiple commands on the same command line. For example, the Oregon
|
||||
Micro Systems (OMS) motor controllers allow the velocity base, slew velocity,
|
||||
acceleration and target position all on the same command line (e.g.,
|
||||
AX VB200 VL4000 AC4444 MA-38866 GD ID). The Newport Motion Master
|
||||
(i.e, MM3000, MM4000, MM4005) and PM500 controllers also support multiple
|
||||
commands. On the other hand, multiple commands are not supported by
|
||||
the Intelligent Motion Systems (IMS) IM483 motor controller.</li>
|
||||
<ol>
|
||||
<ul>
|
||||
<li>If multiple commands on the same command line <b>is</b> supported,
|
||||
then the functions <device>_start_trans(), <device>_end_trans()
|
||||
and <device>_build_trans() in the destination device code should look
|
||||
like those found in any of the Newport device files; i.e., devPM500.c, devMM4000.c
|
||||
or devMM3000.c. In addition, determine the command seperation ASCII
|
||||
character for the destination motor controller and append this ASCII character
|
||||
to the end of each command primitive.</li>
|
||||
<li>If multiple commands on the same command line <b>is</b> <b>not
|
||||
</b>supported, then the functions <device>_start_trans(),
|
||||
<device>_end_trans() and <device>_build_trans() in the should
|
||||
look like those found in any of the IMS device files; i.e., devIM483SM.c
|
||||
or devIM483PL.c.</li>
|
||||
</ul>
|
||||
|
||||
</ol>
|
||||
|
||||
</ul>
|
||||
<li> Modify the driver source code file (e.g., drvOms.c, drvMM4000.c, drvIM483.c,
|
||||
etc.) next.</li>
|
||||
|
||||
<ul>
|
||||
<li> Do a global <i>find and replace</i> on the file; replacing the source
|
||||
root name with the destination root name; e.g., MM4000 to IM483.</li>
|
||||
<li> Locate each call to send_mess() that passes a string constant argument,
|
||||
either explicitly or through a preprocessor macro name. Modify either
|
||||
the string constant or the macro definition for the new controller.</li>
|
||||
<li>Determine whether or not the destination motor controller echos commands
|
||||
and whether or not this feature can be disabled. If echoing cannot
|
||||
be disabled, then set the brdptr->cmnd_response = ON in motor_init().<br>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</ol>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,201 @@
|
||||
NOTES on Motor Record fields
|
||||
============================
|
||||
|
||||
|
||||
Field Function
|
||||
----- --------
|
||||
|
||||
REP Raw Encoder Position. Feedback position read from motor controller.
|
||||
|
||||
If the "Encoder Present" status bit is ON in the MSTA, REP is the raw
|
||||
encoder value read from the controller; if the status bit is OFF, REP
|
||||
is always zero.
|
||||
|
||||
motor_update_values(motordevCom.c): mr->rep = ptrans->encoder_pos
|
||||
motor_callback(motordevCom.c):
|
||||
ptrans->encoder_pos = motor_return->encoder_position
|
||||
set_status(drv[device].c): motor_info->encoder_position = motorData
|
||||
|
||||
|
||||
RMP Raw Motor Position. Commanded position read from motor controller.
|
||||
|
||||
motor_update_values(motordevCom.c): mr->rmp = ptrans->motor_pos
|
||||
motor_callback(motordevCom.c):
|
||||
ptrans->motor_pos = motor_return->position
|
||||
set_status(drv[device].c): motor_info->position = pos
|
||||
|
||||
|
||||
RRBV Raw Readback Value.
|
||||
|
||||
process_motor_info(motorRecord.c):
|
||||
IF UEIP set to YES, AND, MSTA indicates an encoder is present.
|
||||
pmr->rrbv = pmr->rep
|
||||
ELSE
|
||||
pmr->rrbv = pmr->rmp.
|
||||
ENDIF
|
||||
|
||||
|
||||
DRBV Dial Readback Value.
|
||||
|
||||
process_motor_info(motorRecord.c):
|
||||
IF URIP set to YES.
|
||||
pmr->drbv *= pmr->rres; /* Set DRBV from RDBL link. */
|
||||
ELSE
|
||||
IF UEIP set to YES, AND, MSTA indicates an encoder is present.
|
||||
pmr->drbv = pmr->rrbv * pmr->eres
|
||||
ELSE
|
||||
pmr->drbv = pmr->rrbv * pmr->mres
|
||||
ENDIF
|
||||
|
||||
RBV User Readback Value. Actual (i.e, feedback) motor position.
|
||||
|
||||
process_motor_info(motorRecord.c):
|
||||
pmr->rbv = dir * pmr->drbv + pmr->off
|
||||
|
||||
==============================================================================
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
DIR User Direction. Used to convert between dial and user coordinates.
|
||||
Valid values are defined by menu(motorDIR);
|
||||
0 = "motorDIR_Pos"; user has same sign as dial.
|
||||
1 = "motorDIR_Neg"; user has opposite sign of dial.
|
||||
|
||||
|
||||
OFF User Offset (EGU). User and dial coordinates can differ by a sign
|
||||
(the DIR field) and an offset (OFF), according to the following
|
||||
equations:
|
||||
IF DIR == motorDIR_Pos
|
||||
HLM = DHLM + OFF
|
||||
LLM = DLLM + OFF
|
||||
ELSE
|
||||
HLM = -DLLM + OFF
|
||||
LLM = -DHLM + OFF
|
||||
ENDIF
|
||||
|
||||
RBV = (DRBV * DIR) + OFF
|
||||
DVAL = (VAL - OFF) / DIR
|
||||
VAL = (DVAL * DIR) + OFF
|
||||
userVAL = (DialVAL * DIR) + OFFset
|
||||
|
||||
OFF is set by the motor record under the following conditions.
|
||||
|
||||
do_work(): IF new DVAL, AND, the SET position field is ON, AND,
|
||||
the FOFF field is "Variable".
|
||||
OFF = VAL - (DVAL * DIR)
|
||||
ENDIF
|
||||
special(): IF new DIR
|
||||
OFF = VAL - (DVAL * DIR)
|
||||
ENDIF
|
||||
load_pos(): IF FOFF field is "Variable".
|
||||
IF DIR == motorDIR_Pos
|
||||
OFF = VAL - DVAL
|
||||
ELSE
|
||||
OFF = VAL + DVAL
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
SET Set/Use Switch. Used to calibrate the motor's user and dial positions.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
RVAL Raw Desired Value. Target position.
|
||||
|
||||
do_work(): IF new DVAL,
|
||||
pmr->rval = NINT(pmr->dval / pmr->res)
|
||||
postProcess(): IF OMSL is OFF (i.e., "supervisory")
|
||||
pmr->rval = pmr->rrbv ???Reset Target to Actual???
|
||||
|
||||
|
||||
DVAL Dial Desired Value. Target position.
|
||||
|
||||
do_work(): IF new RVAL,
|
||||
pmr->dval = pmr->rval * pmr->res
|
||||
postProcess(): IF OMSL is OFF (i.e., "supervisory")????
|
||||
pmr->dval = pmr->drbv
|
||||
|
||||
|
||||
VAL User Desired Value. Target position.
|
||||
|
||||
do_work(): IF (new DVAL, OR, DMOV is FALSE), AND, SET is FALSE.
|
||||
pmr->val = pmr->dval * dir + pmr->off
|
||||
postProcess(): IF OMSL is OFF (i.e., "supervisory")?????
|
||||
pmr->val = pmr->rbv
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
ERES Encoder Step Size (EGU)
|
||||
do_work(): IF MRES, OR, ERES, OR, UEIP are marked as changed.
|
||||
IF MSTA indicates an encoder is present, AND, UEIP
|
||||
set to YES.
|
||||
if (fabs(pmr->eres) < 1.e-9)
|
||||
pmr->eres = pmr->mres;
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
RRES Readback Step Size (EGU)
|
||||
|
||||
RES Step Size (EGU). With R4.5, RES <=> MRES.
|
||||
|
||||
MRES Motor Step Size (EGU). Motor resolution in EGU/step. MRES=UREV/SREV
|
||||
|
||||
special(motorRecord.c): pmr->mres = pmr->urev / pmr->srev;
|
||||
|
||||
UREV EGU's per Revolution.
|
||||
|
||||
SREV Steps per Revolution. The record never sets this field.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
VBAS Minimum Velocity (EGU/s)
|
||||
SBAS Minimum Speed (revolutions/sec)
|
||||
|
||||
special(motorRecord.c): pmr->sbas = pmr->vbas / fabs(pmr->urev);
|
||||
pmr->vbas = fabs(pmr->urev) * pmr->sbas;
|
||||
|
||||
VMAX Maximum Velocity (EGU/s)
|
||||
SMAX Maximum Speed (revolutions/sec)
|
||||
|
||||
VELO Slew Velocity (EGU/s)
|
||||
S Speed (revolutions/sec)
|
||||
|
||||
BVEL Backlash Velocity (EGU/s)
|
||||
SBAK Backlash Speed (revolutions/sec)
|
||||
|
||||
|
||||
UEIP effects
|
||||
------------
|
||||
|
||||
The state of the UEIP, together with the MSTA encoder indicator, determine;
|
||||
|
||||
1) if the RRBV is set to either the feedback (REP) or the command (RMP)
|
||||
position.
|
||||
2) if the RES is set to either the feedback (ERES) or the command (MRES)
|
||||
resolution.
|
||||
3) whether absolute or relative position commands are used.
|
||||
|
||||
|
||||
The algorithm used in moves to a (dial-coordinate) position called "TARGET"
|
||||
follows:
|
||||
|
||||
1) If the motor is to move a distance greater than the magnitude of BDST, or
|
||||
if the motor is to move in a direction opposite to the sign of BDST, then the
|
||||
motor will move first to position (TARGET-BDST), at an acceleration specified
|
||||
by ACCL and speed VELO, and then to position TARGET, at an acceleration
|
||||
specified by BACC and speed BVEL.
|
||||
|
||||
2) If the motor is to move a distance smaller than the magnitude of BDST, and
|
||||
if the motor is to move in the same direction as the sign of BDST, then
|
||||
backlash is assumed already to have been taken out, and the motor will move to
|
||||
position TARGET at an acceleration specified by BACC and speed BVEL.
|
||||
|
||||
|
||||
#1)
|
||||
IF |DIFF| > |BDST|, OR, sign(DIFF) != sign(BDST)
|
||||
Move to position (TARGET - BDST) using ACCL and VELO.
|
||||
Move to position TARGET using BACC and BVEL.
|
||||
ELSE IF |DIFF| <= |BDST|, AND, sign(DIFF) == sign(BDST).
|
||||
Move to position TARGET using BACC and BVEL.
|
||||
ENDIF
|
||||
|
||||
|
||||
#3) Backlash correction is disabled if and only if |BDST| < |RES|.
|
||||
|
||||
Reference in New Issue
Block a user