Added IPS Driver M.Z.
This commit is contained in:
844
ipsdriv.c
Normal file
844
ipsdriv.c
Normal file
@ -0,0 +1,844 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
I P S D R I V . C
|
||||
|
||||
Driver for the Oxford Instruments IPS/PS magnet power supply.
|
||||
|
||||
Markus Zolliker, June 2004
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <tcl.h>
|
||||
#include <fortify.h>
|
||||
#include <sics.h>
|
||||
#include <splitter.h>
|
||||
#include <obpar.h>
|
||||
#include <devexec.h>
|
||||
#include <nserver.h>
|
||||
#include <interrupt.h>
|
||||
#include <emon.h>
|
||||
#include <evcontroller.h>
|
||||
#include <evcontroller.i>
|
||||
#include <servlog.h>
|
||||
#include <sicsvar.h>
|
||||
#include <evdriver.i>
|
||||
#include <rs232controller.h>
|
||||
|
||||
typedef enum {
|
||||
IPS_INIT,
|
||||
IPS_IDLE,
|
||||
IPS_START,
|
||||
IPS_WAIT,
|
||||
IPS_UP,
|
||||
IPS_STAB1,
|
||||
IPS_START_RAMP,
|
||||
IPS_RAMP,
|
||||
IPS_STAB2,
|
||||
IPS_DOWN
|
||||
} rampState;
|
||||
|
||||
typedef struct {
|
||||
rs232 *ser; /* serial connection */
|
||||
int errCode;
|
||||
int isPS; /* is an old PS-120 instead of an IPS-120 */
|
||||
rampState state;
|
||||
float target; /* target field */
|
||||
float field; /* actual field */
|
||||
float ramp; /* actual ramp rate */
|
||||
int persmode; /* 0: leave switch on, 1: go to persistant mode */
|
||||
int perswitch; /* state of switch */
|
||||
int force; /* flag: put heater switch even when stored field not matched */
|
||||
float forcedfield; /* field user thinks is in magnet */
|
||||
int verbose; /* verbosity 0..2 */
|
||||
int settle; /* settling time/4 */
|
||||
int stabilize; /* do we need to stabilize ? */
|
||||
time_t tim; /* time when last switching the heater */
|
||||
float voltage[4]; /* voltage history */
|
||||
char xstat[32]; /* status response */
|
||||
char msg[2048]; /* a message to return */
|
||||
} IpsDriv;
|
||||
|
||||
#define OX_ILL_ANS -3000
|
||||
#define OX_ILL_FLD -3001
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void IpsSay(IpsDriv *me, int verbosity, char *fmt, ...) {
|
||||
va_list ap;
|
||||
int iRet, l;
|
||||
|
||||
if (verbosity <= me->verbose) {
|
||||
l=strlen(me->msg);
|
||||
if (l > 0 && l < sizeof(me->msg)-1) {
|
||||
strcat(me->msg, "\n");
|
||||
l++;
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(me->msg+l, sizeof(me->msg)-l, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void IpsWriteError(IpsDriv *me) {
|
||||
switch (me->errCode) {
|
||||
case NOTCONNECTED:
|
||||
IpsSay(me, 0, "terminalserver for IPS not connected");
|
||||
break;
|
||||
case FAILEDCONNECT:
|
||||
IpsSay(me, 0, "can not connect to IPS");
|
||||
break;
|
||||
case TIMEOUT:
|
||||
IpsSay(me, 0, "IPS not properly connected");
|
||||
break;
|
||||
case INCOMPLETE:
|
||||
IpsSay(me, 0, "incomplete answer from IPS");
|
||||
break;
|
||||
case OX_ILL_ANS:
|
||||
IpsSay(me, 0, "illegal answer from IPS");
|
||||
break;
|
||||
default:
|
||||
IpsSay(me, 0, "error code %d", me->errCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static char *IpsCmd(IpsDriv *me, char *cmd, int *ret) {
|
||||
int iret;
|
||||
static char buf[32];
|
||||
*ret=transactRS232(me->ser, cmd, strlen(cmd), buf, sizeof(buf));
|
||||
IpsSay(me, 2, "command: %s, answer: %s", cmd, buf);
|
||||
if (*ret != 1) {
|
||||
if (*ret == 0) {
|
||||
*ret == 1;
|
||||
IpsSay(me, 0, "IPS: unknown RS232 error");
|
||||
} else {
|
||||
IpsWriteError(me);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (buf[0] != cmd[0]) {
|
||||
IpsSay(me, 0, "command: %s, answer: %s", cmd, buf);
|
||||
*ret=OX_ILL_ANS;
|
||||
IpsWriteError(me);
|
||||
} else {
|
||||
*ret=0;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static float IpsRead(IpsDriv *me, char *cmd, int fmt, int *ret) {
|
||||
char *buf;
|
||||
float val;
|
||||
|
||||
buf=IpsCmd(me, cmd, ret);
|
||||
if (*ret) return 0.0;
|
||||
if (me->isPS) { /* no decimal point expected */
|
||||
val=atoi(buf+1);
|
||||
for (; fmt>0; fmt--) val=val*0.1;
|
||||
} else {
|
||||
val=atof(buf+1);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static char *IpsStatus(IpsDriv *me, int *ret) {
|
||||
char *ans;
|
||||
ans=IpsCmd(me, "X", ret);
|
||||
if (*ret) return me->xstat;
|
||||
strncpy(me->xstat, ans, sizeof(me->xstat));
|
||||
me->xstat[sizeof(me->xstat)-1]='\0';
|
||||
return me->xstat;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsCheckField(IpsDriv *me, char *name, int *ret) {
|
||||
float fld;
|
||||
if (strstr(me->xstat, "H1")==NULL) {
|
||||
me->perswitch=0;
|
||||
fld=IpsRead(me, "R18", 3, ret); /* read persistant field */
|
||||
if (fabs(fld - me->field) >= 1e-5) {
|
||||
IpsSay(me, 0, "\nit is not sure which field is in the magnet\n"
|
||||
"value stored in power supply: %f\n"
|
||||
" in sics: %f\n"
|
||||
"use command\n \n %s confirm ...\n \n"
|
||||
"to specify the persistent field\n \n"
|
||||
, fld, me->field, name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
me->perswitch=1;
|
||||
fld=IpsRead(me, "R7", 3, ret); /* read actual field */
|
||||
me->field=fld;
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void IpsSet(IpsDriv *me, char *cmd, float val, int fmt, int *ret) {
|
||||
char buf[64];
|
||||
|
||||
if (me->isPS) {
|
||||
for (;fmt>0;fmt--) val=val*10;
|
||||
snprintf(buf, sizeof(buf), "%s%05d", cmd, val);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%s%f", cmd, val);
|
||||
}
|
||||
IpsCmd(me, buf, ret);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsIsStable(IpsDriv *me) {
|
||||
/* returns 1 when 4 subsequent readings within 0.01 Volts.
|
||||
the timeinterval for the readings is specified with me->settle */
|
||||
|
||||
time_t now;
|
||||
float v, vmin, vmax;
|
||||
int i;
|
||||
int *ret;
|
||||
|
||||
assert(me);
|
||||
ret=&me->errCode;
|
||||
time(&now);
|
||||
now = now / me->settle;
|
||||
v = IpsRead(me, "R1", 2, ret); /* voltage */
|
||||
if (*ret) return 0;
|
||||
i = now % 4;
|
||||
me->voltage[i] = v;
|
||||
vmin=me->voltage[0];
|
||||
vmax=vmin;
|
||||
for (i=1; i<4; i++) {
|
||||
if (me->voltage[i] < vmin) vmin = me->voltage[i];
|
||||
if (me->voltage[i] > vmax) vmax = me->voltage[i];
|
||||
}
|
||||
return (fabs(vmax-vmin) < 0.015);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsWait(IpsDriv *me) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (now < me->tim + 30) { /* we have to wait for stabilizing the switch heater */
|
||||
IpsSay(me, 2, "waiting %d sec", me->tim + 30 - now);
|
||||
if (strstr(me->xstat, "H5")!=NULL && now > me->tim+5) {
|
||||
IpsSay(me, 0, "IPS: switch heater is not connected");
|
||||
me->state=IPS_IDLE;
|
||||
return HWFault;
|
||||
}
|
||||
if (now < me->tim+30) return HWBusy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsStepper(void *evcV, SConnection *pCon) {
|
||||
pEVControl evc;
|
||||
pEVDriver self;
|
||||
IpsDriv *me;
|
||||
int *ret;
|
||||
float fld;
|
||||
float step;
|
||||
float ramp;
|
||||
int i;
|
||||
int swi;
|
||||
int hwstate;
|
||||
char *ans;
|
||||
time_t now;
|
||||
|
||||
evc=evcV;
|
||||
assert(evc);
|
||||
self=evc->pDriv;
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
me->msg[0]='\0';
|
||||
me->errCode=0;
|
||||
ret=&me->errCode;
|
||||
|
||||
/* check status */
|
||||
if (me->state == IPS_IDLE) {
|
||||
hwstate = HWIdle;
|
||||
} else {
|
||||
hwstate = HWBusy;
|
||||
ans = IpsStatus(me, ret);
|
||||
if (*ret) goto error;
|
||||
if (strstr(ans, "X00") != ans
|
||||
|| strchr(ans, 'A') == NULL
|
||||
|| strchr(ans, 'C') == NULL
|
||||
|| strchr(ans, 'H') == NULL
|
||||
|| strchr(ans, 'M') == NULL
|
||||
|| strchr(ans, 'P') == NULL) {
|
||||
IpsSay(me, 0, "IPS illegal status: %s", ans);
|
||||
goto error;
|
||||
}
|
||||
if (strstr(ans, "C3") == NULL && me->state > IPS_START) {
|
||||
IpsSay(me, 0, "IPS switched to local - stopped");
|
||||
IpsCmd(me, "C0", ret);
|
||||
goto error;
|
||||
}
|
||||
if (evc->iStop) {
|
||||
IpsSay(me, 0, "IPS stopped");
|
||||
IpsCmd(me, "C0", ret);
|
||||
me->state = IPS_IDLE;
|
||||
hwstate = HWIdle;
|
||||
}
|
||||
}
|
||||
|
||||
switch (me->state) {
|
||||
case IPS_START:
|
||||
swi=IpsCheckField(me, evc->pName, ret);
|
||||
if (*ret) goto error;
|
||||
if (swi < 0) {
|
||||
*ret=1;
|
||||
goto error;
|
||||
}
|
||||
if (fabs(evc->fTarget - me->field) < 1e-5 && me->perswitch != me->persmode) {
|
||||
IpsSay(me, 1, "IPS: we are already at field %f", me->field);
|
||||
me->state = IPS_IDLE;
|
||||
hwstate = HWIdle;
|
||||
break;
|
||||
}
|
||||
IpsCmd(me, "C3", ret);
|
||||
if (*ret) goto error;
|
||||
IpsCmd(me, "F7", ret); /* show current in Tesla */
|
||||
if (*ret) goto error;
|
||||
IpsCmd(me, "A0", ret); /* hold */
|
||||
if (*ret) goto error;
|
||||
if (swi < 0) {
|
||||
*ret=OX_ILL_FLD;
|
||||
goto error;
|
||||
}
|
||||
me->stabilize=0;
|
||||
if (!me->perswitch) {
|
||||
fld=IpsRead(me, "R7", 3, ret); /* read actual current (in Tesla) */
|
||||
if (*ret) goto error;
|
||||
if (fabs(fld - me->field) >= 1e-5) {
|
||||
me->stabilize=1;
|
||||
time(&now);
|
||||
if (now < me->tim+30) {
|
||||
IpsSay(me, 1, "IPS: wait until heat switch is open");
|
||||
}
|
||||
}
|
||||
}
|
||||
me->state=IPS_WAIT;
|
||||
/* fall through */
|
||||
|
||||
case IPS_WAIT:
|
||||
if (me->stabilize) {
|
||||
i=IpsWait(me);
|
||||
if (i) { hwstate=i; break; }
|
||||
IpsSet(me, "J", me->field, 3, ret); /* set point */
|
||||
if (*ret) goto error;
|
||||
IpsSay(me, 1, "IPS: ramp to current for %f Tesla", me->field);
|
||||
IpsCmd(me, "A1", ret); /* go to setpoint */
|
||||
if (*ret) goto error;
|
||||
for (i=0; i<4; i++) { /* initialize voltage history */
|
||||
me->voltage[i] = 10*i; /* just some dirty values */
|
||||
}
|
||||
}
|
||||
me->state = IPS_UP;
|
||||
/* fall through */
|
||||
|
||||
case IPS_UP:
|
||||
fld=IpsRead(me, "R7", 3, ret); /* read actual field */
|
||||
if (fabs(fld - me->field) > 1e-5) break;
|
||||
me->state = IPS_STAB1;
|
||||
if (me->stabilize) {
|
||||
IpsSay(me, 1, "IPS: stabilize");
|
||||
}
|
||||
|
||||
case IPS_STAB1:
|
||||
if (me->stabilize && ! IpsIsStable(me)) break;
|
||||
|
||||
me->state=IPS_START_RAMP;
|
||||
if (strstr(me->xstat, "H1")==NULL) {
|
||||
if (me->force==2) {
|
||||
IpsCmd(me, "H2", ret);
|
||||
} else {
|
||||
IpsCmd(me, "H1", ret);
|
||||
}
|
||||
if (*ret) goto error;
|
||||
me->perswitch = 1;
|
||||
me->force = 0;
|
||||
time(&me->tim);
|
||||
IpsSay(me, 1, "IPS: wait until heat switch is open");
|
||||
break;
|
||||
}
|
||||
me->perswitch = 1;
|
||||
me->force=0;
|
||||
/* fall through */
|
||||
|
||||
case IPS_START_RAMP:
|
||||
i=IpsWait(me);
|
||||
if (i) { hwstate=i; break; }
|
||||
IpsSet(me, "T", me->ramp, 3, ret);
|
||||
if (*ret) goto error;
|
||||
IpsSay(me, 1, "IPS: ramp to %f Tesla", evc->fTarget);
|
||||
|
||||
IpsCmd(me, "A1", ret);
|
||||
if (*ret) goto error;
|
||||
me->state=IPS_RAMP;
|
||||
/* fall through */
|
||||
|
||||
case IPS_RAMP:
|
||||
ramp=IpsRead(me, "R9", 3, ret); /* read ramp rate */
|
||||
if (*ret) goto error;
|
||||
me->field=IpsRead(me, "R7", 3, ret); /* read "current" in Tesla */
|
||||
if (*ret) goto error;
|
||||
step=ramp/20; /* step = ramp * 3sec */
|
||||
if (step < 0.001) step=0.001;
|
||||
if (evc->fTarget > me->field + step) {
|
||||
fld=me->field + step;
|
||||
} else if (evc->fTarget < me->field - step) {
|
||||
fld=me->field - step;
|
||||
} else {
|
||||
fld=evc->fTarget;
|
||||
if (fabs(me->field - evc->fTarget) < 1e-5) {
|
||||
IpsCmd(me, "A0", ret);
|
||||
if (!me->persmode) {
|
||||
IpsCmd(me, "C0", ret);
|
||||
if (*ret) goto error;
|
||||
me->state = IPS_IDLE;
|
||||
hwstate = HWIdle;
|
||||
break;
|
||||
}
|
||||
for (i=0; i<4; i++) { /* initialize voltage history */
|
||||
me->voltage[i]=10*i; /* just some dirty values */
|
||||
}
|
||||
me->state = IPS_STAB2;
|
||||
IpsSay(me, 1, "IPS: stabilize");
|
||||
}
|
||||
}
|
||||
IpsSet(me, "J", fld, 3, ret);
|
||||
if (*ret) goto error;
|
||||
break;
|
||||
|
||||
case IPS_STAB2:
|
||||
evc->eMode = EVMonitor;
|
||||
if (!me->persmode || IpsIsStable(me)) {
|
||||
IpsSay(me, 1, "IPS: wait until heat switch is closed");
|
||||
IpsCmd(me, "H0", ret);
|
||||
if (*ret) goto error;
|
||||
me->perswitch = 0;
|
||||
time(&me->tim);
|
||||
me->state = IPS_DOWN;
|
||||
}
|
||||
hwstate = HWIdle;
|
||||
break;
|
||||
|
||||
case IPS_DOWN:
|
||||
hwstate = HWIdle;
|
||||
i=IpsWait(me);
|
||||
if (i) {
|
||||
if (i == HWFault) {
|
||||
hwstate = HWFault;
|
||||
}
|
||||
} else {
|
||||
IpsSay(me, 1, "IPS: ramp current down");
|
||||
IpsCmd(me, "A2", ret);
|
||||
if (*ret) goto error;
|
||||
IpsCmd(me, "C0", ret);
|
||||
if (*ret) goto error;
|
||||
me->state = IPS_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
error:
|
||||
if (*ret) {
|
||||
me->state = IPS_IDLE;
|
||||
hwstate=HWFault;
|
||||
}
|
||||
if (me->msg[0] != '\0') {
|
||||
if (pCon != NULL) {
|
||||
SCWrite(pCon, me->msg, eWarning);
|
||||
} else {
|
||||
ServerWriteGlobal(me->msg, eWarning);
|
||||
}
|
||||
me->msg[0]='\0';
|
||||
}
|
||||
return hwstate;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int IpsWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]) {
|
||||
pEVControl self = NULL;
|
||||
char cmd[256], result[256], *res;
|
||||
int iRet, *ret;
|
||||
pEVDriver pD;
|
||||
IpsDriv *me;
|
||||
float fVal, fVal2, pf;
|
||||
|
||||
self = (pEVControl)pData;
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
if (argc < 2) {
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
||||
pD=self->pDriv; assert(pD);
|
||||
me=pD->pPrivate; assert(me);
|
||||
me->msg[0]='\0';
|
||||
ret=&me->errCode;
|
||||
|
||||
if (strlen(argv[1]) >= sizeof(cmd)) {
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
||||
strcpy(cmd, argv[1]);
|
||||
strtolower(cmd);
|
||||
if (0==strcmp(cmd, "ramp")) {
|
||||
if (argc > 2) {
|
||||
me->ramp=atof(argv[2]);
|
||||
}
|
||||
sprintf(result, "%f", me->ramp);
|
||||
} else if (0==strcmp(cmd, "limit")) {
|
||||
if (argc == 2) {
|
||||
fVal=ObVal(self->pParam, UPLIMIT);
|
||||
fVal2=ObVal(self->pParam, LOWLIMIT);
|
||||
if (-fVal2 > fVal) fVal=fVal2;
|
||||
} else {
|
||||
fVal=atof(argv[2]);
|
||||
iRet = EVCSetPar(self, "upperlimit", fabs(fVal),pCon);
|
||||
if (!iRet) { *ret=1; goto error; }
|
||||
iRet = EVCSetPar(self, "lowerlimit", fVal,pCon);
|
||||
if (!iRet) { *ret=1; goto error; }
|
||||
}
|
||||
sprintf(result, "%f", fVal);
|
||||
} else if (0==strcmp(cmd, "persmode")) {
|
||||
if (argc > 2) {
|
||||
me->persmode = atoi(argv[2]);
|
||||
}
|
||||
sprintf(result, "%d", me->persmode);
|
||||
} else if (0==strcmp(cmd, "verbose")) {
|
||||
if (argc > 2) {
|
||||
me->verbose = atoi(argv[2]);
|
||||
}
|
||||
sprintf(result, "%d", me->verbose);
|
||||
} else if (0==strcmp(cmd, "list")) {
|
||||
IpsStatus(me, ret);
|
||||
if (*ret) goto error;
|
||||
IpsCheckField(me, self->pName, ret);
|
||||
if (*ret) goto error;
|
||||
IpsSay(me, 0, "%s.%s = %.0f", self->pName, "access", ObVal(self->pParam, ACCESS));
|
||||
IpsSay(me, 0, "%s.%s = %.0f", self->pName, "ErrorHandler", ObVal(self->pParam, ERRORHANDLER));
|
||||
IpsSay(me, 0, "%s.%s = %.0f", self->pName, "interrupt", ObVal(self->pParam, INTERRUPT));
|
||||
IpsSay(me, 0, "%s.%s = %d", self->pName, "persmode", me->persmode);
|
||||
IpsSay(me, 0, "%s.%s = %d", self->pName, "perswitch", me->perswitch);
|
||||
IpsSay(me, 0, "%s.%s = %d", self->pName, "verbose", me->verbose);
|
||||
fVal=ObVal(self->pParam, UPLIMIT);
|
||||
fVal2=ObVal(self->pParam, LOWLIMIT);
|
||||
if (-fVal2 > fVal) fVal=fVal2;
|
||||
IpsSay(me, 0, "%s.%s = %f", self->pName, "limit", fVal);
|
||||
IpsSay(me, 0, "%s.%s = %f", self->pName, "ramp", me->ramp);
|
||||
IpsSay(me, 0, "%s.%s = %f", self->pName, "CurrentValue", me->field);
|
||||
IpsSay(me, 0, "%s.%s = %f", self->pName, "TargetValue", self->fTarget);
|
||||
IpsSay(me, 0, "%s.driver = %s", self->pName, self->driverName);
|
||||
if (self->errorScript != NULL) {
|
||||
IpsSay(me, 0, "%s.errorScript = %s", self->pName, self->errorScript);
|
||||
} else {
|
||||
IpsSay(me, 0, "%s.errorScript = UNDEFINED", self->pName);
|
||||
}
|
||||
result[0]='\0';
|
||||
} else if (0==strcmp(cmd, "confirm")) {
|
||||
if (argc > 2) {
|
||||
if (argc > 3) {
|
||||
IpsSay(me, 0, "Too many arguments");
|
||||
goto error;
|
||||
}
|
||||
fVal=atof(argv[2]);
|
||||
if (fVal < ObVal(self->pParam, LOWLIMIT) ||
|
||||
fVal > ObVal(self->pParam, UPLIMIT)) {
|
||||
IpsSay(me, 0, "Field outside limit");
|
||||
goto error;
|
||||
}
|
||||
res=IpsStatus(me, ret);
|
||||
if (*ret) goto error;
|
||||
if (NULL!=strstr(res, "H1")) {
|
||||
pf=IpsRead(me, "R7", 3, ret); /* read actual field */
|
||||
if (*ret) goto error;
|
||||
IpsSay(me, 0, "switch heater is on - field is %f", pf);
|
||||
goto error;
|
||||
}
|
||||
pf=IpsRead(me, "R18", 3, ret); /* read persistant field */
|
||||
if (*ret) goto error;
|
||||
if (fabs(fVal - me->forcedfield) > 1e-5) {
|
||||
me->force=0;
|
||||
}
|
||||
if (me->force==0) {
|
||||
if (fabs(fVal - pf) > 1e-5 && fabs(fVal - me->field) > 1e-5) {
|
||||
IpsSay(me, 0, "Be aware that this does neither match the stored"
|
||||
" field in sics\nnor the field stored in power supply.");
|
||||
}
|
||||
IpsSay(me, 0, "Please repeat this command, to confirm again"
|
||||
" the persistent field of\n %f Tesla.", fVal);
|
||||
me->force=1;
|
||||
result[0]='\0';
|
||||
} else if (me->force=1) {
|
||||
me->force=2;
|
||||
me->field=fVal;
|
||||
sprintf(result, "%f", me->field);
|
||||
}
|
||||
me->forcedfield = fVal;
|
||||
} else {
|
||||
IpsStatus(me, ret);
|
||||
if (*ret) goto error;
|
||||
IpsCheckField(me, self->pName, ret);
|
||||
if (*ret) goto error;
|
||||
sprintf(result, "%f", me->field);
|
||||
}
|
||||
} else {
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
||||
if (result[0] != '\0') {
|
||||
IpsSay(me, 0, "%s.%s = %s", self->pName, argv[1], result);
|
||||
}
|
||||
error:
|
||||
if (me->msg[0] != '\0') {
|
||||
SCWrite(pCon, me->msg, eWarning);
|
||||
me->msg[0]='\0';
|
||||
}
|
||||
if (*ret) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsGet(pEVDriver self, float *fPos) {
|
||||
IpsDriv *me = NULL;
|
||||
int *ret;
|
||||
time_t now;
|
||||
float fld;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
ret=&me->errCode;
|
||||
IpsStatus(me, ret);
|
||||
if (!*ret) {
|
||||
IpsCheckField(me, "magfield", ret);
|
||||
}
|
||||
*fPos=me->field;
|
||||
if(*ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int IpsRun(pEVDriver self, float fVal) {
|
||||
IpsDriv *me;
|
||||
int *ret;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
ret=&me->errCode;
|
||||
IpsStatus(me, ret);
|
||||
if (*ret) return 0;
|
||||
me->state=IPS_START;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int IpsError(pEVDriver self, int *iCode, char *error, int iErrLen) {
|
||||
IpsDriv *me = NULL;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
*iCode = 1; /* severe */
|
||||
if (me->msg[0]=='\0') {
|
||||
strncpy(error, "undefined error", iErrLen);
|
||||
} else {
|
||||
strncpy(error, me->msg, iErrLen);
|
||||
}
|
||||
error[iErrLen-1]='\0';
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int IpsFix(pEVDriver self, int iError) {
|
||||
IpsDriv *me = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
return(DEVFAULT); /* severe */
|
||||
|
||||
/* never used: return(DEVREDO); */
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int IpsSend(pEVDriver self, char *pCommand, char *pReply, int iLen) {
|
||||
IpsDriv *me = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
iRet = transactRS232(me->ser, pCommand, strlen(pCommand), pReply, iLen);
|
||||
if(iRet < 0)
|
||||
{
|
||||
me->errCode = iRet;
|
||||
IpsWriteError(me);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int IpsInit(pEVDriver self) {
|
||||
IpsDriv *me = NULL;
|
||||
int iRet;
|
||||
char *res, buf[128];
|
||||
pExeList exe;
|
||||
SConnection *con;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
iRet = initRS232(me->ser);
|
||||
if (iRet != 1) {
|
||||
me->errCode = iRet;
|
||||
IpsWriteError(me);
|
||||
return 0;
|
||||
}
|
||||
setRS232ReplyTerminator(me->ser,"\r");
|
||||
setRS232SendTerminator(me->ser,"\r");
|
||||
setRS232Timeout(me->ser,1000); /* microseconds ? milliseconds ? */
|
||||
setRS232Debug(me->ser,0);
|
||||
|
||||
iRet=transactRS232(me->ser, "V", 1, buf, sizeof(buf));
|
||||
if (iRet != 1) {
|
||||
if (iRet == 0) {
|
||||
me->errCode = 1;
|
||||
IpsSay(me, 0, "IPS: unknown RS232 error");
|
||||
} else {
|
||||
me->errCode = iRet;
|
||||
IpsWriteError(me);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0==strncmp(buf, "IPS120", 6)) {
|
||||
me->isPS=0;
|
||||
} else if (0==strncmp(buf, "PS120", 5)) {
|
||||
me->isPS=1;
|
||||
} else {
|
||||
IpsSay(me, 0, "unknown power supply version: %s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IpsStatus(me, &iRet);
|
||||
me->msg[0]='\0';
|
||||
IpsCheckField(me, "magfield", &iRet);
|
||||
me->state = IPS_IDLE;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int IpsClose(pEVDriver self) {
|
||||
/*
|
||||
seems not to be needed
|
||||
|
||||
IpsDriv *me = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
me = (IpsDriv *)self->pPrivate;
|
||||
assert(me);
|
||||
|
||||
me->pData=NULL;
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int IpsHalt(pEVDriver *self) {
|
||||
assert(self);
|
||||
/* to be implemented */
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void IpsKill(void *pData) {
|
||||
IpsDriv *me = NULL;
|
||||
|
||||
me = (IpsDriv *)pData;
|
||||
assert(me);
|
||||
KillRS232(me->ser);
|
||||
free(me);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
pEVDriver CreateIpsDriver(int argc, char *argv[]) {
|
||||
pEVDriver new = NULL;
|
||||
IpsDriv *me = NULL;
|
||||
int port;
|
||||
|
||||
if (argc < 2) {
|
||||
return NULL;
|
||||
}
|
||||
new = CreateEVDriver(argc,argv);
|
||||
me = (IpsDriv *)malloc(sizeof(IpsDriv));
|
||||
memset(me,0,sizeof(IpsDriv));
|
||||
if(!new || !me) return NULL;
|
||||
|
||||
new->pPrivate = me;
|
||||
new->KillPrivate = IpsKill;
|
||||
|
||||
/* initalise IpsDriver */
|
||||
/* me->lastError = NULL; */
|
||||
me->verbose = 0;
|
||||
me->field = 0;
|
||||
me->persmode = 1;
|
||||
me->perswitch = 0;
|
||||
me->force = 0;
|
||||
me->tim = 0;
|
||||
me->settle = 1;
|
||||
me->state=IPS_INIT;
|
||||
me->ramp=0.1;
|
||||
me->isPS=0;
|
||||
|
||||
port=atoi(argv[1]);
|
||||
if (port==0) return NULL;
|
||||
|
||||
me->ser=createRS232(argv[0], port);
|
||||
if (me->ser == NULL) return NULL;
|
||||
|
||||
/* initialise function pointers */
|
||||
new->SetValue = IpsRun;
|
||||
new->GetValue = IpsGet;
|
||||
new->Send = IpsSend;
|
||||
new->GetError = IpsError;
|
||||
new->TryFixIt = IpsFix;
|
||||
new->Init = IpsInit;
|
||||
new->Close = IpsClose;
|
||||
|
||||
return new;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int IpsWatcher(void *data) {
|
||||
pEVControl self;
|
||||
pExeList exe;
|
||||
SConnection *con;
|
||||
int iRet;
|
||||
|
||||
assert(data);
|
||||
self= (pEVControl)data;
|
||||
exe = GetExecutor();
|
||||
con = GetExeOwner(exe);
|
||||
iRet = IpsStepper(self, con);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void IpsCustomize(SConnection *pCon, pEVControl pEvc) {
|
||||
/* customize tecs driver */
|
||||
IpsDriv *me;
|
||||
|
||||
me=pEvc->pDriv->pPrivate;
|
||||
assert(me);
|
||||
pEvc->pDrivInt->CheckStatus=IpsStepper;
|
||||
pEvc->pEnvir->IsInTolerance=IpsWatcher;
|
||||
EVCSetPar(pEvc,"upperlimit",14.9,pCon);
|
||||
EVCSetPar(pEvc,"lowerlimit",-14.9,pCon);
|
||||
if (me->msg[0]!='\0') { /* write message from IpsInit */
|
||||
SCWrite(pCon, me->msg, eWarning);
|
||||
}
|
||||
}
|
25
ipsdriv.h
Normal file
25
ipsdriv.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
I P S D R I V . H
|
||||
|
||||
Driver for the Oxford Instruments IPS/PS magnet power supply.
|
||||
|
||||
Markus Zolliker, June 2004
|
||||
|
||||
copyright: see implementation file.
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef SICSIPS
|
||||
#define SICSIPS
|
||||
/*------------------------- The Driver ------------------------------------*/
|
||||
|
||||
pEVDriver CreateIpsDriver(int argc, char *argv[]);
|
||||
|
||||
|
||||
/*------------------------- The Tecs object ------------------------------*/
|
||||
|
||||
int IpsWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
void IpsCustomize(SConnection *pCon, pEVControl pEvc);
|
||||
|
||||
#endif
|
2
make_gen
2
make_gen
@ -18,7 +18,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
|
||||
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
|
||||
el755driv.o amorscan.o serial.o scontroller.o t_update.o \
|
||||
t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \
|
||||
el737hpv2driv.o swmotor2.o
|
||||
el737hpv2driv.o swmotor2.o ipsdriv.o
|
||||
|
||||
libpsi.a: $(OBJ)
|
||||
rm -f libpsi.a
|
||||
|
26
psi.c
26
psi.c
@ -39,6 +39,7 @@
|
||||
#include "tdchm.h"
|
||||
#include "tecsdriv.h"
|
||||
#include "itc4.h"
|
||||
#include "ipsdriv.h"
|
||||
#include "bruker.h"
|
||||
#include "ltc11.h"
|
||||
#include "A1931.h"
|
||||
@ -313,6 +314,8 @@ static void ConfigureController(char *name, pEVControl pNew,
|
||||
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
|
||||
if(strcmp(name,"tecs") == 0){
|
||||
TecsCustomize(pCon, pNew);
|
||||
} else if(strcmp(name,"ips") == 0){
|
||||
IpsCustomize(pCon, pNew);
|
||||
} else if(strcmp(name,"euro") == 0){
|
||||
EVCSetPar(pNew,"upperlimit",750.0,pCon);
|
||||
EVCSetPar(pNew,"lowerlimit",15.0,pCon);
|
||||
@ -367,6 +370,17 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
|
||||
commandInstalled = 1;
|
||||
}
|
||||
}
|
||||
} else if(strcmp(argv[3],"ips") == 0) {
|
||||
checkError = 1;
|
||||
pDriv = CreateIpsDriver(argc-4,&argv[4]);
|
||||
if(pDriv){
|
||||
pNew = CreateEVController(pDriv,argv[2],&status);
|
||||
if(pNew != NULL){
|
||||
AddCommand(pSics,argv[2],IpsWrapper,DeleteEVController,
|
||||
pNew);
|
||||
commandInstalled = 1;
|
||||
}
|
||||
}
|
||||
} else if(strcmp(argv[3],"bruker") == 0){
|
||||
checkError = 1;
|
||||
pDriv = CreateBrukerDriver(argc-4,&argv[4]);
|
||||
@ -429,12 +443,6 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
|
||||
SCWrite(pCon,"ERROR: failed to create driver",eError);
|
||||
return NULL;
|
||||
}
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to create environment device object",
|
||||
eError);
|
||||
DeleteEVDriver(pDriv);
|
||||
return NULL;
|
||||
}
|
||||
if(status != 1) {
|
||||
SCWrite(pCon,"ERROR: failed to initialize device",
|
||||
eError);
|
||||
@ -442,6 +450,12 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp *pSics,
|
||||
sprintf(pBueffel,"HW reported: %s",pError);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to create environment device object",
|
||||
eError);
|
||||
DeleteEVDriver(pDriv);
|
||||
return NULL;
|
||||
}
|
||||
if(commandInstalled == 0){
|
||||
AddCommand(pSics,argv[2],EVControlWrapper,DeleteEVController,pNew);
|
||||
}
|
||||
|
Reference in New Issue
Block a user