- new double control (former controlmode = 2)
- better sea client compatibility
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#define ARG_INT 2
|
||||
#define ARG_FLT 3
|
||||
#define ARG_ARR 4
|
||||
#define ARG_OUT 5
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -290,14 +291,21 @@ int CocGetArray(CocConn *conn, const char *name, float *value, int value_size) {
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocGetOut(CocConn *conn, const char *name, OutFunc *func) {
|
||||
return(CocPushArg(conn, name, func, ARG_OUT, 0));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocDoIt(CocConn *conn, char *res, int res_len) {
|
||||
StrBuf *buf;
|
||||
int i, pending;
|
||||
float *arr;
|
||||
CocArg *a;
|
||||
char *resp, *t, tag;
|
||||
char *resp, *t, tag, *str;
|
||||
int iret=0;
|
||||
int siz;
|
||||
OutFunc *f;
|
||||
|
||||
assert(conn!=NULL);
|
||||
ERR_I(CocCmdWithRetry(conn));
|
||||
@@ -354,6 +362,10 @@ int CocDoIt(CocConn *conn, char *res, int res_len) {
|
||||
resp="<array>";
|
||||
} else if (a->type==ARG_CHAR) {
|
||||
ERR_P(StrNGet(buf, (char *)a->adr, a->size, COC_SEP));
|
||||
} else if (a->type==ARG_OUT) {
|
||||
ERR_P(str=StrNGet(buf, NULL, 0, COC_SEP));
|
||||
f=(OutFunc *)a->adr;
|
||||
f->func(str, f->arg);
|
||||
} else {
|
||||
ERR_MSG("unknown type");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#include "myc_buf.h"
|
||||
#include "coc_util.h"
|
||||
|
||||
typedef struct {
|
||||
void (* func) (char *, void *);
|
||||
void *arg;
|
||||
} OutFunc;
|
||||
|
||||
typedef struct {
|
||||
void *adr;
|
||||
int type, size;
|
||||
@@ -43,6 +48,7 @@ int CocGetStr(CocConn *conn, const char *name, char *value, int value_len);
|
||||
int CocGetFloat(CocConn *conn, const char *name, float *value);
|
||||
int CocGetInt(CocConn *conn, const char *name, int *value);
|
||||
int CocGetArray(CocConn *conn, const char *name, float *value, int value_size);
|
||||
int CocGetOut(CocConn *conn, const char *name, OutFunc *f);
|
||||
int CocDoIt(CocConn *conn, char *error, int error_len);
|
||||
|
||||
int CocCheck(CocConn *conn);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
typedef enum { NORMAL, SPY, CLIENT, NMODE } Mode;
|
||||
|
||||
#define MAXMSG 256
|
||||
#define MAXMSG 8192
|
||||
|
||||
static char *clcname="six", *servername="sics";
|
||||
static int clclen=3;
|
||||
@@ -580,7 +580,7 @@ int main (int argc, char *argv[]) {
|
||||
int i, j, gotolevel, sicslogin;
|
||||
int home;
|
||||
int savehist = 0;
|
||||
char buf[128], lbuf[16];
|
||||
char buf[512], lbuf[16];
|
||||
char stdPrompt[128]="", prompt[256]="";
|
||||
char *p;
|
||||
char *bar;
|
||||
@@ -754,16 +754,17 @@ int main (int argc, char *argv[]) {
|
||||
ERR_I(sendCmd(sock[0], "status"));
|
||||
ERR_P(readWrite(12000,0,NULL));
|
||||
|
||||
term_read_hist(clcname, instr);
|
||||
} else {
|
||||
sprintf(stdPrompt, "%s[%s] ", clcname, host);
|
||||
status[0]='E'; status[1]='\0';
|
||||
term_read_hist(clcname, host);
|
||||
}
|
||||
|
||||
iret=1;
|
||||
buf[0]='\0';
|
||||
pos=0;
|
||||
|
||||
term_read_hist(clcname);
|
||||
savehist = 1;
|
||||
|
||||
while (1) {
|
||||
|
||||
563
tecs/tecs.c
563
tecs/tecs.c
@@ -115,11 +115,13 @@ static float
|
||||
maxCurrent, /* maxCurrent (not really reached for resist > 25 Ohm */
|
||||
powFact=1, /* power factor (for external power supplies) */
|
||||
resist=10, /* heater resistance */
|
||||
tShift=0, /* setpoint shift */
|
||||
empty, full, /* empty/full value for helium level */
|
||||
prop, integ, deriv, /* pid */
|
||||
maxShift=2, /* maximal shift in when controlMode=2 */
|
||||
maxOver=0, /* maximal overshoot in when controlMode=2 */
|
||||
int2=1200.0, /* integration time (sec) for doublecontrol */
|
||||
tShift=0, /* setpoint shift */
|
||||
maxShift=10, /* maximal shift for doublecontrol */
|
||||
propUp=0.5, /* upper limit coefficient (doublecontrol) */
|
||||
propDown=0.8, /* lower limit coefficient (doublecontrol) */
|
||||
tm=DATA_UNDEF, /* main temperature */
|
||||
ts=DATA_UNDEF, /* sample temperature */
|
||||
tx=DATA_UNDEF, /* controlled temperature */
|
||||
@@ -128,6 +130,7 @@ static float
|
||||
tk=DATA_UNDEF, /* test temperature 2 */
|
||||
he=DATA_UNDEF, /* helium level value */
|
||||
aux=DATA_UNDEF, /* auxiliary value */
|
||||
scanChan=DATA_UNDEF, /* scan channel */
|
||||
ramp=0,
|
||||
slope=0,
|
||||
smooth=0,
|
||||
@@ -135,8 +138,9 @@ static float
|
||||
r1, r2, /* temporary values */
|
||||
still=0,
|
||||
linearPower=0, /* normally 0. Maximum power when loop=2 and the power linear to the output */
|
||||
mout,
|
||||
tInt=0; /* integral time (sec.) for setpoint shift */
|
||||
shiftUp, shiftLow, /* upper and lower limit of tShift correction */
|
||||
state,
|
||||
mout;
|
||||
|
||||
static int
|
||||
logPeriod=5, /* data logging period (sec.) */
|
||||
@@ -146,10 +150,11 @@ static int
|
||||
saveTime, /* time for a CRVSAV command */
|
||||
noResp=1, /* no response */
|
||||
quit, /* quit server */
|
||||
controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */
|
||||
controlMode=0, /* obsolete (now controlSensor/doubleControl) 0: control on heater, 1: control on sample, 2: 2nd loop for difference heater-sample */
|
||||
doubleControl=0,
|
||||
manual=0,
|
||||
int2=30, /* inegration time for controlMode 2 */
|
||||
remoteMode, /* 1: local, 2: remote */
|
||||
local, /* 0: remote, 1: local */
|
||||
maxfld, /* last used display field */
|
||||
busy, /* busy after CRVSAV */
|
||||
relay, relay0, /* relay status */
|
||||
@@ -196,6 +201,7 @@ static char
|
||||
alarmChannels[N_SENSORS],
|
||||
alarmHistory[N_SENSORS],
|
||||
swap[4],
|
||||
controlSensor[4], /* '0': main two, '1': sample two, or any of "slmntkabcd" */
|
||||
dev[80],
|
||||
devHelp[10000],
|
||||
update[32], /* update script option */
|
||||
@@ -215,6 +221,8 @@ static float gradata[COC_RES_LEN/4-100];
|
||||
static char grapar[128];
|
||||
static int* grasize;
|
||||
|
||||
static char ttp[64]; /* temperature, target and power */
|
||||
|
||||
typedef struct {
|
||||
char cmd[COC_CMD_LEN];
|
||||
int logstart;
|
||||
@@ -605,6 +613,8 @@ again:
|
||||
slope=0;
|
||||
ramp=0;
|
||||
controlMode=0;
|
||||
doubleControl=0;
|
||||
controlSensor[0]='0';
|
||||
linearPower=0;
|
||||
powFact=1;
|
||||
config[0]='\0';
|
||||
@@ -678,10 +688,10 @@ again:
|
||||
tLimit=310;
|
||||
tMaxLimit=350;
|
||||
} else {
|
||||
tLimit=tMaxLimit;
|
||||
tLimit=tMaxLimit-10;
|
||||
}
|
||||
} else if (tMaxLimit==0.0) {
|
||||
tMaxLimit=tLimit;
|
||||
tMaxLimit=tLimit+10;
|
||||
} else if (tLimit>tMaxLimit) {
|
||||
tLimit=tMaxLimit;
|
||||
}
|
||||
@@ -699,7 +709,7 @@ again:
|
||||
s->band=10;
|
||||
if (s->scale==0.0) s->scale=1.0;
|
||||
if ((s->alarm==0.0 && typ=='m') || typ=='s') {
|
||||
s->alarm=tLimit;
|
||||
s->alarm=tMaxLimit;
|
||||
s->customAlarm=0;
|
||||
} else {
|
||||
s->customAlarm=1;
|
||||
@@ -904,8 +914,27 @@ void LogMinMax(int new) {
|
||||
}
|
||||
}
|
||||
|
||||
SensorT *findSensor(char txt) {
|
||||
int i;
|
||||
SensorT *s;
|
||||
|
||||
s = NULL;
|
||||
txt = tolower(txt);
|
||||
if (strchr("01slmntkabcde", txt) != 0) {
|
||||
for (i=0; i<4; i++) {
|
||||
if (txt == tolower(sensors[i]->ch[0])
|
||||
|| txt == sensors[i]->typ) {
|
||||
s = sensors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void SetCtlSens(void) {
|
||||
if (controlMode==1) {
|
||||
SensorT *s;
|
||||
|
||||
if (controlSensor[0] == '1') {
|
||||
tShift=0;
|
||||
if (ctlSens==NULL) {
|
||||
ctlSens=samp.sensor1;
|
||||
@@ -920,8 +949,13 @@ void SetCtlSens(void) {
|
||||
} else {
|
||||
ctlSens=samp.sensor1;
|
||||
}
|
||||
} else {
|
||||
if (controlMode!=2) tShift=0;
|
||||
if (controlMode != 2) {
|
||||
controlMode = 1;
|
||||
}
|
||||
} else if (controlSensor[0] == '0') {
|
||||
if (!doubleControl) {
|
||||
tShift=0;
|
||||
}
|
||||
if (ctlSens==NULL) {
|
||||
ctlSens=cryo.sensor1;
|
||||
} else if (ctlSens==cryo.sensor1) {
|
||||
@@ -935,6 +969,26 @@ void SetCtlSens(void) {
|
||||
} else {
|
||||
ctlSens=cryo.sensor1;
|
||||
}
|
||||
if (controlMode != 2) {
|
||||
controlMode = 0;
|
||||
}
|
||||
} else {
|
||||
s = findSensor(controlSensor[0]);
|
||||
if (s) {
|
||||
ctlSens = s;
|
||||
if (controlMode != 2) {
|
||||
if (s->typ == 's' || s->typ == 'l') {
|
||||
controlMode = 1;
|
||||
} else {
|
||||
controlMode = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctlSens = cryo.sensor1; /* should always be defined */
|
||||
if (controlMode != 2) {
|
||||
controlMode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1104,10 +1158,10 @@ int ReadTemp(void) {
|
||||
tm=(rdTim % 3600) * 1.0e-4;
|
||||
ts=(rdTim % 60) * 60.0e-4+0.5;
|
||||
}
|
||||
if (controlMode==0) {
|
||||
tx=tm;
|
||||
} else {
|
||||
if (doubleControl) {
|
||||
tx=ts;
|
||||
} else if (ctlSens) {
|
||||
tx=TrueScale(ctlSens, ctlSens->t);
|
||||
}
|
||||
if (auxSens != NULL) {
|
||||
aux=TrueScale(auxSens, auxSens->t);
|
||||
@@ -1185,8 +1239,9 @@ int ReadHeater(int full) {
|
||||
|
||||
int SetTemp(int switchOn) {
|
||||
int showSet;
|
||||
float diff, tc;
|
||||
|
||||
float tc;
|
||||
float tLim;
|
||||
|
||||
if (set<0 || set>tLimit) {
|
||||
set=0;
|
||||
logfileOut(LOG_MAIN, "set point not within (0 ... %g), reset to 0\n", tLimit);
|
||||
@@ -1199,27 +1254,17 @@ int SetTemp(int switchOn) {
|
||||
if (ctlSens==NULL) return 0;
|
||||
|
||||
str_copy(chan, ctlSens->ch);
|
||||
if (tShift>maxShift) {
|
||||
tShift=maxShift;
|
||||
} else if (tShift<-maxShift) {
|
||||
tShift=-maxShift;
|
||||
if (!doubleControl) {
|
||||
tShift=0.0;
|
||||
}
|
||||
if (controlMode==2) {
|
||||
diff=set-samp.temp;
|
||||
if (diff>maxOver) { /* do overshoot */
|
||||
diff=maxOver;
|
||||
tShift=0;
|
||||
tInt=0;
|
||||
} else if (diff<-maxOver) { /* do undershoot */
|
||||
diff=-maxOver;
|
||||
tShift=0;
|
||||
tInt=0;
|
||||
}
|
||||
} else {
|
||||
diff=0.0;
|
||||
tLim = (tLimit+tMaxLimit)*0.5;
|
||||
if (set+tShift <= 0) { /* set + tShift must not be negative */
|
||||
tShift = -0.999 * set;
|
||||
} else if (set + tShift > tLim) { /* prevent overshoot */
|
||||
tShift = tLim - set;
|
||||
}
|
||||
setH=FakeScale(ctlSens, set+tShift+diff);
|
||||
if (setH > FakeScale(ctlSens, tLimit)) setH=FakeScale(ctlSens, tLimit);
|
||||
setH=FakeScale(ctlSens, set+tShift);
|
||||
if (setH > FakeScale(ctlSens, tLim)) setH=FakeScale(ctlSens, tLim);
|
||||
if (switchOn) {
|
||||
/* switch off other loop */
|
||||
if (loop==1) {
|
||||
@@ -1276,7 +1321,7 @@ int SetTemp(int switchOn) {
|
||||
ERR_P(LscCmd(ser, "SETP?[loop]>fbuf"));
|
||||
if (fabsf(setH-fbuf) >= (fbuf+setH)*1.0e-5) {
|
||||
ERR_P(LscCmd(ser, "SETP [loop]:[setH]"));
|
||||
if (controlMode!=2 && !showSet) {
|
||||
if (!doubleControl && !showSet) {
|
||||
logfileOut(LOG_MAIN, "set %g (on %s) (was changed %g -> %g)\n", set, ctlSens->ch, fbuf, setH);
|
||||
}
|
||||
} else {
|
||||
@@ -1523,7 +1568,7 @@ int SetMaxPower(void) {
|
||||
if (slope<0) slope=-slope;
|
||||
if (slope!=0 && slope<0.1) slope=0.1;
|
||||
SetCtlSens();
|
||||
fbuf=FakeScale(ctlSens, tLimit);
|
||||
fbuf=FakeScale(ctlSens, (tLimit + tMaxLimit)*0.5);
|
||||
if (loop==1) {
|
||||
PidSumHdl(COC_RD, NULL, 0);
|
||||
if (!initMaxPower && lastCurrent != maxCurrent && lastCurrent != 0) {
|
||||
@@ -1665,6 +1710,7 @@ int Settings(void) {
|
||||
|
||||
if (remoteMode!=2) {
|
||||
remoteMode=2; /* set to remote mode */
|
||||
local=0;
|
||||
ERR_I(LoadFromLsc());
|
||||
ERR_P(LscCmd(ser, "MODE:[remoteMode]"));
|
||||
} else {
|
||||
@@ -1846,13 +1892,260 @@ int ConfigByName(int plugNr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define HISTSIZE 65
|
||||
|
||||
typedef struct {
|
||||
int init;
|
||||
float vals[HISTSIZE];
|
||||
float fore;
|
||||
float weight;
|
||||
float err;
|
||||
} Hist;
|
||||
|
||||
/*
|
||||
static Hist fore, mFore;
|
||||
*/
|
||||
|
||||
float forecast(Hist *h, float value, int tim, int nmax) {
|
||||
int i, n, stp, ne;
|
||||
float d1, d2, d, vmean, vsig, val, val1, fact, fact1;
|
||||
float emean, esig, errLin, valLin;
|
||||
|
||||
if (h->init == 0) { /* put a start value */
|
||||
h->init = 1;
|
||||
for (i=0; i<HISTSIZE; i++) {
|
||||
h->vals[i] = value;
|
||||
}
|
||||
h->err = value;
|
||||
return value;
|
||||
}
|
||||
for (i=HISTSIZE-1; i>0; i--) {
|
||||
h->vals[i] = h->vals[i-1];
|
||||
}
|
||||
h->vals[0] = value;
|
||||
h->err = value;
|
||||
h->fore = 0;
|
||||
errLin = value;
|
||||
valLin = value;
|
||||
for (stp = 1; stp*4 < HISTSIZE; stp *= 2) {
|
||||
vmean = 0;
|
||||
vsig = 0;
|
||||
n = 0;
|
||||
val1 = 0;
|
||||
emean = 0;
|
||||
esig = 0;
|
||||
ne = 0;
|
||||
for (i = 0; i < stp*nmax && i + 2 * stp < HISTSIZE; i += stp) {
|
||||
d1 = h->vals[i+stp] - h->vals[i];
|
||||
d2 = h->vals[i+2*stp] - h->vals[i+stp];
|
||||
if (fabs(d2) > fabsf(d1) && d1 * d2 >= 0 && n >= 0) {
|
||||
/* exponential extrapolation */
|
||||
fact = d1 / d2;
|
||||
val = h->vals[i] - d1 * fact / (1 - fact);
|
||||
if (n == 0) {
|
||||
fact1 = fact;
|
||||
val1 = val;
|
||||
}
|
||||
n++;
|
||||
d = val - vmean;
|
||||
vmean += d / n;
|
||||
vsig += d * (val - vmean);
|
||||
} else {
|
||||
n = -1; /* exponential interpolation not possible */
|
||||
}
|
||||
/* linear extrapolation */
|
||||
val = h->vals[i] - 2 * d1 * tim / stp;
|
||||
ne++;
|
||||
d = val - emean;
|
||||
emean += d / ne;
|
||||
esig += d * (val - emean);
|
||||
val = h->vals[i];
|
||||
ne++;
|
||||
d = val - emean;
|
||||
emean += d / ne;
|
||||
esig += d * (val - emean);
|
||||
}
|
||||
if (n > 1) {
|
||||
vsig = sqrt(vsig / (n - 1));
|
||||
if (vsig < h->err) {
|
||||
h->err = vsig;
|
||||
h->fore = val1;
|
||||
if (fact1 > 0.9) {
|
||||
h->weight = (1 - fact1) / stp;
|
||||
} else {
|
||||
h->weight = 1 - pow(fact1, 1.0/stp);
|
||||
}
|
||||
}
|
||||
}
|
||||
esig = sqrt(esig / (ne - 1));
|
||||
if (esig < errLin) {
|
||||
errLin = esig;
|
||||
valLin = emean;
|
||||
}
|
||||
}
|
||||
h->init = 1;
|
||||
if (h->fore == 0) {
|
||||
h->fore = valLin;
|
||||
h->err = errLin;
|
||||
h->init = -1;
|
||||
h->weight = 1.0 / tim;
|
||||
}
|
||||
return h->fore;
|
||||
}
|
||||
|
||||
#define MAXTIMES 16
|
||||
|
||||
typedef struct {
|
||||
int init;
|
||||
int ntimes;
|
||||
float period;
|
||||
float mn[MAXTIMES];
|
||||
float mx[MAXTIMES];
|
||||
float upper;
|
||||
float lower;
|
||||
} Stat;
|
||||
|
||||
static Stat mStat, sStat;
|
||||
|
||||
void statInit(Stat *s, float mn, float mx) {
|
||||
int i;
|
||||
assert(mx >= mn);
|
||||
for (i=1; i < MAXTIMES; i++) {
|
||||
s->mn[i] = mn;
|
||||
s->mx[i] = mx;
|
||||
}
|
||||
}
|
||||
|
||||
void statCrop(Stat *s, float mn, float mx) {
|
||||
int i;
|
||||
float d;
|
||||
|
||||
if (mn > s->upper) {
|
||||
d = mn - s->upper;
|
||||
for (i=1; i < MAXTIMES; i++) {
|
||||
s->mx[i] += d;
|
||||
}
|
||||
}
|
||||
if (mx < s->lower) {
|
||||
d = mx - s->lower;
|
||||
for (i=1; i < MAXTIMES; i++) {
|
||||
s->mn[i] += d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void statBegin(Stat *s, float period, float value) {
|
||||
s->ntimes = 0;
|
||||
s->period = period;
|
||||
s->mn[0] = value;
|
||||
s->mx[0] = value;
|
||||
if (s->init == 0) { /* put a start value */
|
||||
s->init = 1;
|
||||
statInit(s, value*0.9, value*1.1);
|
||||
}
|
||||
s->lower = 0;
|
||||
s->upper = 0;
|
||||
}
|
||||
|
||||
int statTime(Stat *s, float tim1, float tim2) {
|
||||
float w1, w2, dif, mn, mx;
|
||||
int i;
|
||||
|
||||
i = s->ntimes;
|
||||
assert(tim1 <= tim2);
|
||||
assert(i < MAXTIMES-1);
|
||||
|
||||
mn = s->mn[s->ntimes];
|
||||
mx = s->mx[s->ntimes];
|
||||
s->ntimes++;
|
||||
i = s->ntimes;
|
||||
s->upper = s->mx[i];
|
||||
s->lower = s->mn[i];
|
||||
if (tim1 <= 0) {
|
||||
w1 = 1;
|
||||
} else {
|
||||
w1 = 1 - exp(-s->period / tim1);
|
||||
}
|
||||
if (tim2 <= 0) {
|
||||
w2 = 1;
|
||||
} else {
|
||||
w2 = 1 - exp(-s->period / tim2);
|
||||
}
|
||||
dif = mx - s->mx[i];
|
||||
if (dif > 0) {
|
||||
s->mx[i] += w1 * dif;
|
||||
} else {
|
||||
s->mx[i] += w2 * dif;
|
||||
}
|
||||
dif = mn - s->mn[i];
|
||||
if (dif < 0) {
|
||||
s->mn[i] += w1 * dif;
|
||||
} else {
|
||||
s->mn[i] += w2 * dif;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void statEnd(Stat *s) {
|
||||
int i;
|
||||
i = s->ntimes;
|
||||
if (s->upper < s->mx[i]) {
|
||||
s->upper = s->mx[i];
|
||||
}
|
||||
if (s->lower > s->mn[i]) {
|
||||
s->lower = s->mn[i];
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float slope;
|
||||
float last;
|
||||
float mx;
|
||||
int wasmax;
|
||||
time_t lastTim;
|
||||
} Slope;
|
||||
|
||||
|
||||
void maxSlope(Slope *s, float value) {
|
||||
float d;
|
||||
if (rdTim <= s->lastTim + per*0.0015) {
|
||||
return;
|
||||
}
|
||||
s->wasmax = 0;
|
||||
if (s->slope < 0) {
|
||||
s->last = value;
|
||||
s->lastTim = rdTim;
|
||||
s->slope = 0;
|
||||
} else {
|
||||
d = (value - s->last) / (rdTim - s->lastTim);
|
||||
s->slope = d;
|
||||
if (fabsf(d) > s->mx) {
|
||||
s->mx = fabsf(d);
|
||||
s->wasmax = 1;
|
||||
}
|
||||
}
|
||||
s->last = value;
|
||||
s->lastTim = rdTim;
|
||||
}
|
||||
|
||||
static Slope slopeS, slopeU, slopeL;
|
||||
|
||||
|
||||
int PeriodicTask(void) {
|
||||
static int lastIntTim;
|
||||
char buf[256], lbuf[16];
|
||||
char *next, *alms;
|
||||
int i, k, cnt;
|
||||
float p, d, w, t, dif, htr0, mstep, fdif;
|
||||
float t, htr0, mstep, fdif, d, dif2, ml;
|
||||
|
||||
static time_t finTime;
|
||||
static int lastIntTim;
|
||||
static float dif=0;
|
||||
static float oldSet=0;
|
||||
static float oldShift=0;
|
||||
|
||||
/*
|
||||
static float shiftTarget=0;
|
||||
*/
|
||||
if (nScan==0) {
|
||||
ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;BUSY?>busy"));
|
||||
} else {
|
||||
@@ -1997,6 +2290,8 @@ int PeriodicTask(void) {
|
||||
|
||||
ERR_I(ReadTemp());
|
||||
|
||||
snprintf(ttp, sizeof(ttp), "%.6g %.6g %.6g", tm, tr, power);
|
||||
|
||||
if (htrst!=htrst0) {
|
||||
LogMinMax(0);
|
||||
if (htrst==0) {
|
||||
@@ -2075,24 +2370,85 @@ int PeriodicTask(void) {
|
||||
lastIntTim=0;
|
||||
}
|
||||
}
|
||||
if (cryo.sensor1!=samp.sensor1 && controlMode==2) {
|
||||
d=fdif/t; /* relative difference */
|
||||
w=exp(-d*d*230); /* gaussian */
|
||||
/* if (w<0.1) tInt=0; reset when far from setpoint (more than 10 %) */
|
||||
if (int2<1) int2=1;
|
||||
if (tInt<int2) tInt+=w*per/1000; /* increase integral time until int2 sec. */
|
||||
if (tInt>w) {
|
||||
p=w/tInt;
|
||||
} else {
|
||||
p=1.0;
|
||||
ml = set/100;
|
||||
if (ml == 0) ml = 1;
|
||||
|
||||
statBegin(&mStat, per*0.001, TrueScale(ctlSens, ctlSens->t));
|
||||
statTime(&mStat, 10, 20);
|
||||
statTime(&mStat, int2/16, int2/2);
|
||||
statTime(&mStat, int2/1.5, int2+10);
|
||||
statEnd(&mStat);
|
||||
|
||||
statBegin(&sStat, per*0.001, samp.temp);
|
||||
statTime(&sStat, 10, 20);
|
||||
statEnd(&sStat);
|
||||
|
||||
maxSlope(&slopeS, samp.temp);
|
||||
maxSlope(&slopeU, mStat.upper);
|
||||
maxSlope(&slopeL, mStat.lower);
|
||||
|
||||
/* statBegin(&sStat, maxShift*0.01, per*0.001, samp.temp); */
|
||||
|
||||
d = set - samp.temp;
|
||||
shiftLow = mStat.lower - sStat.upper;
|
||||
shiftUp = mStat.upper - sStat.lower;
|
||||
if (cryo.sensor1!=samp.sensor1 && doubleControl) {
|
||||
dif2 = d - dif;
|
||||
if (oldSet == 0) oldSet = samp.temp;
|
||||
if (oldSet != set || fabsf(d) > 50*ml) {
|
||||
if (oldSet != set) {
|
||||
if (set < oldSet) {
|
||||
tShift *= set/oldSet;
|
||||
}
|
||||
state = 1;
|
||||
} else {
|
||||
state = 0;
|
||||
}
|
||||
finTime = rdTim + int2 + 30;
|
||||
slopeS.mx = -1;
|
||||
slopeU.mx = -1;
|
||||
slopeL.mx = -1;
|
||||
}
|
||||
dif=cryo.temp-samp.temp;
|
||||
tShift=tShift*(1.0-p)+p*(cryo.temp-samp.temp);
|
||||
if (rdTim < finTime) {
|
||||
if (slopeS.wasmax) {
|
||||
finTime = rdTim + int2 + 30;
|
||||
}
|
||||
if (fabs(slopeS.slope) > slopeS.mx * 0.2
|
||||
&& finTime < rdTim + per * 0.0035) {
|
||||
finTime = rdTim + per * 0.0035;
|
||||
}
|
||||
if (d > 0) {
|
||||
tShift = oldShift + propUp * d;
|
||||
} else {
|
||||
tShift = oldShift + propDown * d;
|
||||
}
|
||||
} else {
|
||||
if (state != 2) {
|
||||
tShift = oldShift;
|
||||
state = 2;
|
||||
statCrop(&mStat, sStat.lower+tShift, sStat.upper+tShift);
|
||||
}
|
||||
if (shiftLow > tShift) {
|
||||
tShift = shiftLow;
|
||||
} else if (shiftUp < tShift) {
|
||||
tShift = shiftUp;
|
||||
}
|
||||
oldShift = tShift;
|
||||
}
|
||||
if (tShift > ml * maxShift) {
|
||||
tShift = ml * maxShift;
|
||||
} else if (tShift < -ml * maxShift) {
|
||||
tShift = - ml * maxShift;
|
||||
}
|
||||
dif = d;
|
||||
ERR_I(SetTemp(0));
|
||||
} else {
|
||||
ERR_I(SetTemp(0));
|
||||
}
|
||||
} else {
|
||||
oldShift = 0;
|
||||
}
|
||||
oldSet = set;
|
||||
|
||||
if (nScan==0) {
|
||||
ERR_P(LscCmd(ser, "KEYST?>key;DIOST?>cod2,out2;DOUT 3,30"));
|
||||
@@ -2114,6 +2470,13 @@ int PeriodicTask(void) {
|
||||
if (out1==30 && out2==29) {
|
||||
/* code conversion */
|
||||
plug0.code1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */
|
||||
if ((plug0.code1 & 0x2a) == 0x20) {
|
||||
/* for external switch (MA09) */
|
||||
scanChan = cod1 & 0x03;
|
||||
plug0.code1 = plug0.code1 & 0x30;
|
||||
} else {
|
||||
scanChan = DATA_UNDEF;
|
||||
}
|
||||
plug1.code1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]);
|
||||
for (i=0; i<2; i++) {
|
||||
plug=plugs[i];
|
||||
@@ -2145,6 +2508,7 @@ int PeriodicTask(void) {
|
||||
|
||||
if (key!=0) {
|
||||
ERR_P(LscCmd(ser, "MODE?>remoteMode"));
|
||||
local = (remoteMode == 1);
|
||||
if (!touched) {
|
||||
touched=1;
|
||||
logfileOut(LOG_MAIN ,"user touched keys\n");
|
||||
@@ -2153,7 +2517,7 @@ int PeriodicTask(void) {
|
||||
logfileOut(LOG_MAIN ,"user switched to remote\n");
|
||||
touched=0;
|
||||
ERR_I(LoadFromLsc());
|
||||
if (controlMode==2) {
|
||||
if (doubleControl) {
|
||||
ERR_P(LscCmd(ser, "RANGE?>iRange"));
|
||||
if (iRange==0) set=0;
|
||||
} else {
|
||||
@@ -2261,32 +2625,25 @@ int TLimitHdl(int mode, void *base, int fd) {
|
||||
}
|
||||
|
||||
int SwapHdl(int mode, void *base, int fd) {
|
||||
int i,j;
|
||||
static int idx[2];
|
||||
static char swp;
|
||||
static SensorT *s1, *s2;
|
||||
|
||||
if (mode==COC_WR) {
|
||||
if (strlen(swap) != 2) ERR_MSG("must be 2 letters");
|
||||
str_lowcase(swap, swap);
|
||||
for (j=0; j<2; j++) {
|
||||
idx[j]=-1;
|
||||
for (i=0; i<4; i++) {
|
||||
if (swap[j] == tolower(sensors[i]->ch[0])) {
|
||||
swap[j]=sensors[i]->typ;
|
||||
}
|
||||
if (sensors[i]->typ == swap[j]) idx[j]=i;
|
||||
}
|
||||
if (strchr("msnltk", swap[j]) == 0) ERR_MSG("only letters m,s,n,l,e,k are allowed");
|
||||
s1 = findSensor(swap[0]);
|
||||
s2 = findSensor(swap[1]);
|
||||
if (s1 == NULL || s2 == NULL) {
|
||||
ERR_MSG("no such sensor(s)");
|
||||
}
|
||||
if (idx[0]==idx[1]) {
|
||||
if (idx[0]<0) ERR_MSG("no such sensors");
|
||||
if (s1 == s2) {
|
||||
return 0;
|
||||
}
|
||||
return COC_DWR;
|
||||
} else if (mode==COC_DWR) {
|
||||
for (j=0; j<2; j++) {
|
||||
if (idx[j]>=0) {
|
||||
sensors[idx[j]]->typ=swap[1-j];
|
||||
}
|
||||
}
|
||||
swp = s1->typ;
|
||||
s2->typ = s1->typ;
|
||||
s1->typ = swp;
|
||||
AssignTypes();
|
||||
}
|
||||
return 0;
|
||||
@@ -2381,7 +2738,6 @@ int SetHdl(int mode, void *base, int fd) {
|
||||
ERR_P(LscCmd(ser, "CMODE [loop],1;MOUT [loop],0"));
|
||||
}
|
||||
if (cryo.sensor1!=NULL && remoteMode==2) {
|
||||
tInt=0; /* reset integral time */
|
||||
ERR_I(SetTemp(1));
|
||||
}
|
||||
}
|
||||
@@ -2389,6 +2745,26 @@ int SetHdl(int mode, void *base, int fd) {
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
int ControlModeHdl(int mode, void *base, int fd) {
|
||||
if (mode==COC_WR) {
|
||||
if (controlMode == 1) {
|
||||
controlSensor[0]='1';
|
||||
} else {
|
||||
controlSensor[0]='0';
|
||||
}
|
||||
if (controlMode >= 2) {
|
||||
doubleControl = 1;
|
||||
controlMode = 2;
|
||||
} else {
|
||||
doubleControl = 0;
|
||||
if (controlMode < 0) {
|
||||
controlMode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SetHdl(mode, base, fd);
|
||||
}
|
||||
|
||||
int MaxPowerHdl(int mode, void *base, int fd) {
|
||||
static float setpower;
|
||||
if (mode==COC_WR) {
|
||||
@@ -2764,6 +3140,17 @@ int RemoteHdl(int mode, void *base, int fd) {
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
int LocalHdl(int mode, void *base, int fd) {
|
||||
if (mode==COC_RD) {
|
||||
local = (remoteMode == 1);
|
||||
return 0;
|
||||
} else if (mode==COC_WR) {
|
||||
remoteMode = 1 + (local == 0);
|
||||
return RemoteHdl(mode, base, fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelayHdl(int mode, void *base, int fd) {
|
||||
if (mode==COC_WR) {
|
||||
if (alarmChannels[0]!='\0') ERR_MSG("alarm is still active");
|
||||
@@ -2845,7 +3232,6 @@ int MainBody(void) {
|
||||
per=1000; /* 1 sec */
|
||||
cryo.temp=0;
|
||||
samp.temp=0;
|
||||
/* remoteMode=1; */
|
||||
noResp=3;
|
||||
} else if (noResp < 2) {
|
||||
logfileShowErr("no response");
|
||||
@@ -2922,8 +3308,10 @@ int main(int argc, char *argv[]) {
|
||||
CocDefFlt(setH, RD);
|
||||
CocDefFlt(full, RW);
|
||||
CocDefFlt(empty, RW);
|
||||
CocDefFlt(int2, RW);
|
||||
CocDefFlt(propUp, RW);
|
||||
CocDefFlt(propDown, RW);
|
||||
CocDefFlt(maxShift, RW);
|
||||
CocDefFlt(maxOver, RW);
|
||||
CocDefFlt(tm, RD);
|
||||
CocDefFlt(ts, RD);
|
||||
CocDefFlt(tr, RD);
|
||||
@@ -2936,8 +3324,12 @@ int main(int argc, char *argv[]) {
|
||||
CocDefFlt(r1, RD);
|
||||
CocDefFlt(r2, RD);
|
||||
CocDefFlt(tShift, RW);
|
||||
CocDefFlt(tInt, RW);
|
||||
CocDefFlt(linearPower, RW);
|
||||
CocDefFlt(scanChan, RW);
|
||||
|
||||
CocDefFlt(shiftUp, RW);
|
||||
CocDefFlt(shiftLow, RW);
|
||||
CocDefFlt(state, RW);
|
||||
|
||||
CocDefPtr(clData, ClientData);
|
||||
CocStrFld(ClientData, cmd, RW); CocHdl(SendHdl);
|
||||
@@ -2966,6 +3358,7 @@ int main(int argc, char *argv[]) {
|
||||
CocDefStr(devHelp, RD); CocHdl(DevHelpHdl);
|
||||
CocDefStr(update, RW); CocHdl(UpdateHdl);
|
||||
CocDefStr(lscfg, RD);
|
||||
CocDefStr(ttp, RD);
|
||||
|
||||
CocDefInt(cod1, RD);
|
||||
CocDefInt(cod2, RD);
|
||||
@@ -2978,6 +3371,7 @@ int main(int argc, char *argv[]) {
|
||||
CocDefInt(iRange, RD);
|
||||
CocDefInt(jRange, RD);
|
||||
CocDefInt(remoteMode, RW); CocHdl(RemoteHdl);
|
||||
CocDefInt(local, RW); CocHdl(LocalHdl);
|
||||
CocDefInt(relay, RW); CocHdl(RelayHdl);
|
||||
CocDefInt(manual, RW); CocHdl(ManualHdl);
|
||||
CocDefInt(htrst, RD);
|
||||
@@ -2989,14 +3383,16 @@ int main(int argc, char *argv[]) {
|
||||
CocDefInt(logMask, RW);
|
||||
CocDefInt(logPeriod, RW);
|
||||
CocDefInt(readTemp, RW);
|
||||
CocDefInt(controlMode, RW); CocHdl(SetHdl);
|
||||
CocDefInt(int2, RW);
|
||||
CocDefInt(controlMode, RW); CocHdl(ControlModeHdl);
|
||||
CocDefInt(busy, RD);
|
||||
CocDefInt(serialNo, RD);
|
||||
CocDefInt(quit, RW);
|
||||
CocDefInt(nScan, RD);
|
||||
CocDefInt(keepT, RW);
|
||||
CocDefInt(swRangeOn, RW);
|
||||
CocDefInt(doubleControl, RW);
|
||||
|
||||
CocDefStr(controlSensor, RW); CocHdl(SetHdl);
|
||||
|
||||
CocDefStr(grapar, RA);
|
||||
CocDefArr(gradata, RD); CocHdl(GraHdl); grasize=CocSizePtr();
|
||||
@@ -3136,8 +3532,17 @@ int main(int argc, char *argv[]) {
|
||||
ERR_P(DataCreateSet(NULL, "T4", &sensA4.t, logPeriod, LOGLIFETIME, tim));
|
||||
ERR_P(DataCreateSet(NULL, "Aux", &aux, logPeriod, LOGLIFETIME, tim));
|
||||
ERR_P(DataCreateSet(NULL, "P", &power, logPeriod, LOGLIFETIME, tim));
|
||||
|
||||
ERR_P(DataCreateSet(NULL, "ScanChan", &scanChan, logPeriod, LOGLIFETIME, tim));
|
||||
DataUndef(0);
|
||||
ERR_P(DataCreateSet(NULL, "Set", &set, logPeriod, LOGLIFETIME, tim));
|
||||
ERR_P(DataCreateSet(NULL, "shiftUp", &shiftUp, logPeriod, LOGLIFETIME, tim));
|
||||
ERR_P(DataCreateSet(NULL, "shiftLow", &shiftLow, logPeriod, LOGLIFETIME, tim));
|
||||
ERR_P(DataCreateSet(NULL, "state", &state, logPeriod, LOGLIFETIME, tim));
|
||||
DataUndef(DATA_UNDEF);
|
||||
ERR_P(DataCreateSet(NULL, "tShift", &tShift, logPeriod, LOGLIFETIME, tim));
|
||||
|
||||
remoteMode=2;
|
||||
local = 0;
|
||||
prop=50;
|
||||
integ=20;
|
||||
deriv=0;
|
||||
|
||||
@@ -91,6 +91,22 @@ int TeccGetX(pTecsClient conn, float *tC, float *tP, float *tDif) {
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccGetMult(pTecsClient conn, int argc, char *argv[], void (* outfunc)(char *, void *), void *arg) {
|
||||
OutFunc f;
|
||||
int iret, i;
|
||||
|
||||
f.func = outfunc;
|
||||
f.arg = arg;
|
||||
CocReset(conn);
|
||||
for (i=0; i<argc; i++) {
|
||||
ERR_I(CocGetOut(conn, argv[i], &f));
|
||||
}
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
if (iret) ERR_MSG(response);
|
||||
return 0;
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp) {
|
||||
int iret;
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ int TeccGetX(pTecsClient conn, float *tC, float *tP, float *tDif);
|
||||
int TeccGet3(pTecsClient conn, float *tSet, float *tExch, float *tSamp);
|
||||
/* get temperatures */
|
||||
|
||||
int TeccGetMult(pTecsClient conn, int argc, char *argv[], void (* outfunc)(char *, void *), void *arg);
|
||||
/* get multiple values */
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp);
|
||||
/* set temperature */
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct Set {
|
||||
int step, lifetime;
|
||||
int start, end;
|
||||
float *var;
|
||||
float undef;
|
||||
Run *runs;
|
||||
Summary sum;
|
||||
Logger *log;
|
||||
@@ -50,6 +51,12 @@ typedef struct {
|
||||
|
||||
static Base database;
|
||||
|
||||
static float undef_value = DATA_UNDEF; /* additonal undef value */
|
||||
|
||||
void DataUndef(float undef) {
|
||||
undef_value = undef;
|
||||
}
|
||||
|
||||
void InsSum(Summary *sum, int t, float d) {
|
||||
if (sum->tmin == 0) {
|
||||
sum->tmin = t;
|
||||
@@ -127,6 +134,7 @@ Set *CreateSet(Base *base, char *name, float *var, int step, int lifetime, int s
|
||||
s->start = start;
|
||||
s->step = step;
|
||||
s->var = var;
|
||||
s->undef = undef_value;
|
||||
s->log = NULL;
|
||||
ResetSum(&s->sum);
|
||||
return s;
|
||||
@@ -273,6 +281,7 @@ int DataPutAll(DataBase *base, int mytime) {
|
||||
char value[32];
|
||||
char tname[32];
|
||||
static time_t lastOpen = 0;
|
||||
float val;
|
||||
|
||||
if (base == NULL) {
|
||||
s=database.head;
|
||||
@@ -281,8 +290,12 @@ int DataPutAll(DataBase *base, int mytime) {
|
||||
}
|
||||
while (s!=NULL) {
|
||||
if (s->var!=NULL) {
|
||||
ERR_I(Put(s, mytime, *s->var));
|
||||
if (s->log == NULL && *s->var != DATA_UNDEF && time(NULL) > lastOpen + 300) {
|
||||
val = *s->var;
|
||||
if (val == s->undef) {
|
||||
val = DATA_UNDEF;
|
||||
}
|
||||
ERR_I(Put(s, mytime, val));
|
||||
if (s->log == NULL && val != DATA_UNDEF && time(NULL) > lastOpen + 300) {
|
||||
/* try to make logger if not yet tried in the last 5 min. */
|
||||
snprintf(tname, sizeof tname, "tt.%s", s->set.name);
|
||||
s->log = LoggerMake(tname, s->step, 0);
|
||||
@@ -291,10 +304,10 @@ int DataPutAll(DataBase *base, int mytime) {
|
||||
}
|
||||
}
|
||||
if (s->log != NULL) {
|
||||
if (*s->var == DATA_UNDEF) {
|
||||
if (val == DATA_UNDEF) {
|
||||
value[0]='\0';
|
||||
} else {
|
||||
snprintf(value, sizeof value, "%.5g", *s->var);
|
||||
snprintf(value, sizeof value, "%.5g", val);
|
||||
}
|
||||
LoggerWrite(s->log, mycUnixTime(mytime), s->step, value);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ int DataGetMult(char *names, int startTime, int endTime, int step, int stdStep,
|
||||
get multiple datasets
|
||||
*/
|
||||
|
||||
void DataUndef(float undef);
|
||||
|
||||
/*
|
||||
define DATA_UNDEF as a binary and decimal well defined, hopefully rarely used number
|
||||
*/
|
||||
|
||||
16
tecs/term.c
16
tecs/term.c
@@ -191,7 +191,8 @@ FILE *term_open_pref(int temp, char *head, char *mode) {
|
||||
char *usr, *home, *p;
|
||||
int l;
|
||||
FILE *fil;
|
||||
|
||||
mode_t oldmask;
|
||||
|
||||
usr = getenv("USER");
|
||||
if (temp && usr==NULL) return NULL;
|
||||
if (usr != NULL && *usr != '\0' && strstr(usr, "lnsg") != 0) {
|
||||
@@ -226,7 +227,9 @@ FILE *term_open_pref(int temp, char *head, char *mode) {
|
||||
str_append(old, usr);
|
||||
/* new file name */
|
||||
str_copy(buf, "/tmp/six/");
|
||||
mkdir(buf, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH);
|
||||
oldmask = umask(0);
|
||||
mkdir(buf, S_IRWXU+S_IRWXG+S_IRWXO);
|
||||
umask(oldmask);
|
||||
str_append(buf, head);
|
||||
str_append(buf, ".");
|
||||
str_append(buf, usr); /* usr is the username, or lnsg_<subdirectory> */
|
||||
@@ -296,13 +299,14 @@ void term_save_hist(int trimlast) {
|
||||
fclose(fil);
|
||||
}
|
||||
|
||||
void term_read_hist(char *id) {
|
||||
void term_read_hist(char *id, char *instr) {
|
||||
FILE *fil;
|
||||
int i;
|
||||
char buf[1024], *lin;
|
||||
|
||||
str_copy(filehead, id);
|
||||
str_append(filehead, "_hist");
|
||||
str_append(filehead, "_hist_");
|
||||
str_append(filehead, instr);
|
||||
fil=term_open_pref(1, filehead, "r");
|
||||
if (fil==NULL) return;
|
||||
hist_end=0;
|
||||
@@ -340,8 +344,8 @@ int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
|
||||
char *lin;
|
||||
int key;
|
||||
int i,l,iret,buflen;
|
||||
char tmp[512];
|
||||
static char back[128]="";
|
||||
char tmp[1024];
|
||||
static char back[512]="";
|
||||
|
||||
if (back[0] == '\0') {
|
||||
memset(back, '\b', sizeof back);
|
||||
|
||||
@@ -30,7 +30,7 @@ FILE *term_open_pref(int temp, char *head, char *mode);
|
||||
char *term_fgets(char *buf, int size, FILE *fil);
|
||||
/* fgets without newline */
|
||||
|
||||
void term_read_hist(char *id);
|
||||
void term_read_hist(char *id, char *instr);
|
||||
/* read history from temporary file with id */
|
||||
|
||||
void term_save_hist(int trimlast);
|
||||
|
||||
Reference in New Issue
Block a user