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);
|
||
}
|