- various improvements in SE drivers

This commit is contained in:
zolliker
2006-08-17 15:39:37 +00:00
parent 928738dbd8
commit ce25823567
19 changed files with 301 additions and 100 deletions

View File

@ -31,6 +31,7 @@ static ParClass arrayObjClass = { "array", sizeof(ArrayObj) };
typedef struct WrtObjContext {
FILE *file;
int pos;
char filename[PATH_MAX];
} WrtObjContext;
@ -38,9 +39,17 @@ typedef struct WrtObjContext {
int WrtObjOpen(WrtObjContext *ctx, char *fileName) {
int iret;
char *slashpos;
/* create a temporary file first */
iret = snprintf(ctx->filename, sizeof(ctx->filename), ".%s", fileName);
slashpos = strrchr(fileName, '/');
if (slashpos == NULL) {
ctx->pos = 0;
} else {
ctx->pos = slashpos - fileName + 1;
}
iret = snprintf(ctx->filename, sizeof(ctx->filename), "%.*s.%s"
, ctx->pos, fileName, fileName + ctx->pos);
if (iret < 0 || iret >= sizeof(ctx->filename)) {
return 0;
}
@ -66,9 +75,13 @@ void WrtObj(WrtObjContext *ctx, char *objectName) {
}
/*-----------------------------------------------------------------------*/
void WrtObjClose(WrtObjContext *ctx) {
char finalName[PATH_MAX];
if (ctx) {
fclose(ctx->file);
rename(ctx->filename, ctx->filename+1);
snprintf(finalName, sizeof finalName, "%.*s%s"
, ctx->pos, ctx->filename, ctx->filename + ctx->pos + 1);
rename(ctx->filename, finalName);
}
}
/*----------------------------------------------------------------------------*/
@ -277,5 +290,5 @@ static int ArrayObjInit(SConnection *con, int argc, char *argv[], int dynamic) {
/*----------------------------------------------------------------------------*/
void ArrayObjStartup(void) {
ParMakeClass(&arrayObjClass, NULL);
MakeDriver("array", ArrayObjInit, 0);
MakeDriver("array", ArrayObjInit, 0, "String Array Object");
}

16
ease.c
View File

@ -44,6 +44,7 @@ EaseDriv *EaseDrivCast(void *object) {
/*----------------------------------------------------------------------------*/
void EaseStop(EaseBase *eab) {
FsmStop(eab->task, eab->idle);
closeRS232(eab->ser);
eab->state = EASE_notconnected;
}
/*----------------------------------------------------------------------------*/
@ -105,6 +106,7 @@ void EaseWrite(EaseBase *eab, char *cmd) {
snprintf(eab->msg, sizeof eab->msg,
"connection to %s:%d lost", eab->ser->pHost, eab->ser->iPort);
ParPrintf(eab, eError, "ERROR: %s", eab->msg);
closeRS232(eab->ser);
eab->state = EASE_notconnected;
eab->errCode = iRet;
return;
@ -205,9 +207,11 @@ int EaseHandler(EaseBase *eab) {
snprintf(eab->msg, sizeof eab->msg,
"connection for %s failed", eab->p.name);
ParPrintf(eab, eError, "%s", eab->msg);
closeRS232(eab->ser);
eab->state = EASE_notconnected;
return 0;
} else {
eab->tmo = 20;
snprintf(eab->msg, sizeof eab->msg,
"get a first answer from %s", eab->p.name);
eab->state = EASE_idle;
@ -345,7 +349,7 @@ int EaseUpdate(int flag) {
assert(flag >= 0);
assert(flag <= eab->maxflag);
eab->updateFlags[flag / EASE_FLAGBITS] |= 1 << (flag % EASE_FLAGBITS);
FsmSpeed(eab->task);
if (eab->task) FsmSpeed(eab->task);
return 1;
}
return 0;
@ -614,6 +618,7 @@ static int EaseInit(SConnection *pCon, EaseBase *eab, int argc, char *argv[],
eab->version[0] = '\0';
eab->maxflag = maxflag;
eab->sendCmd = NULL;
eab->tmo = 20;
eab->updateFlags = calloc(maxflag / EASE_FLAGBITS + 1, sizeof (*eab->updateFlags));
if (eab->updateFlags == NULL) {
SCWrite(pCon, "out of memory", eError);
@ -723,7 +728,14 @@ void *EaseMakeDriv(SConnection *con, void *class, int argc, char *argv[],
ead->drivInt->SetValue = EaseRun;
ead->drivInt->CheckStatus = EaseCheckStatus;
ead->drivInt->GetValue = EaseGetValue;
ead->maxwait = -1;
ead->lowerLimit = 0;
ead->upperLimit = 1000;
ead->settle = 0;
ead->tolerance = 1;
ead->targetValue = 0;
/* EMon interface to be implemented */
return ead;
}

1
ease.h
View File

@ -49,6 +49,7 @@ typedef struct {
unsigned long *updateFlags;
int startOk;
char *sendCmd;
int tmo;
} EaseBase;
typedef struct {

View File

@ -32,6 +32,7 @@ Markus Zolliker, August 2005
#define EURO2K_SET 1
#define EURO2K_MODE 2
#define EURO2K_PAR 3
typedef enum {read_only, settable, to_set} Euro2kAccess;
@ -49,13 +50,17 @@ typedef struct Euro2kPar {
typedef struct {
EaseDriv d;
char *unit;
int mode, manual;
int mode;
char *script;
int warned;
float temperature;
float output;
float position;
float range;
float asymmetry;
float setpoint;
Euro2kPar *pars, *readPar;
Statistics *stat;
} Euro2k;
static ParClass euro2kClass = { "EURO2K", sizeof(Euro2k) };
@ -68,7 +73,7 @@ static int Euro2kMakePar(void *object, void *userarg, int argc, char *argv[])
int iarg;
assert(drv);
if (argc < 1) goto Usage;
if (argc < 2) goto Usage;
last = &drv->pars;
for (par = drv->pars; par != NULL; par = par->next) {
if (strcasecmp(argv[0], par->name) == 0) {
@ -155,11 +160,17 @@ void Euro2kParDef(void *object) {
ParName("mode"); ParEnum(modeList); ParList(0); EaseUpdate(EURO2K_MODE);
ParInt(&drv->mode, 1);
ParName("manual"); ParEnum(modeList);
ParInt(&drv->manual, 1);
ParName("output"); ParTail("%");
ParFloat(&drv->output, PAR_NAN);
ParName("position"); ParTail("%");
ParFloat(&drv->position, PAR_NAN);
ParName("asymmetry"); ParAccess(usUser);
ParFloat(&drv->asymmetry, PAR_NAN);
ParName("range"); ParAccess(usUser);
ParFloat(&drv->range, PAR_NAN);
ParName("set"); ParTail(drv->unit); EaseUpdate(EURO2K_SET);
ParFloat(&drv->setpoint, PAR_NAN);
@ -206,7 +217,7 @@ void Euro2kParDef(void *object) {
ParFmt(par->fmt);
}
if (par->set >= settable) {
if (EaseUpdate(EURO2K_SET)) {
if (EaseUpdate(EURO2K_PAR)) {
par->set = to_set;
}
}
@ -217,7 +228,7 @@ void Euro2kParDef(void *object) {
ParName("makepar"); ParAccess(usUser); ParCmd(Euro2kMakePar, NULL);
EaseBasePar(drv);
EaseDrivPar(drv, "%#.5g", drv->unit);
EaseDrivPar(drv, "%.5g", drv->unit);
ParStdDef();
EaseMsgPar(drv);
if (ParActionIs(PAR_KILL)) {
@ -239,6 +250,9 @@ void Euro2kParDef(void *object) {
free(par);
}
drv->pars = NULL;
if (drv->stat) {
StatisticsKill(drv->stat);
}
}
}
/*----------------------------------------------------------------------------*/
@ -249,13 +263,16 @@ static long Euro2kRead(long pc, void *object) {
Tcl_Interp *pTcl = NULL;
char *p;
int l, m, iRet;
float dif;
float dif, a;
char buf[4];
Statistics *old;
switch (pc) { default: /* FSM BEGIN *******************************/
if (drv->script && drv->script[0] != '\0' && 0 != strcmp(drv->script, "0")) {
pTcl = InterpGetTcl(pServ->pSics);
old = StatisticsBegin(drv->stat);
iRet = Tcl_Eval(pTcl,drv->script);
StatisticsEnd(old);
if (iRet == TCL_OK) {
if (drv->warned > 0) drv->warned--;
} else if (drv->warned<3) {
@ -263,13 +280,18 @@ static long Euro2kRead(long pc, void *object) {
ParPrintf(drv, eError, "ERROR: %s in %s.task '%s'", pTcl->result, eab->p.name, drv->script);
}
}
ModBusRequestValue(eab, 273); /* get manual or auto */
if (EaseGetUpdate(drv, EURO2K_MODE)) goto skipMode;
ModBusRequestValue(eab, 273, modBusInt); /* get manual or auto */
return __LINE__; case __LINE__: /**********************************/
m = ModBusGetValue(eab, modBusInt);
if (m != drv->manual) { /* mode changed manually */
drv->mode = m;
if (!EaseGetUpdate(drv, EURO2K_MODE)) {
m = ModBusGetValue(eab, modBusInt);
if (m != drv->mode) { /* mode changed manually -> change disp */
drv->mode = m;
EaseSetUpdate(drv, EURO2K_MODE, 1);
}
}
drv->manual= m;
skipMode:
ModBusRequestFloats(eab, 1, 3);
return __LINE__; case __LINE__: /**********************************/
drv->temperature = ModBusGetFloat(eab, 1);
@ -277,11 +299,19 @@ static long Euro2kRead(long pc, void *object) {
drv->setpoint = ModBusGetFloat(eab, 2);
}
drv->output = ModBusGetFloat(eab, 3);
a = drv->output * eab->p.period / drv->range;
if ((drv->position > 50.) == (drv->output > 0)) {
drv->position += a * (1 - drv->asymmetry * 0.01);
} else {
drv->position += a * (1 + drv->asymmetry * 0.01);
}
if (drv->position < 0) drv->position = 0;
if (drv->position > 100) drv->position = 100;
par = drv->pars;
loop:
if (par == NULL) goto finish;
if (par->adr == 0 || par->set == to_set) goto skipPar;
ModBusRequestValue(eab, par->adr);
ModBusRequestValue(eab, par->adr, par->type);
drv->readPar = par;
return __LINE__; case __LINE__: /**********************************/
par = drv->readPar;
@ -333,8 +363,10 @@ static long Euro2kSet(long pc, void *object) {
if (drv->mode == 0) goto loop;
drv->mode = 0;
mode:
drv->manual = drv->mode;
ModBusPutValue(eab, 273, 1, drv->manual); /* set manual to 0 */
if (drv->mode) drv->mode = 1;
ModBusPutValue(eab, 106, modBusInt, drv->mode*5); /* set display std or blank */
return __LINE__; case __LINE__: /**********************************/
ModBusPutValue(eab, 273, modBusInt, drv->mode); /* set manual to 0 */
setIt:
return __LINE__; case __LINE__: /**********************************/
goto loop;
@ -347,13 +379,17 @@ static long Euro2kStart(long pc, void *object) {
EaseBase *eab = object;
switch (pc) { default: /* FSM BEGIN *******************************/
ModBusRequestValue(eab, 1);
ModBusRequestValue(eab, 1, modBusFloat);
return __LINE__; case __LINE__: /**********************************/
if (0 == ModBusGetValue(eab, modBusFloat)) {
ParPrintf(drv, eError, "bad or no response on ModBus");
goto quit;
}
ParPrintf(drv, eStatus, "connected to euro2k");
ModBusPutValue(eab, 111, modBusFloat, drv->d.upperLimit);
return __LINE__; case __LINE__: /**********************************/
ModBusPutValue(eab, 112, modBusFloat, drv->d.lowerLimit);
return __LINE__; case __LINE__: /**********************************/
FsmCall(Euro2kRead);
return __LINE__; case __LINE__: /**********************************/
@ -367,19 +403,21 @@ static int Euro2kInit(SConnection *con, int argc, char *argv[], int dynamic) {
<host> <port>
*/
Euro2k *drv;
char sn[64];
drv = EaseMakeDriv(con, &euro2kClass, argc, argv, dynamic, 7,
Euro2kParDef, ModBusHandler, Euro2kStart, NULL, Euro2kRead,
Euro2kSet);
if (drv == NULL) return 0;
drv->pars = NULL;
snprintf(sn, sizeof sn, "%s task", argv[1]);
drv->stat = StatisticsNew(sn);
setRS232ReplyTerminator(drv->d.b.ser,"");
setRS232SendTerminator(drv->d.b.ser,"");
ParPrintf(drv, eValue, "Eurotherm 2xxx");
return 1;
}
/*----------------------------------------------------------------------------*/
void Euro2kStartup(void) {
ParMakeClass(&euro2kClass, EaseDrivClass());
MakeDriver("EURO2K", Euro2kInit, 0);
MakeDriver("EURO2K", Euro2kInit, 0, "Eurotherm 2xxx");
}

139
ighdriv.c
View File

@ -34,11 +34,12 @@ Markus Zolliker, May 2005
#define OLDIGH -8
#define SORBS_FLAG 1
#define MIXP_FLAG 2
#define STILL_FLAG 3
#define SORBP_FLAG 4
#define MOT_FLAGS 5
#define VALVE_FLAGS 8
#define MAX_FLAG 31
#define MAXP_FLAG 3
#define STILL_FLAG 4
#define SORBP_FLAG 5
#define MOT_FLAGS 6
#define VALVE_FLAGS 9
#define MAX_FLAG 32
static char *valves[]={"V9", "V8", "V7", "V11A", "V13A", "V13B", "V11B", "V12B",
" He4", "V1", "V5", "V4", "V3", "V14", "V10", "V2",
@ -60,6 +61,7 @@ static char *closedOrOpen[]={"closed", "open", NULL};
typedef struct {
EaseDriv d;
float setT;
float sorbS;
float mixT;
float onekT;
@ -69,6 +71,8 @@ typedef struct {
float sorbP;
float press[n_PRESS];
float mv[n_MOTOR];
float v6pos;
time_t v6time;
int pdig;
int v[n_VALVES];
int e; /* heater range */
@ -82,12 +86,40 @@ static ParClass ighClass = { "IGH", sizeof(Igh) };
static long IghSet(long pc, void *object);
/*----------------------------------------------------------------------------*/
static int IghPower2Range(float p) {
int e;
if (p <= 0) return 0;
for (e = 1; e < 5; e++) {
if (p < 1.9994) break;
p /= 10;
}
return e;
}
/*----------------------------------------------------------------------------*/
static float IghRange2Max(int e) {
static float elist[]={0,2,20,200,2000,20000};
if (e < 0) {
e = 0;
} else if (e > 5) {
e = 5;
}
return elist[e];
}
/*----------------------------------------------------------------------------*/
static void IghParDef(void *object) {
Igh *drv = ParCast(&ighClass, object);
EaseBase *eab = object;
int i, flag, l, changed;
char *vPos;
char *vPos, *val;
char fmt[8], vList[80];
float maxP;
ParName(""); ParTail("K"); ParFmt("%.4f");
ParFloat(&drv->mixT, PAR_NAN);
ParName("Tset"); ParTail("K"); ParFmt("%.4f");
if (eab->syntax == OLDIGH) ParList("all");
ParFloat(&drv->setT, PAR_NAN);
ParName("TsorbSet");
EaseUpdate(SORBS_FLAG); ParTail("K"); ParFmt("%.1f");
@ -106,8 +138,7 @@ static void IghParDef(void *object) {
ParFloat(&drv->sorbT, PAR_NAN);
ParName("Pmix");
if (drv->e < 1 || drv->e > 5) drv->e=1;
if (drv->e == 5) {
if (drv->e >= 5 || drv->e < 1) {
strcpy(fmt, "%.0f");
} else {
snprintf(fmt, sizeof fmt, "%%.%df", 4 - drv->e);
@ -115,6 +146,14 @@ static void IghParDef(void *object) {
EaseUpdate(MIXP_FLAG); ParTail("uW"); ParFmt(fmt);
ParFloat(&drv->mixP, PAR_NAN);
ParName("Pmax");
EaseUpdate(MAXP_FLAG); ParTail("uW"); ParFmt("%g");
if ((val = ParGetValueArg())) {
drv->e = IghPower2Range(atof(val) * 0.9);
}
maxP = IghRange2Max(drv->e);
ParFloat(&maxP, PAR_NAN);
ParName("Pstill");
EaseUpdate(STILL_FLAG); ParTail("mW"); ParFmt("%.3f");
ParFloat(&drv->stillP, PAR_NAN);
@ -144,11 +183,16 @@ static void IghParDef(void *object) {
flag = MOT_FLAGS;
for (i=0; i<n_MOTOR; i++) {
ParName(motorValves[i]);
ParFmt("%.1f");
ParTail("%");
if (i == V1K) ParList("all");
EaseUpdate(flag); flag++;
ParFloat(&drv->mv[i], PAR_NAN);
}
ParName("v6pos"); ParFmt("%.1f"); ParTail("%");
ParFloat(&drv->v6pos, PAR_NAN);
assert(flag == VALVE_FLAGS);
l = 0;
for (i=0; i<n_VALVES; i++) {
@ -229,7 +273,13 @@ void IghStatus(Igh *drv) {
drv->a = ans[3] - '0';
drv->s = ans[16] - '0';
drv->o = ans[18] - '0';
drv->e = ans[20] - '0';
if (EaseGetUpdate(drv, MAXP_FLAG) == 0) {
if (drv->a == 0) {
drv->e = 0;
} else {
drv->e = ans[20] - '0';
}
}
if (ans[5] != '3' && drv->remote == 2) {
ParPrintf(drv, eError, "IGH switched to local");
*code = EASE_FAULT;
@ -243,7 +293,8 @@ static long IghRead(long pc, void *object) {
EaseBase *eab = object;
char *p;
int l;
time_t thisPeriod;
time_t now;
float delta;
switch (pc) { default: /* FSM BEGIN *******************************/
EaseWrite(eab, "X");
@ -285,6 +336,12 @@ static long IghRead(long pc, void *object) {
}
if (EaseCheckDoit(eab)) goto quit;
if (eab->syntax == OLDIGH) goto noSetTemp;
EaseWrite(eab, "R33");
return __LINE__; case __LINE__: /**********************************/
drv->setT = OxiGet(eab, 4, NULL, drv->setT);
noSetTemp:
EaseWrite(eab, "R1");
return __LINE__; case __LINE__: /**********************************/
drv->sorbT = OxiGet(eab, 1, NULL, drv->sorbT);
@ -297,6 +354,10 @@ static long IghRead(long pc, void *object) {
if (EaseCheckDoit(eab)) goto quit;
if (drv->e == 0) {
drv->mixP = 0;
goto skip4;
}
if (EaseGetUpdate(drv, MIXP_FLAG)) goto skip4;
EaseWrite(eab, "R4");
return __LINE__; case __LINE__: /**********************************/
@ -325,6 +386,16 @@ static long IghRead(long pc, void *object) {
EaseWrite(eab, "R7");
return __LINE__; case __LINE__: /**********************************/
drv->mv[V6] = OxiGet(eab, 1, NULL, drv->mv[V6]);
time(&now);
delta = (now - drv->v6time) / 2.64; /* speed: 1/2.64 %/sec */
drv->v6time = now;
if (drv->v6pos > drv->mv[V6] + delta) {
drv->v6pos -= delta;
} else if (drv->v6pos < drv->mv[V6] - delta) {
drv->v6pos += delta;
} else {
drv->v6pos = drv->mv[V6];
}
skip7:
if (EaseCheckDoit(eab)) goto quit;
@ -424,6 +495,7 @@ static long IghSet(long pc, void *object) {
if (upd == EASE_RUN) goto set_temp;
if (upd == SORBS_FLAG) goto set_sorb_temp;
if (upd == MIXP_FLAG) goto set_mix_pow;
if (upd == MAXP_FLAG) goto set_max_pow;
if (upd == STILL_FLAG) goto set_still_pow;
if (upd == SORBP_FLAG) goto set_sorb_pow;
goto finish;
@ -482,33 +554,44 @@ static long IghSet(long pc, void *object) {
goto loop;
set_mix_pow:
EaseWrite(eab, "A0");
return __LINE__; case __LINE__: /**********************************/
if (drv->e <= 1) goto skipe;
EaseWrite(eab, "E1");
return __LINE__; case __LINE__: /**********************************/
skipe:
if (drv->mixP > 0) {
mp = drv->mixP * 0.1;
for (i=2; i<6; i++) {
if (mp > 199) {
break;
}
mp = mp * 10;
}
if (mp > 1999) mp = 1999;
drv->e = 7-i;
drv->e = IghPower2Range(drv->mixP);
mp = drv->mixP / IghRange2Max(drv->e) * 2000;
} else {
mp = 0;
mp = 0; /* range unchanged for external heater signal */
}
OxiSet(eab, "M", mp, 0);
return __LINE__; case __LINE__: /**********************************/
if (drv->e == 0) goto loop;
EaseWrite(eab, "A1");
return __LINE__; case __LINE__: /**********************************/
set_max_pow:
if (drv->e == 0) goto seta0;
snprintf(buf, sizeof buf, "E%d", drv->e);
EaseWrite(eab, buf);
return __LINE__; case __LINE__: /**********************************/
EaseWrite(eab, "A1");
goto loop;
seta0:
EaseWrite(eab, "A0");
return __LINE__; case __LINE__: /**********************************/
goto loop;
set_temp:
/* unknown yet */
goto loop;
EaseWrite(eab, "A2");
return __LINE__; case __LINE__: /**********************************/
if (drv->d.targetValue < 0) drv->d.targetValue = 0;
if (drv->d.targetValue > 1.999) drv->d.targetValue = 1.999;
OxiSet(eab, "T", drv->d.targetValue, 4);
return __LINE__; case __LINE__: /**********************************/
goto loop;
@ -521,6 +604,11 @@ static long IghSet(long pc, void *object) {
set_mot:
i = upd - MOT_FLAGS;
if (drv->mv[i] > 99.9) {
drv->mv[i]=99.9;
} else if (drv->mv[i] < 0) {
drv->mv[i]=0;
}
OxiSet(eab, motorCommands[i], drv->mv[i], 1);
return __LINE__; case __LINE__: /**********************************/
goto loop;
@ -544,11 +632,10 @@ static int IghInit(SConnection *con, int argc, char *argv[], int dynamic) {
IghParDef, OxiHandler, IghStart, NULL, IghRead,
IghSet);
if (drv == NULL) return 0;
ParPrintf(drv, eValue, "OI Gas Handling System");
return 1;
}
/*----------------------------------------------------------------------------*/
void IghStartup(void) {
ParMakeClass(&ighClass, EaseDrivClass());
MakeDriver("IGH", IghInit, 0);
MakeDriver("IGH", IghInit, 0, "OI Gas Handling System");
}

View File

@ -186,11 +186,10 @@ static int IlmInit(SConnection *con, int argc, char *argv[], int dynamic) {
drv = EaseMakeBase(con, &ilmClass, argc, argv, dynamic, 0,
IlmParDef, OxiHandler, IlmStart, NULL, IlmRead);
if (drv == NULL) return 0;
ParPrintf(drv, eValue, "OI Level Meter");
return 1;
}
/*----------------------------------------------------------------------------*/
void IlmStartup(void) {
ParMakeClass(&ilmClass, EaseBaseClass());
MakeDriver("ILM", IlmInit, 0);
MakeDriver("ILM", IlmInit, 0, "OI Level Meter");
}

View File

@ -496,12 +496,11 @@ static int IpsInit(SConnection *con, int argc, char *argv[], int dynamic) {
IpsParDef, OxiHandler, IpsStart, NULL, IpsRead,
IpsChangeField);
if (drv == NULL) return 0;
ParPrintf(drv, eValue, "OI Power Supply");
drv->d.maxwait = 999999;
return 1;
}
/*----------------------------------------------------------------------------*/
void IpsStartup(void) {
ParMakeClass(&ipsClass, EaseDrivClass());
MakeDriver("IPS", IpsInit, 0);
MakeDriver("IPS", IpsInit, 0, "OI Power Supply");
}

View File

@ -721,7 +721,6 @@ static int ItcInit(SConnection *con, int argc, char *argv[], int dynamic) {
ItcSet);
if (drv == NULL) return 0;
drv->d.b.syntax = 0;
ParPrintf(drv, eValue, "OI Temperature Controller");
return 1;
}
/*----------------------------------------------------------------------------*/
@ -740,12 +739,11 @@ static int ItcInitLc(SConnection *con, int argc, char *argv[], int dynamic) {
drv->lastCtrl = 0;
drv->lastTdiff = 0;
drv->lastPdiff = 0;
ParPrintf(drv, eValue, "OI Lambda Controller");
return 1;
}
/*----------------------------------------------------------------------------*/
void ItcStartup(void) {
ParMakeClass(&itcClass, EaseDrivClass());
MakeDriver("ITC", ItcInit, 0);
MakeDriver("LC", ItcInitLc, 0);
MakeDriver("ITC", ItcInit, 0, "OI Temperature Controller");
MakeDriver("LC", ItcInitLc, 0, "OI Lambda Controller");
}

View File

@ -220,7 +220,7 @@ int LoggerWrite0(Logger *log, time_t now, int period, char *value) {
}
pos1 = ftell(fil);
strftime(stim, sizeof stim,"%H:%M:%S", tm);
fprintf(fil, "%s\t%s%s\n", stim, value, buf);
fprintf(fil, "%s\t%s\n", stim, value);
for (p = ftell(fil); p < endPos; p++) { /* overwrite dirt after last line */
fprintf(fil, " ");
}

View File

@ -9,6 +9,7 @@
#define LOGGER_NAN -999999.
#define ONE_YEAR (366*24*3600)
#define LLEN 1024
typedef enum { NUMERIC, TEXT } CompType;
@ -21,8 +22,8 @@ typedef struct {
time_t tlim;
time_t tmin, tmax, tlast, told;
float ymin, ymax, ylast, yold;
char slast[256];
char set[256];
char slast[LLEN];
/* char set[LLEN]; */
int np;
char *none;
} Compressor;
@ -43,7 +44,7 @@ static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) {
}
static void OutString(Compressor *c, time_t t, char *str) {
char line[256];
char line[LLEN];
/* printf("out %ld %g\n", t, y); */
if (0 != strcmp(str, c->slast)) {
@ -173,7 +174,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
int yday=0;
time_t t, startim;
struct tm tm;
char stim[32], path[256], line[256], lastval[256];
char stim[32], path[LLEN], line[LLEN], lastval[LLEN];
char *lin, *val, *stp;
FILE *fil;
Compressor c={0};

View File

@ -20,7 +20,8 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o
MZOBJ=fsm.o logger.o sugar.o pardef.o ease.o strobj.o oxinst.o logreader.o \
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \
lscsupport.o lsc370driv.o
libpsi.a: $(OBJ)
rm -f libpsi.a

View File

@ -337,12 +337,17 @@ float ModBusGetFloat(EaseBase *eab, int adr) {
return ieee2double(eab->ans + 3 + i * 4);
}
/*----------------------------------------------------------------------------*/
void ModBusRequestValue(EaseBase *eab, int adr) {
void ModBusRequestValue(EaseBase *eab, int adr, int type) {
eab->cmd[0] = 1; /* device address */
eab->cmd[1] = 3; /* read n words */
fadr2word(adr, eab->cmd + 2);
uint2word(2, eab->cmd + 4);
if (type == modBusInt) {
uint2word(adr, eab->cmd + 2);
uint2word(1, eab->cmd + 4);
} else {
fadr2word(adr, eab->cmd + 2);
uint2word(2, eab->cmd + 4);
}
ModBusWrite(eab, 6);
}
/*----------------------------------------------------------------------------*/
@ -351,13 +356,11 @@ void ModBusPutValue(EaseBase *eab, int adr, int type, float val) {
eab->cmd[0] = 1; /* device address */
eab->cmd[1] = 16; /* write n words */
if (type == modBusTime+9) {
if (type == modBusInt) {
uint2word(adr, eab->cmd + 2);
eab->cmd[4] = 2;
eab->cmd[5] = 0;
eab->cmd[6] = 1;
eab->cmd[7] = (int)(val) / 256;
eab->cmd[8] = (int)(val) % 256;
uint2word(1, eab->cmd + 4);
eab->cmd[6] = 2;
uint2word((int)(val), eab->cmd+7);
ModBusWrite(eab, 9);
return;
}

View File

@ -19,7 +19,7 @@ int ModBusHandler(void *eab);
void ModBusPutFloats(EaseBase *eab, int adr, int npar, float val[]);
void ModBusRequestFloats(EaseBase *eab, int adr, int npar);
float ModBusGetFloat(EaseBase *eab, int adr);
void ModBusRequestValue(EaseBase *eab, int adr);
void ModBusRequestValue(EaseBase *eab, int adr, int type);
float ModBusGetValue(EaseBase *eab, int type);
void ModBusPutValue(EaseBase *eab, int adr, int type, float val);

View File

@ -92,10 +92,11 @@ int OxiHandler(void *object) {
goto quit;
} else if (eab->cmd[2] == 'k') { /* ?ck */
} else {
eab->tmo = 120;
if (eab->syntax <= -8) {
corr = OxiCorrect(eab->ans);
if (corr) {
ParPrintf(eab, eWarning, "corrected bad response from IGH: %s", corr);
// ParPrintf(eab, eWarning, "corrected bad response from IGH: %s", corr);
}
}
if (eab->cmd[0] != eab->ans[0]) {
@ -110,7 +111,7 @@ int OxiHandler(void *object) {
}
eab->state = EASE_read;
} else if (eab->state == EASE_expect) {
if (time(NULL) > eab->cmdtime+20) {
if (time(NULL) > eab->cmdtime + eab->tmo) {
eab->state = EASE_lost;
}
} else if (eab->state == EASE_lost) {

View File

@ -31,11 +31,12 @@ typedef enum { NO_OP, FMT_OP, SET_OP, GET_OP, INIT_OP } ParOp;
typedef struct Context {
struct Context *next;
ParData *obj;
ParAct act;
ParAct action;
ParAct act; /* action called */
ParAct action; /* copy of act, but set to PAR_NOOP when name does not match */
char *parName;
int argc;
char **argv;
char *valueArg;
char *thisPar;
int returnValue;
SConnection *con;
@ -283,6 +284,19 @@ int ParLog(void *object) {
ParEnd();
return next;
}
/*--------------------------------------------------------------------------*/
void ParLogForced(void *object) {
ParData *o = ParCheck(&parClass, object);
int next;
ParBegin();
ctx->now = time(NULL);
showTime = 1;
ParDo(0, o, PAR_LOG, NULL);
o->logTime = ctx->now;
o->logPending = 0;
ParEnd();
}
/*-------------------------------------------------------------------------*/
static int ParCallBack(int event, void *eventData, void *userData,
commandContext cc) {
@ -307,7 +321,7 @@ static int ParOutError(SConnection *con, ParData *o) {
SCPrintf(con, eError, "ERROR: insufficient privilege for %s.%s", o->name, ctx->thisPar);
break;
case ILLNUM:
SCPrintf(con, eError, "ERROR: illegal value", o->name, ctx->argv[0]);
SCPrintf(con, eError, "ERROR: illegal value", o->name, ctx->valueArg);
break;
case ILLARGC:
SCPrintf(con, eError, "ERROR: illegal number of arguments for %s %s", o->name, ctx->thisPar);
@ -434,6 +448,7 @@ static int ParExecute(SConnection *con, SicsInterp *sics, void *object, int argc
if (strcmp(argv[1], "=") == 0) {
ctx->argc = argc - 2;
ctx->argv = argv + 2;
ctx->valueArg = argv[2];
ParDo(con, o, PAR_SET, "");
logIt = 1;
} else {
@ -442,6 +457,7 @@ static int ParExecute(SConnection *con, SicsInterp *sics, void *object, int argc
} else {
ctx->argc = argc - 2;
ctx->argv = argv + 2;
ctx->valueArg = argv[2];
ParDo(con, o, PAR_SET, argv[1]);
logIt = 1;
}
@ -465,7 +481,7 @@ static int ParExecute(SConnection *con, SicsInterp *sics, void *object, int argc
ctx->returnValue = UNKPAR;
}
iret = ParOutError(con, o);
if (logIt) ParLog(o); /* log changes */
if (logIt) ParLogForced(o); /* log changes */
ParEnd();
return iret;
}
@ -984,15 +1000,17 @@ void ParFloat(float *value, float defValue) {
ctx->returnValue = ILLARGC;
return;
}
f = strtod(ctx->argv[0], &endp);
if (endp == ctx->argv[0]) {
f = ParText2Int(ctx->argv[0]);
if (f < 0) {
ctx->returnValue = ILLNUM;
break;
if (ctx->valueArg) {
f = strtod(ctx->valueArg, &endp);
if (endp == ctx->valueArg) {
f = ParText2Int(ctx->valueArg);
if (f < 0) {
ctx->returnValue = ILLNUM;
break;
}
}
*value = f;
}
*value = f;
ParHasChanged();
/* fall through */
case FMT_OP:
@ -1030,15 +1048,17 @@ void ParInt(int *value, int defValue) {
ctx->returnValue = ILLARGC;
return;
}
i = strtol(ctx->argv[0], &endp, 0);
if (endp == ctx->argv[0]) {
i = ParText2Int(ctx->argv[0]);
if (i < 0) {
ctx->returnValue = ILLNUM;
break;
if (ctx->valueArg) {
i = strtol(ctx->valueArg, &endp, 0);
if (endp == ctx->valueArg) {
i = ParText2Int(ctx->valueArg);
if (i < 0) {
ctx->returnValue = ILLNUM;
break;
}
}
*value = i;
}
*value = i;
ParHasChanged();
/* fall through */
case FMT_OP:
@ -1128,6 +1148,17 @@ int ParActionIs(ParAct a) {
return 0;
}
/*----------------------------------------------------------------------------*/
char *ParGetValueArg() {
char *ret;
if (ctx->action == PAR_SET) {
ret = ctx->valueArg;
ctx->valueArg = NULL;
return ret;
} else {
return NULL;
}
}
/*----------------------------------------------------------------------------*/
void *ParObject(void) {
return ctx->obj;
}

View File

@ -195,6 +195,9 @@ typedef struct ParData {
list */
void ParLogReady(ReadyState state); /* set ready state for log */
FILE *ParSaveFile(void); /* get the save-file name when action is PAR_SAVE */
char *ParGetValueArg(); /* get the set argument for floats and ints. If this function
is called, the caller is reponsible for assigning the value
to the object parameter */
/*
functions to be used outside pardef:
@ -237,5 +240,6 @@ typedef struct ParData {
void ParInitPar(void *object, char *name);
/* inititalize dynamic parameter */
#endif

1
psi.c
View File

@ -80,6 +80,7 @@ void SiteInit(void) {
INIT(StrObjStartup);
INIT(LogReaderInit);
INIT(ArrayObjStartup);
INIT(Lsc370Startup);
}

View File

@ -46,5 +46,5 @@ static int StrObjInit(SConnection *con, int argc, char *argv[], int dynamic) {
/*----------------------------------------------------------------------------*/
void StrObjStartup(void) {
ParMakeClass(&strObjClass, NULL);
MakeDriver("string", StrObjInit, 0);
MakeDriver("string", StrObjInit, 0, "String Object");
}

View File

@ -95,6 +95,7 @@ void outFunc(char *str, void *arg) {
pTecsDriv pMe;
float fVal;
Buffer buffer;
ObPar *pPar;
self = (pEVControl)pData;
assert(self);
@ -136,7 +137,10 @@ void outFunc(char *str, void *arg) {
iRet = EVCGetPar(self, "upperlimit", &fVal);
if (abs(fVal - atof(result)) > 1.0e-4 * abs(fVal)) {
fVal = atof(result);
iRet = EVCSetPar(self, "upperlimit", fVal,pCon);
pPar = ObParFind(self->pParam,"upperlimit");
if (pPar != NULL) {
pPar->fVal = fVal;
}
}
iRet = EVControlWrapper(pCon,pSics,pData,argc,argv);
if (iRet != 0) {
@ -161,7 +165,15 @@ void outFunc(char *str, void *arg) {
sprintf(pBueffel,"WARNING: upper limit reduced to maximal allowed value: %g", fVal);
SCWrite(pCon,pBueffel,eWarning);
}
iRet = EVCSetPar(self, "upperlimit", fVal,pCon);
if (argc == 3) {
iRet = EVCSetPar(self, "upperlimit", fVal,pCon);
} else {
pPar = ObParFind(self->pParam,"upperlimit");
if (pPar != NULL) {
pPar->fVal = fVal;
}
iRet = 1;
}
if (iRet) {
sprintf(pBueffel,"%s.%s = %s\n",self->pName,
argv[1],result);
@ -478,5 +490,5 @@ void outFunc(char *str, void *arg) {
pMe->EVLimits=pEvc->pDrivInt->CheckLimits; /* save original CheckLimits function */
pEvc->pDrivInt->CheckLimits=TecsLimits;
EVCSetPar(pEvc,"upperlimit",1800.0,pCon);
EVCSetPar(pEvc,"lowerlimit",0.01,pCon);
EVCSetPar(pEvc,"lowerlimit",0.0,pCon);
}