- ECB motors without encoders, with encoders and with control bits now work
This commit is contained in:
10
Makefile
10
Makefile
@ -9,9 +9,9 @@
|
|||||||
#------- comment or uncomment this if a fortified version is required.
|
#------- comment or uncomment this if a fortified version is required.
|
||||||
# Note: A -DFORTIFY needs to be added to the CFLAGS as well.
|
# Note: A -DFORTIFY needs to be added to the CFLAGS as well.
|
||||||
#
|
#
|
||||||
#FORTIFYOBJ = fortify.o strdup.o
|
FORTIFYOBJ = fortify.o strdup.o
|
||||||
#----
|
#----
|
||||||
FORTIFYOBJ =
|
#FORTIFYOBJ =
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
#==========================================================================
|
#==========================================================================
|
||||||
@ -96,10 +96,10 @@ VELOOBJ = velo.o velosim.o velodorn.o velodornier.o
|
|||||||
BINTARGET=../../bin
|
BINTARGET=../../bin
|
||||||
HDFROOT=$(SINQDIR)/linux
|
HDFROOT=$(SINQDIR)/linux
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
#CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
||||||
|
# -fwritable-strings -DCYGNUS -DNONINTF -g -c
|
||||||
|
CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
||||||
-fwritable-strings -DCYGNUS -DNONINTF -g -c
|
-fwritable-strings -DCYGNUS -DNONINTF -g -c
|
||||||
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -fwritable-strings -DFORTIFY \
|
|
||||||
# -DCYGNUS -DNONINTF -g -c
|
|
||||||
LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
|
LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
|
||||||
$(NILIB) -ltcl -lhdf5 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
|
$(NILIB) -ltcl -lhdf5 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
|
||||||
EXTRA=nintf.o
|
EXTRA=nintf.o
|
||||||
|
47
ecb.c
47
ecb.c
@ -325,6 +325,49 @@ int ECBAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
int ecbAssignEncoder(pECB self, int encoder, int motorNumber){
|
||||||
|
|
||||||
|
if(encoder <= 0 || encoder > 3){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->encoder[encoder-1] = motorNumber;
|
||||||
|
self->encoderDirty = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int ecbLoadEncoder(pECB self){
|
||||||
|
Z80_reg in, out;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if(self->encoderDirty != 1){
|
||||||
|
/*
|
||||||
|
no need to do it if no change
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(self->encoder[0] != 0){
|
||||||
|
in.d = self->encoder[0];
|
||||||
|
}else {
|
||||||
|
in.d = 0;
|
||||||
|
}
|
||||||
|
if(self->encoder[1] != 0){
|
||||||
|
in.e = self->encoder[1];
|
||||||
|
}else {
|
||||||
|
in.e = 0;
|
||||||
|
}
|
||||||
|
if(self->encoder[2] != 0){
|
||||||
|
in.b = self->encoder[2];
|
||||||
|
}else {
|
||||||
|
in.b = 0;
|
||||||
|
}
|
||||||
|
in.c = 1;
|
||||||
|
|
||||||
|
status = ecbExecute(self,152,in,&out);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
void ECBKill(void *pData){
|
void ECBKill(void *pData){
|
||||||
pECB self = (pECB)pData;
|
pECB self = (pECB)pData;
|
||||||
@ -345,7 +388,9 @@ void ECBKill(void *pData){
|
|||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------
|
||||||
|
MakeECB name gpibcontroller boardNo gpib-address
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
int MakeECB(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int MakeECB(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
pECB self = NULL;
|
pECB self = NULL;
|
||||||
|
8
ecb.h
8
ecb.h
@ -34,7 +34,13 @@ typedef struct {
|
|||||||
void *buffer, int byteCount);
|
void *buffer, int byteCount);
|
||||||
void ecbClear(pECB self);
|
void ecbClear(pECB self);
|
||||||
int fixECBError(pECB self);
|
int fixECBError(pECB self);
|
||||||
void ecbErrorDescription(pECB self, char *buffer, int maxBytes);
|
void ecbErrorDescription(pECB self, char *buffer,
|
||||||
|
int maxBytes);
|
||||||
|
int ecbAssignEncoder(pECB self, int encoder, int motorNumber);
|
||||||
|
int ecbLoadEncoder(pECB self);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
21
ecb.w
21
ecb.w
@ -14,6 +14,11 @@ This module now implements three basic functionalities of the ECB:
|
|||||||
\item Write some memory
|
\item Write some memory
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
|
This module also takes care of the encoder assignment for the ECB. The
|
||||||
|
ECB can have up to three encoders which can be assigned to motors. As
|
||||||
|
a single motor driver does not know about the assignments of the other
|
||||||
|
motors, the task of encoder assignement is handled in this module.
|
||||||
|
|
||||||
WARNING: this module contains code which may be endian dependend!
|
WARNING: this module contains code which may be endian dependend!
|
||||||
|
|
||||||
In order to do this we need the following data structure:
|
In order to do this we need the following data structure:
|
||||||
@ -25,6 +30,8 @@ In order to do this we need the following data structure:
|
|||||||
int ecbAddress;
|
int ecbAddress;
|
||||||
int ecbDeviceID;
|
int ecbDeviceID;
|
||||||
int lastError;
|
int lastError;
|
||||||
|
int encoder[3];
|
||||||
|
int encoderDirty;
|
||||||
}ECB;
|
}ECB;
|
||||||
@}
|
@}
|
||||||
The fields:
|
The fields:
|
||||||
@ -36,6 +43,10 @@ The fields:
|
|||||||
\item[ecbDeviceID] The device ID assigned to the ECB when the ECB has
|
\item[ecbDeviceID] The device ID assigned to the ECB when the ECB has
|
||||||
been attached to.
|
been attached to.
|
||||||
\item[lastError] The last error which occurred.
|
\item[lastError] The last error which occurred.
|
||||||
|
\item[encoder] An array holding the motor numbers assigned to the
|
||||||
|
three encoder.
|
||||||
|
\item[encoderDirty] is a flag which is set to true if a download of
|
||||||
|
the encoder assignments is necessary.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
A function in the ECB is executed by sending a function number first,
|
A function in the ECB is executed by sending a function number first,
|
||||||
@ -63,7 +74,13 @@ The function interface then looks like:
|
|||||||
void *buffer, int byteCount);
|
void *buffer, int byteCount);
|
||||||
void ecbClear(pECB self);
|
void ecbClear(pECB self);
|
||||||
int fixECBError(pECB self);
|
int fixECBError(pECB self);
|
||||||
void ecbErrorDescription(pECB self, char *buffer, int maxBytes);
|
void ecbErrorDescription(pECB self, char *buffer,
|
||||||
|
int maxBytes);
|
||||||
|
int ecbAssignEncoder(pECB self, int encoder, int motorNumber);
|
||||||
|
int ecbLoadEncoder(pECB self);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@}
|
@}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
@ -79,6 +96,8 @@ ECB's memory space and not the GPIB address.
|
|||||||
\item[fixECBError] tries to fix the last ECB error.
|
\item[fixECBError] tries to fix the last ECB error.
|
||||||
\item[ecbErrorDescription] retrieves a text description of the last
|
\item[ecbErrorDescription] retrieves a text description of the last
|
||||||
ECB problem. Max maxBytes of description are copied into buffer.
|
ECB problem. Max maxBytes of description are copied into buffer.
|
||||||
|
\item[assignEncoder] assigns an encoder to a motor number.
|
||||||
|
\item[loadEncoder] downloads the encoder assignment to the ECB if necessary.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
564
ecbdriv.c
564
ecbdriv.c
@ -1,5 +1,5 @@
|
|||||||
/*------------------------------------------------------------------------
|
/*------------------------------------------------------------------------
|
||||||
This is a motor driver for the Risoe motor controllers within the
|
this is a motor driver for the Risoe motor controllers within the
|
||||||
ECB system. The motor is controlled through functions invoked in the
|
ECB system. The motor is controlled through functions invoked in the
|
||||||
Z80 processor of the ECB system which is connected through a GPIB
|
Z80 processor of the ECB system which is connected through a GPIB
|
||||||
bus to the wider world. This driver has to do a lot of extra things:
|
bus to the wider world. This driver has to do a lot of extra things:
|
||||||
@ -7,6 +7,11 @@
|
|||||||
- Quite a few parameters, such as ramping parameters,
|
- Quite a few parameters, such as ramping parameters,
|
||||||
have to be downloaded to the ECB
|
have to be downloaded to the ECB
|
||||||
- Risoe motors may have a virtual encoder or a real encoder.
|
- Risoe motors may have a virtual encoder or a real encoder.
|
||||||
|
- The motor may have to control air cushions as well.
|
||||||
|
- Tricky backlash handling. Backlash handling ensures that a position is
|
||||||
|
always arrived at from a defined direction. If backlash is applied
|
||||||
|
a restart flag is set in ECBRunTo. ECBGetStatus checks for that and
|
||||||
|
causes the motor to drive back to the position actually desired.
|
||||||
|
|
||||||
This driver support only P2048a motor controllers, as these are the
|
This driver support only P2048a motor controllers, as these are the
|
||||||
only ones which seem to have arrived at PSI. The P1648 and Tridynamic
|
only ones which seem to have arrived at PSI. The P1648 and Tridynamic
|
||||||
@ -33,10 +38,13 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
#include "obpar.h"
|
#include "obpar.h"
|
||||||
|
#include "splitter.h"
|
||||||
#include "ecb.h"
|
#include "ecb.h"
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
/*------------------------------------------------------------------------
|
||||||
@ -81,6 +89,7 @@ Parameter indexes in ObPar array and meanings
|
|||||||
#define ECBRUNNING -305
|
#define ECBRUNNING -305
|
||||||
#define ECBSTART -306
|
#define ECBSTART -306
|
||||||
#define ECBLIMIT -307
|
#define ECBLIMIT -307
|
||||||
|
#define ECBREADERROR -308
|
||||||
/*================== The Driver data structure ============================*/
|
/*================== The Driver data structure ============================*/
|
||||||
typedef struct __ECBMotorDriv {
|
typedef struct __ECBMotorDriv {
|
||||||
/* general motor driver interface
|
/* general motor driver interface
|
||||||
@ -108,9 +117,13 @@ Parameter indexes in ObPar array and meanings
|
|||||||
/* ECB specific fields */
|
/* ECB specific fields */
|
||||||
pECB ecb; /* ECB controller for everything */
|
pECB ecb; /* ECB controller for everything */
|
||||||
int ecbIndex; /* motor index in ECB */
|
int ecbIndex; /* motor index in ECB */
|
||||||
long targetInSteps;
|
|
||||||
int errorCode;
|
int errorCode;
|
||||||
ObPar driverPar[MAXPAR];
|
int restart; /* flag if we have to restart
|
||||||
|
because of backlash
|
||||||
|
compensation
|
||||||
|
*/
|
||||||
|
float restartTarget; /* target to restart to */
|
||||||
|
ObPar driverPar[MAXPAR]; /* parameters */
|
||||||
} ECBMOTDriv, *pECBMotDriv;
|
} ECBMOTDriv, *pECBMotDriv;
|
||||||
/*=======================================================================
|
/*=======================================================================
|
||||||
Reading the motor position means reading the encoder if such a thing
|
Reading the motor position means reading the encoder if such a thing
|
||||||
@ -133,7 +146,7 @@ static int readEncoder(pECBMotDriv self, long *digits){
|
|||||||
/* pack bytes */
|
/* pack bytes */
|
||||||
data.b.byt3 = 0;
|
data.b.byt3 = 0;
|
||||||
data.b.byt2 = out.b;
|
data.b.byt2 = out.b;
|
||||||
data.b.byt1 = out.b;
|
data.b.byt1 = out.d;
|
||||||
data.b.byt0 = out.e;
|
data.b.byt0 = out.e;
|
||||||
if(out.c != 1){
|
if(out.c != 1){
|
||||||
*digits = -data.result;
|
*digits = -data.result;
|
||||||
@ -158,7 +171,7 @@ static int readPseudoEncoder(pECBMotDriv self, long *digits){
|
|||||||
/* pack bytes */
|
/* pack bytes */
|
||||||
data.b.byt3 = 0;
|
data.b.byt3 = 0;
|
||||||
data.b.byt2 = out.b;
|
data.b.byt2 = out.b;
|
||||||
data.b.byt1 = out.b;
|
data.b.byt1 = out.d;
|
||||||
data.b.byt0 = out.e;
|
data.b.byt0 = out.e;
|
||||||
if(out.c != 1){
|
if(out.c != 1){
|
||||||
*digits = -data.result;
|
*digits = -data.result;
|
||||||
@ -179,6 +192,9 @@ int ECBMOTGetPos(void *pData, float *fPos){
|
|||||||
|
|
||||||
if((int)ObVal(self->driverPar,ENCODER) > 0){
|
if((int)ObVal(self->driverPar,ENCODER) > 0){
|
||||||
status = readEncoder(self, &digits);
|
status = readEncoder(self, &digits);
|
||||||
|
*fPos = digits/ObVal(self->driverPar,DEG2STEP) -
|
||||||
|
ObVal(self->driverPar,OFFSET);
|
||||||
|
return status;
|
||||||
} else {
|
} else {
|
||||||
status = readPseudoEncoder(self, &digits);
|
status = readPseudoEncoder(self, &digits);
|
||||||
}
|
}
|
||||||
@ -201,7 +217,7 @@ In order to start a motor we need to do a couple of steps:
|
|||||||
static int mustDownload(pECBMotDriv self){
|
static int mustDownload(pECBMotDriv self){
|
||||||
int multi;
|
int multi;
|
||||||
|
|
||||||
multi = (int)nintf(ObVal(self->driverPar,MULT));
|
multi = (int)rint(ObVal(self->driverPar,MULT));
|
||||||
if(multi > 0 || multi < 0) {
|
if(multi > 0 || multi < 0) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@ -249,7 +265,7 @@ static int loadAcceleration(pECBMotDriv self){
|
|||||||
Z80_reg in, out;
|
Z80_reg in, out;
|
||||||
int accel, status;
|
int accel, status;
|
||||||
|
|
||||||
accel = (int)nintf(ObVal(self->driverPar,ACCTIME));
|
accel = (int)rint(ObVal(self->driverPar,ACCTIME));
|
||||||
if(accel == 500){
|
if(accel == 500){
|
||||||
parameter = 1;
|
parameter = 1;
|
||||||
}else if(accel == 1000){
|
}else if(accel == 1000){
|
||||||
@ -268,6 +284,8 @@ static int loadAcceleration(pECBMotDriv self){
|
|||||||
in.c = (unsigned char)self->ecbIndex;
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
in.b = 7;
|
in.b = 7;
|
||||||
in.e = parameter;
|
in.e = parameter;
|
||||||
|
in.d = 0;
|
||||||
|
out.d = out.e = out.b = out.c = 0;
|
||||||
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
if(!status){
|
if(!status){
|
||||||
self->errorCode = COMMERROR;
|
self->errorCode = COMMERROR;
|
||||||
@ -306,12 +324,12 @@ const unsigned int high_2048[SPEED_TAB4] = {
|
|||||||
10700, 11200, 11700, 12200, 12800, 13300, 13900, 14500,
|
10700, 11200, 11700, 12200, 12800, 13300, 13900, 14500,
|
||||||
15100, 15800, 16700, 17300, 18000, 18600, 19300, 20000 };
|
15100, 15800, 16700, 17300, 18000, 18600, 19300, 20000 };
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static unsigned char getSpeedIndex(pECBMotDriv self, int value){
|
static unsigned char getSpeedIndex(float value,
|
||||||
|
int range, int *actualValue ){
|
||||||
unsigned char index;
|
unsigned char index;
|
||||||
const unsigned int *table;
|
const unsigned int *table;
|
||||||
int range, length;
|
int length;
|
||||||
|
|
||||||
range = (int)nintf(ObVal(self->driverPar,RANGE));
|
|
||||||
if(range == 0){
|
if(range == 0){
|
||||||
table = low_2048;
|
table = low_2048;
|
||||||
length = SPEED_TAB3;
|
length = SPEED_TAB3;
|
||||||
@ -321,19 +339,21 @@ static unsigned char getSpeedIndex(pECBMotDriv self, int value){
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(index = 0; index < length-1; index++){
|
for(index = 0; index < length-1; index++){
|
||||||
if(table[index] <= value){
|
if(table[index] >= value){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*actualValue = table[index];
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static int loadSpeed(pECBMotDriv self, float value, int code){
|
static int loadSpeed(pECBMotDriv self, float value, int code){
|
||||||
unsigned char parameter;
|
unsigned char parameter;
|
||||||
Z80_reg in, out;
|
Z80_reg in, out;
|
||||||
int accel, status;
|
int accel, status, actual;
|
||||||
|
|
||||||
parameter = getSpeedIndex(self,value);
|
parameter = getSpeedIndex(value, (int)rint(ObVal(self->driverPar,RANGE)),
|
||||||
|
&actual);
|
||||||
|
|
||||||
in.c = (unsigned char)self->ecbIndex;
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
in.b = code;
|
in.b = code;
|
||||||
@ -355,8 +375,8 @@ static int loadDelay(pECBMotDriv self){
|
|||||||
int accel, status;
|
int accel, status;
|
||||||
unsigned char control;
|
unsigned char control;
|
||||||
|
|
||||||
parameter = (int)nintf(ObVal(self->driverPar,DELAY));
|
parameter = (int)rint(ObVal(self->driverPar,DELAY));
|
||||||
control = (unsigned char)nintf(ObVal(self->driverPar,CONTROL));
|
control = (unsigned char)rint(ObVal(self->driverPar,CONTROL));
|
||||||
if(control & 3){
|
if(control & 3){
|
||||||
parameter = 5;
|
parameter = 5;
|
||||||
} else{
|
} else{
|
||||||
@ -379,16 +399,16 @@ static int loadDelay(pECBMotDriv self){
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static int loadMulti(pECBMotDriv self){
|
static int loadMulti(pECBMotDriv self){
|
||||||
unsigned char multi, mult_chan;
|
int multi, mult_chan;
|
||||||
Z80_reg in, out;
|
Z80_reg in, out;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
multi = nintf(ObVal(self->driverPar,MULT));
|
multi = rint(ObVal(self->driverPar,MULT));
|
||||||
if(multi <= 0){
|
if(multi <= 0){
|
||||||
return 1; /* not multiplexed */
|
return 1; /* not multiplexed */
|
||||||
}
|
}
|
||||||
|
|
||||||
mult_chan = (unsigned char)nintf(ObVal(self->driverPar,MULTCHAN));
|
mult_chan = (unsigned char)rint(ObVal(self->driverPar,MULTCHAN));
|
||||||
in.b = -1; /* SET_PORT */
|
in.b = -1; /* SET_PORT */
|
||||||
in.d = (unsigned char)(multi + (mult_chan << 4));
|
in.d = (unsigned char)(multi + (mult_chan << 4));
|
||||||
in.e = self->ecbIndex;
|
in.e = self->ecbIndex;
|
||||||
@ -399,6 +419,33 @@ static int loadMulti(pECBMotDriv self){
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int loadOffset(pECBMotDriv self, float offset){
|
||||||
|
Z80_reg in, out;
|
||||||
|
int status;
|
||||||
|
Ecb_pack data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
ignored
|
||||||
|
*/
|
||||||
|
if(ObVal(self->driverPar,ENCODER) <=.0){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.result = offset * ObVal(self->driverPar,STEPS2DEG);
|
||||||
|
in.b = data.b.byt2;
|
||||||
|
in.d = data.b.byt1;
|
||||||
|
in.e = data.b.byt0;
|
||||||
|
in.c = (unsigned char)rint(ObVal(self->driverPar,ENCODER));
|
||||||
|
|
||||||
|
status = ecbExecute(self->ecb,168,in,&out);
|
||||||
|
if(status == 1){
|
||||||
|
self->driverPar[OFFSET].fVal = offset;
|
||||||
|
} else {
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
static int downloadECBParam(pECBMotDriv self){
|
static int downloadECBParam(pECBMotDriv self){
|
||||||
int status, parameter;
|
int status, parameter;
|
||||||
@ -437,6 +484,15 @@ static int downloadECBParam(pECBMotDriv self){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(status = ecbLoadEncoder(self->ecb) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadOffset(self,ObVal(self->driverPar,OFFSET)) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
It would be good practice to read the parameters written back
|
It would be good practice to read the parameters written back
|
||||||
in order to check them. This does not seem to be supported with the
|
in order to check them. This does not seem to be supported with the
|
||||||
@ -461,6 +517,65 @@ int degree2Step(pECBMotDriv self, float degree)
|
|||||||
}
|
}
|
||||||
return ((int) steps);
|
return ((int) steps);
|
||||||
}
|
}
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
controlMotor enables or disables the motor, according to flag enable.
|
||||||
|
This is also used to switch on air cushions and the like.
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
static int controlMotor(pECBMotDriv self, int enable){
|
||||||
|
int status, delay, control;
|
||||||
|
Z80_reg in, out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
nothing to do if we are not in control
|
||||||
|
*/
|
||||||
|
control = (int)rint(ObVal(self->driverPar,CONTROL));
|
||||||
|
if(!(control & 1)){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay = (int)rint(ObVal(self->driverPar,DELAY));
|
||||||
|
if(enable == 1){
|
||||||
|
/*
|
||||||
|
enabling
|
||||||
|
*/
|
||||||
|
in.e = 12; /* 8 + 4 */
|
||||||
|
in.b = 11; /* set control signal */
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
wait for air cushions to settle
|
||||||
|
*/
|
||||||
|
usleep(delay);
|
||||||
|
return 1;
|
||||||
|
}else {
|
||||||
|
/*
|
||||||
|
disable motor
|
||||||
|
*/
|
||||||
|
in.e = 8;
|
||||||
|
in.b = 11; /* set control signal */
|
||||||
|
in.c = -self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
usleep(delay);
|
||||||
|
in.e = 0;
|
||||||
|
in.b = 11; /* set control signal */
|
||||||
|
in.c = -self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
usleep(delay);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
static int ECBRunTo(void *pData, float newPosition){
|
static int ECBRunTo(void *pData, float newPosition){
|
||||||
pECBMotDriv self = (pECBMotDriv)pData;
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
@ -496,6 +611,20 @@ static int ECBRunTo(void *pData, float newPosition){
|
|||||||
return OKOK;
|
return OKOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
save restartTarget for backlash handling
|
||||||
|
*/
|
||||||
|
self->restartTarget = newPosition;
|
||||||
|
|
||||||
|
/*
|
||||||
|
enable and push up airy cushions
|
||||||
|
*/
|
||||||
|
status = controlMotor(self,1);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
write control data
|
write control data
|
||||||
*/
|
*/
|
||||||
@ -504,7 +633,7 @@ static int ECBRunTo(void *pData, float newPosition){
|
|||||||
in.d |= 32; /* positive direction */
|
in.d |= 32; /* positive direction */
|
||||||
}
|
}
|
||||||
in.d |= 16; /* interrupts */
|
in.d |= 16; /* interrupts */
|
||||||
if(nintf(ObVal(self->driverPar,RANGE)) == 1.){
|
if(rint(ObVal(self->driverPar,RANGE)) == 1.){
|
||||||
in.d |= 64; /* fast speed */
|
in.d |= 64; /* fast speed */
|
||||||
}
|
}
|
||||||
in.c = (unsigned char)self->ecbIndex;
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
@ -517,15 +646,18 @@ static int ECBRunTo(void *pData, float newPosition){
|
|||||||
/*
|
/*
|
||||||
calculate steps
|
calculate steps
|
||||||
*/
|
*/
|
||||||
|
self->restart = 0;
|
||||||
backlash = ObVal(self->driverPar,BACKLASH);
|
backlash = ObVal(self->driverPar,BACKLASH);
|
||||||
if(diff < 0){
|
if(diff < 0){
|
||||||
diff = -diff;
|
diff = -diff;
|
||||||
if(backlash > 0){
|
if(backlash > 0.){
|
||||||
diff += backlash;
|
diff += backlash;
|
||||||
|
self->restart = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(backlash < 0){
|
if(backlash < 0.){
|
||||||
diff -= backlash;
|
diff -= backlash;
|
||||||
|
self->restart = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.result = degree2Step(self,diff);
|
data.result = degree2Step(self,diff);
|
||||||
@ -550,10 +682,36 @@ static int ECBRunTo(void *pData, float newPosition){
|
|||||||
return OKOK;
|
return OKOK;
|
||||||
}
|
}
|
||||||
/*=======================================================================*/
|
/*=======================================================================*/
|
||||||
|
static int checkStatusResponse(pECBMotDriv self, Z80_reg out){
|
||||||
|
|
||||||
|
if(out.c == '\0'){
|
||||||
|
if(out.b & 4) {
|
||||||
|
self->errorCode = ECBINUSE;
|
||||||
|
} else {
|
||||||
|
self->errorCode = ECBREADERROR;
|
||||||
|
}
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(out.b & 128){
|
||||||
|
self->errorCode = ECBMANUELL;
|
||||||
|
return HWFault;
|
||||||
|
} else if(out.b & 32){
|
||||||
|
return HWBusy;
|
||||||
|
} else if(out.b & 64){
|
||||||
|
self->errorCode = ECBINHIBIT;
|
||||||
|
return HWFault;
|
||||||
|
} else if(out.b & 16){
|
||||||
|
self->errorCode = ECBLIMIT;
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
static int ECBGetStatus(void *pData){
|
static int ECBGetStatus(void *pData){
|
||||||
pECBMotDriv self = (pECBMotDriv)pData;
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
Z80_reg in, out;
|
Z80_reg in, out;
|
||||||
int status;
|
int status, result;
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
@ -565,17 +723,24 @@ static int ECBGetStatus(void *pData){
|
|||||||
return HWFault;
|
return HWFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = checkMotorResult(self,out);
|
result = checkStatusResponse(self,out);
|
||||||
if(status == 0){
|
if(result == HWFault || result == HWIdle){
|
||||||
if(self->errorCode == ECBRUNNING){
|
/*
|
||||||
self->errorCode = 0;
|
run down airy cushions ........
|
||||||
return HWBusy;
|
*/
|
||||||
} else {
|
controlMotor(self,0);
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return HWIdle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
take care of backlash.....
|
||||||
|
*/
|
||||||
|
if(result == HWIdle && self->restart == 1){
|
||||||
|
self->restart = 0;
|
||||||
|
ECBRunTo(self,self->restartTarget);
|
||||||
|
return HWBusy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
/*======================================================================*/
|
/*======================================================================*/
|
||||||
static void ECBGetError(void *pData, int *iCode, char *buffer, int bufferlen){
|
static void ECBGetError(void *pData, int *iCode, char *buffer, int bufferlen){
|
||||||
@ -622,7 +787,7 @@ static int ECBTryAndFixIt(void *pData, int iCode, float fNew){
|
|||||||
|
|
||||||
switch(iCode){
|
switch(iCode){
|
||||||
case ECBMANUELL:
|
case ECBMANUELL:
|
||||||
in.d =1 ;
|
in.d = 1 ;
|
||||||
ecbExecute(self->ecb,162,in,&out);
|
ecbExecute(self->ecb,162,in,&out);
|
||||||
result = MOTREDO;
|
result = MOTREDO;
|
||||||
break;
|
break;
|
||||||
@ -644,13 +809,15 @@ static int ECBHalt(void *pData){
|
|||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if(nintf(ObVal(self->driverPar,RANGE)) == 1){
|
if(rint(ObVal(self->driverPar,RANGE)) == 1){
|
||||||
par |= 64;
|
par |= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
in.b = 9;
|
in.b = 9;
|
||||||
in.e = par;
|
in.e = par;
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
ecbExecute(self->ecb,MOPARA,in,&out);
|
ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
self->restart = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*=======================================================================*/
|
/*=======================================================================*/
|
||||||
@ -669,17 +836,88 @@ static int ECBGetDriverPar(void *pData,char *name, float *value){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*=====================================================================*/
|
/*=====================================================================*/
|
||||||
|
static float fixAccTime(float newValue){
|
||||||
|
float corrected, min, diff;
|
||||||
|
int val, possibleValues[4] = { 500, 1000, 2000, 5000}, i;
|
||||||
|
|
||||||
|
val = (int)rint(newValue);
|
||||||
|
min = 9999999.99;
|
||||||
|
for(i = 0; i < 4; i++){
|
||||||
|
diff = val - possibleValues[i];
|
||||||
|
if(ABS(diff) < min){
|
||||||
|
min = ABS(diff);
|
||||||
|
corrected = possibleValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return corrected;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static void setDownloadFlag(pECBMotDriv self, int parNumber){
|
||||||
|
int mustDownload;
|
||||||
|
|
||||||
|
switch(parNumber){
|
||||||
|
case CONTROL:
|
||||||
|
case MULT:
|
||||||
|
case MULTCHAN:
|
||||||
|
case ACCTIME:
|
||||||
|
case ROTDIR:
|
||||||
|
case STARTSPEED:
|
||||||
|
case MAXSPEED:
|
||||||
|
case SLOWAUTO:
|
||||||
|
case SLOWMAN:
|
||||||
|
case DELAY:
|
||||||
|
mustDownload = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mustDownload = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mustDownload && (self->driverPar[MULT].fVal == 0)){
|
||||||
|
self->driverPar[MULT].fVal = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static int putMotorPosition(pECBMotDriv self, float newValue){
|
||||||
|
Z80_reg in,out;
|
||||||
|
Ecb_pack data;
|
||||||
|
float oldPos;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if(ABS(ObVal(self->driverPar,ENCODER)) > .1){
|
||||||
|
status = ECBMOTGetPos(self,&oldPos);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return loadOffset(self,oldPos - newValue);
|
||||||
|
} else {
|
||||||
|
data.result = newValue*ObVal(self->driverPar,STEPS2DEG);
|
||||||
|
in.b = data.b.byt2;
|
||||||
|
in.d = data.b.byt1;
|
||||||
|
in.e = data.b.byt0;
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,142,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!checkMotorResult(self, out)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
static int ECBSetDriverPar(void *pData, SConnection *pCon, char *name,
|
static int ECBSetDriverPar(void *pData, SConnection *pCon, char *name,
|
||||||
float newValue){
|
float newValue){
|
||||||
pECBMotDriv self = (pECBMotDriv)pData;
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
int parNumber;
|
int parNumber, speedNumber, actualSpeed, status;
|
||||||
char pBueffel[256];
|
char pBueffel[256];
|
||||||
float correctedValue;
|
float correctedValue;
|
||||||
|
|
||||||
parNumber = ObParIndex(self->driverPar,name);
|
assert(self);
|
||||||
if(parNumber < 0){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
only managers shall edit these parameters....
|
only managers shall edit these parameters....
|
||||||
@ -687,9 +925,255 @@ static int ECBSetDriverPar(void *pData, SConnection *pCon, char *name,
|
|||||||
if(!SCMatchRights(pCon,usMugger)){
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is rather a command and forces a parameter download
|
||||||
|
to the ECB
|
||||||
|
*/
|
||||||
|
if(strcmp(name,"download") == 0){
|
||||||
|
status = downloadECBParam(self);
|
||||||
|
if(status != 1){
|
||||||
|
ECBGetError(self,&actualSpeed, pBueffel,254);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
this is another command and assigns a position to the current
|
||||||
|
motor place
|
||||||
|
*/
|
||||||
|
if(strcmp(name,"putpos") == 0){
|
||||||
|
status = putMotorPosition(self,newValue);
|
||||||
|
if(status != 1){
|
||||||
|
ECBGetError(self,&actualSpeed, pBueffel,254);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
get the parameter number
|
||||||
|
*/
|
||||||
|
parNumber = ObParIndex(self->driverPar,name);
|
||||||
|
if(parNumber < 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
make these parameters right, at least as far as we can .......
|
||||||
|
*/
|
||||||
|
switch(parNumber){
|
||||||
|
case ACCTIME:
|
||||||
|
correctedValue = fixAccTime(newValue);
|
||||||
|
break;
|
||||||
|
case STARTSPEED:
|
||||||
|
getSpeedIndex(rint(newValue),1,&actualSpeed);
|
||||||
|
correctedValue = actualSpeed;
|
||||||
|
if(correctedValue < 10){
|
||||||
|
correctedValue = 10;
|
||||||
|
}
|
||||||
|
if(correctedValue > 4400){
|
||||||
|
correctedValue = 4400;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MAXSPEED:
|
||||||
|
getSpeedIndex(rint(newValue),1,&actualSpeed);
|
||||||
|
correctedValue = actualSpeed;
|
||||||
|
break;
|
||||||
|
case SLOWAUTO:
|
||||||
|
case SLOWMAN:
|
||||||
|
getSpeedIndex(rint(newValue),0,&actualSpeed);
|
||||||
|
correctedValue = actualSpeed;
|
||||||
|
if(correctedValue > 500){
|
||||||
|
correctedValue = 500;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DELAY:
|
||||||
|
correctedValue = newValue;
|
||||||
|
if(correctedValue > 2500){
|
||||||
|
correctedValue = 2500;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RANGE:
|
||||||
|
correctedValue = newValue;
|
||||||
|
if(correctedValue != 0.0 && correctedValue != 1.0){
|
||||||
|
correctedValue = .0; /* slow by default! */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ENCODER:
|
||||||
|
if(newValue < 0. || newValue > 3.){
|
||||||
|
SCWrite(pCon,"ERROR: encoder numbers can only be 0 - 3", eError);
|
||||||
|
return 0;
|
||||||
|
} else if(newValue == 0){
|
||||||
|
correctedValue = newValue;
|
||||||
|
} else {
|
||||||
|
ecbAssignEncoder(self->ecb,(int)newValue, self->ecbIndex);
|
||||||
|
correctedValue = newValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STEPS2DEG:
|
||||||
|
case DEG2STEP:
|
||||||
|
if(ABS(newValue) < .1){
|
||||||
|
correctedValue = 1.;
|
||||||
|
} else {
|
||||||
|
correctedValue = newValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OFFSET:
|
||||||
|
correctedValue = newValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
correctedValue = newValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ABS(correctedValue - newValue) > 0.){
|
||||||
|
sprintf(pBueffel,"WARNING: Illegal value %6.2f verbosely coerced to %6.2f",
|
||||||
|
newValue,correctedValue);
|
||||||
|
SCWrite(pCon,pBueffel,eWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObParSet(self->driverPar,self->name,name,correctedValue,pCon);
|
||||||
|
|
||||||
|
setDownloadFlag(self,parNumber);
|
||||||
|
|
||||||
assert(self);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*=========================================================================*/
|
||||||
|
static void ECBListPar(void *pData, char *motorName, SConnection *pCon){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
char pBueffel[256];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < MAXPAR-1; i++){
|
||||||
|
sprintf(pBueffel,"%s.%s = %f",
|
||||||
|
motorName,self->driverPar[i].name,
|
||||||
|
self->driverPar[i].fVal);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*========================================================================*/
|
||||||
|
static int interpretArguments(pECBMotDriv self, SConnection *pCon,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
char pBueffel[256];
|
||||||
|
TokenList *pList, *pCurrent;
|
||||||
|
|
||||||
|
pList = SplitArguments(argc,argv);
|
||||||
|
if(!pList || argc < 4){
|
||||||
|
SCWrite(pCon,"ERROR: no arguments to CreateECBMotor",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pCurrent = pList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
first should be the name of the ECB to use
|
||||||
|
*/
|
||||||
|
if(pCurrent->Type != eText){
|
||||||
|
sprintf(pBueffel,"ERROR: expected EDB name, got: %s",
|
||||||
|
pCurrent->text);
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->ecb = (pECB)FindCommandData(pServ->pSics,pCurrent->text,"ECB");
|
||||||
|
if(!self->ecb){
|
||||||
|
sprintf(pBueffel,"ERROR: %s is no ECB controller",pCurrent->text);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
next the motor number
|
||||||
|
*/
|
||||||
|
pCurrent = pCurrent->pNext;
|
||||||
|
if(pCurrent->Type != eInt){
|
||||||
|
sprintf(pBueffel,"ERROR: expected int motor number, got %s",
|
||||||
|
pCurrent->text);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->ecbIndex = pCurrent->iVal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
next the limits
|
||||||
|
*/
|
||||||
|
pCurrent = pCurrent->pNext;
|
||||||
|
if(pCurrent->Type != eFloat){
|
||||||
|
sprintf(pBueffel,"ERROR: expected float type limit, got %s",
|
||||||
|
pCurrent->text);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->fLower = pCurrent->fVal;
|
||||||
|
pCurrent = pCurrent->pNext;
|
||||||
|
if(pCurrent->Type != eFloat){
|
||||||
|
sprintf(pBueffel,"ERROR: expected float type limit, got %s",
|
||||||
|
pCurrent->text);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->fUpper = pCurrent->fVal;
|
||||||
|
DeleteTokenList(pList);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static void initializeParameters(pECBMotDriv self){
|
||||||
|
ObParInit(self->driverPar,ENCODER,"encoder",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,CONTROL,"control",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,RANGE,"range",1,usMugger);
|
||||||
|
ObParInit(self->driverPar,MULT,"multi",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,MULTCHAN,"multchan",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,ACCTIME,"acceleration",500,usMugger);
|
||||||
|
ObParInit(self->driverPar,ROTDIR,"rotation_dir",1,usMugger);
|
||||||
|
ObParInit(self->driverPar,STARTSPEED,"startspeed",100,usMugger);
|
||||||
|
ObParInit(self->driverPar,MAXSPEED,"maxspeed",2000,usMugger);
|
||||||
|
ObParInit(self->driverPar,SLOWAUTO,"auto",100,usMugger);
|
||||||
|
ObParInit(self->driverPar,SLOWMAN,"manuell",100,usMugger);
|
||||||
|
ObParInit(self->driverPar,DELAY,"delay",50,usMugger);
|
||||||
|
ObParInit(self->driverPar,OFFSET,"offset",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,TOLERANCE,"dtolerance",0.,usMugger);
|
||||||
|
ObParInit(self->driverPar,STEPS2DEG,"step2deg",1,usMugger);
|
||||||
|
ObParInit(self->driverPar,DEG2STEP,"step2dig",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,BACKLASH,"backlash",0,usMugger);
|
||||||
|
ObParInit(self->driverPar,MAXPAR-1,"tueet",-100,-100); /* sentinel! */
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
MotorDriver *CreateECBMotor(SConnection *pCon, int argc, char *argv[]){
|
||||||
|
pECBMotDriv self = NULL;
|
||||||
|
|
||||||
|
self = (pECBMotDriv)malloc(sizeof(ECBMOTDriv));
|
||||||
|
if(self == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(self,0,sizeof(ECBMOTDriv));
|
||||||
|
|
||||||
|
if(!interpretArguments(self,pCon,argc,argv)){
|
||||||
|
free(self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeParameters(self);
|
||||||
|
|
||||||
|
/*
|
||||||
|
set function pointers
|
||||||
|
*/
|
||||||
|
self->GetPosition = ECBMOTGetPos;
|
||||||
|
self->RunTo = ECBRunTo;
|
||||||
|
self->GetStatus = ECBGetStatus;
|
||||||
|
self->GetError = ECBGetError;
|
||||||
|
self->TryAndFixIt = ECBTryAndFixIt;
|
||||||
|
self->Halt = ECBHalt;
|
||||||
|
self->GetDriverPar = ECBGetDriverPar;
|
||||||
|
self->SetDriverPar = ECBSetDriverPar;
|
||||||
|
self->ListDriverPar = ECBListPar;
|
||||||
|
|
||||||
|
self->errorCode = 0;
|
||||||
|
return (MotorDriver *)self;
|
||||||
|
}
|
||||||
|
48
motor.c
48
motor.c
@ -12,6 +12,9 @@
|
|||||||
endscript facility added: Mark Koennecke, August 2002
|
endscript facility added: Mark Koennecke, August 2002
|
||||||
Modified to support driver parameters, Mark Koennecke, January 2003
|
Modified to support driver parameters, Mark Koennecke, January 2003
|
||||||
|
|
||||||
|
TODO: currently motor drivers have to be installed in MakeMotor
|
||||||
|
and remembered in KillMotor. Sort this some day!
|
||||||
|
|
||||||
Copyright:
|
Copyright:
|
||||||
|
|
||||||
Labor fuer Neutronenstreuung
|
Labor fuer Neutronenstreuung
|
||||||
@ -463,6 +466,10 @@ extern void KillPiPiezo(void *pData);
|
|||||||
{
|
{
|
||||||
KillPiPiezo((void *)pM->pDriver);
|
KillPiPiezo((void *)pM->pDriver);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(pM->drivername,"ECB") == 0)
|
||||||
|
{
|
||||||
|
free(pM->pDriver);
|
||||||
|
}
|
||||||
free(pM->drivername);
|
free(pM->drivername);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,6 +537,19 @@ extern void KillPiPiezo(void *pData);
|
|||||||
assert(self);
|
assert(self);
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
|
/*
|
||||||
|
try set driver parameters
|
||||||
|
*/
|
||||||
|
if(self->pDriver->SetDriverPar != NULL)
|
||||||
|
{
|
||||||
|
iRet = self->pDriver->SetDriverPar(self->pDriver,pCon,name,fVal);
|
||||||
|
if(iRet == 1)
|
||||||
|
{
|
||||||
|
return iRet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(strcmp(name,"softzero") == 0)
|
if(strcmp(name,"softzero") == 0)
|
||||||
{
|
{
|
||||||
/* set it first, this also tests the necessary privileges */
|
/* set it first, this also tests the necessary privileges */
|
||||||
@ -571,16 +591,6 @@ extern void KillPiPiezo(void *pData);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
try set driver parameters
|
|
||||||
*/
|
|
||||||
if(iRet == 0)
|
|
||||||
{
|
|
||||||
if(self->pDriver->SetDriverPar != NULL)
|
|
||||||
{
|
|
||||||
iRet = self->pDriver->SetDriverPar(self->pDriver,pCon,name,fVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
@ -866,6 +876,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||||
|
extern MotorDriver *CreateECBMotor(SConnection *pCon, int argc, char *argv[]);
|
||||||
|
|
||||||
int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -906,6 +917,23 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(strcmp(argv[2],"ecb") == 0)
|
||||||
|
{
|
||||||
|
iD = argc - 3;
|
||||||
|
pDriver = CreateECBMotor(pCon,iD,&argv[3]);
|
||||||
|
if(!pDriver)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* create the motor */
|
||||||
|
pNew = MotorInit("ECB",argv[1],pDriver);
|
||||||
|
if(!pNew)
|
||||||
|
{
|
||||||
|
sprintf(pBueffel,"Failure to create motor %s",argv[1]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(strcmp(argv[2],"el734dc") == 0)
|
else if(strcmp(argv[2],"el734dc") == 0)
|
||||||
{
|
{
|
||||||
iD = argc - 3;
|
iD = argc - 3;
|
||||||
|
1
nigpib.c
1
nigpib.c
@ -103,4 +103,5 @@ void NIassign(pGPIB self){
|
|||||||
self->send = NIwrite;
|
self->send = NIwrite;
|
||||||
self->read = NIread;
|
self->read = NIread;
|
||||||
self->getErrorDescription = NIerror;
|
self->getErrorDescription = NIerror;
|
||||||
|
self->clear = NIclear;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,14 @@ a77 SoftUpperLim 30.000000
|
|||||||
a77 Fixed -1.000000
|
a77 Fixed -1.000000
|
||||||
a77 InterruptMode 0.000000
|
a77 InterruptMode 0.000000
|
||||||
a77 AccessCode 2.000000
|
a77 AccessCode 2.000000
|
||||||
|
# Motor 2t
|
||||||
|
2t sign 1.000000
|
||||||
|
2t SoftZero 0.000000
|
||||||
|
2t SoftLowerLim -120.000000
|
||||||
|
2t SoftUpperLim 120.000000
|
||||||
|
2t Fixed -1.000000
|
||||||
|
2t InterruptMode 0.000000
|
||||||
|
2t AccessCode 2.000000
|
||||||
samplename KohlSulfid
|
samplename KohlSulfid
|
||||||
samplename setAccess 2
|
samplename setAccess 2
|
||||||
comment UNKNOWN
|
comment UNKNOWN
|
||||||
|
Reference in New Issue
Block a user