- New oscillator module - Bug fixes SKIPPED: psi/buffer.c psi/el734hp.c psi/el737hpdriv.c psi/make_gen psi/nextrics.c psi/nxamor.c psi/pimotor.c psi/polterwrite.c psi/psi.c psi/swmotor2.c psi/tasscan.c psi/tricssupport.c psi/tricssupport.h psi/tecs/make_gen psi/utils/ecb_load_new/ecb_load.c psi/utils/ecb_load_new/ecb_load.h psi/utils/ecb_load_new/ecbdriv_els.c psi/utils/ecb_load_new/gpib_els.c psi/utils/ecb_load_new/makefile psi/utils/ecb_load_new/makefile_EGPIB psi/utils/ecb_load_new/makefile_GPIB
232 lines
6.2 KiB
C
232 lines
6.2 KiB
C
/*-----------------------------------------------------------------------
|
|
Oscillator runs a motor back and forth between its software limits.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, November 2004
|
|
------------------------------------------------------------------------*/
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <tcl.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "task.h"
|
|
#include "oscillate.h"
|
|
/*================== real work =========================================*/
|
|
static void StopOscillation(pOscillator self){
|
|
assert(self != NULL);
|
|
if(self->taskID > 0){
|
|
self->pMot->pDriver->Halt(self->pMot->pDriver);
|
|
self->stopFlag = 1;
|
|
MotorSetPar(self->pMot,self->pCon,"accesscode",(float)self->oldRights);
|
|
self->taskID = -1;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
static int OscillationTask(void *data){
|
|
pOscillator self = (pOscillator)data;
|
|
int status, code, errStatus;
|
|
char error[256];
|
|
float pos;
|
|
|
|
|
|
assert(self);
|
|
if(self->stopFlag == 1){
|
|
return 0;
|
|
}
|
|
|
|
status = self->pMot->pDriver->GetStatus(self->pMot->pDriver);
|
|
switch(status){
|
|
case HWFault:
|
|
case HWPosFault:
|
|
self->pMot->pDriver->GetError(self->pMot->pDriver,&code,error,255);
|
|
SCWrite(self->pCon,error,eError);
|
|
if(self->nextTargetFlag == 1){
|
|
pos = self->lowerLimit;
|
|
} else {
|
|
pos = self->upperLimit;
|
|
}
|
|
errStatus = self->pMot->pDriver->TryAndFixIt(self->pMot->pDriver,code,pos);
|
|
self->errorCount++;
|
|
if(errStatus == MOTFAIL){
|
|
MotorRun(self->pMot,self->pCon,pos);
|
|
}
|
|
break;
|
|
case HWBusy:
|
|
break;
|
|
case HWIdle:
|
|
if(self->nextTargetFlag == 1){
|
|
pos = self->upperLimit;
|
|
self->nextTargetFlag = 0;
|
|
} else {
|
|
pos = self->lowerLimit;
|
|
self->nextTargetFlag = 1;
|
|
}
|
|
MotorRun(self->pMot,self->pCon,pos);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------*/
|
|
static int StartOscillation(pOscillator self, SConnection *pCon){
|
|
float fval;
|
|
int status;
|
|
char error[80], pBueffel[255];
|
|
|
|
assert(self);
|
|
|
|
if(self->taskID > 0){
|
|
SCWrite(pCon,"ERROR: oscillation already running",eError);
|
|
return 1;
|
|
}
|
|
|
|
MotorGetPar(self->pMot,"softlowerlim",&self->lowerLimit);
|
|
self->lowerLimit += .5;
|
|
MotorGetPar(self->pMot,"softupperlim",&self->upperLimit);
|
|
self->upperLimit -= .5;
|
|
MotorGetPar(self->pMot,"accesscode",&fval);
|
|
self->oldRights = (int)fval;
|
|
MotorSetPar(self->pMot,self->pCon,"accesscode",(float)usInternal);
|
|
self->nextTargetFlag = 0;
|
|
self->errorCount = 0;
|
|
self->stopFlag = 0;
|
|
|
|
/*
|
|
check reachability of limits
|
|
*/
|
|
status = MotorCheckBoundary(self->pMot,self->lowerLimit,&fval,error,79);
|
|
if(!status){
|
|
snprintf(pBueffel,255,"ERROR: cannot reach %f: %s reported",
|
|
self->lowerLimit,error);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
status = MotorCheckBoundary(self->pMot,self->upperLimit,&fval,error,79);
|
|
if(!status){
|
|
snprintf(pBueffel,255,"ERROR: cannot reach %f: %s reported",
|
|
self->upperLimit,error);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
start task
|
|
*/
|
|
self->taskID = TaskRegister(pServ->pTasker,
|
|
OscillationTask,
|
|
NULL,
|
|
NULL,
|
|
self,
|
|
10);
|
|
if(self->taskID < 0){
|
|
SCWrite(pCon,"ERROR: failed to start oscillation task",eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*===================== life and death =================================*/
|
|
static void KillOscillator(void *data){
|
|
pOscillator self = (pOscillator)data;
|
|
if(self != NULL){
|
|
StopOscillation(self);
|
|
if(self->pDes != NULL){
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if(self->pCon != NULL){
|
|
SCDeleteConnection(self->pCon);
|
|
}
|
|
free(self);
|
|
}
|
|
}
|
|
/*========================================================================*/
|
|
int MakeOscillator(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pOscillator pNew = NULL;
|
|
pMotor pMot = NULL;
|
|
char pBueffel[132];
|
|
int status;
|
|
|
|
if(argc < 3){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeOscilator",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
pMot = FindMotor(pSics,argv[2]);
|
|
if(pMot == NULL){
|
|
snprintf(pBueffel,131,"ERROR: %s is no motor",argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
pNew = (pOscillator)malloc(sizeof(Oscillator));
|
|
if(pNew == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory creating oscillator",eError);
|
|
return 0;
|
|
}
|
|
memset(pNew,0,sizeof(Oscillator));
|
|
pNew->pDes = CreateDescriptor("Oscillator");
|
|
pNew->pMot = pMot;
|
|
pNew->pCon = SCCreateDummyConnection(pSics);
|
|
if(!pNew->pDes || !pNew->pCon){
|
|
SCWrite(pCon,"ERROR: out of memory creating oscillator",eError);
|
|
return 0;
|
|
}
|
|
SCSetWriteFunc(pNew->pCon,SCFileWrite);
|
|
SCSetRights(pNew->pCon,usInternal);
|
|
|
|
status = AddCommand(pSics,argv[1],
|
|
OscillatorWrapper,
|
|
KillOscillator,
|
|
pNew);
|
|
if(!status){
|
|
snprintf(pBueffel,131,"ERROR: duplicate command %s not created",argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*========================================================================*/
|
|
int OscillatorWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pOscillator self = (pOscillator)pData;
|
|
char pBueffel[256];
|
|
|
|
assert(self);
|
|
if(argc < 2){
|
|
SCWrite(pCon,"ERROR: need start/stop argument for oscillator",eError);
|
|
return 0;
|
|
}
|
|
|
|
if(!SCMatchRights(pCon,usUser)){
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[1]);
|
|
if(strcmp(argv[1],"start") == 0){
|
|
return StartOscillation(self,pCon);
|
|
} else if(strcmp(argv[1],"stop") == 0) {
|
|
StopOscillation(self);
|
|
snprintf(pBueffel,255,"Oscillation stopped with %d errors, %s",
|
|
self->errorCount,
|
|
"see commandlog for details");
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
} else if(strcmp(argv[1],"status") == 0) {
|
|
if(self->taskID > 0){
|
|
snprintf(pBueffel,255,"Oscillation running, %d errors so far, %s",
|
|
self->errorCount,
|
|
" error details in commandlog");
|
|
} else {
|
|
snprintf(pBueffel,255,"Oscillation stopped");
|
|
}
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
} else {
|
|
SCWrite(pCon,"ERROR: invalid sub command for oscillator requested",
|
|
eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|