# Strukturierter Text für Anfänger



## Monsignore (30 September 2013)

Hallo Leute!

Bin gerade an meinem ersten richtigen Projekt mit Strukturierten Text. Ich glaube das ich zu umständlich programmiere. z.b. ich möchte das Variable1 den Wert von Variable2 übernimmt und behält wenn ich einen Taster betätige. Variable1 selbst geändert werden können.

Hintergrund ist eine Heizungssteuerung mit 24 Reglern. Variable2 stellt den gemeinsamen Sollwert da den alle per Knopfdruck übernehmen sollen. Ist jedoch dieser Sollwert für einzelne Regler nicht zutreffend soll dieser Regler einzeln per Variable1-24 angepasst werden können. Meine Idee mit der IF Anweisung würde zwar funktionieren aber kommt mir etwas aufwändig vor da ich alle Bedingungen programmieren muss. Habt ihr eine einfachere Lôsung oder komm ich da nicht drum herum?

Danke
Andi


----------



## PN/DP (30 September 2013)

Für bedingte Zuweisungen an numerische Variablen braucht man IF..THEN

Mach Dir mal keinen Kopf, das ist schon richtig so.
"Umständlich" fängt da an, wenn Du auch boolsche Zuweisungen in IF..THEN packst.

Was meinst Du mit "etwas aufwändig"? Magst Du uns ein Beispiel geben?

Harald


----------



## Monsignore (30 September 2013)

Ich habe auch schon BOOLSCHE Zustände per IF definiert das waren dann aber 10 Variablen den ich dann ihre Zustände zugwiesen habe. Mit aufwändig meine ich das ich einmal die IF anweisung für Zustand TRUE und Zustand FALSE schreiben muss... ist mir eben viel vorgekommen. Aber wenn das so seine richtigkeit hat dann past ja. Ich bei intresse auch einen Programmteil Online stellen.

Danke für die schnelle Antwort

Gruß
Andi


----------



## PN/DP (30 September 2013)

Monsignore schrieb:


> das ich einmal die IF anweisung für Zustand TRUE und Zustand FALSE schreiben muss


Vielleicht verkürzt da ELSE oder ELSIF

Harald


----------



## hucki (30 September 2013)

Monsignore schrieb:


> Mit aufwändig meine ich das ich einmal die IF anweisung für Zustand TRUE und Zustand FALSE schreiben muss...


Da kann man sich meistens das IF...THEN sparen und der Variablen den IF-Ausdruck zuweisen
Z.B.:
	
	



```
IF A=1 THEN
   B:=TRUE;
ELSE
   B:=FALSE;
END_IF;
```
kann man besser als

```
B:=A=1;
```
schreiben.
Ist eigentlich banal, aber sieht man immer wieder in der IF..THEN-Version.

Alternativ gibt es die SEL(ect)-Zuweisung (zumindest bei SCL, dann bestimmt auch bei ST), wenn man keinen boolschen Wert zuweisen möchte.


----------



## Monsignore (30 September 2013)

Danke für eure Tips werde morgen mal einen Teil meines Programms posten. Fals ihr dann noch Vorschläge habt nehm ich sie sehr dankend an.

Gruß
Andi


----------



## HrWechler (30 September 2013)

Man kann es wirklich verkürzen. Ich denke da an meine C/C++ Zeiten. Da habe ich immer sehr viele Ausdrücke sehr kompliziert geschrieben, bis man mir gezeigt hat, dass man einige Sachen auch kürzer haben kann. Begleitet mich bis jetzt in die SPS Zeiten. Ich versuche alles imm "keep easy and smart" zu machen, dann verliert man nicht so schnell den Überblick.


----------



## Monsignore (1 Oktober 2013)

Hier ein Auszuge aus meinem Heizungsregler Programm ich hoffe ihr versteht eingermaßen meine Ansätz..


```
PROGRAM _CYCLIC
	
	
	(*Temperaturregler Heizungen*)

	DO_HZG1		:=		(AI_TEMP1 < SET_HZG1) AND bHZG1 AND EV_HZG1 AND HM_RUN;
	
	(*Einheitstemperatur für Regler*)

	IF bSET_Temp THEN
		SET_HZG1	:=		SET_Temp;
	ELSIF
		NOT bSET_Temp THEN
		SET_HZG1	:=		SET_HZG1;
	END_IF
	
		(*Einschaltverzögerung Heizungen*)	
	
	
	
	
													(*Einschaltverzögerung Heizung 1*)
	TON_HZG1.IN		:=		HM_RUN AND bHZG1;
	TON_HZG1.PT		:=		T#5s;
	TON_HZG1();
	EV_HZG1			:=		TON_HZG1.Q;
	
													(*Einschaltverzögerung Heizung 2*)
	TON_HZG2.IN		:=		HM_RUN AND bHZG2 AND EV_HZG1;
	TON_HZG2.PT		:=		T#5s;
	TON_HZG2();
	EV_HZG2			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 3*)
	TON_HZG3.IN		:=		HM_RUN AND bHZG3 AND EV_HZG2;
	TON_HZG3.PT		:=		T#5s;
	TON_HZG3();
	EV_HZG3			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 4*)
	TON_HZG4.IN		:=		HM_RUN AND bHZG4 AND EV_HZG3;
	TON_HZG.PT		:=		T#5s;
	TON_HZG4();
	EV_HZG4			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 5*)
	TON_HZG5.IN		:=		HM_RUN AND bHZG5 AND EV_HZG4;
	TON_HZG5.PT		:=		T#5s;
	TON_HZG5();
	EV_HZG5			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 6*)
	TON_HZG6.IN		:=		HM_RUN AND bHZG6 AND EV_HZG5;
	TON_HZG6.PT		:=		T#5s;
	TON_HZG6();
	EV_HZG6			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 7*)
	TON_HZG7.IN		:=		HM_RUN AND bHZG7 AND EV_HZG6;
	TON_HZG7.PT		:=		T#5s;
	TON_HZG7();
	EV_HZG7			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 8*)
	TON_HZG8.IN		:=		HM_RUN AND bHZG8 AND EV_HZG7;
	TON_HZG8.PT		:=		T#5s;
	TON_HZG8();
	EV_HZG8			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 9*)
	TON_HZG9.IN		:=		HM_RUN AND bHZG9 AND EV_HZG8;
	TON_HZG9.PT		:=		T#5s;
	TON_HZG9();
	EV_HZG9			:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 10*)
	TON_HZG10.IN	:=		HM_RUN AND bHZG10 AND EV_HZG9;
	TON_HZG10.PT	:=		T#5s;
	TON_HZG10();
	EV_HZG10		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 11*)
	TON_HZG11.IN	:=		HM_RUN AND bHZG11 AND EV_HZG10;
	TON_HZG11.PT	:=		T#5s;
	TON_HZG11();
	EV_HZG11		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 12*)
	TON_HZG12.IN	:=		HM_RUN AND bHZG12 AND EV_HZG11;
	TON_HZG12.PT	:=		T#5s;
	TON_HZG12();
	EV_HZG12		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 13*)
	TON_HZG13.IN	:=		HM_RUN AND bHZG13 AND EV_HZG12;
	TON_HZG13.PT	:=		T#5s;
	TON_HZG13();
	EV_HZG13		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 14*)
	TON_HZG14.IN	:=		HM_RUN AND bHZG14 AND EV_HZG13;
	TON_HZG14.PT	:=		T#5s;
	TON_HZG14();
	EV_HZG14		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 15*)
	TON_HZG15.IN	:=		HM_RUN AND bHZG15 AND EV_HZG14;
	TON_HZG15.PT	:=		T#5s;
	TON_HZG15();
	EV_HZG15		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 16*)
	TON_HZG16.IN	:=		HM_RUN AND bHZG16 AND EV_HZG15;
	TON_HZG16.PT	:=		T#5s;
	TON_HZG16();
	EV_HZG16		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 17*)
	TON_HZG17.IN	:=		HM_RUN AND bHZG17 AND EV_HZG16;
	TON_HZG17.PT	:=		T#5s;
	TON_HZG17();
	EV_HZG17		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 18*)
	TON_HZG18.IN	:=		HM_RUN AND bHZG18 AND EV_HZG17;
	TON_HZG18.PT	:=		T#5s;
	TON_HZG18();
	EV_HZG18		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 19*)
	TON_HZG19.IN	:=		HM_RUN AND bHZG19 AND EV_HZG18;
	TON_HZG19.PT	:=		T#5s;
	TON_HZG19();
	EV_HZG19		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 20*)
	TON_HZG20.IN	:=		HM_RUN AND bHZG20 AND EV_HZG19;
	TON_HZG20.PT	:=		T#5s;
	TON_HZG20();
	EV_HZG20		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 21*)
	TON_HZG21.IN	:=		HM_RUN AND bHZG21 AND EV_HZG20;
	TON_HZG21.PT	:=		T#5s;
	TON_HZG21();
	EV_HZG21		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 22*)
	TON_HZG22.IN	:=		HM_RUN AND bHZG22 AND EV_HZG21;
	TON_HZG22.PT	:=		T#5s;
	TON_HZG22();
	EV_HZG22		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 23*)
	TON_HZG23.IN	:=		HM_RUN AND bHZG23 AND EV_HZG22;
	TON_HZG23.PT	:=		T#5s;
	TON_HZG23();
	EV_HZG23		:=		TON_HZG2.Q;
	
													(*Einschaltverzögerung Heizung 24*)
	TON_HZG24.IN	:=		HM_RUN AND bHZG24 AND EV_HZG23;
	TON_HZG24.PT	:=		T#5s;
	TON_HZG24();
	EV_HZG24		:=		TON_HZG2.Q;
	
	
	
	
	
	
															(*Anwahl Regleranzahl*)
	



	IF bHZG_Aktiv=0 THEN				(*Wenn keine Regler aktiviert werden Freigabe Bit´s 0*)
		bHZG1 		:= 		FALSE;
		bHZG2		:= 		FALSE;
		bHZG3 		:= 		FALSE;
		bHZG4 		:= 		FALSE;
		bHZG5 		:= 		FALSE;
		bHZG6 		:= 		FALSE;
		bHZG7 		:= 		FALSE;
		bHZG8 		:= 		FALSE;
		bHZG9 		:= 		FALSE;
		bHZG10 		:= 		FALSE;
		bHZG11 		:= 		FALSE;
		bHZG12 		:= 		FALSE;
	ELSIF bHZG_Aktiv=1 THEN				(*Regler 1 Aktiv*)
		bHZG1 		:=		TRUE;
		bHZG2 		:=		FALSE;
		bHZG3 		:=		FALSE;
		bHZG4 		:=		FALSE;
		bHZG5 		:=		FALSE;
		bHZG6 		:=		FALSE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv=2 THEN				(*Regler 1,2 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:=		FALSE;
		bHZG4 		:=		FALSE;
		bHZG5 		:=		FALSE;
		bHZG6 		:=		FALSE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 3 THEN			(*Regler 1,2,3 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:=		FALSE;
		bHZG5 		:=		FALSE;
		bHZG6 		:=		FALSE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 4 THEN			(*Regler 1,2,3,4 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:=		FALSE;
		bHZG6 		:=		FALSE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 5 THEN			(*Regler 1,2,3,4,5 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:=		FALSE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 6 THEN			(*Regler 1,2,3,4,5,6 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:=		FALSE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 7 THEN			(*Regler 1,2,3,4,5,6,7 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:=		FALSE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 8 THEN			(*Regler 1,2,3,4,5,6,7,8 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:= 		TRUE;
		bHZG9		:=		FALSE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 9 THEN			(*Regler 1,2,3,4,5,6,7,8,9 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:= 		TRUE;
		bHZG9 		:= 		TRUE;
		bHZG10		:=		FALSE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 10 THEN			(*Regler 1,2,3,4,5,6,7,8,9,10 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:= 		TRUE;
		bHZG9 		:= 		TRUE;
		bHZG10 		:= 		TRUE;
		bHZG11		:=		FALSE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 11 THEN			(*Regler 1,2,3,4,5,6,7,8,9,10,11 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:= 		TRUE;
		bHZG9 		:= 		TRUE;
		bHZG10 		:= 		TRUE;
		bHZG11 		:= 		TRUE;
		bHZG12		:=		FALSE;
	ELSIF bHZG_Aktiv= 12 THEN			(*Regler 1,2,3,4,5,6,7,8,9,10,11,12 Aktiv*)
		bHZG1 		:= 		TRUE;
		bHZG2 		:= 		TRUE;
		bHZG3 		:= 		TRUE;
		bHZG4 		:= 		TRUE;
		bHZG5 		:= 		TRUE;
		bHZG6 		:= 		TRUE;
		bHZG7 		:= 		TRUE;
		bHZG8 		:= 		TRUE;
		bHZG9 		:= 		TRUE;
		bHZG10 		:= 		TRUE;
		bHZG11 		:= 		TRUE;
		bHZG12 		:= 		TRUE;
	END_IF
	
										(*Freigabe Ventile und Umschaltboxen nach Erreichen mindest Temperatur*)
	
	
	
	
	FG_HZG1			:=		bHZG1 AND (AI_TEMP1 > SET_TEMP_MIN);	(*Freigabe aus Heizung 1*)
	FG_HZG2			:=		bHZG2 AND (AI_TEMP2 > SET_TEMP_MIN);	(*Freigabe aus Heizung 2*)
	FG_HZG3			:=		bHZG3 AND (AI_TEMP3 > SET_TEMP_MIN);	(*Freigabe aus Heizung 3*)
	FG_HZG4			:=		bHZG4 AND (AI_TEMP4 > SET_TEMP_MIN);	(*Freigabe aus Heizung 4*)
	FG_HZG5			:=		bHZG5 AND (AI_TEMP5 > SET_TEMP_MIN);	(*Freigabe aus Heizung 5*)
	FG_HZG6			:=		bHZG6 AND (AI_TEMP6 > SET_TEMP_MIN);	(*Freigabe aus Heizung 6*)
	FG_HZG7			:=		bHZG7 AND (AI_TEMP7 > SET_TEMP_MIN);	(*Freigabe aus Heizung 7*)
	FG_HZG8			:=		bHZG8 AND (AI_TEMP8 > SET_TEMP_MIN);	(*Freigabe aus Heizung 8*)
	
	FG_Umschaltbox	:=		FG_HZG1 AND NOT bHZG2 OR FG_HZG2 AND NOT bHZG3 OR FG_HZG3 AND NOT bHZG4 OR FG_HZG4 AND NOT bHZG5 OR FG_HZG5 AND NOT bHZG6 OR FG_HZG6 AND NOT bHZG7 OR FG_HZG7 AND NOT bHZG8 OR FG_HZG8; (*Freigabe aus aktiven Heizungen 1,2,3,4,5,6,7,8*)
	
END_PROGRAM
```

Gruß
Andi


----------



## StructuredTrash (1 Oktober 2013)

Da lässt sich schon einiges vereinfachen. Zunächst hier:

```
IF bSET_Temp THEN
		SET_HZG1	:=		SET_Temp;
	ELSIF
		NOT bSET_Temp THEN
		SET_HZG1	:=		SET_HZG1;
	END_IF
```
Die negierte Abfrage von bSET_Temp im ELSE-Zweig ist überflüsig, die ist ja sozusagen schon im ELSE vorhanden:

```
IF bSET_Temp
THEN
   SET_HZG1:=SET_Temp;
ELSE
   SET_HZG1:=SET_HZG1;   (* Hier wird mir der Sinn nicht klar. Du weist SET_HZG1 den Wert zu, den die Variable eh schon hat. Tippfehler? *)
END_IF
```
Wesentlich grösser ist das Potenzial allerdings bei den Zuweisungen von bHZG1..bHZG12 in Abhängigkeit von bHZG_Aktiv:

```
bHZG1:=bHZG_Aktiv>0;
bHZG2:=bHZG_Aktiv>1;
bHZG3:=bHZG_Aktiv>2;
(* usw.,
    bis *)
bHZG12:=bHZG_Aktiv>11;
```
Und wenn Du Dein erstes ST-Programm am Laufen hast, kannst Du Dich mal mit Arrays und Schleifen befassen. Damit könnte man vielleicht noch mehr erreichen.


----------



## Monsignore (1 Oktober 2013)

Danke für die super Tipps. Werde morgen versuchen das umzusetzen. 

@ StructuredTrash

Ich möchte erreichen dass wenn ich den Button bSET_Temp drücke alle 24 Regler den Wert SET_Temp übernehmen. Es soll jedoch wenn der Button bSET_Temp nicht gedrückt wird bzw ist  jeder Reglersollwert SET_HZG1-24 einzeln parametrierbar ist deshalb die zuweisung im Else zweig.


----------



## StructuredTrash (1 Oktober 2013)

Dann brauchst Du aber für jeden Regler noch eine weitere Variable, die den aktuell verwendeten Sollwert enthält, z. B. ActualSet1..ActualSet24. Die Zuweisung würde dann so aussehen:

```
IF bSet_Temp
THEN
   ActualSet1:=SET_Temp;
   ActualSet2:=SET_Temp;
   (* usw. *)
   ActualSet24:=SET_Temp;
ELSE
   ActualSet1:=SET_HZG1;
   ActualSet2:=SET_HZG2;
   (* usw. *)
   ActualSet24:=SET_HZG24;
END_IF
```
Und an dieser Stelle wird es wirklich Zeit, sich mit Arrays zu befassen. Ich stelle mal den entsprechenden Code hier ein, um Dir die Sache schmackhaft zu machen:

```
VAR
   ActualSet:ARRAY[1..24] OF REAL;  (bzw. den Datentyp, *)
   SET_HZG:ARRAY[1..24] OF REAL;  (den Du für die Sollwerte verwendest *)
   HZG_Index:USINT; (* Schleifenzähler *)
END_VAR

(* und der Code *)
IF bSET_Temp
THEN
   FOR HZG_Index:=1 TO 24 DO
      ActualSet[HZG_Index]:=SET_Temp;
   END_FOR
ELSE
(* entweder mit Schleife *)
   FOR HZG_Index:=1 TO 24 DO
      ActualSet[HZG_Index]:=SET_HZG[HZG_Index];
   END_FOR
(* oder noch einfacher, Zuweisung des Arrays in einem Rutsch *)
   ActualSet:=SET_HZG; (* Diese Zuweisung ist möglich, weil ActualSet und SET_HZG vom gleichen Datentyp sind *)
ENDIF
```


----------



## Monsignore (1 Oktober 2013)

Danke für die schnelle Hilfe. Mit dem Array muss ich mich morgen noch befassen da ich da noch wenig durchblick habe.

Gruß
Andi


----------



## blimaa (3 Oktober 2013)

Hi

Wenn wir schon an Ausdrücken und Zuweisungen verkürzen sind, ich hätte da auch seit längerem eine Frage.
Wenn ich eine Schrittkette mit dem Befehl "CASE ... OF" mache, mache ich die Ausgangsbeschaltung nach dem CASE. Sprich:

```
var: 
step:int; 
end_var

CASE step of

0: bla bla bla
1: bla bla bla 
3: etc. .....
end_case

IF step= 1 or step=3 or step=15 or step=28 or step=98 THEN
Ausgang:= true;
ELSE
Ausgang:= false;
END_IF
```

Nun wäre es noch recht hübsch wenn ich die ellenlange Vergleicherei (step= 1 or step=3 or step=15 or step=28 or step=98) auf etwas wie step=1,3,15,28,95 oder so könnte kürzen.
Leider habe ich noch keine schlaue Möglichkeit gefunden. Hat da jemand ein guter Tipp?

Gruss blimaa


----------



## Monsignore (3 Oktober 2013)

Hi

@StructuredTrash 

Danke für das Array Beispiel leider durchschaue ich das noch nicht ganz. Kannst du mir vielleicht dazu noch etwas Hilfestellung geben?

Danke

Gruß
Andi


----------



## RobiHerb (3 Oktober 2013)

*Etwas einfacher geht es so ...*



blimaa schrieb:


> Hi
> 
> Wenn wir schon an Ausdrücken und Zuweisungen verkürzen sind, ...
> 
> ...



Erst einmal feststellen, was am häufigsten vorkommt, ich nehme einmal an, Ausgang sollte in > 50 % der Cases FALSE sein:

var: 
step:int; 
end_var
Ausgang := FALSE; (*setze vorab den Standard Fall *)
CASE step of

0: bla bla bla Ausgang := TRUE;
1: bla bla bla 
2: bla bla bla 
3: bla bla bla Ausgang := TRUE;
4: etc. .....
end_case

Also in der Case Anweisung gleich die "Ausnahmen" mitbehandeln.

Alternativ auch danach suchen, ob ganze Gruppen zusammen gefasst werden können.


----------



## vollmi (3 Oktober 2013)

Monsignore schrieb:


> Ich möchte erreichen dass wenn ich den Button bSET_Temp drücke alle 24 Regler den Wert SET_Temp übernehmen. Es soll jedoch wenn der Button bSET_Temp nicht gedrückt wird bzw ist  jeder Reglersollwert SET_HZG1-24 einzeln parametrierbar ist deshalb die zuweisung im Else zweig.



Dann lässt du den Else Zweig einfach weg.

Also nur noch 

```
IF bSET_Temp
THEN
   SET_HZG1:=SET_Temp;
END_IF
```

Wenn die Bedingung nicht erfüllt ist. kannst du jederzeit von irgendwoher auf SET_HZG1 schreiben weil die Bedingung ja nicht mehr erfüllt ist und daher nicht vom IF Construkt überschrieben wird.


Hier..

```
IF bHZG_Aktiv=0 THEN                (*Wenn keine Regler aktiviert werden Freigabe Bit´s 0*)
        bHZG1         :=         FALSE;
        bHZG2        :=         FALSE;
        bHZG3         :=         FALSE;
        bHZG4         :=         FALSE;
        bHZG5         :=         FALSE;
        bHZG6         :=         FALSE;
        bHZG7         :=         FALSE;
        bHZG8         :=         FALSE;
        bHZG9         :=         FALSE;
        bHZG10         :=         FALSE;
        bHZG11         :=         FALSE;
        bHZG12         :=         FALSE;
```

Würde ich die False Zuweisung direkt vor dem IF unbedingt machen. Und im IF Konstrukt immer nur die True zuweisen.
Wenn natürlich keine IF Bedingung erfüllt ist, ist dann aber immer alles auf FALSE.

also


```
bHZG1         :=         FALSE;   (*Wenn keine Regler aktiviert werden Freigabe Bit´s 0*)
        bHZG2        :=         FALSE;
        bHZG3         :=         FALSE;
        bHZG4         :=         FALSE;
        bHZG5         :=         FALSE;
        bHZG6         :=         FALSE;
        bHZG7         :=         FALSE;
        bHZG8         :=         FALSE;
        bHZG9         :=         FALSE;
        bHZG10         :=         FALSE;
        bHZG11         :=         FALSE;
        bHZG12         :=         FALSE

   IF bHZG_Aktiv=1 THEN             
        bHZG1         :=         True;
   elsif bHZG_Aktiv=2 then
        bHZG1         :=         True;
        bHZG2         :=         True;

etc.
```
mfG René


----------



## blimaa (3 Oktober 2013)

@RobiHerb
Gar keine schlechte Idee! Muss man auch zuerst darauf kommen 
Aber prinzipiell etwas änliches wie step=1,3,15,28,98 oder so gibt es also nicht im ST?
Ich schreibe halt die Ausgänge gerne unter dem CASE Befehl, somit weiss ich genau, von wo überall der Ausgang beschrieben sein könnte. Respektiv es wird nur an einer Stelle auf den Ausgang geschriben. 
Vieleicht hat noch jemand anderes eine ebenfalls schlaue Idee 

Gruss blimaa


----------



## Thomas_v2.1 (3 Oktober 2013)

blimaa schrieb:


> Aber prinzipiell etwas änliches wie step=1,3,15,28,98 oder so gibt es also nicht im ST?



Du kannst bei der Case-Anweisung für die Auswahl auch eine Wertliste angeben.

```
CASE step OF
  1, 3, 15, 28, 98: Ausgang := true;
ELSE
  Ausgang := false;
END_CASE
```

Oder noch klarer

```
Ausgang := step= 1 or step=3 or step=15 or step=28 or step=98;
```


----------



## blimaa (3 Oktober 2013)

Hi
@Thomas_v2.1:  Natürlich, Logisch :s1:   

```
CASE step OF
  1, 3, 15, 28, 98: Ausgang := true;
ELSE
  Ausgang := false;
END_CASE
```

Das würde meiner Vorstellung etwa entsprechen. Werde ich doch direkt beim nächsten Projekt anwenden 

So und nun zurück zum Problem des Themenstarters (Sorry für den Thread-Missbrauch)

Gruss blimaa


----------



## StructuredTrash (7 Oktober 2013)

Monsignore schrieb:


> Hi
> 
> @StructuredTrash
> 
> ...


Ich denke, dass Deine Doku (CoDeSys?) Arrays und Schleifen besser erklärt als ich das hier in Kürze könnte. Lies Dich erst mal da ein, dann wird bestimmt einiges klarer.


----------



## Monsignore (16 Oktober 2013)

Hi Leute!

Danke für eure super Tipps, habe mein Programm überarbeitet und es ist sehr viel übersichtlicher geworden. Bin zwar von der Profiliga noch weit entfernt aber immerhin ein leichter fortschritt. Habt ihr vielleicht noch Ansätze zum Programmaufbau für mich?

Gruß
Andi


----------



## drfunfrock (18 Oktober 2013)

Teste auf die steigende Flanke vom Taster und setze den Wert. 


```
VAR
  Taster : R_TRIG;
END_VAR

Taster(IN:=bT1093);

IF Taster.Q THEN
  Temperatur := <was auch immer>;
END_IF
```

Dann mach einen Funktionsblock  FB_Regler und instanziere den in einem Array: 


```
Regler : ARRAY[1..24] OF FB_Regler;
```

Dann kannst du einfach eine Schleife fahren: 


```
FOR idx:=1 TO 24 DO
  Regler[idx](SetPoint := <was auch immer>, Out => Heater);
END_FOR ;
```

und wenn du zu mehr Lust hast: 

Jeder Block wie eine Heizung etc. bekommt einen Eingang für statische Parameter und einen Eingang für Sensoren. Als Ausgang nimmste alles, was ein FB berechnet. Damit das geht, machste 3 Strukturen. 


```
Type ST_Parameter
  STRUCT 
    Soll : LREAL; 
    Verzoegerung : TIME;
  END_STRUCT;
END_TYPE;

Type ST_Signal
  STRUCT 
    RealeTemp : LREAL; 
    Taster : BOOL;
  END_STRUCT;
END_TYPE;

Type ST_Runtime
  STRUCT 
    ReglerAnHeizung: LREAL; 
    Alarm : BOOL;
  END_STRUCT;
END_TYPE;

FB_Regler;
VAR_INPUT
  Parameter : ST_Parameter;
  Signal : ST_Signal
END_VAR
VAR_OUTPUT
  RT : ST_Runtime;
END_VAR

IF Signal.Taster THEN
  RT.ReglerAnheizung := <blabla>
END_IF;
```

Grundsätzlich ist es natürlich hässlich in einer Schleife mit Zahlen zu arbeiten, weil man weiss nie, ob man die nicht ändern muss. Dh. eine Konstante für den Endwert anlegen, ist schon Pflicht


```
VAR CONSTANT
 nAnzahlRegler : INT := 24;
END_VAR
```

Dann kann man 


```
Regler : ARRAY [1..nAnzahlRegler] OF FB_REGLER ;
```


----------



## Monsignore (18 Oktober 2013)

Hi

Danke für die Antwort sehe ich das richtig erstellt man so einen Funktionsblock? Kannst du mir das ein bischen genauer erklären?

Danke schönes Wochenende

Andi


----------



## drfunfrock (18 Oktober 2013)

Das ist abhängig von deiner verwendeten Software. :TOOL:

Lese einfach die Hilfe.


----------



## Monsignore (18 Oktober 2013)

Ich verwende zum Großteil B&R Automationstudio 3.090....


----------



## drfunfrock (18 Oktober 2013)

Ich denke, das fängt damit an einen neuen POU zu erstellen und dann kann wählen zwischen Programm und FB


----------



## Monsignore (21 Oktober 2013)

Morgen Leute

Heute habe ich die Nachricht erhalten mein Programm mit einer neuen funktion auszustatten. Auch wenn alle 24 Regler angewählt sind soll immer nur einer aktiv heizen um die Temperatur zu halten. Grund dafür ist die aufnahme Leistung auf ein minimum zu beschränken. Könnt ihr mir einen ansatz liefern wie ich das machen kann? Ich bin derzeit noch etwas überfordert damit.

Danke

Gruß
Andi


----------

