210 lines
11 KiB
TeX
210 lines
11 KiB
TeX
\subsection{Motors}
|
|
Most neutron scattering instruments have lots of motors to drive
|
|
monochromators, samples and detectors through space.This module implements
|
|
support for them. As usual for hardware objects in SICS motors are
|
|
subdivided into a driver and the logical object.
|
|
|
|
\subsubsection{The Motor Driver}
|
|
There is a problem here. There are some data fields and functions
|
|
which must be present for any motor driver. Then there are fields
|
|
which are specific just to a special implementation of a mot
|
|
driver. There are several ways to deal with this. The way chosen for
|
|
the motor driver is a kind of overlay. The first few fields of a valid
|
|
motor driver structure MUST be specified in the same order as given
|
|
below. A special motor driver can add additional fields at the end of
|
|
the standard list. As an example for this scheme compare the
|
|
AbstractMoDriv structure with the one for the EL734 motor driver.
|
|
\begin{verbatim}
|
|
typedef struct __AbstractMoDriv {
|
|
/* general motor driver interface
|
|
fields. REQUIRED!
|
|
*/
|
|
float fUpper; /* upper limit */
|
|
float fLower; /* lower limit */
|
|
char *name;
|
|
int (*GetPosition)(void *self, float *fPos);
|
|
int (*RunTo)(void *self,float fNewVal);
|
|
int (*GetStatus)(void *self);
|
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
|
int (*TryAndFixIt)(void *self, int iError,float fNew);
|
|
int (*ContinueAfterWarn)(void *self);
|
|
int (*Halt)(void *self);
|
|
}
|
|
MotorDriver;
|
|
\end{verbatim}
|
|
All functions return 0 on failure or 1 on success, if not stated otherwise.
|
|
The first parameter is always a pointer to the motor driver structure.
|
|
The fields and their meanings: \begin{description}
|
|
\item[fUpper,fLower] The hardware upper and lower limits for the motor.
|
|
These are the real hardware limits as implemented by limit switches bolted
|
|
to the instrument.
|
|
\item[name] The real motor name.
|
|
\item[GetPosition] retrieves the current hardware position of the motor into
|
|
fPos.
|
|
\item[RunTo] starts the motor to run to fNewVal. This sends a command to the
|
|
motor and returns immediately.
|
|
\item[GetStatus] requests the status from the motor. Possible answers are:
|
|
\begin{description}
|
|
\item[HWIdle, OKOK] The motor has finished or is idle.
|
|
\item[HWFault] A fault has been found at the motor.
|
|
\item[HWBusy] The motor is busy moving.
|
|
\item[HWWarn] The motor hardware complained but managed to reach the
|
|
requested position.
|
|
\item[HWPosFault] The motor could not go where it should go for some reason.
|
|
However, the motor is intact and ready to move somewhere else. This can
|
|
happen when there is a concrete block in the instruments way which is not
|
|
accounted for by a limit switch. This can also happen when the motor hits a
|
|
limit switch. However, the general idea of SICS is that the limits will be
|
|
checked for before even starting to run the motor. In order for this to
|
|
work, the limits SICS knows about must macth those actually implemented.
|
|
\end{description}
|
|
\item[GetError] This gets called when an error has been detected during one
|
|
of the previous operations. The function has to return more information
|
|
about the error: iCode an driver dependent integer error code and maximum
|
|
iErrLen characters of problem description in error.
|
|
\item[TryAndFixIt] takes the integer error code returned in iCode from
|
|
GetError and tries to solve the problem with the hardware. This function can
|
|
either return MOTREDO which means the problem has been fixed and the
|
|
operation needs to be redone, MOTOK when the problem has been fixed and no
|
|
resending of a command is necessary or MOTFAIL which means that it is not
|
|
possible to resolve the problem in software.
|
|
\item[ContinueAfterWarn] will be called after a warning from the motor. This
|
|
function is supposed to do whatever is needed to clear the warning from the
|
|
motor and keep him going.
|
|
\item[Halt] emergency stop the motor, NOW.
|
|
\end{description}
|
|
|
|
As an example for a derived motor driver the SINQ EL734 motor driver is
|
|
shown below. It add to the general fields the special things for that motor:
|
|
host, port and channel number of the motor controller and a pointer to the
|
|
driver communications structure.
|
|
\begin{verbatim}
|
|
typedef struct __MoDriv {
|
|
/* general motor driver interface
|
|
fields. REQUIRED!
|
|
*/
|
|
float fUpper; /* upper limit */
|
|
float fLower; /* lower limit */
|
|
char *name;
|
|
int (*GetPosition)(void *self,float *fPos);
|
|
int (*RunTo)(void *self, float fNewVal);
|
|
int (*GetStatus)(void *self);
|
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
|
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
|
int (*ContinueAfterWarn)(void *self);
|
|
int (*Halt)(void *self);
|
|
|
|
|
|
/* EL-734 specific fields */
|
|
int iPort;
|
|
char *hostname;
|
|
int iChannel;
|
|
int iMotor;
|
|
void *EL734struct;
|
|
int iMSR;
|
|
} EL734Driv;
|
|
\end{verbatim}
|
|
|
|
Most of the interaction with the motor driver happens through the functions
|
|
defined in its data structure. The rest is creation and deletion:
|
|
\begin{description}
|
|
\item[MotorDriver *CreateEL734(SConnection *pCon, int argc, char
|
|
*argv[])]
|
|
creates a EL734 motor driver. The argc, \verb+argv[]+ pair contains the
|
|
necessary drive parameters.
|
|
\item[MotorDriver *CreateEL734DC(SConnection *pCon, int argc, char
|
|
*argv[])]
|
|
created an EL734 DC motor driver.
|
|
\item[void KillEL734(void *pData)] deletes a EL734 motor driver.
|
|
\item[MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[])]
|
|
creates a simulation motor driver.
|
|
\item[void KillSIM(void *pData)] deletes a simulated motor driver.
|
|
\end{description}
|
|
|
|
\subsubsection{The Motor Logical Object}
|
|
The motor object represents the motor to SICS. One of its responsibilities
|
|
is to drive motor operations and error checking. The scheme
|
|
implemented is that the motor object tries to bring the motor to its
|
|
position at least three times before a failure is recorded. Also the
|
|
motor object keeps track of a count of failed operations. If this
|
|
count gets too high an interrupt is issued to stop the instrument. This
|
|
was put in after Druechal tried to drive over a slab of concrete for a
|
|
whole night and subsequently broke a clutch.
|
|
Motors are represented by the
|
|
following data structure:
|
|
\begin{verbatim}
|
|
typedef struct __Motor {
|
|
pObjectDescriptor pDescriptor;
|
|
ObPar *ParArray;
|
|
pIDrivable pDrivInt;
|
|
pICallBack pCall;
|
|
char *drivername;
|
|
char *name;
|
|
MotorDriver *pDriver;
|
|
float fTarget;
|
|
float fPosition;
|
|
} Motor;
|
|
typedef Motor *pMotor;
|
|
\end{verbatim}
|
|
The fields: \begin{description}
|
|
\item[pDescriptor] The usual SICS object descriptor.
|
|
\item[ParArray] A dictionary of parameter names and float values. This array
|
|
holds all the different parameters used to operate the motor.
|
|
\item[pDrivInt] A pointer to the drivable interface implemented by the motor
|
|
object.
|
|
\item[pCall] A pointer to the callback interface implemented by the motor
|
|
object.
|
|
\item[drivername] The name of the motor driver.
|
|
\item[name] The name of the motor.
|
|
\item[pDriver] A pointer to the motor driver to use.
|
|
\item[fTarget] The target position for the motor.
|
|
\item[fPosition] The last known position of the motor.
|
|
\end{description}
|
|
|
|
Much of the action of the motor is hidden in the implementation of the
|
|
drivable interface to the motor. Additionally the functions as given below
|
|
are defined. All functions take a pointer to the motor object data structure
|
|
as a parameter. They return 0 on success or 1 on failure while not stated
|
|
otherwise.
|
|
\begin{description}
|
|
\item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the
|
|
value of the parameter name in fVal.
|
|
\item[int MotorSetPar(pMotor self, SConnection *pCon, char *name, float
|
|
fVal)] tries to write fVal to the parameter name. Errors are written to
|
|
the connection pCon.
|
|
\item[long MotorRun(void *self, SConnection *pCon, float fNew)] starts a
|
|
motor running to fNew. Does not wait for the motor to finish.
|
|
\item[int MotorCheckBoundary(pMotor self, float fVal, float *fHard,
|
|
char *error, int iErrLen)] checks if the position
|
|
fVal violates any of the motors software or hardware limits. In case of
|
|
success a new hardware position is returned in fHard. fHard is then
|
|
corrected for possible software zero points. In case of a limit violation
|
|
maximum iErrLen characters of error information are returned in error.
|
|
\item[int MotorCheckPosition(void *self, SConnection *pCon)] returns 1 if
|
|
the motor is at the target position, 0 else, or -1 if the motor could not be
|
|
read.
|
|
\item[int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal)]
|
|
reads the current motor position into fVal. This position is corrected for
|
|
software zero points.
|
|
\item[int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal)]
|
|
reads the current position of the motor as returned from the hardware.
|
|
\item[int MakeMotor(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])] the motor factory function. To
|
|
be hacked when a new driver needs to be included.
|
|
\item[pMotor MotorInit(char *drivername,char *name, MotorDriver *pDriv)]
|
|
creates a new motor object with driver pDriv. Returns NULL on failure.
|
|
\item[void MotorKill(void *self)] deletes a motor object. Needs to be
|
|
modified for a new driver in order to clean out the new driver properly.
|
|
\item[int MotorAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])] the object wrapper function for
|
|
the motor. Implements the user interface.
|
|
\item[pMotor FindMotor(SicsInterp *pSics, char *name)] finds a motor name in
|
|
the interpreter pSics. This is a convenience function. Returns NULL if no
|
|
motor could be found, else a pointer to its data structure.
|
|
\end{description}
|
|
|
|
|
|
|
|
|
|
|