- Adding first working version of new AMOR settings module
- Improved sls magnet driver
This commit is contained in:
110
amorcomp.c
Normal file
110
amorcomp.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------
|
||||
AMOR component handling module. For the new (2005) calculation of the
|
||||
positions using the beam height as zero.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
-----------------------------------------------------------------------*/
|
||||
#include "amorcomp.h"
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
|
||||
double calcCompPosition(pamorComp comp){
|
||||
return ABS(comp->scaleOffset - comp->markOffset - comp->readPosition);
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
int handleCompCommand(pamorComp comp, SConnection *pCon,
|
||||
int argc, char *argv[]){
|
||||
char pBueffel[512];
|
||||
|
||||
if(argc < 3) {
|
||||
SCWrite(pCon,"ERROR: not enough arguments",eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[2]);
|
||||
if(strcmp(argv[2],"list") == 0){
|
||||
snprintf(pBueffel,511,
|
||||
"%s %s active = %d\n%s %s offset = %f\n%s %s scaleoffset = %f\n%s %s read = %f\n%s %s calc = %f\n",
|
||||
argv[0], argv[1], comp->activeFlag,
|
||||
argv[0], argv[1], comp->markOffset,
|
||||
argv[0], argv[1], comp->scaleOffset,
|
||||
argv[0], argv[1], comp->readPosition,
|
||||
argv[0], argv[1], calcCompPosition(comp));
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
} else if (strcmp(argv[2], "active") == 0) {
|
||||
if(argc > 3) {
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
SCparChange(pCon);
|
||||
comp->activeFlag = atoi(argv[3]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,511," %s %s active = %d",
|
||||
argv[0], argv[1], comp->activeFlag);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[2], "offset") == 0) {
|
||||
if(argc > 3) {
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
SCparChange(pCon);
|
||||
comp->markOffset = atof(argv[3]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,511," %s %s offset = %f",
|
||||
argv[0], argv[1], comp->markOffset);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[2], "scaleoffset") == 0) {
|
||||
if(argc > 3) {
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
comp->scaleOffset = atof(argv[3]);
|
||||
SCparChange(pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,511," %s %s scaleoffset = %f",
|
||||
argv[0], argv[1], comp->scaleOffset);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[2], "read") == 0) {
|
||||
if(argc > 3) {
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
comp->readPosition = atof(argv[3]);
|
||||
SCparChange(pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,511," %s %s read = %f",
|
||||
argv[0], argv[1], comp->readPosition);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
snprintf(pBueffel,511,"ERROR: subcommand %s to %s %s not understood",
|
||||
argv[2], argv[0], argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int saveAmorComp(FILE *fd, char *name, char *compname, pamorComp comp){
|
||||
fprintf(fd,"%s %s active %d\n", name, compname, comp->activeFlag);
|
||||
fprintf(fd,"%s %s offset %f\n", name, compname, comp->markOffset);
|
||||
fprintf(fd,"%s %s scaleoffset %f\n", name, compname, comp->scaleOffset);
|
||||
fprintf(fd,"%s %s read %f\n", name, compname, comp->readPosition);
|
||||
return 1;
|
||||
}
|
28
amorcomp.h
Normal file
28
amorcomp.h
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
AMOR component handling module. For the new (2005) calculation of the
|
||||
positions using the beam height as zero.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
-----------------------------------------------------------------------*/
|
||||
#ifndef AMORCOMP
|
||||
#define AMORCOMP
|
||||
#include <stdio.h>
|
||||
#include <sics.h>
|
||||
|
||||
typedef struct {
|
||||
int activeFlag; /* component present */
|
||||
double markOffset; /* offset mark to real */
|
||||
double scaleOffset; /* offset of the scale */
|
||||
double readPosition; /* the position as read */
|
||||
} amorComp, *pamorComp;
|
||||
/*----------------------------------------------------------------------*/
|
||||
double calcCompPosition(pamorComp comp);
|
||||
int handleCompCommand(pamorComp comp, SConnection *pCon,
|
||||
int argc, char *argv[]);
|
||||
int saveAmorComp(FILE *fd, char *name, char *compname, pamorComp comp);
|
||||
|
||||
#endif
|
||||
|
170
amordrive.c
Normal file
170
amordrive.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*--------------------------------------------------------------------
|
||||
Part of the AMOR position calculation module.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
----------------------------------------------------------------------*/
|
||||
#include "amorset.h"
|
||||
#include "amordrive.h"
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
static void *AMODRIVGetInterface(void *data, int iD){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
|
||||
if(iD == DRIVEID && self != NULL){
|
||||
return self->pDriv;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return either OKOK or HWFault when thing
|
||||
go wrong. However, the return value of Halt is usually ignored!
|
||||
------------------------------------------------------------------*/
|
||||
static int AMODRIVHalt(void *data) {
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
|
||||
return self->mama->pDriv->Halt(self->mama);
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return either 1 or 0. 1 means the position can
|
||||
be reached, 0 NOT
|
||||
If 0, error shall contain up to errlen characters of information
|
||||
about which limit was violated
|
||||
Due to the complex nauture of the calculation: no check here
|
||||
------------------------------------------------------------------*/
|
||||
static int AMODRIVCheckLimits(void *data, float val,
|
||||
char *error, int errlen){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return 0 when a limit problem occurred
|
||||
OKOK when the motor was successfully started
|
||||
HWFault when a problem occured starting the device
|
||||
Possible errors shall be printed to pCon
|
||||
For real motors, this is supposed to try at least three times
|
||||
to start the motor in question
|
||||
val is the value to drive the motor too
|
||||
------------------------------------------------------------------*/
|
||||
static long AMODRIVSetValue(void *data, SConnection *pCon, float val){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
|
||||
amorSetMotor(self->mama, self->type, val);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
Checks the status of a running motor. Possible return values
|
||||
HWBusy The motor is still running
|
||||
OKOK or HWIdle when the motor finished driving
|
||||
HWFault when a hardware problem ocurred
|
||||
HWPosFault when the hardware cannot reach a position
|
||||
Errors are duly to be printed to pCon
|
||||
For real motors CheckStatus again shall try hard to fix any
|
||||
issues with the motor
|
||||
------------------------------------------------------------------*/
|
||||
static int AMODRIVCheckStatus(void *data, SConnection *pCon){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
|
||||
return self->mama->pDriv->CheckStatus(self->mama, pCon);
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
GetValue is supposed to read a motor position
|
||||
On errors, -99999999.99 is returned and messages printed to pCon
|
||||
------------------------------------------------------------------*/
|
||||
static float AMODRIVGetValue(void *data, SConnection *pCon){
|
||||
pamorDrive self = NULL;
|
||||
float val = -99999999.99;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
return amorGetMotor(self->mama,pCon,self->type);
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
returns NULL on failure, a new datastrcuture else
|
||||
------------------------------------------------------------------*/
|
||||
static pamorDrive AMODRIVMakeObject(){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)malloc(sizeof(amorDrive));
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(self,0,sizeof(amorDrive));
|
||||
self->pDes = CreateDescriptor("AmorDrive");
|
||||
self->pDriv = CreateDrivableInterface();
|
||||
if(self->pDes == NULL || self->pDriv == NULL){
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->pDes->GetInterface = AMODRIVGetInterface;
|
||||
self->pDriv->Halt = AMODRIVHalt;
|
||||
self->pDriv->CheckLimits = AMODRIVCheckLimits;
|
||||
self->pDriv->SetValue = AMODRIVSetValue;
|
||||
self->pDriv->CheckStatus = AMODRIVCheckStatus;
|
||||
self->pDriv->GetValue = AMODRIVGetValue;
|
||||
|
||||
return self;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
void killAmorDrive(void *data){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = (pamorDrive)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->pDes != NULL){
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pDriv != NULL){
|
||||
free(self->pDriv);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
pamorDrive makeAmorDrive(pamorSet papa, int type){
|
||||
pamorDrive self = NULL;
|
||||
|
||||
self = AMODRIVMakeObject();
|
||||
if(self == NULL){
|
||||
return self;
|
||||
}
|
||||
self->mama = papa;
|
||||
self->type = type;
|
||||
return self;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int AmorDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pamorDrive self = NULL;
|
||||
float val;
|
||||
char pBueffel[132];
|
||||
|
||||
self = (pamorDrive)pData;
|
||||
assert(self);
|
||||
val = amorGetMotor(self->mama, pCon,self->type);
|
||||
if(val > -999999) {
|
||||
snprintf(pBueffel,131, " %s = %f", argv[0], val);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
25
amordrive.h
Normal file
25
amordrive.h
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Part of the AMOR position calculation module.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
----------------------------------------------------------------------*/
|
||||
#ifndef AMORDRIVE
|
||||
#define AMORDRIVE
|
||||
|
||||
typedef struct{
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pamorSet mama;
|
||||
int type;
|
||||
} amorDrive, *pamorDrive;
|
||||
/*-----------------------------------------------------------------*/
|
||||
pamorDrive makeAmorDrive(pamorSet papa, int type);
|
||||
void killAmorDrive(void *data);
|
||||
int AmorDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif
|
||||
|
600
amorset.c
Normal file
600
amorset.c
Normal file
@ -0,0 +1,600 @@
|
||||
/*-------------------------------------------------------------------
|
||||
AMORSET together with amorcomp and amordrive implement the position
|
||||
control facility for the reflectometer AMOR. This uses the algorithm
|
||||
with the beam height as the baseline.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
--------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "amorset.h"
|
||||
#include <motorlist.h>
|
||||
#include "amorcomp.h"
|
||||
#include "amordrive.h"
|
||||
#include <trigd.h>
|
||||
#include <lld.h>
|
||||
#include "motor.h"
|
||||
/*--------------------- type defines ------------------------------*/
|
||||
#define TYM2T 1
|
||||
#define TYS2T 2
|
||||
#define TYATH 3
|
||||
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
/*------------ The meat of it all: The settings calculation --------*/
|
||||
static int readMotors(pamorSet self, SConnection *pCon){
|
||||
int result, status;
|
||||
float val;
|
||||
|
||||
result = LLDcreate(sizeof(MotControl));
|
||||
status = addMotorToList(result,"d2t",.0);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: configuration error: d2t not found", eError);
|
||||
return -1;
|
||||
}
|
||||
status = addMotorToList(result,"d3t",.0);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: configuration error: d3t not found", eError);
|
||||
return -1;
|
||||
}
|
||||
status = addMotorToList(result,"d4t",.0);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: configuration error: d4t not found", eError);
|
||||
return -1;
|
||||
}
|
||||
status = addMotorToList(result,"d5t",.0);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: configuration error: d5t not found", eError);
|
||||
return -1;
|
||||
}
|
||||
val = self->listDrive->GetValue(&result,pCon);
|
||||
if(val < -99999){
|
||||
LLDdelete(result);
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static int calcAmorSettings(pamorSet self,SConnection *pCon){
|
||||
int readList;
|
||||
double val, dist, com = .0, soz, mot;
|
||||
|
||||
/*
|
||||
* read motors
|
||||
*/
|
||||
readList = readMotors(self,pCon);
|
||||
if(readList < 0){
|
||||
SCWrite(pCon,
|
||||
"ERROR: failed to read motors for amor settings",eError);
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* initialize drive list
|
||||
*/
|
||||
LLDdelete(self->driveList);
|
||||
self->driveList = LLDcreate(sizeof(MotControl));
|
||||
|
||||
/*
|
||||
* soz
|
||||
*/
|
||||
dist = calcCompPosition(&self->S) - calcCompPosition(&self->M);
|
||||
soz = dist*Tand(self->targetm2t);
|
||||
addMotorToList(self->driveList,"soz",soz);
|
||||
|
||||
/*
|
||||
* monochromator slit
|
||||
*/
|
||||
if(self->DS.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->DS) - calcCompPosition(&self->M);
|
||||
val = dist*Tand(self->targetm2t) - self->dspar;
|
||||
addMotorToList(self->driveList,"dbs",val);
|
||||
}
|
||||
|
||||
/*
|
||||
* slit 2
|
||||
*/
|
||||
if(self->D2.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->D2) - calcCompPosition(&self->M);
|
||||
mot = getListMotorPosition(readList,"d2t");
|
||||
if(mot < -99999){
|
||||
SCWrite(pCon,"WARNING: skipping d2 because of bad read on d2t",
|
||||
eWarning);
|
||||
} else {
|
||||
val = dist*Tand(self->targetm2t) - .5 * mot;
|
||||
addMotorToList(self->driveList,"d2b",val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slit 3
|
||||
*/
|
||||
if(self->D3.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->D3) - calcCompPosition(&self->M);
|
||||
mot = getListMotorPosition(readList,"d3t");
|
||||
if(mot < -99999){
|
||||
SCWrite(pCon,"WARNING: skipping d3 because of bad read on d3t",
|
||||
eWarning);
|
||||
} else {
|
||||
val = dist*Tand(self->targetm2t) - .5 * mot;
|
||||
addMotorToList(self->driveList,"d3b",val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* detector
|
||||
*/
|
||||
com = self->targetm2t + self->targets2t;
|
||||
if(self->D.activeFlag == 1){
|
||||
addMotorToList(self->driveList,"com",com);
|
||||
dist = calcCompPosition(&self->D) - calcCompPosition(&self->S);
|
||||
val = dist*(Cosd(com) - 1.);
|
||||
addMotorToList(self->driveList,"cox",val);
|
||||
val = dist*Sind(com) + soz;
|
||||
addMotorToList(self->driveList,"coz",val);
|
||||
}
|
||||
|
||||
/*
|
||||
* slit 4
|
||||
*/
|
||||
if(self->D4.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->D4) - calcCompPosition(&self->S);
|
||||
mot = getListMotorPosition(readList,"d4t");
|
||||
if(mot < -99999){
|
||||
SCWrite(pCon,"WARNING: skipping d4 because of bad read on d4t",
|
||||
eWarning);
|
||||
} else {
|
||||
val = soz + dist*Tand(com) - .5 * mot;
|
||||
addMotorToList(self->driveList,"d4b",val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slit 5
|
||||
*/
|
||||
if(self->D5.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->D5) - calcCompPosition(&self->S);
|
||||
mot = getListMotorPosition(readList,"d5t");
|
||||
if(mot < -99999){
|
||||
SCWrite(pCon,"WARNING: skipping d5 because of bad read on d5t",
|
||||
eWarning);
|
||||
} else {
|
||||
val = soz + dist*Tand(com) - .5 * mot;
|
||||
addMotorToList(self->driveList,"d5b",val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Analyzer
|
||||
*/
|
||||
if(self->A.activeFlag == 1){
|
||||
dist = calcCompPosition(&self->A) - calcCompPosition(&self->S);
|
||||
val = soz + dist*Tand(com);
|
||||
addMotorToList(self->driveList,"aoz",val);
|
||||
addMotorToList(self->driveList,"aom",com + self->targetath);
|
||||
}
|
||||
|
||||
LLDdelete(readList);
|
||||
self->mustDrive = 0;
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static int updateActualPositions(pamorSet self, SConnection *pCon){
|
||||
int readList, status;
|
||||
float val, dist, tmp, com;
|
||||
|
||||
/**
|
||||
* read some motors
|
||||
*/
|
||||
readList = LLDcreate(sizeof(MotControl));
|
||||
addMotorToList(readList,"soz",125);
|
||||
addMotorToList(readList,"com",125);
|
||||
addMotorToList(readList,"aom",125);
|
||||
val = self->listDrive->GetValue(&readList,pCon);
|
||||
if(val < -99999.){
|
||||
SCWrite(pCon,
|
||||
"ERROR: failed to read motors, values for m2t,s2t,ath invalid",
|
||||
eError);
|
||||
LLDdelete(readList);
|
||||
return 0;
|
||||
}
|
||||
val = getListMotorPosition(readList,"soz");
|
||||
dist = calcCompPosition(&self->S) - calcCompPosition(&self->M);
|
||||
tmp = val/dist;
|
||||
if(ABS(tmp) > .0001){
|
||||
self->actualm2t = Atand(tmp);
|
||||
} else {
|
||||
self->actualm2t = .0;
|
||||
}
|
||||
com = getListMotorPosition(readList,"com");
|
||||
self->actuals2t = com - self->actualm2t;
|
||||
|
||||
val = getListMotorPosition(readList,"aom");
|
||||
self->actualath = val - com;
|
||||
|
||||
LLDdelete(readList);
|
||||
self->mustRecalculate = 1;
|
||||
return 1;
|
||||
}
|
||||
/*=================== SICS internal interface functions============*/
|
||||
static void *AMOSETGetInterface(void *data, int iD){
|
||||
pamorSet self = NULL;
|
||||
|
||||
/*
|
||||
* this object shall never be driven directly
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return either OKOK or HWFault when thing
|
||||
go wrong. However, the return value of Halt is usually ignored!
|
||||
------------------------------------------------------------------*/
|
||||
static int AMOSETHalt(void *data) {
|
||||
pamorSet self = NULL;
|
||||
|
||||
self = (pamorSet)data;
|
||||
|
||||
self->listDrive->Halt(&self->driveList);
|
||||
return OKOK;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return either 1 or 0. 1 means the position can
|
||||
be reached, 0 NOT
|
||||
If 0, error shall contain up to errlen characters of information
|
||||
about which limit was violated
|
||||
------------------------------------------------------------------*/
|
||||
static int AMOSETCheckLimits(void *data, float val,
|
||||
char *error, int errlen){
|
||||
pamorSet self = NULL;
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
This routine can return 0 when a limit problem occurred
|
||||
OKOK when the motor was successfully started
|
||||
HWFault when a problem occured starting the device
|
||||
Possible errors shall be printed to pCon
|
||||
For real motors, this is supposed to try at least three times
|
||||
to start the motor in question
|
||||
val is the value to drive the motor too
|
||||
------------------------------------------------------------------*/
|
||||
static long AMOSETSetValue(void *data, SConnection *pCon, float val){
|
||||
pamorSet self = NULL;
|
||||
return OKOK;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
Checks the status of a running motor. Possible return values
|
||||
HWBusy The motor is still running
|
||||
OKOK or HWIdle when the motor finished driving
|
||||
HWFault when a hardware problem ocurred
|
||||
HWPosFault when the hardware cannot reach a position
|
||||
Errors are duly to be printed to pCon
|
||||
For real motors CheckStatus again shall try hard to fix any
|
||||
issues with the motor
|
||||
------------------------------------------------------------------*/
|
||||
static int AMOSETCheckStatus(void *data, SConnection *pCon){
|
||||
pamorSet self = NULL;
|
||||
int status;
|
||||
|
||||
self = (pamorSet)data;
|
||||
|
||||
if(self->mustDrive == 1){
|
||||
status = calcAmorSettings(self,pCon);
|
||||
if(status <= 0){
|
||||
return HWFault;
|
||||
}
|
||||
if(self->verbose == 1){
|
||||
printMotorList(self->driveList,pCon);
|
||||
}
|
||||
return self->listDrive->SetValue(&self->driveList,pCon,.37);
|
||||
} else {
|
||||
self->mustRecalculate = 1;
|
||||
return self->listDrive->CheckStatus(&self->driveList,pCon);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
GetValue is supposed to read a motor position
|
||||
On errors, -99999999.99 is returned and messages printed to pCon
|
||||
------------------------------------------------------------------*/
|
||||
static float AMOSETGetValue(void *data, SConnection *pCon){
|
||||
pamorSet self = NULL;
|
||||
float val = -99999999.99;
|
||||
|
||||
self = (pamorSet)data;
|
||||
|
||||
return val;
|
||||
}
|
||||
/*================ external functions for amordrive ============*/
|
||||
void amorSetMotor(pamorSet amor, int type, double value){
|
||||
switch(type){
|
||||
case TYM2T:
|
||||
amor->targetm2t = value;
|
||||
break;
|
||||
case TYS2T:
|
||||
amor->targets2t = value;
|
||||
break;
|
||||
case TYATH:
|
||||
amor->targetath = value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
amor->mustDrive = 1;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
double amorGetMotor(pamorSet amor, SConnection *pCon, int type){
|
||||
if(amor->mustRecalculate == 1){
|
||||
updateActualPositions(amor,pCon);
|
||||
}
|
||||
switch(type){
|
||||
case TYM2T:
|
||||
return amor->actualm2t;
|
||||
break;
|
||||
case TYS2T:
|
||||
return amor->actuals2t;
|
||||
break;
|
||||
case TYATH:
|
||||
return amor->actualath;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return -99999.999;
|
||||
}
|
||||
/*----------------------------------------------------------------
|
||||
Live and Deatch of objects.........
|
||||
returns NULL on failure, a new datastructure else
|
||||
------------------------------------------------------------------*/
|
||||
static int amorSetSave(void *data, char *name,FILE *fd){
|
||||
pamorSet self = NULL;
|
||||
|
||||
self = (pamorSet)data;
|
||||
if(self == NULL){
|
||||
return 0;
|
||||
}
|
||||
fprintf(fd,"%s dspar %f\n", name, self->dspar);
|
||||
fprintf(fd,"%s verbose %d\n", name, self->verbose);
|
||||
saveAmorComp(fd,name,"mono",&self->M);
|
||||
saveAmorComp(fd,name,"ds",&self->DS);
|
||||
saveAmorComp(fd,name,"slit2",&self->D2);
|
||||
saveAmorComp(fd,name,"slit3",&self->D3);
|
||||
saveAmorComp(fd,name,"sample",&self->S);
|
||||
saveAmorComp(fd,name,"slit4",&self->D4);
|
||||
saveAmorComp(fd,name,"slit5",&self->D5);
|
||||
saveAmorComp(fd,name,"ana",&self->A);
|
||||
saveAmorComp(fd,name,"detector",&self->D);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------*/
|
||||
static pamorSet AMOSETMakeObject(){
|
||||
pamorSet self = NULL;
|
||||
|
||||
self = (pamorSet)malloc(sizeof(amorSet));
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(self,0,sizeof(amorSet));
|
||||
self->pDes = CreateDescriptor("AmorSet");
|
||||
self->pDriv = CreateDrivableInterface();
|
||||
self->listDrive = makeMotListInterface();
|
||||
self->driveList = LLDcreate(sizeof(MotControl));
|
||||
if(self->pDes == NULL || self->pDriv == NULL ||
|
||||
self->listDrive == NULL || self->driveList < 0){
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->pDes->GetInterface = AMOSETGetInterface;
|
||||
self->pDes->SaveStatus = amorSetSave;
|
||||
self->pDriv->Halt = AMOSETHalt;
|
||||
self->pDriv->CheckLimits = AMOSETCheckLimits;
|
||||
self->pDriv->SetValue = AMOSETSetValue;
|
||||
self->pDriv->CheckStatus = AMOSETCheckStatus;
|
||||
self->pDriv->GetValue = AMOSETGetValue;
|
||||
|
||||
return self;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static void killAmorSet(void *data){
|
||||
pamorSet self = (pamorSet)data;
|
||||
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
if(self->pDes != NULL) {
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pDriv != NULL){
|
||||
free(self->pDriv);
|
||||
}
|
||||
if(self->listDrive != NULL){
|
||||
free(self->listDrive);
|
||||
}
|
||||
LLDdelete(self->driveList);
|
||||
free(self);
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int testRequiredMotors(SConnection *pCon){
|
||||
char motList[][20] = {"soz", "com",
|
||||
"cox","coz","dbs","d2b","d2t",
|
||||
"d3b", "d3t", "d4b","d4t",
|
||||
"d5t", "d5b","aoz", "aom"};
|
||||
int i = 0, status = 1;
|
||||
pMotor pMot = NULL;
|
||||
char pBueffel[132];
|
||||
|
||||
|
||||
for(i = 0; i < 15; i++){
|
||||
pMot = NULL;
|
||||
pMot = FindMotor(pServ->pSics,motList[i]);
|
||||
if(pMot == NULL){
|
||||
snprintf(pBueffel,131,"ERROR: motor %s for amorset not found",
|
||||
motList[i]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*======================= interpreter interface section ============*/
|
||||
int AmorSetFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
int status;
|
||||
pamorSet pNew = NULL;
|
||||
pamorDrive pTuk = NULL;
|
||||
|
||||
if(testRequiredMotors(pCon) == 0){
|
||||
SCWrite(pCon,
|
||||
"ERROR: aborting initialization of amorset due to missing motors",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pNew = AMOSETMakeObject();
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating amorset",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,"amorset",AmorSetAction,killAmorSet,pNew);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: duplicate command amorset NOT created",eError);
|
||||
return 0;
|
||||
}
|
||||
pTuk = makeAmorDrive(pNew,TYM2T);
|
||||
if(pTuk == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to allocate data fro m2t",eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,"m2t",AmorDriveAction,killAmorDrive,pTuk);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: duplicate command amorset m2t reated",eError);
|
||||
return 0;
|
||||
}
|
||||
pTuk = makeAmorDrive(pNew,TYATH);
|
||||
if(pTuk == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to allocate data for ath",eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,"ath",AmorDriveAction,killAmorDrive,pTuk);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: duplicate command amorset ath reated",eError);
|
||||
return 0;
|
||||
}
|
||||
pTuk = makeAmorDrive(pNew,TYS2T);
|
||||
if(pTuk == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to allocate data for s2t",eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,"s2t",AmorDriveAction,killAmorDrive,pTuk);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: duplicate command amorset s2t reated",eError);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static pamorComp locateComponent(pamorSet self, char *name){
|
||||
if(strcmp(name,"mono") == 0){
|
||||
return &self->M;
|
||||
} else if(strcmp(name,"ds") == 0){
|
||||
return &self->DS;
|
||||
}else if(strcmp(name,"slit2") == 0){
|
||||
return &self->D2;
|
||||
}else if(strcmp(name,"slit3") == 0){
|
||||
return &self->D3;
|
||||
}else if(strcmp(name,"sample") == 0){
|
||||
return &self->S;
|
||||
} else if(strcmp(name,"slit4") == 0){
|
||||
return &self->D4;
|
||||
}else if(strcmp(name,"slit5") == 0){
|
||||
return &self->D5;
|
||||
}else if(strcmp(name,"detector") == 0){
|
||||
return &self->D;
|
||||
}else if(strcmp(name,"ana") == 0){
|
||||
return &self->A;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static double calcCD(pamorSet self){
|
||||
double soz, cmh, smh, sdh, cd, dist;
|
||||
|
||||
soz = dist*Cotd(self->targetm2t);
|
||||
cmh = calcCompPosition(&self->M);
|
||||
smh = calcCompPosition(&self->S) - calcCompPosition(&self->M);
|
||||
sdh = calcCompPosition(&self->D) - calcCompPosition(&self->M);
|
||||
cd = cmh + sqrt(smh*smh + soz*soz) + sdh;
|
||||
return cd;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int AmorSetAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pamorSet self = NULL;
|
||||
pamorComp comp = NULL;
|
||||
char pBueffel[132];
|
||||
|
||||
self = (pamorSet)pData;
|
||||
assert(self);
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: not enough arguments to amorset",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* catch component commands
|
||||
*/
|
||||
strtolower(argv[1]);
|
||||
comp = locateComponent(self,argv[1]);
|
||||
if(comp != NULL){
|
||||
return handleCompCommand(comp,pCon,argc,argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* now it is for us ....
|
||||
*/
|
||||
if(strcmp(argv[1],"dspar") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
self->dspar = atof(argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,131,"%s dspar = %f", argv[0], self->dspar);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}else if(strcmp(argv[1],"verbose") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
self->verbose = atoi(argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,131,"%s verbose = %d", argv[0], self->verbose);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"cd") == 0){
|
||||
snprintf(pBueffel,131,"%s cd = %f", argv[0], calcCD(self));
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: unknown subcommand to amorset",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
50
amorset.h
Normal file
50
amorset.h
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
AMORSET together with amorcomp and amordrive implement the position
|
||||
control facility for the reflectometer AMOR. This uses the algorithm
|
||||
with the beam height as the baseline.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
--------------------------------------------------------------------*/
|
||||
#ifndef AMORSET
|
||||
#define AMORSET
|
||||
#include "amorcomp.h"
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pIDrivable listDrive;
|
||||
amorComp M;
|
||||
amorComp DS;
|
||||
amorComp D2;
|
||||
amorComp D3;
|
||||
amorComp S;
|
||||
amorComp D4;
|
||||
amorComp A;
|
||||
amorComp D5;
|
||||
amorComp D;
|
||||
double targetm2t;
|
||||
double targets2t;
|
||||
double targetath;
|
||||
double actualm2t;
|
||||
double actuals2t;
|
||||
double actualath;
|
||||
int mustDrive;
|
||||
int mustRecalculate;
|
||||
int driveList;
|
||||
double dspar;
|
||||
int verbose;
|
||||
}amorSet, *pamorSet;
|
||||
/*--------------------------------------------------------------------*/
|
||||
int AmorSetFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int AmorSetAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*============ helper functions for the virtual motors ===============*/
|
||||
void amorSetMotor(pamorSet amor, int type, double value);
|
||||
double amorGetMotor(pamorSet amor, SConnection *pCon, int type);
|
||||
|
||||
#endif
|
||||
|
209
amorset.tex
Normal file
209
amorset.tex
Normal file
@ -0,0 +1,209 @@
|
||||
\subsection{AMOR Reflectometer Settings}
|
||||
This is yet another module for calculating the settings for the AMOR
|
||||
spectrometer. This version is of 2005 and implements the new calculation
|
||||
scheme as devised by the Jochen where the base line and height zero point
|
||||
is the beam height at the chop, chop, chopper.
|
||||
|
||||
Again a lot of parameters have to be maintained. For each optical bench
|
||||
component an active flag, a fixed offset for correcting the scale reading to
|
||||
the actual position and an offset regarding the zero point of the scale need
|
||||
to be kept. And of course the value as read. This is offloaded into a
|
||||
separate module, amorcomp. Beamline components to be controlled are:
|
||||
\begin{description}
|
||||
\item[DS] The slit at the monochromator bunker
|
||||
\item[M] The monochromator
|
||||
\item[Dx] various slits
|
||||
\item[A] the analyzer
|
||||
\item[D] the detector.
|
||||
\end{description}
|
||||
|
||||
A master module encloses all those beamline components and performs the
|
||||
actual calculation. The calculation is controlled through three virtual
|
||||
motors: m2t (monochromator 2 theta), s2t (sample 2 theta) and ath, the
|
||||
analyzer angle. For the formula used for the exact calculation, see the
|
||||
paper from the Jochen.
|
||||
|
||||
|
||||
The amorcomp module provides the following interface:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$amorcompint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int activeFlag; /* component present */@\\
|
||||
\mbox{}\verb@ double markOffset; /* offset mark to real */@\\
|
||||
\mbox{}\verb@ double scaleOffset; /* offset of the scale */@\\
|
||||
\mbox{}\verb@ double readPosition; /* the position as read */@\\
|
||||
\mbox{}\verb@} amorComp, *pamorComp;@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@double calcCompPosition(pamorComp comp); @\\
|
||||
\mbox{}\verb@int handleCompCommand(pamorComp comp, SConnection *pCon, @\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@int saveAmorComp(FILE *fd, char *name, char *compname, pamorComp comp); @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The amorset module implements the container for all the data and the actual
|
||||
calculation. Most of the interesting stuff is in the functions relating to
|
||||
the interpreter interface and the drivable interface. Again the virtual
|
||||
motors only set values in the amorset data structure and amorset then takes
|
||||
control off the driving operation.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$amorsetint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ pIDrivable listDrive;@\\
|
||||
\mbox{}\verb@ amorComp M;@\\
|
||||
\mbox{}\verb@ amorComp DS;@\\
|
||||
\mbox{}\verb@ amorComp D2;@\\
|
||||
\mbox{}\verb@ amorComp D3;@\\
|
||||
\mbox{}\verb@ amorComp S;@\\
|
||||
\mbox{}\verb@ amorComp D4;@\\
|
||||
\mbox{}\verb@ amorComp A;@\\
|
||||
\mbox{}\verb@ amorComp D5;@\\
|
||||
\mbox{}\verb@ amorComp D;@\\
|
||||
\mbox{}\verb@ double targetm2t;@\\
|
||||
\mbox{}\verb@ double targets2t;@\\
|
||||
\mbox{}\verb@ double targetath;@\\
|
||||
\mbox{}\verb@ double actualm2t;@\\
|
||||
\mbox{}\verb@ double actuals2t;@\\
|
||||
\mbox{}\verb@ double actualath;@\\
|
||||
\mbox{}\verb@ int mustDrive;@\\
|
||||
\mbox{}\verb@ int mustRecalculate;@\\
|
||||
\mbox{}\verb@ int driveList;@\\
|
||||
\mbox{}\verb@ double dspar;@\\
|
||||
\mbox{}\verb@ int verbose;@\\
|
||||
\mbox{}\verb@}amorSet, *pamorSet;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@int AmorSetFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@int AmorSetAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*============ helper functions for the virtual motors ===============*/ @\\
|
||||
\mbox{}\verb@void amorSetMotor(pamorSet amor, int type, double value);@\\
|
||||
\mbox{}\verb@double amorGetMotor(pamorSet amor, SConnection *pCon, int type);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The virtual motors just implement the bare minimum:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$amordriveint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct{@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ pamorSet mama;@\\
|
||||
\mbox{}\verb@ int type;@\\
|
||||
\mbox{}\verb@} amorDrive, *pamorDrive;@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@pamorDrive makeAmorDrive(pamorSet papa, int type);@\\
|
||||
\mbox{}\verb@void killAmorDrive(void *data);@\\
|
||||
\mbox{}\verb@int AmorDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"amorset.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ AMORSET together with amorcomp and amordrive implement the position@\\
|
||||
\mbox{}\verb@ control facility for the reflectometer AMOR. This uses the algorithm@\\
|
||||
\mbox{}\verb@ with the beam height as the baseline.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see file COPYRIGHT@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 2005@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORSET@\\
|
||||
\mbox{}\verb@#define AMORSET@\\
|
||||
\mbox{}\verb@#include "amorcomp.h"@\\
|
||||
\mbox{}\verb@@$\langle$amorsetint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
\verb@"amorcomp.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ AMOR component handling module. For the new (2005) calculation of the@\\
|
||||
\mbox{}\verb@ positions using the beam height as zero.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see file COPYRIGHT@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 2005@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ #ifndef AMORCOMP@\\
|
||||
\mbox{}\verb@ #define AMORCOMP@\\
|
||||
\mbox{}\verb@ #include <stdio.h>@\\
|
||||
\mbox{}\verb@ #include <sics.h>@\\
|
||||
\mbox{}\verb@ @$\langle$amorcompint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@ #endif@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
\verb@"amordrive.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*--------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Part of the AMOR position calculation module.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see file COPYRIGHT@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 2005@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORDRIVE@\\
|
||||
\mbox{}\verb@#define AMORDRIVE@\\
|
||||
\mbox{}\verb@@$\langle$amordriveint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ @$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
152
amorset.w
Normal file
152
amorset.w
Normal file
@ -0,0 +1,152 @@
|
||||
\subsection{AMOR Reflectometer Settings}
|
||||
This is yet another module for calculating the settings for the AMOR
|
||||
spectrometer. This version is of 2005 and implements the new calculation
|
||||
scheme as devised by the Jochen where the base line and height zero point
|
||||
is the beam height at the chop, chop, chopper.
|
||||
|
||||
Again a lot of parameters have to be maintained. For each optical bench
|
||||
component an active flag, a fixed offset for correcting the scale reading to
|
||||
the actual position and an offset regarding the zero point of the scale need
|
||||
to be kept. And of course the value as read. This is offloaded into a
|
||||
separate module, amorcomp. Beamline components to be controlled are:
|
||||
\begin{description}
|
||||
\item[DS] The slit at the monochromator bunker
|
||||
\item[M] The monochromator
|
||||
\item[Dx] various slits
|
||||
\item[A] the analyzer
|
||||
\item[D] the detector.
|
||||
\end{description}
|
||||
|
||||
A master module encloses all those beamline components and performs the
|
||||
actual calculation. The calculation is controlled through three virtual
|
||||
motors: m2t (monochromator 2 theta), s2t (sample 2 theta) and ath, the
|
||||
analyzer angle. For the formula used for the exact calculation, see the
|
||||
paper from the Jochen.
|
||||
|
||||
|
||||
The amorcomp module provides the following interface:
|
||||
@d amorcompint @{
|
||||
typedef struct {
|
||||
int activeFlag; /* component present */
|
||||
double markOffset; /* offset mark to real */
|
||||
double scaleOffset; /* offset of the scale */
|
||||
double readPosition; /* the position as read */
|
||||
} amorComp, *pamorComp;
|
||||
/*----------------------------------------------------------------------*/
|
||||
double calcCompPosition(pamorComp comp);
|
||||
int handleCompCommand(pamorComp comp, SConnection *pCon,
|
||||
int argc, char *argv[]);
|
||||
int saveAmorComp(FILE *fd, char *name, char *compname, pamorComp comp);
|
||||
@}
|
||||
|
||||
The amorset module implements the container for all the data and the actual
|
||||
calculation. Most of the interesting stuff is in the functions relating to
|
||||
the interpreter interface and the drivable interface. Again the virtual
|
||||
motors only set values in the amorset data structure and amorset then takes
|
||||
control off the driving operation.
|
||||
|
||||
@d amorsetint @{
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pIDrivable listDrive;
|
||||
amorComp M;
|
||||
amorComp DS;
|
||||
amorComp D2;
|
||||
amorComp D3;
|
||||
amorComp S;
|
||||
amorComp D4;
|
||||
amorComp A;
|
||||
amorComp D5;
|
||||
amorComp D;
|
||||
double targetm2t;
|
||||
double targets2t;
|
||||
double targetath;
|
||||
double actualm2t;
|
||||
double actuals2t;
|
||||
double actualath;
|
||||
int mustDrive;
|
||||
int mustRecalculate;
|
||||
int driveList;
|
||||
double dspar;
|
||||
int verbose;
|
||||
}amorSet, *pamorSet;
|
||||
/*--------------------------------------------------------------------*/
|
||||
int AmorSetFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int AmorSetAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*============ helper functions for the virtual motors ===============*/
|
||||
void amorSetMotor(pamorSet amor, int type, double value);
|
||||
double amorGetMotor(pamorSet amor, SConnection *pCon, int type);
|
||||
@}
|
||||
|
||||
|
||||
The virtual motors just implement the bare minimum:
|
||||
@d amordriveint @{
|
||||
typedef struct{
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pamorSet mama;
|
||||
int type;
|
||||
} amorDrive, *pamorDrive;
|
||||
/*-----------------------------------------------------------------*/
|
||||
pamorDrive makeAmorDrive(pamorSet papa, int type);
|
||||
void killAmorDrive(void *data);
|
||||
int AmorDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@}
|
||||
|
||||
|
||||
@o amorset.h @{
|
||||
/*-------------------------------------------------------------------
|
||||
AMORSET together with amorcomp and amordrive implement the position
|
||||
control facility for the reflectometer AMOR. This uses the algorithm
|
||||
with the beam height as the baseline.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
--------------------------------------------------------------------*/
|
||||
#ifndef AMORSET
|
||||
#define AMORSET
|
||||
#include "amorcomp.h"
|
||||
@<amorsetint@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
||||
@o amorcomp.h @{
|
||||
/*---------------------------------------------------------------------
|
||||
AMOR component handling module. For the new (2005) calculation of the
|
||||
positions using the beam height as zero.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
-----------------------------------------------------------------------*/
|
||||
#ifndef AMORCOMP
|
||||
#define AMORCOMP
|
||||
#include <stdio.h>
|
||||
#include <sics.h>
|
||||
@<amorcompint@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
||||
|
||||
@o amordrive.h @{
|
||||
/*--------------------------------------------------------------------
|
||||
Part of the AMOR position calculation module.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, October 2005
|
||||
----------------------------------------------------------------------*/
|
||||
#ifndef AMORDRIVE
|
||||
#define AMORDRIVE
|
||||
@<amordriveint@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
418
dspcode.c
Normal file
418
dspcode.c
Normal file
@ -0,0 +1,418 @@
|
||||
void slsdspCodeToText(int code, char *text, int textlen){
|
||||
switch(code){
|
||||
case 0x0:
|
||||
strncpy(text,"NO",textlen);
|
||||
break;
|
||||
case 0x1:
|
||||
strncpy(text,"DEVICE_STATE_ERROR",textlen);
|
||||
break;
|
||||
case 0x2:
|
||||
strncpy(text,"DEVICE_SUPERVISOR_DISABLED",textlen);
|
||||
break;
|
||||
case 0x3:
|
||||
strncpy(text,"COMMAND_ABORT",textlen);
|
||||
break;
|
||||
case 0x4:
|
||||
strncpy(text,"DATA_NOT_STORED",textlen);
|
||||
break;
|
||||
case 0x5:
|
||||
strncpy(text,"ERROR_ERASING_FLASH",textlen);
|
||||
break;
|
||||
case 0x6:
|
||||
strncpy(text,"COMMUNICATION_BREAK",textlen);
|
||||
break;
|
||||
case 0x7:
|
||||
strncpy(text,"INTERNAL_COMMUNICATION_ERROR",textlen);
|
||||
break;
|
||||
case 0x8:
|
||||
strncpy(text,"MASTER_CARD_ERROR",textlen);
|
||||
break;
|
||||
case 0x9:
|
||||
strncpy(text,"INTERNAL_BUFFER_FULL",textlen);
|
||||
break;
|
||||
case 0xa:
|
||||
strncpy(text,"WRONG_SECTOR",textlen);
|
||||
break;
|
||||
case 0xb:
|
||||
strncpy(text,"DATA_NOT_COPIED",textlen);
|
||||
break;
|
||||
case 0xc:
|
||||
strncpy(text,"WRONG_DOWNLOAD_PARAMETERS",textlen);
|
||||
break;
|
||||
case 0xd:
|
||||
strncpy(text,"DEVICE_PARAMETRIZATION_ERROR",textlen);
|
||||
break;
|
||||
case 0x10:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE",textlen);
|
||||
break;
|
||||
case 0x11:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_ON",textlen);
|
||||
break;
|
||||
case 0x12:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_OFF",textlen);
|
||||
break;
|
||||
case 0x13:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_ON",textlen);
|
||||
break;
|
||||
case 0x14:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_OFF",textlen);
|
||||
break;
|
||||
case 0x15:
|
||||
strncpy(text,"TIMEOUT_DATA_DOWNLOAD",textlen);
|
||||
break;
|
||||
case 0x20:
|
||||
strncpy(text,"INTERLOCK",textlen);
|
||||
break;
|
||||
case 0x21:
|
||||
strncpy(text,"MASTER_SWITCH",textlen);
|
||||
break;
|
||||
case 0x22:
|
||||
strncpy(text,"MAGNET_INTERLOCK",textlen);
|
||||
break;
|
||||
case 0x23:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER",textlen);
|
||||
break;
|
||||
case 0x24:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER",textlen);
|
||||
break;
|
||||
case 0x25:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER",textlen);
|
||||
break;
|
||||
case 0x26:
|
||||
strncpy(text,"CURRENT_TRANSDUCER",textlen);
|
||||
break;
|
||||
case 0x27:
|
||||
strncpy(text,"TEMPERATURE_POLARITY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x28:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR",textlen);
|
||||
break;
|
||||
case 0x29:
|
||||
strncpy(text,"MAIN_RELAY",textlen);
|
||||
break;
|
||||
case 0x2a:
|
||||
strncpy(text,"AD_CONVERTER_CARD",textlen);
|
||||
break;
|
||||
case 0x2b:
|
||||
strncpy(text,"POLARITY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x2c:
|
||||
strncpy(text,"AUXILIARY_RELAY",textlen);
|
||||
break;
|
||||
case 0x2d:
|
||||
strncpy(text,"MASTER_SWITCH_T1",textlen);
|
||||
break;
|
||||
case 0x2e:
|
||||
strncpy(text,"MASTER_SWITCH_T2",textlen);
|
||||
break;
|
||||
case 0x2f:
|
||||
strncpy(text,"TEMPERATURE_MAGNET",textlen);
|
||||
break;
|
||||
case 0x30:
|
||||
strncpy(text,"WATER_MAGNET",textlen);
|
||||
break;
|
||||
case 0x31:
|
||||
strncpy(text,"WATER_RACK",textlen);
|
||||
break;
|
||||
case 0x40:
|
||||
strncpy(text,"LOAD_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x41:
|
||||
strncpy(text,"DC_LINK_VOLTAGE_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x42:
|
||||
strncpy(text,"DC_LINK_VOLTAGE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x43:
|
||||
strncpy(text,"LOAD_VOLTAGE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x44:
|
||||
strncpy(text,"LOAD_CURRENT_RIPPLE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x45:
|
||||
strncpy(text,"DC_LINK_ISOLATION_NOT_OK",textlen);
|
||||
break;
|
||||
case 0x46:
|
||||
strncpy(text,"LOAD_ISOLATION_NOT_OK",textlen);
|
||||
break;
|
||||
case 0x47:
|
||||
strncpy(text,"LOAD_IMPEDANCE_OUT_OF_RANGE",textlen);
|
||||
break;
|
||||
case 0x48:
|
||||
strncpy(text,"SHUT_OFF_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x49:
|
||||
strncpy(text,"LOAD_DC_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4a:
|
||||
strncpy(text,"CURRENT_I1A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4b:
|
||||
strncpy(text,"CURRENT_I1B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4c:
|
||||
strncpy(text,"CURRENT_I1A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4d:
|
||||
strncpy(text,"CURRENT_I1B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4e:
|
||||
strncpy(text,"CURRENT_I2A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4f:
|
||||
strncpy(text,"CURRENT_I2B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x50:
|
||||
strncpy(text,"CURRENT_I2A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x51:
|
||||
strncpy(text,"CURRENT_I2B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x52:
|
||||
strncpy(text,"CURRENT_I3P_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x53:
|
||||
strncpy(text,"CURRENT_I3N_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x54:
|
||||
strncpy(text,"CURRENT_IE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x55:
|
||||
strncpy(text,"VOLTAGE_U1A_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x56:
|
||||
strncpy(text,"VOLTAGE_U1B_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x57:
|
||||
strncpy(text,"DIFF_CURRENT_I1A1_I1A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x58:
|
||||
strncpy(text,"DIFF_CURRENT_I1B1_I1B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x59:
|
||||
strncpy(text,"DIFF_CURRENT_I2A1_I2A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5a:
|
||||
strncpy(text,"DIFF_CURRENT_I2B1_I2B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5b:
|
||||
strncpy(text,"DIFF_CURRENT_I3P_I3N_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5c:
|
||||
strncpy(text,"CURRENT_I1A_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5d:
|
||||
strncpy(text,"CURRENT_I1B_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5e:
|
||||
strncpy(text,"CURRENT_I3A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5f:
|
||||
strncpy(text,"CURRENT_I3B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x60:
|
||||
strncpy(text,"CURRENT_I3A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x61:
|
||||
strncpy(text,"CURRENT_I3B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x62:
|
||||
strncpy(text,"CURRENT_I4_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x63:
|
||||
strncpy(text,"CURRENT_I5_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x64:
|
||||
strncpy(text,"DIFF_CURRENT_I3A1_I3A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x65:
|
||||
strncpy(text,"DIFF_CURRENT_I3B1_I3B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x66:
|
||||
strncpy(text,"DIFF_CURRENT_I4_I5_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x67:
|
||||
strncpy(text,"VOLTAGE_U3A_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x68:
|
||||
strncpy(text,"VOLTAGE_U3B_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x69:
|
||||
strncpy(text,"VOLTAGE_U1_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x6a:
|
||||
strncpy(text,"VOLTAGE_U3A_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x6b:
|
||||
strncpy(text,"VOLTAGE_U3B_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x6c:
|
||||
strncpy(text,"SPEED_ERROR_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x70:
|
||||
strncpy(text,"MAIN_RELAY_A",textlen);
|
||||
break;
|
||||
case 0x71:
|
||||
strncpy(text,"MAIN_RELAY_B",textlen);
|
||||
break;
|
||||
case 0x72:
|
||||
strncpy(text,"POWER_SWITCH_A",textlen);
|
||||
break;
|
||||
case 0x73:
|
||||
strncpy(text,"POWER_SWITCH_B",textlen);
|
||||
break;
|
||||
case 0x74:
|
||||
strncpy(text,"MONITOR_TRAFO_A",textlen);
|
||||
break;
|
||||
case 0x75:
|
||||
strncpy(text,"MONITOR_TRAFO_B",textlen);
|
||||
break;
|
||||
case 0x76:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER_A",textlen);
|
||||
break;
|
||||
case 0x77:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER_B",textlen);
|
||||
break;
|
||||
case 0x78:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x79:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x7a:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x7b:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x7c:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x7d:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x7e:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER_A",textlen);
|
||||
break;
|
||||
case 0x7f:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER_B",textlen);
|
||||
break;
|
||||
case 0x80:
|
||||
strncpy(text,"WATER_RECTIFIER_A",textlen);
|
||||
break;
|
||||
case 0x81:
|
||||
strncpy(text,"WATER_RECTIFIER_B",textlen);
|
||||
break;
|
||||
case 0x82:
|
||||
strncpy(text,"WATER_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x83:
|
||||
strncpy(text,"WATER_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x84:
|
||||
strncpy(text,"WATER_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x85:
|
||||
strncpy(text,"WATER_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x86:
|
||||
strncpy(text,"WATER_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x87:
|
||||
strncpy(text,"WATER_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x88:
|
||||
strncpy(text,"WATER_TRANSFORMER_A",textlen);
|
||||
break;
|
||||
case 0x89:
|
||||
strncpy(text,"WATER_TRANSFORMER_B",textlen);
|
||||
break;
|
||||
case 0x8a:
|
||||
strncpy(text,"DOOR_A",textlen);
|
||||
break;
|
||||
case 0x8b:
|
||||
strncpy(text,"DOOR_B",textlen);
|
||||
break;
|
||||
case 0x8c:
|
||||
strncpy(text,"DOOR_C",textlen);
|
||||
break;
|
||||
case 0x8d:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x8e:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x8f:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x90:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x91:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x92:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x93:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I3P",textlen);
|
||||
break;
|
||||
case 0x94:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I3N",textlen);
|
||||
break;
|
||||
case 0x95:
|
||||
strncpy(text,"MAGNET_INTERLOCK_1",textlen);
|
||||
break;
|
||||
case 0x96:
|
||||
strncpy(text,"MAGNET_INTERLOCK_2",textlen);
|
||||
break;
|
||||
case 0x97:
|
||||
strncpy(text,"VENTILATOR",textlen);
|
||||
break;
|
||||
case 0x98:
|
||||
strncpy(text,"EMERGENCY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x99:
|
||||
strncpy(text,"CAPACITOR_DISCHARGE_A_ON",textlen);
|
||||
break;
|
||||
case 0x9a:
|
||||
strncpy(text,"CAPACITOR_DISCHARGE_B_ON",textlen);
|
||||
break;
|
||||
case 0x9b:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I4",textlen);
|
||||
break;
|
||||
case 0x9c:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I5",textlen);
|
||||
break;
|
||||
case 0xb0:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_A",textlen);
|
||||
break;
|
||||
case 0xb1:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_B",textlen);
|
||||
break;
|
||||
case 0xb2:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_ON",textlen);
|
||||
break;
|
||||
case 0xb3:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_ON",textlen);
|
||||
break;
|
||||
case 0xb4:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_OFF",textlen);
|
||||
break;
|
||||
case 0xb5:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_OFF",textlen);
|
||||
break;
|
||||
case 0xb6:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_A_ON",textlen);
|
||||
break;
|
||||
case 0xb7:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_B_ON",textlen);
|
||||
break;
|
||||
case 0xb8:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_A_OFF",textlen);
|
||||
break;
|
||||
case 0xb9:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_B_OFF",textlen);
|
||||
break;
|
||||
}
|
||||
}
|
@ -843,7 +843,7 @@ static void ECBGetError(void *pData, int *iCode, char *buffer, int bufferlen){
|
||||
strncpy(buffer,"failed to start motor",bufferlen);
|
||||
break;
|
||||
case ECBLIMIT:
|
||||
strncpy(buffer,"hit limit switch",bufferlen);
|
||||
strncpy(buffer,"hit limit switch or amplifier error",bufferlen);
|
||||
break;
|
||||
default:
|
||||
strncpy(buffer,"unidentified error code",bufferlen);
|
||||
|
5
make_gen
5
make_gen
@ -15,8 +15,9 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
|
||||
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
|
||||
el755driv.o amorscan.o serial.o scontroller.o t_update.o \
|
||||
t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \
|
||||
el737hpv2driv.o swmotor2.o tricssupport.o \
|
||||
fsm.o logger.o sugar.o pardef.o ease.o strobj.o oxinst.o \
|
||||
el737hpv2driv.o swmotor2.o tricssupport.o amorcomp.o \
|
||||
fsm.o logger.o sugar.o pardef.o amordrive.o\
|
||||
ease.o strobj.o oxinst.o amorset.o\
|
||||
ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o \
|
||||
dgrambroadcast.o sinq.o tabledrive.o
|
||||
|
||||
|
32
makedspcodes
Executable file
32
makedspcodes
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/tclsh
|
||||
#----- little script which converts ukas Tanners error code header file into a
|
||||
#------ subroutine which converts into text
|
||||
|
||||
set f [open MessagesCodes.h r]
|
||||
|
||||
puts stdout "void slsdspCodeToText(int code, char *text, int textlen){"
|
||||
puts stdout " switch(code){"
|
||||
|
||||
proc tokenize {txt} {
|
||||
set l [split $txt]
|
||||
foreach w $l {
|
||||
if {[string length $w] > 1} {
|
||||
lappend result $w
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
while {[gets $f line] >= 0} {
|
||||
if {[string first "#define" $line] >= 0} {
|
||||
set l [tokenize $line]
|
||||
puts stdout " case [lindex $l 2]:"
|
||||
puts stdout " strncpy(text,\"[lindex $l 1]\",textlen);"
|
||||
puts stdout " break;"
|
||||
}
|
||||
}
|
||||
|
||||
puts stdout " }"
|
||||
puts stdout "}"
|
||||
close $f
|
||||
exit 0
|
7
nxamor.c
7
nxamor.c
@ -119,6 +119,13 @@ static int psdSave = 1;
|
||||
|
||||
/* chopper */
|
||||
NXDputalias(hfil,hdict,"cname",CHOPPERNAME);
|
||||
SNXSPutDrivable(pServ->pSics, pCon,hfil,hdict, "chopperspeed",
|
||||
"crot");
|
||||
SNXSPutDrivable(pServ->pSics, pCon,hfil,hdict,"chopper1phase",
|
||||
"cphase1");
|
||||
SNXSPutDrivable(pServ->pSics, pCon,hfil,hdict, "chopper2phase",
|
||||
"cphase2");
|
||||
|
||||
SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"crot",
|
||||
"chopperrotation");
|
||||
|
||||
|
4
psi.c
4
psi.c
@ -53,7 +53,7 @@
|
||||
#include "tricssupport.h"
|
||||
#include "sinq.h"
|
||||
#include "tabledrive.h"
|
||||
|
||||
#include "amorset.h"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void SiteInit(void) {
|
||||
@ -101,6 +101,7 @@ static void AddPsiCommands(SicsInterp *pInter){
|
||||
AddCommand(pInter,"Remob",RemobCreate,NULL,NULL);
|
||||
AddCommand(pInter,"MakeSinq",SinqFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeTableDrive",TableDriveFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeAmorSet",AmorSetFactory,NULL,NULL);
|
||||
/*
|
||||
AddCommand(pInter,"MakeDifrac",MakeDifrac,NULL,NULL);
|
||||
*/
|
||||
@ -131,6 +132,7 @@ static void RemovePsiCommands(SicsInterp *pSics){
|
||||
RemoveCommand(pSics,"SerialInit");
|
||||
RemoveCommand(pSics,"MakeSinq");
|
||||
RemoveCommand(pSics,"MakeTableDrive");
|
||||
RemoveCommand(pSics,"MakeAmorSet");
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
MotorDriver *CreateEL734(SConnection *pCon, int argc, char *argv[]);
|
||||
|
529
slsmagnet.c
529
slsmagnet.c
@ -45,7 +45,9 @@
|
||||
before doing a timeout. 100 corresponds to one second
|
||||
*/
|
||||
#define MAXLOOP 100
|
||||
|
||||
#define BADLOWLIM -5301
|
||||
#define BADHIGHLIM -5302
|
||||
#define DEVICERROR -5304
|
||||
/*
|
||||
packet header codes
|
||||
*/
|
||||
@ -153,7 +155,7 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
static int GetSLSPos(pEVDriver self, float *fPos)
|
||||
{
|
||||
pSLSDriv pMe = NULL;
|
||||
int iRet, ival;
|
||||
int iRet, ival, err;
|
||||
double dval;
|
||||
char msg[6], reply[6];
|
||||
long lVal;
|
||||
@ -178,19 +180,75 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
*fPos = (float)dval;
|
||||
pMe->iError = 0;
|
||||
|
||||
/*
|
||||
* try read error codes
|
||||
*/
|
||||
msg[1] = 0x29;
|
||||
iRet = communicateSLS(pMe->pSock,msg,reply);
|
||||
if(iRet < 0)
|
||||
{
|
||||
pMe->iError = iRet;
|
||||
return iRet;
|
||||
}
|
||||
err = (int)reply[5];
|
||||
if(err != 0){
|
||||
pMe->iError = -7000 - err;
|
||||
return pMe->iError;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int SLSRun(pEVDriver self, float fVal)
|
||||
{
|
||||
pSLSDriv pMe = NULL;
|
||||
int iRet, ival,i;
|
||||
int iRet, ival, i;
|
||||
char msg[6], reply[6];
|
||||
double min, max;
|
||||
|
||||
assert(self);
|
||||
pMe = (pSLSDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
/*
|
||||
* test high limit
|
||||
*/
|
||||
msg[0] = DSPREAD;
|
||||
msg[1] = 0x76;
|
||||
iRet = communicateSLS(pMe->pSock,msg,reply);
|
||||
if(iRet <= 0)
|
||||
{
|
||||
pMe->iError = iRet;
|
||||
return iRet;
|
||||
}
|
||||
memcpy(&ival,reply+2,4);
|
||||
max = DSPfloat2double(ival);
|
||||
if(fVal > max){
|
||||
pMe->iError = BADHIGHLIM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* test low limit
|
||||
*/
|
||||
msg[0] = DSPREAD;
|
||||
msg[1] = 0x77;
|
||||
iRet = communicateSLS(pMe->pSock,msg,reply);
|
||||
if(iRet <= 0)
|
||||
{
|
||||
pMe->iError = iRet;
|
||||
return iRet;
|
||||
}
|
||||
memcpy(&ival,reply+2,4);
|
||||
min = DSPfloat2double(ival);
|
||||
if(fVal < min){
|
||||
pMe->iError = BADLOWLIM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* actual set the new value
|
||||
*/
|
||||
msg[0] = DSPWRITE;
|
||||
msg[1] = 0x90;
|
||||
ival = double2DSPfloat((double)fVal);
|
||||
@ -199,18 +257,438 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
if(iRet <= 0)
|
||||
{
|
||||
pMe->iError = iRet;
|
||||
return iRet;
|
||||
return 0;
|
||||
}
|
||||
for(i = 1; i < 6; i++)
|
||||
{
|
||||
if(msg[i] != reply[i])
|
||||
{
|
||||
pMe->iError = BADECHO;
|
||||
return BADECHO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void slsdspCodeToText(int code, char *text, int textlen){
|
||||
switch(code){
|
||||
case 0x0:
|
||||
strncpy(text,"NO",textlen);
|
||||
break;
|
||||
case 0x1:
|
||||
strncpy(text,"DEVICE_STATE_ERROR",textlen);
|
||||
break;
|
||||
case 0x2:
|
||||
strncpy(text,"DEVICE_SUPERVISOR_DISABLED",textlen);
|
||||
break;
|
||||
case 0x3:
|
||||
strncpy(text,"COMMAND_ABORT",textlen);
|
||||
break;
|
||||
case 0x4:
|
||||
strncpy(text,"DATA_NOT_STORED",textlen);
|
||||
break;
|
||||
case 0x5:
|
||||
strncpy(text,"ERROR_ERASING_FLASH",textlen);
|
||||
break;
|
||||
case 0x6:
|
||||
strncpy(text,"COMMUNICATION_BREAK",textlen);
|
||||
break;
|
||||
case 0x7:
|
||||
strncpy(text,"INTERNAL_COMMUNICATION_ERROR",textlen);
|
||||
break;
|
||||
case 0x8:
|
||||
strncpy(text,"MASTER_CARD_ERROR",textlen);
|
||||
break;
|
||||
case 0x9:
|
||||
strncpy(text,"INTERNAL_BUFFER_FULL",textlen);
|
||||
break;
|
||||
case 0xa:
|
||||
strncpy(text,"WRONG_SECTOR",textlen);
|
||||
break;
|
||||
case 0xb:
|
||||
strncpy(text,"DATA_NOT_COPIED",textlen);
|
||||
break;
|
||||
case 0xc:
|
||||
strncpy(text,"WRONG_DOWNLOAD_PARAMETERS",textlen);
|
||||
break;
|
||||
case 0xd:
|
||||
strncpy(text,"DEVICE_PARAMETRIZATION_ERROR",textlen);
|
||||
break;
|
||||
case 0x10:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE",textlen);
|
||||
break;
|
||||
case 0x11:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_ON",textlen);
|
||||
break;
|
||||
case 0x12:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_OFF",textlen);
|
||||
break;
|
||||
case 0x13:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_ON",textlen);
|
||||
break;
|
||||
case 0x14:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_OFF",textlen);
|
||||
break;
|
||||
case 0x15:
|
||||
strncpy(text,"TIMEOUT_DATA_DOWNLOAD",textlen);
|
||||
break;
|
||||
case 0x20:
|
||||
strncpy(text,"INTERLOCK",textlen);
|
||||
break;
|
||||
case 0x21:
|
||||
strncpy(text,"MASTER_SWITCH",textlen);
|
||||
break;
|
||||
case 0x22:
|
||||
strncpy(text,"MAGNET_INTERLOCK",textlen);
|
||||
break;
|
||||
case 0x23:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER",textlen);
|
||||
break;
|
||||
case 0x24:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER",textlen);
|
||||
break;
|
||||
case 0x25:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER",textlen);
|
||||
break;
|
||||
case 0x26:
|
||||
strncpy(text,"CURRENT_TRANSDUCER",textlen);
|
||||
break;
|
||||
case 0x27:
|
||||
strncpy(text,"TEMPERATURE_POLARITY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x28:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR",textlen);
|
||||
break;
|
||||
case 0x29:
|
||||
strncpy(text,"MAIN_RELAY",textlen);
|
||||
break;
|
||||
case 0x2a:
|
||||
strncpy(text,"AD_CONVERTER_CARD",textlen);
|
||||
break;
|
||||
case 0x2b:
|
||||
strncpy(text,"POLARITY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x2c:
|
||||
strncpy(text,"AUXILIARY_RELAY",textlen);
|
||||
break;
|
||||
case 0x2d:
|
||||
strncpy(text,"MASTER_SWITCH_T1",textlen);
|
||||
break;
|
||||
case 0x2e:
|
||||
strncpy(text,"MASTER_SWITCH_T2",textlen);
|
||||
break;
|
||||
case 0x2f:
|
||||
strncpy(text,"TEMPERATURE_MAGNET",textlen);
|
||||
break;
|
||||
case 0x30:
|
||||
strncpy(text,"WATER_MAGNET",textlen);
|
||||
break;
|
||||
case 0x31:
|
||||
strncpy(text,"WATER_RACK",textlen);
|
||||
break;
|
||||
case 0x40:
|
||||
strncpy(text,"LOAD_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x41:
|
||||
strncpy(text,"DC_LINK_VOLTAGE_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x42:
|
||||
strncpy(text,"DC_LINK_VOLTAGE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x43:
|
||||
strncpy(text,"LOAD_VOLTAGE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x44:
|
||||
strncpy(text,"LOAD_CURRENT_RIPPLE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x45:
|
||||
strncpy(text,"DC_LINK_ISOLATION_NOT_OK",textlen);
|
||||
break;
|
||||
case 0x46:
|
||||
strncpy(text,"LOAD_ISOLATION_NOT_OK",textlen);
|
||||
break;
|
||||
case 0x47:
|
||||
strncpy(text,"LOAD_IMPEDANCE_OUT_OF_RANGE",textlen);
|
||||
break;
|
||||
case 0x48:
|
||||
strncpy(text,"SHUT_OFF_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x49:
|
||||
strncpy(text,"LOAD_DC_CURRENT_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4a:
|
||||
strncpy(text,"CURRENT_I1A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4b:
|
||||
strncpy(text,"CURRENT_I1B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4c:
|
||||
strncpy(text,"CURRENT_I1A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4d:
|
||||
strncpy(text,"CURRENT_I1B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4e:
|
||||
strncpy(text,"CURRENT_I2A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x4f:
|
||||
strncpy(text,"CURRENT_I2B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x50:
|
||||
strncpy(text,"CURRENT_I2A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x51:
|
||||
strncpy(text,"CURRENT_I2B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x52:
|
||||
strncpy(text,"CURRENT_I3P_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x53:
|
||||
strncpy(text,"CURRENT_I3N_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x54:
|
||||
strncpy(text,"CURRENT_IE_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x55:
|
||||
strncpy(text,"VOLTAGE_U1A_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x56:
|
||||
strncpy(text,"VOLTAGE_U1B_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x57:
|
||||
strncpy(text,"DIFF_CURRENT_I1A1_I1A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x58:
|
||||
strncpy(text,"DIFF_CURRENT_I1B1_I1B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x59:
|
||||
strncpy(text,"DIFF_CURRENT_I2A1_I2A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5a:
|
||||
strncpy(text,"DIFF_CURRENT_I2B1_I2B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5b:
|
||||
strncpy(text,"DIFF_CURRENT_I3P_I3N_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5c:
|
||||
strncpy(text,"CURRENT_I1A_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5d:
|
||||
strncpy(text,"CURRENT_I1B_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5e:
|
||||
strncpy(text,"CURRENT_I3A1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x5f:
|
||||
strncpy(text,"CURRENT_I3B1_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x60:
|
||||
strncpy(text,"CURRENT_I3A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x61:
|
||||
strncpy(text,"CURRENT_I3B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x62:
|
||||
strncpy(text,"CURRENT_I4_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x63:
|
||||
strncpy(text,"CURRENT_I5_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x64:
|
||||
strncpy(text,"DIFF_CURRENT_I3A1_I3A2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x65:
|
||||
strncpy(text,"DIFF_CURRENT_I3B1_I3B2_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x66:
|
||||
strncpy(text,"DIFF_CURRENT_I4_I5_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x67:
|
||||
strncpy(text,"VOLTAGE_U3A_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x68:
|
||||
strncpy(text,"VOLTAGE_U3B_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x69:
|
||||
strncpy(text,"VOLTAGE_U1_TOO_LOW",textlen);
|
||||
break;
|
||||
case 0x6a:
|
||||
strncpy(text,"VOLTAGE_U3A_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x6b:
|
||||
strncpy(text,"VOLTAGE_U3B_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x6c:
|
||||
strncpy(text,"SPEED_ERROR_TOO_HIGH",textlen);
|
||||
break;
|
||||
case 0x70:
|
||||
strncpy(text,"MAIN_RELAY_A",textlen);
|
||||
break;
|
||||
case 0x71:
|
||||
strncpy(text,"MAIN_RELAY_B",textlen);
|
||||
break;
|
||||
case 0x72:
|
||||
strncpy(text,"POWER_SWITCH_A",textlen);
|
||||
break;
|
||||
case 0x73:
|
||||
strncpy(text,"POWER_SWITCH_B",textlen);
|
||||
break;
|
||||
case 0x74:
|
||||
strncpy(text,"MONITOR_TRAFO_A",textlen);
|
||||
break;
|
||||
case 0x75:
|
||||
strncpy(text,"MONITOR_TRAFO_B",textlen);
|
||||
break;
|
||||
case 0x76:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER_A",textlen);
|
||||
break;
|
||||
case 0x77:
|
||||
strncpy(text,"TEMPERATURE_RECTIFIER_B",textlen);
|
||||
break;
|
||||
case 0x78:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x79:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x7a:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x7b:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x7c:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x7d:
|
||||
strncpy(text,"TEMPERATURE_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x7e:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER_A",textlen);
|
||||
break;
|
||||
case 0x7f:
|
||||
strncpy(text,"TEMPERATURE_TRANSFORMER_B",textlen);
|
||||
break;
|
||||
case 0x80:
|
||||
strncpy(text,"WATER_RECTIFIER_A",textlen);
|
||||
break;
|
||||
case 0x81:
|
||||
strncpy(text,"WATER_RECTIFIER_B",textlen);
|
||||
break;
|
||||
case 0x82:
|
||||
strncpy(text,"WATER_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x83:
|
||||
strncpy(text,"WATER_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x84:
|
||||
strncpy(text,"WATER_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x85:
|
||||
strncpy(text,"WATER_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x86:
|
||||
strncpy(text,"WATER_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x87:
|
||||
strncpy(text,"WATER_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x88:
|
||||
strncpy(text,"WATER_TRANSFORMER_A",textlen);
|
||||
break;
|
||||
case 0x89:
|
||||
strncpy(text,"WATER_TRANSFORMER_B",textlen);
|
||||
break;
|
||||
case 0x8a:
|
||||
strncpy(text,"DOOR_A",textlen);
|
||||
break;
|
||||
case 0x8b:
|
||||
strncpy(text,"DOOR_B",textlen);
|
||||
break;
|
||||
case 0x8c:
|
||||
strncpy(text,"DOOR_C",textlen);
|
||||
break;
|
||||
case 0x8d:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A",textlen);
|
||||
break;
|
||||
case 0x8e:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B",textlen);
|
||||
break;
|
||||
case 0x8f:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A1",textlen);
|
||||
break;
|
||||
case 0x90:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B1",textlen);
|
||||
break;
|
||||
case 0x91:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_A2",textlen);
|
||||
break;
|
||||
case 0x92:
|
||||
strncpy(text,"POWER_SEMICONDUCTOR_CONVERTER_B2",textlen);
|
||||
break;
|
||||
case 0x93:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I3P",textlen);
|
||||
break;
|
||||
case 0x94:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I3N",textlen);
|
||||
break;
|
||||
case 0x95:
|
||||
strncpy(text,"MAGNET_INTERLOCK_1",textlen);
|
||||
break;
|
||||
case 0x96:
|
||||
strncpy(text,"MAGNET_INTERLOCK_2",textlen);
|
||||
break;
|
||||
case 0x97:
|
||||
strncpy(text,"VENTILATOR",textlen);
|
||||
break;
|
||||
case 0x98:
|
||||
strncpy(text,"EMERGENCY_SWITCH",textlen);
|
||||
break;
|
||||
case 0x99:
|
||||
strncpy(text,"CAPACITOR_DISCHARGE_A_ON",textlen);
|
||||
break;
|
||||
case 0x9a:
|
||||
strncpy(text,"CAPACITOR_DISCHARGE_B_ON",textlen);
|
||||
break;
|
||||
case 0x9b:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I4",textlen);
|
||||
break;
|
||||
case 0x9c:
|
||||
strncpy(text,"CURRENT_TRANSDUCER_I5",textlen);
|
||||
break;
|
||||
case 0xb0:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_A",textlen);
|
||||
break;
|
||||
case 0xb1:
|
||||
strncpy(text,"TIMEOUT_DC_LINK_VOLTAGE_PART_B",textlen);
|
||||
break;
|
||||
case 0xb2:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_ON",textlen);
|
||||
break;
|
||||
case 0xb3:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_ON",textlen);
|
||||
break;
|
||||
case 0xb4:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_A_OFF",textlen);
|
||||
break;
|
||||
case 0xb5:
|
||||
strncpy(text,"TIMEOUT_AUXILIARY_RELAY_B_OFF",textlen);
|
||||
break;
|
||||
case 0xb6:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_A_ON",textlen);
|
||||
break;
|
||||
case 0xb7:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_B_ON",textlen);
|
||||
break;
|
||||
case 0xb8:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_A_OFF",textlen);
|
||||
break;
|
||||
case 0xb9:
|
||||
strncpy(text,"TIMEOUT_MAIN_RELAY_B_OFF",textlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SLSError(pEVDriver self, int *iCode, char *error, int iErrLen)
|
||||
{
|
||||
@ -224,6 +702,12 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
assert(pMe);
|
||||
|
||||
*iCode = pMe->iError;
|
||||
if(*iCode < -7000){
|
||||
slsdspCodeToText(-(pMe->iError + 7000),error,iErrLen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
switch(*iCode)
|
||||
{
|
||||
case BADECHO:
|
||||
@ -235,6 +719,12 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
case TIMEOUT:
|
||||
strncpy(error,"Timeout waiting for response", iErrLen);
|
||||
break;
|
||||
case BADHIGHLIM:
|
||||
strncpy(error,"Device internal upper limit violated",iErrLen);
|
||||
break;
|
||||
case BADLOWLIM:
|
||||
strncpy(error,"Device internal lower limit violated",iErrLen);
|
||||
break;
|
||||
default:
|
||||
getRS232Error(*iCode,error,iErrLen);
|
||||
break;
|
||||
@ -276,6 +766,9 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
msg[1] = 0x31;
|
||||
*/
|
||||
msg[1] = 0x3c;
|
||||
/*
|
||||
* ival = 0: ausschalten
|
||||
*/
|
||||
ival = 1;
|
||||
memcpy(msg+2, &ival,4);
|
||||
iRet = communicateSLS(pMe->pSock,msg,reply);
|
||||
@ -299,12 +792,28 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
static int SLSClose(pEVDriver self)
|
||||
{
|
||||
pSLSDriv pMe = NULL;
|
||||
int iRet;
|
||||
int iRet, ival;
|
||||
char msg[6], reply[6];
|
||||
|
||||
assert(self);
|
||||
pMe = (pSLSDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
/*
|
||||
* switch the thing off
|
||||
*/
|
||||
msg[0] = DSPWRITE;
|
||||
msg[1] = 0x3c;
|
||||
/*
|
||||
* ival = 0: ausschalten
|
||||
*/
|
||||
ival = 0;
|
||||
memcpy(msg+2, &ival,4);
|
||||
iRet = communicateSLS(pMe->pSock,msg,reply);
|
||||
/*
|
||||
* we are on our way out: ignore errors
|
||||
*/
|
||||
|
||||
NETClosePort(pMe->pSock);
|
||||
pMe->pSock = NULL;
|
||||
return 1;
|
||||
@ -319,8 +828,16 @@ static int communicateSLS(mkChannel *pSock, char msg[6], char reply[6])
|
||||
pMe = (pSLSDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
if(iError < -7000){
|
||||
return DEVFAULT;
|
||||
}
|
||||
|
||||
switch(iError)
|
||||
{
|
||||
case BADHIGHLIM:
|
||||
case BADLOWLIM:
|
||||
return DEVFAULT;
|
||||
break;
|
||||
case BADECHO:
|
||||
case TIMEOUT:
|
||||
return DEVREDO;
|
||||
|
175
tabledrive.tex
Normal file
175
tabledrive.tex
Normal file
@ -0,0 +1,175 @@
|
||||
\subsection{Tabled Driving}
|
||||
This object implements driving several motors along a predefined path. The definition
|
||||
of the path happens through a table. Positions between tabulated positions are
|
||||
interpolated by linear interpolation. Additionally, each motor may be driven a
|
||||
bit from the tabulated positions for fine adjustments. Of course the limits are
|
||||
variable from position to position. Thus this object also sets the software limits of the
|
||||
motors accordingly. This object assumes that motors can be driven between positions
|
||||
without watching for collisions. The original use of this module is to coordinate the
|
||||
movements of the MARS triffids or girafs.
|
||||
|
||||
The table lives in a separate file. The format of the file is very simple:
|
||||
Each block starts with a line containing:
|
||||
\begin{verbatim}
|
||||
# motorname
|
||||
\end{verbatim}
|
||||
This is a hash and the name of the motor.
|
||||
These lines are followed by n lines of:
|
||||
\begin{verbatim}
|
||||
lower position upper
|
||||
\end{verbatim}
|
||||
These are three numbers giving the lower and upper limit for this position in the table
|
||||
and, as the middle value, the target position for this entry.
|
||||
|
||||
|
||||
In order to achieve all this, we need a data structure per table entry:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$tdentry {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct{@\\
|
||||
\mbox{}\verb@ double lower, position, upper;@\\
|
||||
\mbox{}\verb@ int tablePos;@\\
|
||||
\mbox{}\verb@ }tdEntry, *ptdEntry;@\\
|
||||
\mbox{}\verb@ @$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The fields are the lower and upper limits, the position for this table entry and the
|
||||
number of the entry.
|
||||
|
||||
|
||||
For each motor we need another data structure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$tdmotor {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct {@\\
|
||||
\mbox{}\verb@ char motorName[132];@\\
|
||||
\mbox{}\verb@ int table;@\\
|
||||
\mbox{}\verb@ pMotor pMot;@\\
|
||||
\mbox{}\verb@ }tdMotor, *ptdMotor; @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[motorName] The name of the motor
|
||||
\item[table] A list of tabulated positions in the form of tdEntry
|
||||
\item[pMot] A pointer to the motor data structure.
|
||||
\end{description}
|
||||
|
||||
|
||||
The tabledrive object itself needs a data structure too:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$tdobj {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct{@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ int motorTable;@\\
|
||||
\mbox{}\verb@ int tableLength;@\\
|
||||
\mbox{}\verb@ float targetPosition;@\\
|
||||
\mbox{}\verb@ float currentPosition;@\\
|
||||
\mbox{}\verb@ int state;@\\
|
||||
\mbox{}\verb@ char orientMotor[80];@\\
|
||||
\mbox{}\verb@ int debug;@\\
|
||||
\mbox{}\verb@ }TableDrive, *pTableDrive;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor
|
||||
\item[pDriv] The drivable interface which encapsulates most of the magic of this module.
|
||||
\item[motorTable] A list of tdMotor entries.
|
||||
\item[tableLength] The length of the path of positions.
|
||||
\item[targetPosition] The target position we have to drive to.
|
||||
\item[currentPosition] where we are now.
|
||||
\item[state] A state variable used during driving the path.
|
||||
\item[orientMotor] is the name of the orienting motor, i.e. the one used to determine
|
||||
the position.
|
||||
\end{description}
|
||||
|
||||
|
||||
In terms of an interface, this object implements the drivable interface which has to
|
||||
deal with most of the work. There is just an interpreter interface which allows to
|
||||
configure and query the object.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$tdint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@int TableDriveFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@int TableDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ @$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
\verb@"tabledrive.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ SICS object for driving a couple of motors along a tabulated given path.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see file COPYRIGHT@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, July 2005@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSTABLEDRIVE@\\
|
||||
\mbox{}\verb@#define SICSTABLEDRIVE@\\
|
||||
\mbox{}\verb@#include <sics.h>@\\
|
||||
\mbox{}\verb@#include "../motor.h"@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$tdentry {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$tdmotor {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$tdobj {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$tdint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ @$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
8
tas.h
8
tas.h
@ -146,8 +146,14 @@
|
||||
#define HCONV3 127
|
||||
#define HCONV4 128
|
||||
#define POLFIL 129
|
||||
#define PIX 130
|
||||
#define PIY 131
|
||||
#define PIZ 132
|
||||
#define PFX 133
|
||||
#define PFY 134
|
||||
#define PFZ 135
|
||||
|
||||
#define MAXPAR 130
|
||||
#define MAXPAR 136
|
||||
#define MAXADD 20
|
||||
#define MAXEVAR 12
|
||||
|
||||
|
@ -201,6 +201,12 @@ char *tasVariableOrder[] = {
|
||||
"hconv3",
|
||||
"hconv4",
|
||||
"polfile",
|
||||
"pix",
|
||||
"piy",
|
||||
"piz",
|
||||
"pfx",
|
||||
"pfy",
|
||||
"pfz",
|
||||
NULL};
|
||||
/*-------------------------------------------------------------------
|
||||
Normally SICS does not store motor hardware limits into status files as
|
||||
|
Reference in New Issue
Block a user