Files
sics/sel2.c
2000-02-07 10:38:55 +00:00

529 lines
15 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/************************************************************************/
/* 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);
}