From 735a0e6987341196730fc92e4987a7c14efb64c8 Mon Sep 17 00:00:00 2001 From: zolliker Date: Tue, 20 Jun 2006 13:30:48 +0000 Subject: [PATCH] - new double control (former controlmode = 2) - better sea client compatibility --- tecs/coc_client.c | 14 +- tecs/coc_client.h | 6 + tecs/six.c | 7 +- tecs/tecs.c | 563 +++++++++++++++++++++++++++++++++++++++------- tecs/tecs_cli.c | 16 ++ tecs/tecs_cli.h | 3 + tecs/tecs_data.c | 21 +- tecs/tecs_data.h | 2 + tecs/term.c | 16 +- tecs/term.h | 2 +- 10 files changed, 556 insertions(+), 94 deletions(-) diff --git a/tecs/coc_client.c b/tecs/coc_client.c index cd2ab13..1790e2a 100644 --- a/tecs/coc_client.c +++ b/tecs/coc_client.c @@ -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=""; } 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"); } diff --git a/tecs/coc_client.h b/tecs/coc_client.h index a08ea55..37d1a4e 100644 --- a/tecs/coc_client.h +++ b/tecs/coc_client.h @@ -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); diff --git a/tecs/six.c b/tecs/six.c index d2ab7b5..9f67952 100644 --- a/tecs/six.c +++ b/tecs/six.c @@ -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) { diff --git a/tecs/tecs.c b/tecs/tecs.c index a9cf779..7e23f79 100644 --- a/tecs/tecs.c +++ b/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; ivals[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 (tIntw) { - 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; diff --git a/tecs/tecs_cli.c b/tecs/tecs_cli.c index 9e9aa53..28e0ace 100644 --- a/tecs/tecs_cli.c +++ b/tecs/tecs_cli.c @@ -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; itmin == 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); } diff --git a/tecs/tecs_data.h b/tecs/tecs_data.h index 75bc112..048ddf3 100644 --- a/tecs/tecs_data.h +++ b/tecs/tecs_data.h @@ -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 */ diff --git a/tecs/term.c b/tecs/term.c index 9da298e..752d8d0 100644 --- a/tecs/term.c +++ b/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_ */ @@ -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); diff --git a/tecs/term.h b/tecs/term.h index 93abddf..54010dc 100644 --- a/tecs/term.h +++ b/tecs/term.h @@ -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);