529 lines
15 KiB
C
529 lines
15 KiB
C
/************************************************************************/
|
|
/* Hahn-Meitner-Institut Berlin */
|
|
/* Bereich Strukturforschung */
|
|
/* Abteilung NI / BENSC */
|
|
/* Glienicker Strasse 100 */
|
|
/* D-14109 Berlin (Wannsee) */
|
|
/* Software:K. Emmelmann, Tel.(030)8062-2588, Mail: klaus@dvwbs5.hmi.de */
|
|
/************************************************************************/
|
|
/* Datei: SEL.C */
|
|
/* Teil von: KWS.C */
|
|
/* Anwendung bei: V4 - KWS */
|
|
/* Titel: Treiberprogramm fuer Geschwindigkeitsselektor DORNIER */
|
|
/* Version: 1.0 vom: 30.1.96 */
|
|
/************************************************************************/
|
|
/*
|
|
Legende
|
|
=======
|
|
|
|
30.1.96 Emmelmann Implementierung
|
|
1.2.96 Emmelmann Statusdekodierung eingebaut
|
|
27.2.96 Emmelmann Strom wird auch im Status geliefert
|
|
|
|
|
|
Das Handbuch sagt Empfangsterminator ist Linefeed.
|
|
|
|
|
|
Jeder Befehl erzeugt ein Echo; argumentlose Befehle werden im Echo
|
|
zusaetzlich mit einer Zahl versehen, deren Bedeutung unbekannt ist.
|
|
|
|
|
|
FEHLERMELDUNGEN, die bekannt sind:
|
|
****************************************
|
|
|
|
1. Solldrehzahl zu klein !
|
|
2. Solldrehzahl zu gross !
|
|
3. derzeit keine Ausfuehrung moeglich !
|
|
4. Solldrehzahl in einem kritischen Bereich
|
|
- return to m
|
|
5. HOCHFAHREN 1
|
|
6.
|
|
|
|
zu 3: Abfrage der Istgeschwindigkeit ist waehrend des Hochfahrens aus dem
|
|
Stillstand nur ueber Lesen des Gesamtstatus moeglich
|
|
zu 4: es gibt verbotene Geschwindigkeitsbereiche
|
|
zu 5: beim Uebergang von Stop in den gestarteten Zustand
|
|
|
|
Zeitliches Protokollverhalten
|
|
-----------------------------
|
|
Wird ein Befehl bearbeitet, werden alle weiteren ueber die serielle
|
|
Schnittstelle einlaufenden Befehle ignoriert - auch nicht gepuffert !
|
|
|
|
Max. Befahlsrate: 1 Befehl / 5 Sekunden
|
|
|
|
Geraete-Verhalten
|
|
-----------------
|
|
Der Startbefehl faehrt den Selektor auf die Minimalgeschwindigkeit (3100U/min)
|
|
|
|
Das Protokoll: fuer jeden Befehl erzeugt der Selektor-PC ein Echo !
|
|
|
|
Host -> Selektor
|
|
------------------------
|
|
REM (disabled) Remote-Betrieb einschalten
|
|
Rueckmeldung: ENABLED / Host nicht betriebsbereit!
|
|
|
|
TTY (disabled) Local-Betrieb einschalten
|
|
Rueckmeldung: DISABLED
|
|
|
|
??? Sende Status (Status ist nicht fest und geht von der
|
|
Interpretation der Kennworte aus !)
|
|
|
|
TIM (disabled) Setzen des Zeitintervalles zur Time-Out-Ueberwachung des PCs
|
|
????
|
|
|
|
SST Start des Selektors und Ausregeln der Drehzahl (Nur wenn der
|
|
Selektor steht !); liefert als Rueckmeldung die Solldrehzahl
|
|
|
|
SDR nnnnn Vorgabe einer Soll-Drehzahl und geregelten Betrieb einschalten.
|
|
3100 => nnnnn <=28300 U/min; liegt der Wert in einem kritischen
|
|
Bereich (geht aus Setup-Menue hervor), kommt eine entsprechende
|
|
Rueckmeldung
|
|
|
|
FDR Sende die Solldrehzahl (Format 'RPM n')
|
|
|
|
STB Leerlauf ohne Regelung
|
|
|
|
BRE Beginne eine Verlustleistungsmessung - ist bei Statusabruf
|
|
lesbar, wenn dort die Betriebsart regeln erscheint !
|
|
|
|
HAL Bremse Selektor bis zum Stillstand ab (unterhalb 3000 U/min.)
|
|
|
|
*/
|
|
#include stdio.h
|
|
#include descrip.h
|
|
#include iodef.h
|
|
#include errno.h
|
|
#include lnmdef.h
|
|
|
|
#define FALSE 0
|
|
#define TRUE !FALSE
|
|
|
|
#define OK 0L
|
|
#define NOT_OK !OK
|
|
|
|
#define LIMIT_U 3100 /* niedrigste Drehzahl */
|
|
#define LIMIT_O 28300
|
|
|
|
/* Verbotene Drehzahlbereiche (Resonanzgefahr) */
|
|
|
|
#define RESONANZ_1U 3648
|
|
#define RESONANZ_1O 4552
|
|
#define RESONANZ_2U 5248
|
|
#define RESONANZ_2O 6449
|
|
#define RESONANZ_3U 9148
|
|
#define RESONANZ_3O 9949
|
|
|
|
#define TOK_BUF_L 25
|
|
|
|
#define SELE_LUN 0
|
|
|
|
extern FILE *fs;
|
|
|
|
static short chan_s=6;
|
|
|
|
/* *********************************************************************** */
|
|
/* ------------------------------------------------------------------------ */
|
|
long select_setup()
|
|
{
|
|
register rc;
|
|
$DESCRIPTOR(dev_descr, "TXA1:");
|
|
chan_s=SELE_LUN;
|
|
if ((rc=sys$assign(&dev_descr, &chan_s, NULL,NULL)) != 1)
|
|
{printf("Error in Selector_SETUP: Ret = %d\n",rc); return(NOT_OK);}
|
|
return(OK);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Function liest ueberprueft das Befehlsecho */
|
|
long sele_test_echo(cmd, lng)
|
|
char *cmd[];
|
|
int lng;
|
|
{
|
|
char echo[80];
|
|
if (sele_read(&echo)!= OK) return(NOT_OK);
|
|
if (strncmp(&echo, cmd, lng) != 0)
|
|
{printf("Selector:protocol error%s\n",echo); return(NOT_OK);}
|
|
else
|
|
return(OK);
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Function prueft die Anzahl der sich im Typeahead-Buffer befindenden Bytes
|
|
und liefert das naechste dort anstehende Zeichen, jedoch ohne es
|
|
aus dem Puffer zu entnehmen.
|
|
*/
|
|
long tst_buf_s(bt)
|
|
int *bt;
|
|
{
|
|
int bytes;
|
|
register rc;
|
|
struct {unsigned short status, bytes;
|
|
int pid; } iosb;
|
|
if ((rc=sys$qiow(NULL,chan_s,IO$_SENSEMODE | IO$M_TYPEAHDCNT,&iosb,
|
|
NULL, NULL, &bytes, NULL, NULL, NULL, NULL, NULL)) != 1)
|
|
{print_error(fs,"Error in QIOW"); return(NOT_OK);}
|
|
/**ch = (bytes >> 16) & 0xff;*/
|
|
*bt = bytes & 0xffff;
|
|
return(OK);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
long sele_read(message)
|
|
char *message;
|
|
{
|
|
char char_l[8], *ptr;
|
|
register rc;
|
|
struct {unsigned short status, bytes;
|
|
int pid; } iosb;
|
|
ptr = message;
|
|
for (;;)
|
|
{
|
|
if ((rc=sys$qiow(NULL,chan_s,IO$_READVBLK | IO$M_NOECHO,
|
|
&iosb,NULL,
|
|
NULL, char_l, 1, NULL, NULL, NULL, NULL)) != 1)
|
|
{printf("Error in QIOW, READ_MESS: %d\n", rc);return(NOT_OK);}
|
|
*ptr = char_l[0];
|
|
/* Terminator (linefeed) ? */
|
|
ptr++;
|
|
if (char_l[0] == '\n') break;
|
|
}
|
|
return(OK);
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
/* Pruefe ob der Selektor eine Fehlermeldung erzeugt hat und gib sie aus */
|
|
|
|
long select_error_msg(err)
|
|
long *err;
|
|
{
|
|
char chr[10], msg[80];
|
|
float waiti=3.0; /* Selektor PC hat 3 Sekunden Reaktionszeit !! */
|
|
|
|
/* Warte ein wenig - es koennte auf den Befehl hin eine Fehlermeldung erscheinen */
|
|
lib$wait(&waiti);
|
|
|
|
/* Es koennen auch mehrere Zeilen sein */
|
|
*err = FALSE;
|
|
for (;;)
|
|
{if (tst_buf_s(&chr) != OK) return(NOT_OK);
|
|
if (chr[0] != NULL)
|
|
{
|
|
if (sele_read(&msg) != OK) return(NOT_OK);
|
|
printf("Selektor failure:");
|
|
printf("%s\n\7",msg);
|
|
*err = TRUE;
|
|
}
|
|
else
|
|
return(OK);
|
|
}
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
long sele_write(message)
|
|
char message[];
|
|
{
|
|
char msg[80];
|
|
long err;
|
|
register rc;
|
|
struct
|
|
{
|
|
unsigned short status, bytes;
|
|
int pid; } iosb;
|
|
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
|
|
if ((rc=sys$qiow(NULL,chan_s,IO$_WRITEVBLK,&iosb,NULL, NULL,
|
|
message, strlen(message), NULL, NULL, NULL, NULL)) != 1)
|
|
{printf("Error in QIOW: %d\n",rc); return(NOT_OK);}
|
|
return(OK);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/*
|
|
Ein-/ Ausschalten von Stoerungsmeldungen vom Selektor an den Host
|
|
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
|
*/
|
|
long select_msg(tim)
|
|
long tim;
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[20] = "TIM ";
|
|
sprintf(&cmd+4,"%5u\0",tim);
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
return(OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Einschaltung der Fremdsteuerung des Selektors
|
|
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
|
*/
|
|
long select_remote()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "REM";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Ausschaltung der Fremdsteuerung des Selektors -
|
|
ein Steuerung kann dann nur noch ueber den PC des Geraetes
|
|
erfolgen.
|
|
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
|
*/
|
|
long select_local()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "TTY";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Starten des Selektors nach Stillstand auf die Minimaldrehzahl
|
|
*/
|
|
long select_start()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "SST";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Bremsen des Selektors bis zum Stillstand; eine
|
|
Drehzahlanzeige unterhalb 3000 U/min ist nicht moeglich.
|
|
*/
|
|
long select_stop()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "HAL";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Einschalten des geregelten Betriebes mit dem Setzen eines Sollwertes
|
|
der Drehzahl.
|
|
Aenderungen werden spontan uebernommen und ausgefuehrt.
|
|
Neben dem absoluten Minimum und Maximum existieren verbotene
|
|
Drehzahlbereiche, die z.Z. noch nicht exakt bekannt sind.
|
|
*/
|
|
long select_set_rpm(rpm)
|
|
int rpm;
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "SDR", s_dat[10] = "SDR 00000";
|
|
if ((rpm < LIMIT_U) || (rpm > LIMIT_O))
|
|
{
|
|
print_error(fs,"nominal value out of allowed range");
|
|
return;
|
|
}
|
|
/* Resonanzbereiche sind auch verboten */
|
|
if (
|
|
((rpm >= RESONANZ_1U) && (rpm <= RESONANZ_1O)) ||
|
|
((rpm >= RESONANZ_2U) && (rpm <= RESONANZ_2O)) ||
|
|
((rpm >= RESONANZ_3U) && (rpm <= RESONANZ_3O)))
|
|
{
|
|
print_error(fs,"nominal value within inhibited range");
|
|
return;
|
|
}
|
|
sprintf(&s_dat+4,"%5u",rpm);
|
|
sts = sele_write(s_dat);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Leerlauf des Selektors einschalten; weder Antrieb noch
|
|
Verzoegerung erfolgen - eine anschliessende Abbremsung oder
|
|
ein Uebergang zum geregelten Betrieb ist moeglich.
|
|
*/
|
|
long select_set_idle()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "STB";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Starten der Messung der elektrischen Verlustleistung des
|
|
Selektors. Anscheinend wird waehrend der Zeit die
|
|
Regelung deaktiviert.
|
|
Nach Abschluss der Messung erfolgt ein Uebergang in den\
|
|
geregelten Berieb.
|
|
Das Messergebnis wird in den Statusinformationsblock eingetragen.
|
|
*/
|
|
long select_read_power()
|
|
{
|
|
int sts;
|
|
long err;
|
|
char cmd[] = "BRE";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Lesen der aktuellen Drehzahl des Selektors */
|
|
long select_read_rpm(rpm)
|
|
int *rpm;
|
|
{
|
|
int sts, tmp;
|
|
long err;
|
|
char status[80], cmd[] = "FDR";
|
|
sts = sele_write(cmd);
|
|
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
|
|
|
sts = sele_read(&status);
|
|
sscanf(&status+4,"%d",&tmp);
|
|
*rpm = tmp;
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Auslesen des kompletten Statusblockes des Selektors.
|
|
Der Informationseintrag 'Verlustleistung' ist anscheinend nur dann
|
|
aktuell, wenn zuvor eine Verlustleistungsmessung aktiviert wurde.
|
|
Argumente:
|
|
rm = Betriebsstatus
|
|
[REG == regelnd]
|
|
[STB == im Leerlauf]
|
|
[BRE == bremsend]
|
|
nom_rpm = Soll der Drehzahl (U/min)
|
|
cur_rpm = Ist der Drehzahl (U/min)
|
|
pwr = Verlustleistung (W)
|
|
curr = elektr. Stomstaerke (A)
|
|
rot_temp= Temperatur des Rotors (C)
|
|
cont_temp= Temperatur des Gehaeuses (C)
|
|
inl_temp= Temperatur Kuehlwasser-Einlass
|
|
outl_temp= Temperatur Kuehlwasser-Abfluss
|
|
cool_wat= Kuehlwasser-Durchfluss (l/min)
|
|
vacuum = Betriebsvakuum (mbar)
|
|
accel = Rotationsbeschleunigung (g)
|
|
komm = Kommunikation zwischen Selektor-PC und Host
|
|
'ENABLED' oder "DISABLED'
|
|
dat = Tagesdatum dd.m.yyyy
|
|
tim = Tageszeit hh.mm.s
|
|
|
|
*/
|
|
long select_read_status(rm,nom_rpm, cur_rpm, pwr, curr, rot_temp, cont_temp,
|
|
inl_temp, outl_temp, cool_wat, vacuum, accel, komm, dat, tim)
|
|
char *rm[];
|
|
int *nom_rpm, *cur_rpm, *pwr, *rot_temp, *cont_temp, *inl_temp, *outl_temp;
|
|
float *cool_wat, *vacuum, *accel, *curr;
|
|
char *dat[], *tim[];
|
|
short *komm;
|
|
{
|
|
int cnt, key_id, sl, sts;
|
|
long err;
|
|
char ena_str[] = "ENABLED";
|
|
char dis_str[] = "DISABLED";
|
|
char keys[15][9] =
|
|
{
|
|
"Status:\0 ",
|
|
"S_DREH:\0 ",
|
|
"I_DREH:\0 ",
|
|
"P_VERL:\0 ",
|
|
"STROM:\0 ",
|
|
"T_ROT:\0 ",
|
|
"T_GEH:\0 ",
|
|
"T_VOR:\0 ",
|
|
"T_RUECK:\0",
|
|
"DURCHFL:\0",
|
|
"VAKUUM:\0 ",
|
|
"BESCHL:\0 ",
|
|
"KOM: \0 ",
|
|
"DATE: \0 ",
|
|
"TIME: \0 "};
|
|
|
|
char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr, tok_c[] = "/\0";
|
|
|
|
char status[255], cmd[] = "???";
|
|
|
|
if (sele_write(cmd) != OK) return(NOT_OK);
|
|
|
|
if (sele_test_echo(&cmd, 3) == NOT_OK) lib$stop(-1);
|
|
|
|
if (sele_read(&status) != OK) return(NOT_OK); /* Und nun der Status */
|
|
ptr_src = &status;
|
|
for (;;)
|
|
{
|
|
/* Lies Zeichenfolge bis zum naechsten Trennzeichen '/' */
|
|
ptr_token = strtok(ptr_src, &tok_c);
|
|
ptr_src = NULL; /* fuer die weitere Suche notwendig */
|
|
if (ptr_token == NULL) break;
|
|
strcpy(&tok_buf,ptr_token);
|
|
|
|
for (key_id = 0; key_id<=14; key_id++)
|
|
{
|
|
/* Ist das Schluesselwort enthalten ? */
|
|
sl = strlen(keys[key_id]);
|
|
if (strncmp(&keys[key_id][0], &tok_buf, sl) == NULL)
|
|
{
|
|
/* Schiebe das Schluesselwort raus */
|
|
for (cnt=0;cnt+sl < TOK_BUF_L; cnt++)
|
|
tok_buf[cnt] = tok_buf[cnt+sl];
|
|
switch (key_id)
|
|
{
|
|
case 0:
|
|
{
|
|
ptr = rm;
|
|
strcpy(ptr, &tok_buf);
|
|
break;
|
|
}
|
|
case 1: {sscanf(&tok_buf,"%d",nom_rpm); break;}
|
|
case 2: {sscanf(&tok_buf,"%d",cur_rpm); break;}
|
|
case 3: {sscanf(&tok_buf,"%d",pwr); break;}
|
|
case 4: {sscanf(&tok_buf,"%f",curr); break;}
|
|
case 5: {sscanf(&tok_buf,"%d",rot_temp); break;}
|
|
case 6: {sscanf(&tok_buf,"%d",cont_temp); break;}
|
|
case 7: {sscanf(&tok_buf,"%d",inl_temp); break;}
|
|
case 8: {sscanf(&tok_buf,"%d",outl_temp); break;}
|
|
case 9: {sscanf(&tok_buf,"%f",cool_wat); break;}
|
|
case 10: {sscanf(&tok_buf,"%f",vacuum); break;}
|
|
case 11: {sscanf(&tok_buf,"%f",accel); break;}
|
|
case 12:
|
|
{
|
|
if (strcmp(&tok_buf, &ena_str) == NULL)
|
|
{*komm = TRUE; break;}
|
|
if (strcmp(&tok_buf, &dis_str) == NULL)
|
|
{*komm = FALSE;break;}
|
|
printf("Invalid Communication value");
|
|
break;
|
|
}
|
|
case 13:
|
|
{
|
|
ptr = dat;
|
|
strcpy(ptr, &tok_buf);
|
|
break;
|
|
}
|
|
case 14:
|
|
{
|
|
ptr = tim;
|
|
strcpy(ptr, &tok_buf);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (select_error_msg(&err) != OK) return(NOT_OK);
|
|
if (err == TRUE) return(NOT_OK);
|
|
return(OK);
|
|
}
|