9. Lösungen: Funktionsblöcke (FBs) ======================================================================= Aufgabe 9.1b SR PROGRAM PLC_PRG (*vorrangig setzen*) VAR S1_Start AT %IX0.1:BOOL; S0_Stopp AT %IX0.0:BOOL; Out AT %QX1.0:BOOL; SR1 :SR; (*Instanz*) END_VAR (*Instanzaufruf des FBs mit Parameterübergabe*) SR1(SET1:= S1_Start, RESET:= S0_Stopp); Out:= SR1.Q1; _______________________________________________________________________ Aufgabe 9.1c mit R=, S= PROGRAM PLC_PRG (****************************************************************** Selbsthaltung, setzen vorrangig Zur Simulation werden nach dem Einloggen und Start die Werte von xS1_Start und xS0_Stopp wechselnd vorbereitet und geschrieben (Strg+F7). xOut wird beobachtet. *******************************************************************) VAR xS1_Start, xS0_Stopp, xOut :BOOL; END_VAR xOut R= xS0_Stopp; xOut S= xS1_Start; _______________________________________________________________________ Taktgeber PROGRAM PLC_PRG (*Taktgeber*) VAR TP_1, TP_2 :TP; e0 AT %IX0.0: BOOL; a0 AT %QX1.0: BOOL; m: BOOL; END_VAR TP_1(IN:=(e0 AND NOT a0) , PT:= T#1s); m:= TP_1.Q; TP_2(IN:=(NOT m) , PT:= T#0.5s); a0:= TP_2.Q; _______________________________________________________________________ Aufgabe 9.2 Bandsteuerung VAR_GLOBAL S0_Band_AUS AT %IX2.0:BOOL;(*Ö*) S1_Band_Ein AT %IX2.1:BOOL; Q1_Band1 AT %QX0.0:BOOL; Q2_Band2 AT %QX0.1:BOOL; END_VAR PROGRAM BANDANL VAR (*Instanzen*) RS_Band_1:RS; TON_1:TON; TOF_1,TOF_2:TOF; END_VAR (*Band 1*) RS_Band_1(SET:= S1_Band_Ein, RESET1:= NOT S0_Band_AUS); TOF_1(IN:= RS_Band_1.Q1, PT:= T#2s); Q1_Band1:= TOF_1.Q; (*Band 2*) TON_1(IN:= Q1_Band1, PT:= T#1s500ms); TOF_2(IN:= TON_1.Q, PT:= T#3s); Q2_Band2:= TOF_2.Q; PROGRAM PLC_PRG VAR END_VAR BANDANL();(*Aufruf des Unterprogramms*) _______________________________________________________________________ Aufgabe 9.3 a) Behälterfüllung VAR_GLOBAL M10_Ventil_A AT %QX0.0:BOOL; M11_Ventil_B AT %QX0.1:BOOL; END_VAR PROGRAM PLC_PRG (*Behälter füllen*) VAR xStart:BOOL;(*visu. Schaltfläche*) rK :REAL:=2.0;(*Mischverhältnis VA/VB*) tTa, tTb: TIME;(*Ventilöffnungszeiten*) rTa, rTb: REAL;(*in ms*) TP_A, TP_B :TP;(*Instanzen*) END_VAR (*Öffnungszeit abhängig von k berechnen*) IF rK>0 THEN rTa:= 30.0/(rK+1.0)* rK; rTb:= 30.0-rTa; tTa:=REAL_TO_TIME(rTa*1000.0); tTb:=REAL_TO_TIME(rTb*1000.0); (*Aufruf der Instanzen von TP*) TP_A(IN:=xStart , PT:=tTa); M10_Ventil_A:=TP_A.Q; TP_B(IN:=TP_A.Q , PT:=tTb); M11_Ventil_B:=TP_B.Q; END_IF; _______________________________________________________________________ Aufgabe 9.3 b) Behälterfüllung VAR_GLOBAL M10_Ventil_A AT %QX0.0:BOOL; M11_Ventil_B AT %QX0.1:BOOL; M20_Ventil_A AT %QX0.2:BOOL; M21_Ventil_B AT %QX0.3:BOOL; END_VAR Aufgabe 9.3 b) Lösung 1 TYPE BEHAELTER : STRUCT xStart, xVentil_A, xVentil_B:BOOL; rK:REAL:=2.0;(*Mischverhältnis VA/VB*) tTa, tTb:TIME;(*Öffnungszeit der Ventile*) rTa,rTb:REAL;(*in ms*) TP_A, TP_B:TP;(*Instanz*) END_STRUCT END_TYPE PROGRAM PLC_PRG (*2 Behälter füllen*) VAR Beh_1:BEHAELTER; Beh_2:BEHAELTER; END_VAR (*Behälter 1 Öffnungszeit abhängig von k berechnen*) IF Beh_1.rK > 0.0 THEN Beh_1.rTa:= 30.0/(Beh_1.rK+1.0)*Beh_1.rK; Beh_1.rTb:=30.0-Beh_1.rTa; Beh_1.tTa:=REAL_TO_TIME(Beh_1.rTa*1000.0); Beh_1.tTb:=REAL_TO_TIME(Beh_1.rTb*1000.0); (*Aufruf der Instanzen von TP*) Beh_1.TP_A(IN:=Beh_1.xStart , PT:= Beh_1.tTa); Beh_1.xVentil_A:= Beh_1.TP_A.Q; Beh_1.TP_B(IN:= Beh_1.TP_A.Q, PT:= Beh_1.tTb); Beh_1.xVentil_B:= Beh_1.TP_B.Q; END_IF; M10_Ventil_A:= Beh_1.xVentil_A; M11_Ventil_B:=Beh_1.xVentil_B; (*Behälter 2 Öffnungszeit abhängig von k berechnen*) IF Beh_2.rK > 0.0 THEN Beh_2.rTa:= 30.0/(Beh_2.rK+1.0)*Beh_2.rK; Beh_2.rTb:=30.0-Beh_2.rTa; Beh_2.tTa:=REAL_TO_TIME(Beh_2.rTa*1000.0); Beh_2.tTb:=REAL_TO_TIME(Beh_2.rTb*1000.0); (*Aufruf der Instanzen von TP*) Beh_2.TP_A(IN:=Beh_2.xStart , PT:= Beh_2.tTa); Beh_2.xVentil_A:= Beh_2.TP_A.Q; Beh_2.TP_B(IN:= Beh_2.TP_A.Q, PT:= Beh_2.tTb); Beh_2.xVentil_B:= Beh_2.TP_B.Q; END_IF; M20_Ventil_A:=Beh_2.xVentil_A; M21_Ventil_B:=Beh_2.xVentil_B; _______________________________________________________________________ Aufgabe 9.3 b) Lösung 2 PROGRAM PLC_PRG (*Zwei Behälter füllen*) VAR Beh:ARRAY[1..2] OF BEHAELTER; i: USINT; END_VAR FOR i := 1 TO 2 DO (*Öffnungszeit abhängig von k berechnen*) IF Beh[i].rK > 0.0 THEN Beh[i].rTa:= 30.0/(Beh[i].rK+1.0)*Beh[i].rK; Beh[i].rTb:= 30.0-Beh[i].rTa; Beh[i].tTa:= REAL_TO_TIME(Beh[i].rTa*1000.0); Beh[i].tTb:= REAL_TO_TIME(Beh[i].rTb*1000.0); (*Aufruf der Instanzen von TP*) Beh[i].TP_A(IN:=Beh[i].xStart , PT:= Beh[i].tTa); Beh[i].xVentil_A:= Beh[i].TP_A.Q; Beh[i].TP_B(IN:= Beh[i].TP_A.Q, PT:= Beh[i].tTb); Beh[i].xVentil_B:= Beh[i].TP_B.Q; END_IF; END_FOR; (*Ventile Behälter 1*) M10_Ventil_A:= Beh[1].xVentil_A; M11_Ventil_B:= Beh[1].xVentil_B; (*Ventile Behälter 2*) M20_Ventil_A:=Beh[2].xVentil_A; M21_Ventil_B:=Beh[2].xVentil_B; _______________________________________________________________________ Aufgabe 9.4 a) Zwei Behälter mit FB VAR_GLOBAL M10_Ventil_A AT %QX0.0:BOOL; M11_Ventil_B AT %QX0.1:BOOL; M20_Ventil_A AT %QX0.2:BOOL; M21_Ventil_B AT %QX0.3:BOOL; END_VAR PROGRAM PLC_PRG (*********************************************************************** Behälter füllen mit anwenderdefinierten FB. Zur Simulation werden nach dem Einloggen und Start die Werte von xStart und rK vorbereitet und geschrieben (Strg+F7). Beobachten Sie in der GLV das verzögerte Schalten von M10_Ventil_A ... abhängig vom rK-Wert. ************************************************************************) VAR (*Behälter 1*) xStart_1:BOOL; rK_1:REAL:=2.0; BEHAELTER1: BEHAELTER_K; (*Behälter 2*) xStart_2:BOOL; rK_2:REAL:=0.5; BEHAELTER2: BEHAELTER_K; END_VAR (*Aufruf der Instanzen des FBs*) BEHAELTER1(START:= xStart_1, K:= rK_1, YA=> M10_Ventil_A, YB=> M11_Ventil_B); BEHAELTER2(START:= xStart_2, K:= rK_2, YA=> M20_Ventil_A, YB=> M21_Ventil_B ); FUNCTION_BLOCK BEHAELTER_K (*Behälter, Mischverhältnis, Füllzeit*) VAR_INPUT START:BOOL; K:REAL;(*Mischverhältnis VA/VB*) END_VAR VAR_OUTPUT YA:BOOL; YB:BOOL; END_VAR VAR ta, tb: TIME;(*Öffnungszeit der Ventile A,B in ms*) ta_real, tb_real: REAL;(*Öffnungszeit der Ventile*) TP_A, TP_B:TP;(*Instanzen*) END_VAR (*Öffnungszeit abhängig von k berechnen*) ta_real:= 15.0 / (K+1.0)*K; tb_real:= 15.0 - ta_real; ta:=REAL_TO_TIME(ta_real*1000.0); tb:=REAL_TO_TIME(tb_real*1000.0); (*Aufruf der Instanzen von TP*) TP_A(IN:=START , PT:=ta); YA:=TP_A.Q; TP_B(IN:=YA , PT:=tb); YB:=TP_B.Q; _______________________________________________________________________ Aufgabe 9.4 b) Zwei Behälter mit FB und Übergabe der max. Füllzeit VAR_GLOBAL M10_Ventil_A AT %QX0.0:BOOL; M11_Ventil_B AT %QX0.1:BOOL; M20_Ventil_A AT %QX0.2:BOOL; M21_Ventil_B AT %QX0.3:BOOL; END_VAR PROGRAM PLC_PRG VAR (*Behälter 1*) start_1:BOOL; k_1:REAL:=2.0; Fuellzeit_1:TIME:=T#10s; BEHAELTER1: BEHAELTER_K; (*Behälter 2*) start_2:BOOL; k_2:REAL:=0.5; Fuellzeit_2:TIME:=T#15s; BEHAELTER2: BEHAELTER_K; END_VAR BEHAELTER1(START:= start_1 , K:= k_1, T_FUELL:= Fuellzeit_1); M10_Ventil_A:= BEHAELTER1.YA; M11_Ventil_B:= BEHAELTER1.YB; BEHAELTER2(START:= start_2 , K:= k_2, T_FUELL:= Fuellzeit_2); M20_Ventil_A:= BEHAELTER2.YA; M21_Ventil_B:= BEHAELTER2.YB; oder PROGRAM PLC_PRG (*Die Eingangsparameter werden direkt über die Visu beschrieben*) VAR (*Behälter 1*) BEHAELTER1: BEHAELTER_K; (*Behälter 2*) BEHAELTER2: BEHAELTER_K; END_VAR BEHAELTER1( YA=> M10_Ventil_A, YB=> M11_Ventil_B); BEHAELTER2( YA=> M20_Ventil_A, YB=> M21_Ventil_B); FUNCTION_BLOCK BEHAELTER_K (*Behälter, Mischverhältnis, Füllzeit*) VAR_INPUT START:BOOL; K:REAL:=1.0;(*Mischverhältnis VA/VB*) T_FUELL:TIME:=T#30s;(*Füllzeit*) END_VAR VAR_OUTPUT YA:BOOL; YB:BOOL; END_VAR VAR ta, tb: TIME;(*Öffnungszeit der Ventile A,B in ms*) ta_real, tb_real, tf_real: REAL;(*Öffnungszeit der Ventile*) TP_A, TP_B:TP;(*Instanzen*) END_VAR (*T_FUELL in REAL umwandeln und in s umrechnen*) tf_real:= TIME_TO_REAL(T_FUELL)/1000.0; (*Öffnungszeit abhängig von k berechnen*) ta_real:= tf_real/(K+1.0)*K; tb_real:= tf_real-ta_real; ta:= REAL_TO_TIME(ta_real*1000.0); tb:= REAL_TO_TIME(tb_real*1000.0); (*Aufruf der Instanzen von TP*) TP_A(IN:=START , PT:=ta); YA:=TP_A.Q; TP_B(IN:=YA , PT:=tb); YB:=TP_B.Q; _______________________________________________________________________ Aufgabe 9.4 c) Aufruf der Instanzen über eine Schleife PROGRAM PLC_PRG VAR xStart:ARRAY [1..2]OF BOOL; rK:ARRAY [1..2]OF REAL:= [2.0, 0.5]; tFuellzeit:ARRAY [1..2]OF TIME:= [T#10s, T#15s]; BEHAELTER:ARRAY [1..2]OF BEHAELTER_K; i:INT:=1; END_VAR FOR i := 1 TO 2 DO BEHAELTER[i](START:= xStart[i], K:= rK[i], T_FUELL:= tFuellzeit[i]); END_FOR; M10_Ventil_A:= BEHAELTER[1].YA; M11_Ventil_B:= BEHAELTER[1].YB; M20_Ventil_A:= BEHAELTER[2].YA; M21_Ventil_B:= BEHAELTER[2].YB; oder PROGRAM PLC_PRG (*Die Eingangsparameter werden direkt über die Visu beschrieben*) VAR BEHAELTER:ARRAY [1..2]OF BEHAELTER_K; i:INT:=1; END_VAR FOR i := 1 TO 2 DO BEHAELTER[i](); END_FOR; M10_Ventil_A:=BEHAELTER[1].YA; M11_Ventil_B:=BEHAELTER[1].YB; M20_Ventil_A:=BEHAELTER[2].YA; M21_Ventil_B:=BEHAELTER[2].YB; _______________________________________________________________________ Aufgabe 9.5 a) FB-Zweipunktregler FUNCTION_BLOCK Z_REG (*Zweipunktregler*) VAR_INPUT W:REAL;(*Sollwert*) X:REAL;(*Istwert*) H:REAL;(*Hysterese*) END_VAR VAR_OUTPUT Y:BOOL;(*Stellwert*) END_VAR (*Schalten*) IF X > W + H/2.0 THEN Y := FALSE; ELSIF X < W – H/2.0 THEN Y := TRUE; END_IF; PROGRAM PLC_PRG (*Aufruf der Zweipunktregler: y1 und y2 werden abhängig vom Sollwert w1, w2, dem Istwert x1, x2 und der Hysterese h1, h2 geschaltet. Den Istwert liefert der Prozess, in der Simulation wird er vorgegeben*) VAR w1:REAL:= 150.0; x1:REAL; h1:REAL:= 10.0; y1:BOOL; w2:REAL:= 200.0; x2:REAL; h2:REAL:= 5.0; y2:BOOL; Z_REG1:Z_REG;(*Instanz*) Z_REG2:Z_REG;(*Instanz*) END_VAR (*Aufruf mit Parameterübergabe*) Z_REG1(W:= w1,X:= x1,H:= h1); y1:= Z_REG1.Y; Z_REG2(W:= w2,X:= x2,H:= h2); y2:= Z_REG2.Y; _______________________________________________________________________ Aufgabe 9.5 b) Mehrere FBs-Zweipunktregler über eine Schleife aufrufen PROGRAM PLC_PRG (*Mehrere FBs-Zweipunktregler über eine Schleife aufrufen*) VAR i: INT; Z_REG_:ARRAY [0..2]OF Z_REG; rW:ARRAY [0..2]OF REAL:= [150.0, 120.0, 180.0]; rX:ARRAY [0..2]OF REAL; rH:ARRAY [0..2]OF REAL:= [10.0, 20.0, 30.0]; END_VAR rX[0]:=INT_TO_REAL(Temp0); rX[1]:=INT_TO_REAL(Temp1); rX[2]:=INT_TO_REAL(Temp2); (*Temperaturen lesen*) FOR i := 0 TO 2 DO Z_REG_[i](W:= rW[i], X:= rX[i], H:= rH[i]); END_FOR; Q0:=Z_REG_[0].Y; Q1:=Z_REG_[1].Y; Q2:=Z_REG_[2].Y;(*Schütze schalten*) _______________________________________________________________________ Aufgabe 9.6 Tanksteuerung, IN_OUT-Parameter mit anwenderdefiniertem Datentyp. TYPE TYPE typTANK : STRUCT rTemperatur:REAL; rDurchfluss:REAL; xHeizung, xEin:BOOL; END_STRUCT END_TYPE FUNCTION_BLOCK FbTANK_ANL (*Steuerung eines Tanks*) VAR_IN_OUT ANL:typTANK; END_VAR IF ANL.xEIN AND ANL.rDurchfluss > 25.0 THEN IF ANL.rTemperatur > 100.0 THEN ANL.xHeizung:= FALSE; ELSIF ANL.rTemperatur < 95.0 THEN ANL.xHeizung:= TRUE; END_IF; ELSE ANL.xHeizung:= FALSE; END_IF; a) Aufruf der Instanzen PROGRAM PLC_PRG VAR (****************************************************************** FbTANK_ANL mit IN-OUT-Parameter und anwenderdefiniertem Datentyp erstellen und mehrere Instanzen aufrufen. Zur Simulation werden nach dem Einloggen und Start die Werte in Tankanlage_1 und 2 vorbereitet und geschrieben (Strg+F7). Beurteilen Sie die xHeizung-Werte. *******************************************************************) Tankanlage_1:typTANK; instTANK_ANL_1:FbTANK_ANL; (*Instanz des FBs*) Tankanlage_2:typTANK; instTANK_ANL_2:FbTANK_ANL; END_VAR (*Instanzaufrufe*) instTANK_ANL_1(ANL:= Tankanlage_1); instTANK_ANL_2(ANL:= Tankanlage_2); b) Aufruf der Instanzen in einer FOR-Schleife mit GLV VAR_GLOBAL (*Tank1*) Temp1 AT %IW0 :INT; (*1000=>100°C*) Durchf1 AT %IW3 :INT;(*327600=>100Liter/min*) S1_Ein AT %IX2.0:BOOL; Q1_Heiz AT %QX0.0:BOOL; (*Tank2*) Temp2 AT %IW1 :INT; Durchf2 AT %IW4 :INT; S2_Ein AT %IX2.1:BOOL; Q2_Heiz AT %QX0.1:BOOL; END_VAR PROGRAM PLC_PRG VAR (****************************************************************** FB "TANK_ANL" mit IN-OUT-Parameter und anwenderdefiniertem Datentyp erstellen und mehrere Instanzen in einer FOR-Schleife aufrufen. Zur Simulation werden nach dem Einloggen und Start die Werte in der GVL vorbereitet und geschrieben (Strg+F7). Beurteilen Sie die Q1 und Q2 Werte. *******************************************************************) Tankanlage:ARRAY[1..2] OF typTANK; instTANK_ANL:ARRAY[1..2] OF FbTANK_ANL; i: INT; END_VAR (*Globale Var. lesen*) Tankanlage[1].rTemperatur:=Temp1/10.0; (*1000=>100°C*) Tankanlage[1].rDurchfluss:=Durchf1/327.60;(*327600=>100Liter/min*) Tankanlage[1].xEin:=S1_Ein; Tankanlage[2].rTemperatur:=Temp2/10.0; Tankanlage[2].rDurchfluss:=Durchf2/327.60; Tankanlage[2].xEin:=S2_Ein; (*Instanzaufrufe*) FOR i:=1 TO 2 DO instTANK_ANL[i](ANL:= Tankanlage[i]); END_FOR; (*Globale Var. beschreiben*) Q1_Heiz:=Tankanlage[1].xHeizung; Q2_Heiz:=Tankanlage[2].xHeizung; _______________________________________________________________________ Übung: Bandanlage mit bibliotheksfähigen FB VAR_GLOBAL S0_visu, S1_visu, S2_visu:BOOL; S0 AT %IX2.0:BOOL;(*Öffner*) S1 AT %IX2.1:BOOL;(*vor*) S2 AT %IX2.2:BOOL;(*zurück*) B1_hinten AT %IX2.4:BOOL; B2_vorne AT %IX2.5:BOOL; Q1_vor AT %QX0.4:BOOL; Q2_zur AT %QX0.5:BOOL; Q3_schleich AT %QX0.6:BOOL; END_VAR FUNCTION_BLOCK BAND_REV VAR_INPUT ON,OFF,SENSOR1,SENSOR2:BOOL; END_VAR VAR_OUTPUT OUT_LEFT, OUT_RIGHT:BOOL; END_VAR VAR SR_Enable, SR_Rigth, SR_Left:SR; END_VAR (*Freigabe*) SR_Enable(SET1:= ON, RESET:= OFF); (*Vor*) SR_Rigth(SET1:= SENSOR1, RESET:= SENSOR2); OUT_RIGHT:= SR_Enable.Q1 AND SR_Rigth.Q1 AND NOT OUT_LEFT; (*Zurück*) SR_Left(SET1:= SENSOR2, RESET:= SENSOR1); OUT_LEFT:= SR_Enable.Q1 AND SR_Left.Q1 AND NOT OUT_RIGHT; Über Web-Visu steuerbar PROGRAM MAIN VAR Band1:BAND_REV; END_VAR Band1(ON:= S1_visu, OFF:= S0_visu, SENSOR1:= B1_hinten, SENSOR2:= B2_vorne, OUT_LEFT=> Q2_zur, OUT_RIGHT=> Q1_vor); =======================================================================