Files

1612 lines
68 KiB
Plaintext

FUNCTION_BLOCK "MHMOmniSchleuse"
TITLE = HM-Omni-Schleuse (Schrittkette)
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : IBAE
FAMILY : Module
NAME : MHMOmni
//SCL-Portierung des AWL-Bausteins FB1274 "MHMOmniSchleuse" (verhaltensgleich).
//Statische Daten (SAVE/Para/Status2/Schleuse/Dyn) sind unveraendert -> Instanz-DBs bleiben gueltig.
//
//ABWEICHUNGEN ZUM AWL-ORIGINAL (bei Inbetriebnahme pruefen!):
// - DatenOut-Aufrufe verwenden lokale Puffer statt der Merker-Scratch-Bereiche
// MW200/M220../MB199/MW196 (Ergebnis identisch, keine Nebenwirkung auf Merker).
// Die Merker-Schnittstelle zu den indirekten FCs (MW190..MW198, MD182, MD192,
// M180.x) und die Fehler-Schnittstelle MW200/M200.x/M201.x bleiben erhalten.
// - Erfolg von "DatenOut" wird ueber RE_VAL Bit7 statt BR/JBI erkannt
// (bei PARA=0-Suchen aequivalent).
// - Indirekte Aufrufe UC FC[LeserFC/ZielFC/DraussenFC] sind als CASE ueber die
// projektierten FC-Nummern ausgefuehrt (Station UH06).
// - Registerindirekte Zugriffe auf Weichen-/Leser-DB sind durch PEEK/POKE ersetzt.
// - NW21 ("Schrittkette anhalten") ist im Original durch CLR+JU deaktiviert -> entfaellt.
// - NW10-Schritt "NoLesung": das AWL verglich HMI.TrolleyID_Input mit einem
// undefinierten Akku-Altwert; hier wird die beabsichtigte Pruefung
// (TrolleyID_Input <> 0) verwendet. VERHALTEN PRUEFEN!
VAR_INPUT
Schleusen_Nr : Int; // Aufruf fuer Schleuse
ErrQuit : Bool; // Ablaufstoerung quittieren
B_VorSchleuse : Bool; // Sensor Trolley faehrt in Bereich
B_InSchleuse : Bool; // Sensor Trolley ist in Schleuse
B_AusSchleuse : Bool; // Sensor Trolley hat Schleuse verlassen
B_Stau_raus : Bool; // Sensor Stau im Bereich rausfahren
Start_Ok : Bool; // Starten ist erlaubt
Antrieb_Schleuse_aktiv : Bool; // Kreisel-Antrieb aktiv
Antrieb_plus_aktiv : Bool; // Kreisel-Antrieb plus aktiv
"Schleuse_geöffnet" : Bool; // Schleuse hat geoeffnet
RestZeit_Bereich_plus : Int := 999; // Bereich +1: Restzeit bis AFS stoppt (s)
END_VAR
VAR_OUTPUT
Y_Schleuse_Auf : Bool; // Schleuse oeffnen
Error : Word; // Stoerungen uebergeben
END_VAR
VAR_IN_OUT
Antrieb_Schleuse_vor : Bool; // Schleusen-Antrieb einschalten
Antrieb_Schleuse_start : Bool; // Schleusen-Antrieb mit Zeit starten
Antrieb_Schleuse_stop : Bool; // Schleusen-Antrieb stoppen
Antrieb_Schleuse_PS : Bool; // Schleusen-Antrieb Energie sparen
Antrieb_plus_vor : Bool; // Antrieb plus einschalten
Antrieb_plus_start : Bool; // Antrieb plus mit Zeit starten
hStOk : Bool; // Anzeige Start n. Stoerung aktivieren
END_VAR
VAR
SAVE : Struct
Weichen_DB : Int; // Weichen-FIFO-DB
Weichen_DW : Int; // Weichen-FIFO-DW
"Weiche+1" : Int; // Weiche +1, wo reserviert wurde
Frei18 : Int;
Frei20 : Int;
END_STRUCT;
Para : Struct // Parameter
Schleusen_DL_DB : Int; // Einsprung Schleuse-Datenliste-DB
Weichen_DL_DB : Int; // Einsprung Weichen-Datenliste-DB
Leser_DL_DB : Int; // Einsprung Leser-Datenliste-DB
END_STRUCT;
Status2 : Struct
Trolley_an_Schleuse : Bool; // Trolley ist an Schleuse
"Warten_3.V" : Bool; // Warten auf 3.V
"2.Lesung_aktiv" : Bool; // 2.Lesung erfolgt
"3.Lesung_aktiv" : Bool; // 3.Lesung erfolgt
"TrolleyPos_übergeben" : Bool; // Trolley-Pos. uebergeben
"Warten_4.V" : Bool; // Warten auf 4.V
Ausfahrzeit_lernen : Bool; // Ausfahrzeit lernen
"Weichen-Schritt" : Bool; // Schritt 13-17 aktiv (Weiche evtl. belegen)
Trolley_ist_draussen : Bool; // Rueckmeldung von Sensor / Weiche
Einfahrzeit_lernen : Bool; // Einfahrzeit lernen
Telegramm_gesendet : Bool; // Telegramm wurde in Send-FIFO eingetragen
END_STRUCT;
Schleuse : "UDLHMOmniSchleuse"; // Statische Schleusendaten (aus DL)
Dyn : Struct // Dynamische Daten
Status : Struct
"Trolley_fährt_in_Schleuse" : Bool; // Trolley faehrt in Schleuse
Trolley_wartet_Lesung : Bool; // Trolley wartet auf Auftrag
"Trolley_wartet_auf_Ziel-FC" : Bool;
"Trolley_wartet_auf_Weiche+1" : Bool;
"Trolley_wartet_Bereich+1" : Bool; // Trolley wartet auf Bereich +1
"Trolley_fährt_aus" : Bool; // Trolley faehrt aus
MindestZeit_ok : Bool; // Schleuse ist MindestZeit geoeffnet
Trolley_draussen : Bool; // Trolley ist ausgefahren
Leser_triggern : Bool;
SF_angefordert : Bool;
Kein_Stop_mehr : Bool; // Kein Stop mehr, Antrieb soll starten
"Trolley_fährt_rückwärts" : Bool; // Trolley in Schleuse rueckwaerts erkannt
Weiche_geschaltet : Bool;
"Trolley ausserhalb Weiche" : Bool; // Trolley hat Weiche verlassen (von Weiche)
Error_aktiv : Bool; // Stoerung vorhanden
Reset_aktiv : Bool := TRUE; // Reset aktiv
END_STRUCT;
TrolleyID_Schleuse : DInt; // Trolley-Nr in der Schleuse
Trolley_EndZiel : Word; // Trolley-EndZiel
Trolley_ZwischenZiel : Word; // Trolley-ZwischenZiel
Trolley_ShopGroup : DInt; // Trolley-ShopGroup
Weichen_Ziel : Word; // Weichen-Ziel (fuer WeichenModul von Ziel-FC)
TrolleyID_Eingefahren : DInt; // Trolley-Nr von Bereich -1 gemeldet
TrolleyID_ausgefahren : DInt; // TrolleyID des ausgefahrenen Trolleys
HMI : Struct
TrolleyID_in_Schleuse : DInt; // Trolley-Nr in Schleuse (IN:PLC, OUT:PLC)
TrolleyID_Input : DInt; // Trolley-Nr Input (IN:HMI, OUT:PLC)
Schleuse_resetten : Bool; // Schleuse resetten (IN:HMI, Out:PLC)
END_STRUCT;
Sk : "USk_ILS"; // Status der Schrittkette
Leser : Struct
"IN" : Struct
xOutReadyForNewScan : Bool; // DBX10.1: Reader ist bereit fuer Leseanforderung
xOutReadingDone : Bool; // DBX10.0: Lesevorgang abgeschlossen / Handshake raus
xOutCodeGood : Bool; // DBX278.0: Gute Lesung
xOutCodeBad : Bool; // DBX278.1: Schlechte Lesung
nOutBarcode : DInt; // DBD12: Trolley ID
END_STRUCT;
"OUT" : Struct
xInStartReading : Bool; // DBX4.1: Starte Lesevorgang
xInHandshakeDone : Bool; // DBX4.2: Handshake Daten abgeholt
xInErrQuit : Bool; // DBX4.4: Fehler ruecksetzen
xInReset : Bool; // DBX4.5: Allgemeines Ruecksetzen des Bausteins
END_STRUCT;
END_STRUCT;
TrolleyID_unbekannt_Schleuse : DInt; // TrolleyID unbekannt (Trolley in Schleuse)
Rueckmld : Struct
RET_VAL_BLKMOV_Schleuse : Int; // Rueckmeldung nach BLKMOV-Aufruf
RET_VAL_DL_Schleuse : Byte;
RET_VAL_DL_Weiche : Byte; // Rueckmeldung nach DatenOut-Aufruf
RET_VAL_DL_Leser : Byte; // Rueckmeldung nach DatenOut-Aufruf
END_STRUCT;
Error : "UErrHMOmniSchleuse";
Stau_Zeit : Int; // Sensor B_VorSep ist belegt [100ms]
Mindest_Zeit : Int; // Sensor B_VorSep ist frei [100ms]
Leer_Zeit : Int;
Stop_Ursache : Word; // Stop-Stelle: Nw + Position
Vereinzelungstakte : DInt; // Anzahl der getaetigten Vereinzelungstakte
ZwischenZiel_eingefahren : Word; // Trolley-ZwischenZiel von Bereich -1
Ohne_B : Int;
SAVE2 : Struct
Leser_DB : Int; // Leser-FIFO-DB
Leser_DD : DInt; // Leser-FIFO-DD
END_STRUCT;
WarteZeit_PS : Int;
Restzeit_bis_Schleuse : Int;
Res200 : Array[1..16] of Int; // Reserve
END_STRUCT;
END_VAR
VAR_TEMP
Ueb_akt : Bool; // Ueberwachungszeit aktivieren
Weiter : Bool; // Weiterschaltbedingung ist erfuellt
Warte_neu : Bool; // Wartezeit neu triggern
Warte_stop : Bool; // Wartezeit stoppen
"Kein_Weichenbereich +1" : Bool;
"Reservierung_Weiche+1_aktiv" : Bool;
Leser_Zugriff : Bool; // Leser-Zugriff vorhanden
LeserFC_vorhanden : Bool;
ZielFC_vorhanden : Bool;
DraussenFC_vorhanden : Bool;
"TrolleyID_Bereich-1" : Bool; // Trolley-ID von Bereich -1 gemeldet
Einfahrzeit_nicht_bekannt : Bool;
LeserFC : Int; // Leser-FC
ZielFC : Int; // Ziel-FC
DraussenFC : Int; // Draussen-FC
tReVal : Byte; // Rueckmeldung DatenOut (statt MB199)
tPosition : Int; // Position von DatenOut (statt MW196)
tSuchInt : Int; // Suchdaten 1 Wort (statt MW200)
tSuchID : DInt; // Suchdaten TrolleyID (statt MD220)
tOutDaten : Array[0..19] of Word; // OutDaten-Puffer (statt M220..)
tByte : Byte; // Byte-Zwischenwert (statt MB200-Scratch)
tNeuSchritt : Int; // Uebergabe an Neu_Mig
tWartezeit : Int; // Uebergabe an Plus (*10ms)
tUebzeit : Int; // Uebergabe an tueb (*1s)
tWeichDb : DInt; // Weichen-DB fuer PEEK/POKE
tWeichBase : DInt; // Weichen-DW Basisoffset
tLeserDb : DInt; // Leser-DB fuer PEEK/POKE
tLeserBase : DInt; // Leser-DD Basisoffset
END_VAR
BEGIN
REGION NW1: Parameter-Uebergabe
#Para.Schleusen_DL_DB := 274; // Einsprung Schleuse-DL (vor Aufruf uebergeben!)
#Para.Weichen_DL_DB := 279; // Einsprung Weichen-DL
#Para.Leser_DL_DB := 273; // Einsprung Leser-DL
END_REGION
REGION NW2: Anzeige OP
IF #ErrQuit THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Ueberwachungszeit abgelaufen quittieren
END_IF;
IF NOT #Dyn.Sk.Bereich_ok THEN
#Dyn.Sk.OP_Schritt := 252; // Bereichsstop / Not-Aus
ELSIF NOT #Dyn.Sk.Auto_akt AND NOT #Dyn.Sk.Hand_akt THEN
#Dyn.Sk.OP_Schritt := 253; // Keine Betriebsart
ELSIF #Dyn.Sk.Hand_akt THEN
#Dyn.Sk.OP_Schritt := 255; // Handbetrieb aktiv
ELSE
#Dyn.Sk.OP_Schritt := #Dyn.Sk.Akt_Schritt; // Aktiver Schritt
END_IF;
END_REGION
REGION NW3: Out-Bits zum Zuruecksetzen (jeden Zyklus neu)
#Y_Schleuse_Auf := FALSE;
#Dyn.Status.Trolley_wartet_Lesung := FALSE;
#Dyn.Status."Trolley_wartet_auf_Ziel-FC" := FALSE;
#Dyn.Status."Trolley_wartet_auf_Weiche+1" := FALSE;
#Dyn.Status."Trolley_wartet_Bereich+1" := FALSE;
#Dyn.Status."Trolley_fährt_aus" := FALSE;
#Dyn.Status.Trolley_draussen := FALSE;
#Leser_Zugriff := FALSE;
#Status2."Weichen-Schritt" := FALSE;
#Dyn.Status.Reset_aktiv := #Dyn.Sk.Reset_Akt;
END_REGION
REGION NW4: HMI-Zeug
IF #Dyn.HMI.Schleuse_resetten THEN // von HMI
#Dyn.HMI.Schleuse_resetten := FALSE;
#Dyn.Sk.Reset := TRUE; // SK zuruecksetzen
END_IF;
#Dyn.HMI.TrolleyID_in_Schleuse := #Dyn.TrolleyID_Schleuse; // an HMI
END_REGION
REGION NW5: Schrittkette zuruecksetzen
IF #ErrQuit THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
END_IF;
IF #Dyn.Sk.Reset THEN // SK zuruecksetzen
#Dyn.Sk.Akt_Schritt := 0; // Schritt 0: Warten
#Dyn.Sk.Terr_Zelle := 0; // Zeitwerte loeschen
#Dyn.Sk.Tok_Zelle := 0;
#Dyn.Error.Err_BLKMov := FALSE;
#Dyn.Sk.Reset := FALSE;
#Dyn.Sk.Err_Schritt := FALSE;
#Dyn.Sk.Err_Uebzeit := FALSE;
#Status2.Telegramm_gesendet := FALSE;
#Dyn.Sk.Reset_Akt := TRUE; // Reset ist aktiv
#Dyn.Error.Schleuse_DL := FALSE;
#Dyn.Error.Undef_Schleuse := FALSE;
#Dyn.Error.Err_Trolley_nicht_in_Schleuse := FALSE;
#Dyn.Error.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Schritt := FALSE;
#Dyn.Error.Err_Stau_Einfahrt := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#Dyn.Error.Err_Raus_Sensor := FALSE;
#Dyn.Error.Err_Ziel := FALSE;
#Dyn.Error.Err_Weichen_DL := FALSE;
#Dyn.Error.Err_Undef_Weiche := FALSE;
#Dyn.Error.Err_Weiche_belegt := FALSE;
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#Dyn.Error.Err_Leser_nicht_bereit := FALSE;
#Dyn.Leser."IN".nOutBarcode := 0;
#Dyn.Stau_Zeit := 0;
#Dyn.Mindest_Zeit := 0;
#SAVE."Weiche+1" := 0;
#SAVE.Weichen_DB := 0;
#SAVE.Weichen_DW := 0;
#Dyn.SAVE2.Leser_DB := 0;
#Dyn.SAVE2.Leser_DD := 0;
#Schleuse.Schleusen_Nr := 0; // Damit statische Werte neu aus Datenbank geholt werden!
GOTO mRET;
END_IF;
END_REGION
REGION NW6: Stoerungen nach aussen uebergeben (Schnittstelle MW200)
"MW200" := 16#0000;
"M200.0" := #Dyn.Error.Schleuse_DL; // Schleuse-Datenliste fehlerhaft
"M200.1" := #Dyn.Error.Undef_Schleuse; // undefinierte Schleuse
"M200.2" := #Dyn.Error.Err_Trolley_nicht_in_Schleuse; // Trolley faehrt nicht in Schleuse
#Dyn.Error.Err_Uebzeit := #Dyn.Sk.Err_Uebzeit; // Ueberwachungszeit ist abgelaufen
"M200.3" := #Dyn.Sk.Err_Uebzeit;
IF NOT #Dyn.Sk.Err_Uebzeit THEN // AWL: NEG + R
#Dyn.Sk.Err_Uebzeit_AnzOk := FALSE;
END_IF;
#Dyn.Error.Err_Schritt := #Dyn.Sk.Err_Schritt; // Schritt-Nummer ist nicht definiert
"M200.4" := #Dyn.Sk.Err_Schritt;
"M200.5" := #Dyn.Error.Err_Stau_Einfahrt AND NOT #B_InSchleuse AND NOT #Y_Schleuse_Auf;
"M200.6" := #Dyn.Error.Err_BLKMov; // Error bei Block kopieren
"M200.7" := #Dyn.Error.Err_Trolley_raus; // Trolley faehrt nicht aus
"M201.0" := #Dyn.Error.Err_Raus_Sensor; // Raus-/Belade-Sensor wird nicht erreicht
"M201.1" := #Dyn.Error.Err_Ziel; // Trolley-Ziel nicht bekannt
"M201.2" := #Dyn.Error.Err_Weichen_DL; // Weichen-Datenliste fehlerhaft
"M201.3" := #Dyn.Error.Err_Undef_Weiche; // undefinierte Weiche
"M201.4" := #Dyn.Error.Err_Weiche_belegt; // Weiche bleibt belegt
"M201.5" := #Dyn.Error.Err_Kein_LeseErgebnis;
"M201.6" := #Dyn.Error.Err_Leser_nicht_bereit;
"M201.7" := #Dyn.Error.Barcode_nicht_bekannt;
// Andere Meldung als Ueberwachungszeit aktiv?
IF (("MW200" AND 2#1111_0111_1111_1111) <> 16#0000)
OR NOT #Dyn.Sk.Err_Uebzeit_AnzOk THEN
"M200.3" := FALSE; // Ueb.Zeit-Meldung nicht an PC senden
END_IF;
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Sk.Err_Uebzeit_AnzOk := TRUE; // Stoerung anzeigen ok, da 2.Zyklus aktiv!
END_IF;
#Error := "MW200"; // Schnittstelle nach aussen
// Stoerung vorhanden:
#Dyn.Status.Error_aktiv := ("MW200" <> 16#0000);
IF #Dyn.Status.Error_aktiv THEN
#hStOk := TRUE;
END_IF;
// Antrieb stoppen:
IF NOT #Dyn.Sk.Auto_akt OR #Dyn.Sk.Hand_akt OR NOT #Dyn.Sk.Bereich_ok THEN
#Antrieb_Schleuse_stop := TRUE; // SystemVoraussetzungen fehlen
END_IF;
// Stoerungen pro Zyklus neu erzeugen:
#Dyn.Error.Schleuse_DL := FALSE;
#Dyn.Error.Undef_Schleuse := FALSE;
#Dyn.Error.Err_Schritt := FALSE;
#Dyn.Error.Err_BLKMov := FALSE;
#Dyn.Error.Err_Raus_Sensor := FALSE;
#Dyn.Error.Err_Ziel := FALSE;
#Dyn.Error.Err_Weichen_DL := FALSE;
#Dyn.Error.Err_Undef_Weiche := FALSE;
#Dyn.Error.Err_Weiche_belegt := FALSE;
#Dyn.Error.Barcode_nicht_bekannt := FALSE;
IF NOT #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Error.Err_Trolley_nicht_in_Schleuse := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#Dyn.Error.Err_Raus_Sensor := FALSE;
END_IF;
END_REGION
REGION NW7: Statische Schleusen-Parameter holen
IF #Schleuse.Schleusen_Nr = #Schleusen_Nr THEN // schon geholt
#Dyn.Error.Schleuse_DL := FALSE;
#Dyn.Error.Undef_Schleuse := FALSE;
ELSE
#tSuchInt := #Schleusen_Nr; // Search-Daten (AWL: MW200)
"DatenOut"(SSDB := #Para.Schleusen_DL_DB,
SSDW := 0,
PARA := WORD#16#0000,
SEARCHDATEN := #tSuchInt,
RE_VAL => #tReVal,
Position => #tPosition,
OUTDATEN := #Schleuse); // Datensatz direkt in Schleuse-Struktur
#Dyn.Rueckmld.RET_VAL_DL_Schleuse := #tReVal;
IF #tReVal.%X7 THEN // AWL: JBI G_Ok (Datensatz gefunden)
#Dyn.Error.Schleuse_DL := FALSE;
#Dyn.Error.Undef_Schleuse := FALSE;
#Dyn.Rueckmld.RET_VAL_BLKMOV_Schleuse := 0; // kein BLKMOV mehr noetig
#Dyn.Error.Err_BLKMov := FALSE;
#Dyn.Stop_Ursache := 16#A063;
IF #Schleuse.Schleusen_Typ <> 1274 THEN // Dieser Aufruf-FB?
#Dyn.Error.Undef_Schleuse := TRUE; // undefinierte Schleuse
#Schleuse.Schleusen_Nr := 0; // Schleuse ungueltig!
#Dyn.Stop_Ursache := 16#A064;
END_IF;
ELSIF #tReVal.%X0 THEN // kein Datenlisten-Bereich
#Dyn.Error.Schleuse_DL := TRUE; // Schleusendatenbank fehlerhaft
#Dyn.Stop_Ursache := 16#A061;
ELSE
#Dyn.Error.Undef_Schleuse := TRUE; // undefinierte Schleuse
#Dyn.Stop_Ursache := 16#A062;
END_IF;
GOTO mRET; // in diesem Zyklus keine Schrittkette
END_IF;
END_REGION
REGION NW8: Einsprung Weiche plus ermitteln
IF #SAVE.Weichen_DB > 0 THEN // Einsprung-Zeiger bekannt
#"Kein_Weichenbereich +1" := FALSE;
ELSE
#"Kein_Weichenbereich +1" := (#Schleuse.RausWeichen_Nr = 0);
IF #"Kein_Weichenbereich +1" THEN
#Dyn.Error.Err_Undef_Weiche := FALSE; // keine Weiche projektiert
ELSE
#tSuchInt := #Schleuse.RausWeichen_Nr; // Search-Daten
"DatenOut"(SSDB := #Para.Weichen_DL_DB,
SSDW := 0,
PARA := WORD#16#0000,
SEARCHDATEN := #tSuchInt,
RE_VAL => #tReVal,
Position => #tPosition,
OUTDATEN := #tOutDaten);
#Dyn.Rueckmld.RET_VAL_DL_Weiche := #tReVal;
IF #tReVal.%X7 THEN // AWL: JBI W_Ok
#SAVE.Weichen_DB := WORD_TO_INT(#tOutDaten[2]); // (AWL: MW224)
IF #SAVE.Weichen_DB <= 0 THEN // sinnvoller Wert?
#Dyn.Error.Err_Undef_Weiche := TRUE; // undefinierte Weiche
ELSE
#SAVE.Weichen_DW := WORD_TO_INT(#tOutDaten[3]); // (AWL: MW226)
END_IF;
ELSE
#Dyn.Error.Err_Weichen_DL := #tReVal.%X0; // Weichen-Datenliste fehlerhaft
IF NOT #tReVal.%X0 THEN
#Dyn.Error.Err_Undef_Weiche := TRUE; // undefinierte Weiche
END_IF;
END_IF;
END_IF;
END_IF;
END_REGION
REGION NW9: Trolley in Schleuse entprellen
IF #B_InSchleuse THEN
#Dyn.Ohne_B := 0;
ELSIF #Status2.Trolley_an_Schleuse AND "1s-Impuls" THEN
#Dyn.Ohne_B := #Dyn.Ohne_B + 1; // Zeit ohne Sensor +1s
IF #Dyn.Ohne_B >= 3 THEN // Nach ca. 3s
#Status2.Trolley_an_Schleuse := FALSE;
#Dyn.Ohne_B := 0;
END_IF;
END_IF;
END_REGION
REGION NW10: Antrieb zusaetzlich starten / stoppen / Schleuse geoeffnet
IF #ErrQuit OR #"Schleuse_geöffnet" THEN
#Antrieb_Schleuse_start := TRUE; // Antrieb starten
#Antrieb_plus_start := TRUE; // Kreisel-Antrieb plus starten
END_IF;
IF #"Schleuse_geöffnet" THEN
#Dyn.Status."Trolley_fährt_in_Schleuse" := FALSE;
END_IF;
IF #"Schleuse_geöffnet"
AND (#Dyn.Status.Weiche_geschaltet OR #"Kein_Weichenbereich +1")
AND #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden THEN
#Antrieb_plus_vor := TRUE; // Antrieb plus einschalten
END_IF;
IF #"Schleuse_geöffnet"
AND (#Dyn.Status.Weiche_geschaltet OR #"Kein_Weichenbereich +1")
AND (#Antrieb_plus_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden) THEN
#Antrieb_Schleuse_vor := TRUE; // Antrieb einschalten
END_IF;
// Trolley ist in Schleuse und wartet -> Energiesparen nach ca. 3s
IF (#Status2.Trolley_an_Schleuse AND NOT #"Schleuse_geöffnet"
AND (NOT #B_VorSchleuse OR #Dyn.Error.Err_Stau_Einfahrt)
AND NOT #Dyn.Status.Kein_Stop_mehr)
OR (#"Schleuse_geöffnet"
AND #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden
AND NOT #Antrieb_plus_aktiv) THEN
IF #Dyn.WarteZeit_PS < 3 THEN // ca. 3s rum?
IF "1s-Impuls" THEN
#Dyn.WarteZeit_PS := #Dyn.WarteZeit_PS + 1;
END_IF;
ELSE
#Antrieb_Schleuse_PS := TRUE; // Antrieb in Energiesparen schalten
END_IF;
ELSE
#Dyn.WarteZeit_PS := 0;
END_IF;
END_REGION
REGION NW11: Einfahrzeit lernen
#Einfahrzeit_nicht_bekannt := (#Schleuse.EinfahrZeit = 0) OR #Status2.Einfahrzeit_lernen;
IF #Einfahrzeit_nicht_bekannt AND #B_VorSchleuse AND #Antrieb_Schleuse_aktiv
AND NOT #B_InSchleuse AND NOT #"Schleuse_geöffnet" THEN
#Status2.Einfahrzeit_lernen := TRUE;
END_IF;
IF #B_InSchleuse AND NOT #"Schleuse_geöffnet" THEN
#Status2.Einfahrzeit_lernen := FALSE;
END_IF;
IF #Status2.Einfahrzeit_lernen THEN
#Antrieb_Schleuse_vor := TRUE; // Antrieb einschalten
END_IF;
IF #Status2.Einfahrzeit_lernen AND #Antrieb_Schleuse_aktiv AND "1s-Impuls" THEN
#Schleuse.EinfahrZeit := #Schleuse.EinfahrZeit + 1;
END_IF;
END_REGION
REGION NW12: PS deaktivieren, da Trolley einfaehrt
IF NOT #Einfahrzeit_nicht_bekannt THEN // also bekannt
IF #B_VorSchleuse THEN // Neuer Trolley faehrt ein
#Dyn.Restzeit_bis_Schleuse := #Schleuse.EinfahrZeit;
END_IF;
// Restzeit zurueckzaehlen:
IF #Antrieb_Schleuse_aktiv AND NOT #"Schleuse_geöffnet" AND "1s-Impuls" THEN
#Dyn.Restzeit_bis_Schleuse := #Dyn.Restzeit_bis_Schleuse - 1;
IF #Dyn.Restzeit_bis_Schleuse <= 0 THEN
#Dyn.Restzeit_bis_Schleuse := 0; // Minimum uebergeben
END_IF;
END_IF;
// Trolley faehrt noch ein:
IF (#Dyn.Restzeit_bis_Schleuse > 0) AND NOT #B_InSchleuse AND NOT #"Schleuse_geöffnet" THEN
#Antrieb_Schleuse_vor := TRUE; // dadurch wird PS-Modus deaktiviert
END_IF;
END_IF;
END_REGION
REGION NW13: Ausfahrzeit lernen
IF #Status2.Ausfahrzeit_lernen AND #Antrieb_Schleuse_aktiv AND "1s-Impuls" THEN
#Schleuse.AusfahrZeit := #Schleuse.AusfahrZeit + 1;
END_IF;
END_REGION
REGION NW14: Spezial-FCs vorhanden?
#LeserFC := #Schleuse.Leser_FC;
#LeserFC_vorhanden := (#LeserFC > 0);
#ZielFC := #Schleuse.Ziel_FC;
#ZielFC_vorhanden := (#ZielFC > 0);
#DraussenFC := #Schleuse.Draussen_FC;
#DraussenFC_vorhanden := (#DraussenFC > 0);
END_REGION
REGION NW15: Error: Stau Bereich-Eingang
// TrolleyID zum Einfahren gemeldet / Trolley faehrt in Bereich:
#"TrolleyID_Bereich-1" := (#Dyn.TrolleyID_Eingefahren <> 0);
IF #"TrolleyID_Bereich-1" OR #B_VorSchleuse THEN
#Dyn.Status."Trolley_fährt_in_Schleuse" := TRUE;
END_IF;
// Antrieb einschalten:
IF #B_VorSchleuse AND NOT #B_InSchleuse AND NOT #"Schleuse_geöffnet" THEN
#Antrieb_Schleuse_vor := TRUE;
END_IF;
IF #B_VorSchleuse THEN
#Antrieb_Schleuse_start := TRUE;
END_IF;
// Sensor bei Bereichs-Einfahrt bleibt belegt?
IF NOT #B_VorSchleuse OR #"Schleuse_geöffnet" THEN
#Dyn.Error.Err_Stau_Einfahrt := FALSE;
#Dyn.Stau_Zeit := 0; // StauZeit neu aufziehen
ELSIF "1s-Impuls"
AND NOT (#Schleuse.Parameter_allg.Antrieb_vorhanden AND NOT #Antrieb_Schleuse_aktiv)
AND NOT #Dyn.Error.Err_Stau_Einfahrt THEN
#Dyn.Stau_Zeit := #Dyn.Stau_Zeit + 1; // Sensor B_VorSep ist belegt [1s]
IF #Dyn.Stau_Zeit >= 20 THEN // Stau-Zeit erreicht?
#Dyn.Error.Err_Stau_Einfahrt := TRUE; // Stau bei Einfahrt
#Dyn.Stau_Zeit := 0;
END_IF;
END_IF;
END_REGION
REGION NW16: Schleuse Mindestzeit geoeffnet/frei
IF (#Dyn.Sk.Akt_Schritt < 3) OR (#Dyn.Sk.Akt_Schritt > 6) OR NOT #"Schleuse_geöffnet" THEN
#Dyn.Status.MindestZeit_ok := FALSE;
#Dyn.Mindest_Zeit := 0; // FreiZeit neu aufziehen
ELSIF NOT ((#Schleuse.Parameter_allg.Antrieb_vorhanden AND NOT #Antrieb_Schleuse_aktiv)
OR (#Schleuse.Parameter_allg.Antrieb_Plus_vorhanden AND NOT #Antrieb_plus_aktiv)
OR #Dyn.Status.MindestZeit_ok
OR NOT "1s-Impuls") THEN
#Dyn.Mindest_Zeit := #Dyn.Mindest_Zeit + 1;
IF #Dyn.Mindest_Zeit >= #Schleuse.Mindeszeit_Schleuse_geoeffnet THEN // Mindest-Zeit erreicht?
#Dyn.Status.MindestZeit_ok := TRUE;
#Dyn.Mindest_Zeit := 0;
END_IF;
END_IF;
END_REGION
REGION NW17: Schleuse: Trolley ist draussen (Sensor/Weiche)
IF (#Dyn.Sk.Akt_Schritt < 5) OR (#Dyn.Sk.Akt_Schritt > 6) OR NOT #"Schleuse_geöffnet" THEN
#Status2.Trolley_ist_draussen := FALSE;
#Status2.Ausfahrzeit_lernen := FALSE;
ELSE
// Trolley ist draussen sofort (Rueckmeldung von Sensor/Weiche):
IF (#B_AusSchleuse AND #Schleuse.Parameter_allg.B_AusSep_vorhanden)
OR (#Dyn.Status."Trolley ausserhalb Weiche" AND NOT #"Kein_Weichenbereich +1") THEN
#Status2.Trolley_ist_draussen := TRUE;
END_IF;
END_IF;
END_REGION
REGION NW18: Einsprung Leser ermitteln
IF #Dyn.SAVE2.Leser_DB > 0 THEN // Einsprung-Zeiger bekannt
#Leser_Zugriff := TRUE;
ELSIF WORD_TO_INT(#Schleuse.Leser_ID) <> 0 THEN // Leser angegeben?
#tSuchInt := WORD_TO_INT(#Schleuse.Leser_ID); // Search-Daten
"DatenOut"(SSDB := #Para.Leser_DL_DB,
SSDW := 0,
PARA := WORD#16#0000,
SEARCHDATEN := #tSuchInt,
RE_VAL => #tReVal,
Position => #tPosition,
OUTDATEN := #tOutDaten);
#Dyn.Rueckmld.RET_VAL_DL_Leser := #tReVal;
IF #tReVal.%X7 THEN // AWL: JBI W_OkL
#Dyn.SAVE2.Leser_DB := WORD_TO_INT(#tOutDaten[1]); // (AWL: MW222)
IF #Dyn.SAVE2.Leser_DB <= 0 THEN // sinnvoller Wert?
#Dyn.Error.Err_Leser_nicht_bereit := TRUE; // undefinierter Leser
ELSE
// (AWL: MD224)
#Dyn.SAVE2.Leser_DD := DWORD_TO_DINT(
SHL(IN := WORD_TO_DWORD(#tOutDaten[2]), N := 16) OR WORD_TO_DWORD(#tOutDaten[3]));
#Dyn.Error.Err_Leser_nicht_bereit := FALSE;
#Leser_Zugriff := TRUE; // Leser-Zugriff vorhanden
END_IF;
ELSE
#Dyn.Error.Err_Leser_nicht_bereit := TRUE; // Leser-Datenliste fehlerhaft
END_IF;
END_IF;
END_REGION
REGION NW19: Reservierung bei Weiche plus noch aktiv?
IF #"Kein_Weichenbereich +1" THEN
#"Reservierung_Weiche+1_aktiv" := FALSE;
ELSE
#tWeichDb := INT_TO_DINT(#SAVE.Weichen_DB);
#tWeichBase := INT_TO_DINT(#SAVE.Weichen_DW);
// Schleuse -1 (DBW 78) mit dieser Schleuse belegt?
#"Reservierung_Weiche+1_aktiv" :=
(WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tWeichDb,
byteOffset := #tWeichBase + 78)) = #Schleusen_Nr);
// Mindestzeit nachtriggern (DBX 71.3):
IF #"Schleuse_geöffnet" AND #B_InSchleuse THEN
POKE_BOOL(area := 16#84, dbNumber := #tWeichDb,
byteOffset := #tWeichBase + 71, bitOffset := 3, value := TRUE);
END_IF;
END_IF;
END_REGION
REGION NW20: Leser-Einheit managen (Inputs holen)
IF NOT #Leser_Zugriff OR NOT #Schleuse.Parameter_allg.Leser_eingebaut THEN
#Dyn.Status.Leser_triggern := FALSE; // fuer Status-Anzeige
ELSE
#tLeserDb := INT_TO_DINT(#Dyn.SAVE2.Leser_DB);
#tLeserBase := #Dyn.SAVE2.Leser_DD;
// Offset 10:
#tByte := PEEK(area := 16#84, dbNumber := #tLeserDb, byteOffset := #tLeserBase + 10);
#Dyn.Leser."IN".xOutReadingDone := #tByte.%X0;
#Dyn.Leser."IN".xOutReadyForNewScan := #tByte.%X1;
// Offset 274:
#tByte := PEEK(area := 16#84, dbNumber := #tLeserDb, byteOffset := #tLeserBase + 274);
#Dyn.Leser."IN".xOutCodeGood := #tByte.%X0;
#Dyn.Leser."IN".xOutCodeBad := #tByte.%X1;
// Offset 12:
#Dyn.Leser."IN".nOutBarcode := DWORD_TO_DINT(
PEEK_DWORD(area := 16#84, dbNumber := #tLeserDb, byteOffset := #tLeserBase + 12));
END_IF;
END_REGION
// NW21 "Schrittkette anhalten": im AWL-Original durch CLR + JU dauerhaft
// deaktiviert (toter Code) -> entfaellt.
REGION NW22: Trolley wurde zurueckgezogen
IF NOT ((#Dyn.Sk.Akt_Schritt < 10) OR (#Dyn.Sk.Akt_Schritt > 12)
OR #Status2.Trolley_an_Schleuse OR #"Schleuse_geöffnet") THEN
#Antrieb_Schleuse_start := TRUE;
#Dyn.Leser."OUT".xInReset := TRUE;
#Dyn.Sk.Akt_Schritt := 0; // Neubeginn
IF #Schleuse.Parameter_allg.Leser_eingebaut THEN // sonst Daten behalten
#Dyn.Trolley_ZwischenZiel := 16#0000;
#Dyn.TrolleyID_Schleuse := 0;
END_IF;
END_IF;
END_REGION
REGION NW23: Sprungverteiler
IF #Dyn.Sk.Neu_Schritt <> -1 THEN // Schritt fuer naechsten Zyklus angegeben?
#Dyn.Sk.Akt_Schritt := #Dyn.Sk.Neu_Schritt; // Neuen Schritt uebergeben
#Dyn.Sk.Neu_Schritt := -1; // Urzustand
END_IF;
END_REGION
mNEU:
#Warte_neu := FALSE; // Wartezeit neutriggern
#Warte_stop := FALSE; // Wartezeit stoppen
CASE #Dyn.Sk.Akt_Schritt OF
0: // NW25 Schritt 0: Warten auf Trolley
#Weiter := #B_InSchleuse AND #Dyn.Sk.Auto_akt AND #Dyn.Sk.Bereich_ok;
// Trolley-Schleusendaten loeschen:
#Dyn.TrolleyID_Schleuse := 0;
#Dyn.Trolley_ShopGroup := 0;
#Dyn.Trolley_EndZiel := 16#0000;
#Dyn.Weichen_Ziel := 16#0000;
#Dyn.HMI.TrolleyID_Input := 0; // HMI-Zeug
IF #Dyn.Sk.Reset_Akt THEN // Reset ist aktiv
#tNeuSchritt := 20;
GOTO mNeuMig;
END_IF;
#Dyn.Error.Err_Leser_nicht_bereit := FALSE;
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#Dyn.Status.SF_angefordert := FALSE;
#Status2."TrolleyPos_übergeben" := FALSE;
#Status2.Telegramm_gesendet := FALSE;
IF #Weiter THEN // Weiterschaltbedingung ist erfuellt
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#tWartezeit := 50; // Angabe der Wartezeit (*10ms)
GOTO mPlus;
END_IF;
#Dyn.Stop_Ursache := 16#B001;
IF #Dyn.Status."Trolley_fährt_in_Schleuse" AND NOT #B_InSchleuse THEN
#Antrieb_Schleuse_vor := TRUE; // Antrieb einschalten
// S000A: Ueberwachungszeit starten
#Ueb_akt := #Dyn.Status."Trolley_fährt_in_Schleuse" AND NOT #B_InSchleuse
AND (#Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden);
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Trolley_nicht_in_Schleuse := TRUE;
#Dyn.Status."Trolley_fährt_in_Schleuse" := FALSE;
END_IF;
#tUebzeit := #Schleuse."Übzeit_in_Schleuse";
GOTO mTueb;
END_IF;
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Stop_Ursache := 16#B000;
GOTO mRET;
1: // NW26 Schritt 1: Trolley in Schleuse / Leser? / Daten vorhanden?
IF #B_InSchleuse THEN
#Status2.Trolley_an_Schleuse := TRUE;
END_IF;
IF NOT #Status2.Trolley_an_Schleuse AND #Schleuse.Parameter_allg.Leser_eingebaut THEN
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
// Zwischen-Ziel von Bereich -1 vorhanden?
IF (#Dyn.ZwischenZiel_eingefahren <> 16#0000)
AND NOT #Schleuse.Parameter_allg.Leser_eingebaut THEN
// Daten von Bereich -1 uebergeben:
#Dyn.Trolley_ZwischenZiel := #Dyn.ZwischenZiel_eingefahren;
#Dyn.ZwischenZiel_eingefahren := 16#0000;
#Dyn.TrolleyID_Schleuse := #Dyn.TrolleyID_Eingefahren;
#Dyn.TrolleyID_Eingefahren := 0;
#tNeuSchritt := 12; // Weiter mit Schritt 12
GOTO mNeuMig;
END_IF;
// X001:
#Dyn.Trolley_ZwischenZiel := 16#0000;
IF #Schleuse.Parameter_allg.Leser_eingebaut THEN // Leser vorhanden
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#tNeuSchritt := 9; // Weiter mit Schritt 9 (Leser bereit)
GOTO mNeuMig;
END_IF;
// Trolleydaten vorhanden? (Uebergabe von Bereich -1)
#Dyn.TrolleyID_Schleuse := #Dyn.TrolleyID_Eingefahren;
IF #Dyn.TrolleyID_Eingefahren <> 0 THEN
#tNeuSchritt := 11; // Weiter mit Schritt 11 (Trolleydaten lesen)
GOTO mNeuMig;
END_IF;
IF #ZielFC_vorhanden THEN
#tNeuSchritt := 12; // Weiter mit Schritt 12 (Ziel-FC)
GOTO mNeuMig;
END_IF;
#tNeuSchritt := 14; // Weiter mit Schritt 14 (Weichenbereich +1 vorhanden)
GOTO mNeuMig;
2: // NW27 Schritt 2: Ausfahren ok?
IF NOT #Status2.Trolley_an_Schleuse AND #Schleuse.Parameter_allg.Leser_eingebaut THEN
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
// Anlage aus oder Stoerung:
#Dyn.Stop_Ursache := 16#B021;
IF NOT #Dyn.Sk.Auto_akt OR NOT #Dyn.Sk.Bereich_ok THEN
GOTO mRET;
END_IF;
// Starten erlaubt?
#Dyn.Stop_Ursache := 16#B022;
IF NOT #Start_Ok THEN
GOTO mRET;
END_IF;
// Stau im Bereich +1:
#Dyn.Stop_Ursache := 16#B023;
#Dyn.Status."Trolley_wartet_Bereich+1" := TRUE;
IF #B_Stau_raus THEN // Sensor Stau im Bereich rausfahren
GOTO mRET;
END_IF;
// B_Aus_Schleuse aktiv:
#Dyn.Stop_Ursache := 16#B024;
#Dyn.Error.Err_Raus_Sensor := #Schleuse.Parameter_allg.B_AusSep_vorhanden AND #B_AusSchleuse;
IF #Dyn.Error.Err_Raus_Sensor THEN
GOTO mRET;
END_IF;
// Restzeit zum Ausfahren ausreichend?
#Dyn.Stop_Ursache := 16#B025;
IF ((#RestZeit_Bereich_plus < #Schleuse.AusfahrZeit) OR (#Schleuse.AusfahrZeit = 0))
AND (#RestZeit_Bereich_plus <> 999) THEN
RETURN; // AWL: BEC (Baustein sofort beenden, NW50 entfaellt)
END_IF;
// Antriebe aktivieren / aktiv?
IF #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden THEN
#Antrieb_plus_vor := TRUE;
END_IF;
IF #Antrieb_plus_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden THEN
#Antrieb_Schleuse_vor := TRUE;
END_IF;
#Dyn.Stop_Ursache := 16#B026;
IF NOT #Antrieb_plus_aktiv AND #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden THEN
GOTO mRET;
END_IF;
#Dyn.Status.Kein_Stop_mehr := NOT #Antrieb_Schleuse_aktiv
AND #Schleuse.Parameter_allg.Antrieb_vorhanden;
IF #Dyn.Status.Kein_Stop_mehr THEN
GOTO mRET;
END_IF;
#Status2."Warten_3.V" := FALSE;
IF NOT #Schleuse.Parameter_allg."2.V_bei_Ausfahrt_checken" THEN
#tNeuSchritt := 5; // Nur 1 langes Signal!
ELSE
#tNeuSchritt := 3; // 2.V bei Ausfahrt checken
END_IF;
GOTO mNeuMig;
3: // NW28 Schritt 3: Trolley faehrt aus / 1.V ausgefahren?
#Weiter := NOT #B_InSchleuse;
#Y_Schleuse_Auf := TRUE; // Schleuse oeffnen
#Dyn.Status."Trolley_fährt_aus" := TRUE;
IF #Weiter THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.Error.Err_Trolley_raus := FALSE;
#tWartezeit := 30; // Angabe der Wartezeit (*10ms)
GOTO mPlus;
END_IF;
IF NOT #"Kein_Weichenbereich +1" AND NOT #"Reservierung_Weiche+1_aktiv" THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Weiche nicht mehr angemeldet
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Error.Err_Trolley_raus := TRUE; // Trolley faehrt nicht aus
END_IF;
#Dyn.Stop_Ursache := 16#B031;
#Ueb_akt := #Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden;
#tUebzeit := #Schleuse."Übzeit_aus_Schleuse";
GOTO mTueb;
4: // NW29 Schritt 4: Trolley faehrt aus / Warten auf 2.V
#Weiter := #B_InSchleuse OR #Dyn.Status."Trolley ausserhalb Weiche";
// Bei Raus-Sensor nicht zaehlen:
IF #Schleuse.Parameter_allg.B_AusSep_vorhanden AND #B_AusSchleuse THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#tNeuSchritt := 5; // Zaehlen ueberspringen
GOTO mNeuMig;
END_IF;
#Y_Schleuse_Auf := TRUE; // Schleuse oeffnen
#Dyn.Status."Trolley_fährt_aus" := TRUE;
IF #Weiter THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#tWartezeit := 0;
GOTO mPlus;
END_IF;
IF NOT #"Kein_Weichenbereich +1" AND NOT #"Reservierung_Weiche+1_aktiv" THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
#tNeuSchritt := 0;
GOTO mNeuMig;
END_IF;
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Error.Err_Trolley_raus := TRUE;
END_IF;
#Dyn.Stop_Ursache := 16#B041;
#Ueb_akt := #Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden;
#tUebzeit := #Schleuse."Übzeit_aus_Schleuse";
GOTO mTueb;
5: // NW30 Schritt 5: Trolley faehrt aus?
#Weiter := NOT #B_InSchleuse
AND (#Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden)
AND (#Antrieb_plus_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_Plus_vorhanden);
// Ausfahrzeit lernen:
IF NOT #Schleuse.Parameter_allg.B_AusSep_vorhanden THEN
#Schleuse.AusfahrZeit := #Schleuse."Übzeit_aus_Schleuse"; // ohne Sensor: Ueb.Zeit uebergeben
END_IF;
IF (#Schleuse.AusfahrZeit = 0) AND #Schleuse.Parameter_allg.B_AusSep_vorhanden THEN
#Status2.Ausfahrzeit_lernen := TRUE;
END_IF;
#Y_Schleuse_Auf := TRUE; // Schleuse oeffnen
#Dyn.Status."Trolley_fährt_aus" := TRUE;
IF #B_InSchleuse THEN // B in Schleuse aktiv
#Dyn.Sk.Tok_Zelle := 0;
END_IF;
// Trolley ist draussen mit Verzoegerung:
IF #Weiter THEN
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#tWartezeit := 300;
GOTO mPlus;
END_IF;
// Trolley faehrt nicht raus!
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Error.Err_Trolley_raus := TRUE;
END_IF;
#Dyn.Stop_Ursache := 16#B051;
#Ueb_akt := #Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden;
#tUebzeit := #Schleuse."Übzeit_aus_Schleuse";
GOTO mTueb;
6: // NW31 Schritt 6: Schleuse Mindestzeit geoeffnet / Trolley draussen?
#Weiter := #Dyn.Status.MindestZeit_ok AND NOT #B_InSchleuse
AND ((NOT #Schleuse.Parameter_allg.B_AusSep_vorhanden AND #"Kein_Weichenbereich +1")
OR #Status2.Trolley_ist_draussen);
IF #Weiter THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.Error.Err_Trolley_raus := FALSE;
END_IF;
#Y_Schleuse_Auf := TRUE; // Schleuse oeffnen
#Dyn.Status."Trolley_fährt_aus" := TRUE;
// Erneutes Signal von B in Schleuse?
IF #B_InSchleuse THEN
#Dyn.Sk.Neu_Schritt := 5;
#Dyn.Mindest_Zeit := 0; // Mindest-Zeit neu starten
#Dyn.Status.MindestZeit_ok := FALSE;
GOTO mRET;
END_IF;
IF NOT #Weiter THEN // X060
#Dyn.Stop_Ursache := 16#B061;
// Trolley faehrt nicht raus!
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Error.Err_Trolley_raus := TRUE;
END_IF;
IF #Dyn.Error.Err_Trolley_raus AND NOT #Status2.Trolley_ist_draussen
AND #Schleuse.Parameter_allg.B_AusSep_vorhanden THEN
#Dyn.Error.Err_Trolley_raus := FALSE;
#Dyn.Error.Err_Raus_Sensor := TRUE; // Raus-Sensor wird nicht erreicht!
END_IF;
#Ueb_akt := #Antrieb_Schleuse_aktiv OR NOT #Schleuse.Parameter_allg.Antrieb_vorhanden;
#tUebzeit := #Schleuse."Übzeit_aus_Schleuse";
GOTO mTueb;
END_IF;
// X006: Trolley hat Schleuse verlassen
#Dyn.Status.Trolley_draussen := TRUE; // 1 Zyklus
#Dyn.Status."Trolley_fährt_in_Schleuse" := FALSE;
#Status2.Telegramm_gesendet := FALSE;
#Dyn.Vereinzelungstakte := #Dyn.Vereinzelungstakte + 1;
// Draussen-FC?
IF #DraussenFC_vorhanden THEN
"MW190" := INT_TO_WORD(#Schleusen_Nr); // Schleusen-Nr uebergeben
"MD182" := DINT_TO_DWORD(#Dyn.Trolley_ShopGroup); // Shop-Gruppe
"MW198" := #Dyn.Weichen_Ziel; // Weichenziel
CASE #DraussenFC OF // AWL: UC FC[#DraussenFC]
1182: "Arbeitsplatz_Draussen_FC"();
ELSE ; // unbekannter Draussen-FC
END_CASE;
END_IF;
#tNeuSchritt := 7; // Weiter mit Schritt 7
GOTO mNeuMig;
7: // NW32 Schritt 7: Trolley ausserhalb der Weiche
#Weiter := (NOT #"Kein_Weichenbereich +1" AND NOT #"Reservierung_Weiche+1_aktiv")
OR #Dyn.Status."Trolley ausserhalb Weiche"
OR #"Kein_Weichenbereich +1";
#Y_Schleuse_Auf := TRUE; // Schleuse oeffnen
#Dyn.Status."Trolley_fährt_aus" := TRUE;
IF #Dyn.Status.Weiche_geschaltet OR #"Kein_Weichenbereich +1" THEN
#Antrieb_Schleuse_vor := TRUE;
#Antrieb_plus_vor := TRUE;
END_IF;
IF NOT #Weiter THEN
#Dyn.Stop_Ursache := 16#B071;
GOTO mRET;
END_IF;
// X007: Trolley ist ausserhalb der Weiche?
IF #"Kein_Weichenbereich +1" THEN
GOTO mEndeMig;
END_IF;
// Weichen-Rueckmeldungen loeschen:
#Dyn.Status.Weiche_geschaltet := FALSE;
#Dyn.Status."Trolley ausserhalb Weiche" := FALSE;
// Weichen-Reservierung loeschen:
#tWeichDb := INT_TO_DINT(#SAVE.Weichen_DB);
#tWeichBase := INT_TO_DINT(#SAVE.Weichen_DW);
IF WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tWeichDb,
byteOffset := #tWeichBase + 78)) <> #Schleusen_Nr THEN
GOTO mEndeMig; // nicht diese Schleuse
END_IF;
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 78,
value := WORD#16#0000); // Schleuse -1 (DBW 78) loeschen
#SAVE."Weiche+1" := 0; // Hier wurde reserviert
#tWartezeit := 0;
GOTO mPlus; // Naechsten Schritt starten (Schritt 8)
8: // NW33 Schritt 8: Weichen-Rueckmeldungen = 0?
IF NOT #Dyn.Status.Weiche_geschaltet AND NOT #Dyn.Status."Trolley ausserhalb Weiche" THEN
GOTO mEndeMig;
END_IF;
#Dyn.Stop_Ursache := 16#B080;
GOTO mRET;
9: // NW34 Schritt 9: Lese-Einheit bereit?
#Weiter := (#Dyn.Leser."IN".nOutBarcode = 0)
AND #Dyn.Leser."IN".xOutReadyForNewScan
AND NOT #Dyn.Leser."IN".xOutReadingDone
AND NOT #Dyn.Leser."IN".xOutCodeGood
AND NOT #Dyn.Leser."IN".xOutCodeBad;
IF #Weiter THEN
#Dyn.Error.Err_Leser_nicht_bereit := FALSE;
END_IF;
IF NOT #Status2.Trolley_an_Schleuse AND #Schleuse.Parameter_allg.Leser_eingebaut THEN
#Dyn.Error.Err_Leser_nicht_bereit := FALSE;
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
#Dyn.Leser."OUT".xInStartReading := #Weiter; // Leser triggern
IF #Weiter THEN
#tWartezeit := 0;
GOTO mPlus;
END_IF;
// Leser nicht bereit:
IF #Dyn.Leser."IN".xOutReadingDone OR #Dyn.Leser."IN".xOutCodeGood
OR #Dyn.Leser."IN".xOutCodeBad THEN
#Dyn.Leser."OUT".xInHandshakeDone := TRUE; // Falls altes Handshake noch gewollt
END_IF;
IF #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.Error.Err_Leser_nicht_bereit := TRUE;
#Dyn.Leser."OUT".xInErrQuit := TRUE; // Vielleicht hilft es
END_IF;
IF #Dyn.Error.Err_Leser_nicht_bereit AND #ErrQuit THEN
#Dyn.Leser."OUT".xInReset := TRUE; // Mit Quittierung zusaetzlich reset!
END_IF;
// HMI-TrolleyID bei Leser nicht bereit:
IF (#Dyn.HMI.TrolleyID_Input <> 0) AND #Dyn.Error.Err_Leser_nicht_bereit THEN
#tWartezeit := 0;
GOTO mPlus;
END_IF;
#Ueb_akt := TRUE;
#tUebzeit := 5; // Angabe der Ueberwachungszeit (*1s)
GOTO mTueb;
10: // NW35 Schritt 10: Warten auf Leseeinheit
#Weiter := #Dyn.Leser."IN".xOutReadingDone
AND #Dyn.Leser."IN".xOutCodeGood
AND NOT #Dyn.Leser."IN".xOutCodeBad;
IF #Weiter THEN
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
END_IF;
IF NOT #Status2.Trolley_an_Schleuse AND #Schleuse.Parameter_allg.Leser_eingebaut THEN
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
#Dyn.Leser."OUT".xInStartReading := FALSE; // Leseeinheit triggern
IF #Weiter THEN
// X010: Leserdaten uebergeben
#Dyn.Leser."OUT".xInHandshakeDone := TRUE;
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.TrolleyID_Schleuse := #Dyn.Leser."IN".nOutBarcode;
IF (#Dyn.Leser."IN".nOutBarcode = 0) OR (#Dyn.Leser."IN".nOutBarcode = -1) THEN
#Dyn.Error.Err_Kein_LeseErgebnis := TRUE; // Unbekannt / Fehl-Lesung
#tNeuSchritt := 9; // Weiter mit Schritt 9 (Leser bereit)
GOTO mNeuMig;
END_IF;
#tNeuSchritt := 11; // Weiter mit Schritt 11
GOTO mNeuMig;
END_IF;
#Dyn.Status.Trolley_wartet_Lesung := TRUE;
IF NOT #Dyn.Error.Err_Leser_nicht_bereit THEN // von Schritt 9
IF #Dyn.Sk.Err_Uebzeit OR #Dyn.Leser."IN".xOutCodeBad THEN
#Dyn.Leser."OUT".xInHandshakeDone := TRUE;
// L2: Erst bei 3.Fehllesung Error!
IF NOT #Status2."2.Lesung_aktiv" THEN
#Status2."2.Lesung_aktiv" := TRUE;
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.Sk.Neu_Schritt := 9;
GOTO mRET;
END_IF;
// L3:
IF NOT #Status2."3.Lesung_aktiv" THEN
#Status2."3.Lesung_aktiv" := TRUE;
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#Dyn.Sk.Neu_Schritt := 9;
GOTO mRET;
END_IF;
// LX: Nach 3.Fehl-Lesung erst Leserfehler!
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Kein_LeseErgebnis := TRUE;
ELSE
#Dyn.Stop_Ursache := 16#B101;
#Ueb_akt := TRUE;
#tUebzeit := 10; // Angabe der Ueberwachungszeit (*1s)
GOTO mTueb;
END_IF;
ELSE
// LX (direkt von Schritt-9-Fehler):
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Kein_LeseErgebnis := TRUE;
END_IF;
// NoLesung: HMI-Eingabe?
#Dyn.TrolleyID_Schleuse := #Dyn.HMI.TrolleyID_Input;
IF #Dyn.HMI.TrolleyID_Input <> 0 THEN // ACHTUNG: AWL verglich mit undefiniertem Akku!
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#Dyn.Error.Err_Leser_nicht_bereit := FALSE; // von Schritt 9
#tWartezeit := 0;
GOTO mPlus;
END_IF;
// No_HMIa: Leser-FC aufrufen:
IF #LeserFC_vorhanden THEN
"MW190" := INT_TO_WORD(#Schleusen_Nr); // Schleusen-Nr uebergeben
"MW196" := #Dyn.Trolley_ZwischenZiel;
"M180.0" := #Dyn.Error.Err_Kein_LeseErgebnis;
"M180.1" := FALSE;
CASE #LeserFC OF // AWL: UC FC[#LeserFC] (Beeinflussung der Fehllesung)
1180: "Arbeitsplatz_Leser_FC"();
ELSE ; // unbekannter Leser-FC
END_CASE;
#Dyn.Stop_Ursache := 16#B102;
#Dyn.Trolley_ZwischenZiel := "MW196"; // Zwischenziel uebergeben
IF "MW196" <> 16#0000 THEN
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#tNeuSchritt := 12; // Weiter mit Schritt 12
GOTO mNeuMig;
END_IF;
END_IF;
// NoLFC:
#Dyn.Sk.Neu_Schritt := 9;
GOTO mRET;
11: // NW36 Schritt 11: Trolleydaten aus DL lesen
#Dyn.TrolleyID_Eingefahren := 0; // Eintrag von Weiche -1
#tSuchID := #Dyn.TrolleyID_Schleuse; // Search-Daten (AWL: MD220)
"DatenOut"(SSDB := #Schleuse.Gesamt_Trolley_DL,
SSDW := 0,
PARA := WORD#16#0000,
SEARCHDATEN := #tSuchID,
RE_VAL => #tReVal,
Position => #tPosition,
OUTDATEN := "TrolleyDL_OutDaten".OUTDaten); // Eintrag lesen (AWL: DB1011.DBX0.0)
#Dyn.Stop_Ursache := 16#B111;
#Dyn.Error.Barcode_nicht_bekannt := NOT #tReVal.%X7;
IF NOT #Dyn.Error.Barcode_nicht_bekannt THEN
// Relevante Trolleydaten auslesen:
#Dyn.Trolley_EndZiel := "TrolleyDL_OutDaten".OUTDaten.EndZiel;
IF #Dyn.Trolley_ZwischenZiel = 16#0000 THEN // ZwischenZiel nicht ueberschreiben
#Dyn.Trolley_ZwischenZiel := "TrolleyDL_OutDaten".OUTDaten.ZwischenZiel;
END_IF;
#Dyn.Trolley_ShopGroup := "TrolleyDL_OutDaten".OUTDaten.ShopGroup;
#tWartezeit := 0;
GOTO mPlus; // Naechsten Schritt starten
END_IF;
// UnbekanntBC / Nix_HMI: Leser-FC aufrufen:
IF #LeserFC_vorhanden THEN
"MW190" := INT_TO_WORD(#Schleusen_Nr);
"MD192" := DINT_TO_DWORD(#Dyn.TrolleyID_Schleuse);
"MW196" := #Dyn.Trolley_ZwischenZiel;
"M180.1" := #Dyn.Error.Barcode_nicht_bekannt;
"M180.0" := FALSE;
CASE #LeserFC OF // AWL: UC FC[#LeserFC] (Weiterfahrt bei nicht bekanntem Trolley)
1180: "Arbeitsplatz_Leser_FC"();
ELSE ;
END_CASE;
#Dyn.Trolley_ZwischenZiel := "MW196"; // ZwischenZiel uebergeben
IF "MW196" <> 16#0000 THEN
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#tNeuSchritt := 12; // Weiter mit Schritt 12
GOTO mNeuMig;
END_IF;
END_IF;
// Nix_LFC:
GOTO mRET;
12: // NW37 Schritt 12: Ziel-FC
IF NOT #Status2.Trolley_an_Schleuse AND #Schleuse.Parameter_allg.Leser_eingebaut
AND NOT #"Schleuse_geöffnet" THEN
#tNeuSchritt := 0; // Weiter mit Schritt 0
GOTO mNeuMig;
END_IF;
#Dyn.Status."Trolley_wartet_auf_Ziel-FC" := TRUE;
IF NOT #ZielFC_vorhanden THEN
#Dyn.Status."Trolley_wartet_auf_Ziel-FC" := FALSE;
#tNeuSchritt := 13; // Weiter mit Schritt 13
GOTO mNeuMig;
END_IF;
"M180.6" := FALSE; // Rueckmeldungen erst mal resetten
"MW190" := INT_TO_WORD(#Schleusen_Nr); // Schleusen-Nr uebergeben
"MD182" := DINT_TO_DWORD(#Dyn.Trolley_ShopGroup); // Shop-Gruppe
"MW194" := #Dyn.Trolley_EndZiel; // End-Ziel
"MW196" := #Dyn.Trolley_ZwischenZiel;
"MW198" := 16#0000; // Weichenziel erst mal nullen
CASE #ZielFC OF // AWL: UC FC[#ZielFC] (Beeinflussung der Weiterfahrt)
181: "HWtoAMRZielFC"();
1181: "Arbeitsplatz_Ziel_FC"();
2181: "HWtoOB_Ziel_FC"();
ELSE ; // unbekannter Ziel-FC
END_CASE;
#Dyn.Stop_Ursache := 16#B122;
// Spezial-Fall bei Uebergabe an Sorter / Turm (M180.6 wird nie im Ziel-FC gesetzt!)
// aber anderer Partner hat Schleuse extern geoeffnet:
IF #"Schleuse_geöffnet" AND NOT "M180.6" AND NOT #Status2."TrolleyPos_übergeben" THEN
#Status2."TrolleyPos_übergeben" := TRUE; // Nur einmalig
#Dyn.Vereinzelungstakte := #Dyn.Vereinzelungstakte + 1;
"Trolley_DL_Neue_Pos"(Gesamt_Trolley_DL := #Schleuse.Gesamt_Trolley_DL,
TrolleyID := #Dyn.TrolleyID_Schleuse,
Position := #Schleuse.Leser_ID,
ShopGroup := DINT#0,
Err => "M199.0");
// Draussen-FC?
IF NOT #DraussenFC_vorhanden THEN
GOTO mRET;
END_IF;
"MW190" := INT_TO_WORD(#Schleusen_Nr);
CASE #DraussenFC OF // AWL: UC FC[#DraussenFC] (z.B. Daten anpassen)
1182: "Arbeitsplatz_Draussen_FC"();
ELSE ;
END_CASE;
GOTO mRET;
END_IF;
// Normal:
IF "M180.6" THEN // Weiterfahrt von Ziel-FC erlaubt
// X012:
#Dyn.Trolley_ZwischenZiel := "MW196"; // zurueckschreiben, falls veraendert
#Dyn.Weichen_Ziel := "MW198"; // Weichenziel uebergeben
#tNeuSchritt := 13; // Weiter mit Schritt 13
GOTO mNeuMig;
END_IF;
IF NOT #Schleuse.Parameter_allg.Leser_eingebaut THEN
GOTO mRET;
END_IF;
#Dyn.Sk.Neu_Schritt := 11;
GOTO mRET;
13: // NW38 Schritt 13: Schleusen-Position zurueckschreiben
#Status2."Weichen-Schritt" := TRUE;
// Neue Position an Gesamt-Trolley-DL uebergeben:
"Trolley_DL_Neue_Pos"(Gesamt_Trolley_DL := #Schleuse.Gesamt_Trolley_DL,
TrolleyID := #Dyn.TrolleyID_Schleuse,
Position := #Schleuse.Leser_ID,
ShopGroup := DINT#0,
Err => "M199.0");
#tWartezeit := 0;
GOTO mPlus; // Naechsten Schritt starten
14: // NW39 Schritt 14: Weichenbereich +1 vorhanden
IF #"Kein_Weichenbereich +1" THEN
#tNeuSchritt := 2; // Weiter mit Schritt 2 (Ausfahren ok?)
GOTO mNeuMig;
END_IF;
#Status2."Weichen-Schritt" := TRUE;
#Dyn.Status.Weiche_geschaltet := FALSE;
#Dyn.Status."Trolley ausserhalb Weiche" := FALSE;
#tWartezeit := 0;
GOTO mPlus;
15: // NW40 Schritt 15: Weichenbereich raus bereit?
#Status2."Weichen-Schritt" := TRUE;
IF #Dyn.Weichen_Ziel = 16#0000 THEN // Weichenziel bekannt?
#Dyn.Sk.Neu_Schritt := 12; // Ziel-FC
#Dyn.Stop_Ursache := 16#B154;
GOTO mRET;
END_IF;
// X15A:
#Dyn.Status."Trolley_wartet_auf_Weiche+1" := TRUE;
#Dyn.Stop_Ursache := 16#B155;
IF #SAVE.Weichen_DB <= 0 THEN // Einsprung-Zeiger bekannt?
#Dyn.Stop_Ursache := 16#B150;
GOTO mRET;
END_IF;
// S015A: Weichendaten auslesen
#tWeichDb := INT_TO_DINT(#SAVE.Weichen_DB);
#tWeichBase := INT_TO_DINT(#SAVE.Weichen_DW);
#Dyn.Stop_Ursache := 16#B152;
IF NOT (NOT PEEK_BOOL(area := 16#84, dbNumber := #tWeichDb,
byteOffset := #tWeichBase + 70, bitOffset := 0) // Weichenbereich frei? (DBX70.0)
OR #Dyn.Status.Weiche_geschaltet
OR #Dyn.Status."Trolley ausserhalb Weiche") THEN
#tNeuSchritt := 16; // Weiter mit Schritt 16 (Daten an Weiche uebergeben)
GOTO mNeuMig;
END_IF;
// S015B: Reservierung schon erfolgt?
#Dyn.Status.Weiche_geschaltet := FALSE;
#Dyn.Status."Trolley ausserhalb Weiche" := FALSE;
IF WORD_TO_INT(PEEK_WORD(area := 16#84, dbNumber := #tWeichDb,
byteOffset := #tWeichBase + 78)) = #Schleusen_Nr THEN
// Reservierung loeschen:
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 78,
value := WORD#16#0000); // Schleuse -1 (DBW 78)
END_IF;
GOTO mRET;
16: // NW41 Schritt 16: Daten an Rausweiche uebergeben
#Status2."Weichen-Schritt" := TRUE;
#tWeichDb := INT_TO_DINT(#SAVE.Weichen_DB);
#tWeichBase := INT_TO_DINT(#SAVE.Weichen_DW);
// Trolley-ID (DBD 72):
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 72,
value := DINT_TO_DWORD(#Dyn.TrolleyID_Schleuse));
// Weichenziel (DBW 76):
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 76,
value := #Dyn.Weichen_Ziel);
// Zwischenziel (DBW 80):
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 80,
value := #Dyn.Trolley_ZwischenZiel);
// Schleuse -1 (DBW 78):
POKE(area := 16#84, dbNumber := #tWeichDb, byteOffset := #tWeichBase + 78,
value := INT_TO_WORD(#Schleusen_Nr));
#"Reservierung_Weiche+1_aktiv" := TRUE; // (da erst im naechsten Zyklus gelesen)
#SAVE."Weiche+1" := #Schleuse.RausWeichen_Nr; // Hier wurde reserviert
#tNeuSchritt := 17; // Weiter mit Schritt 17 (Hat Weiche geschaltet?)
GOTO mNeuMig;
17: // NW42 Schritt 17: Hat Rausweiche geschaltet?
#Status2."Weichen-Schritt" := TRUE;
// Weiche +1 noch mit dieser Schleuse aktiv?
IF NOT #"Reservierung_Weiche+1_aktiv" THEN
#tNeuSchritt := 14; // Weiter mit Schritt 14
GOTO mNeuMig;
END_IF;
#Dyn.Status."Trolley_wartet_auf_Weiche+1" := TRUE;
#Dyn.Stop_Ursache := 16#B170;
IF #Dyn.Status."Trolley ausserhalb Weiche" THEN // Rueckmeldung von Weiche +1
GOTO mRET;
END_IF;
IF #Dyn.Status.Weiche_geschaltet THEN // Rueckmeldung von Weiche +1
#tNeuSchritt := 2; // Weiter mit Schritt 2 (Ausfahren ok?)
GOTO mNeuMig;
END_IF;
#Dyn.Stop_Ursache := 16#B171;
GOTO mRET;
20: // NW43 Schritt 20: Schleuse resetten (Wartezeit)
#Weiter := #B_InSchleuse;
// ELS in Grundstellung fahren:
#Antrieb_Schleuse_vor := TRUE;
#Antrieb_Schleuse_start := TRUE;
IF #Weiter OR #Dyn.Sk.Err_Uebzeit THEN
#Dyn.Sk.Err_Uebzeit := FALSE; // Sofort weiter!
#tNeuSchritt := 21; // Weiter mit Schritt 21
GOTO mNeuMig;
END_IF;
#Dyn.Stop_Ursache := 16#B201;
#Ueb_akt := TRUE;
#tUebzeit := 60; // AWL: L Wartezeit_bis_leer; L 60 -> 60 wirksam
GOTO mTueb;
21: // NW44 Schritt 21: Reset ist zu Ende
#Dyn.Sk.Reset_Akt := FALSE; // Reset ist aktiv
#Status2."Warten_3.V" := FALSE;
#Status2."TrolleyPos_übergeben" := FALSE;
#Dyn.Error.Err_Trolley_nicht_in_Schleuse := FALSE;
#Dyn.Error.Err_Uebzeit := FALSE;
#Dyn.Error.Err_Stau_Einfahrt := FALSE;
#Dyn.Error.Err_Trolley_raus := FALSE;
#Dyn.Status."Trolley_fährt_in_Schleuse" := FALSE;
#SAVE.Weichen_DB := 0;
#SAVE.Weichen_DW := 0;
#SAVE."Weiche+1" := 0; // Dadurch wird in Weiche Reservierung geloescht
#Schleuse.Schleusen_Nr := 0; // Damit stat. Daten neu geholt werden!
#Dyn.Status.Trolley_draussen := TRUE;
GOTO mEndeMig; // Neubeginn
ELSE // Schritte 18/19/22..30 und ungueltige Werte
GOTO mEnde; // Undefinierter Schritt
END_CASE;
GOTO mEnde; // (nicht erreichbar; alle Zweige enden mit GOTO)
REGION Schrittketten-Verwaltung (AWL: Ende / Neu_Mig / ENDE_Mig / Plus / tueb / RET)
mEnde: // NW23 Ende: Undefinierter Schritt
#Dyn.Sk.Err_Schritt := TRUE;
#Dyn.Stop_Ursache := 16#A131;
GOTO mRET;
mNeuMig: // Neu_Mig: neuen Schritt sofort (im selben Zyklus) aktivieren
IF #Dyn.Sk.Err_Uebzeit THEN // Stoerung noch nicht quittiert
#Dyn.Stop_Ursache := 16#A132;
GOTO mRET;
END_IF;
#Dyn.Sk.Akt_Schritt := #tNeuSchritt;
#Dyn.Sk.Terr_Zelle := 0; // Zeitwerte loeschen
#Dyn.Sk.Tok_Zelle := 0;
GOTO mNEU; // zurueck zum Sprungverteiler
mEndeMig: // NW45: Schrittkette beenden
#Dyn.Sk.Akt_Schritt := 0; // Schritt 0: Warten
#Dyn.Sk.Terr_Zelle := 0; // Zeitwert loeschen
#Dyn.Sk.Tok_Zelle := 0;
#Dyn.ZwischenZiel_eingefahren := 16#0000;
#Dyn.TrolleyID_Eingefahren := 0; // Eintrag von Weiche -1
#Dyn.TrolleyID_Schleuse := 0;
#Dyn.Trolley_ZwischenZiel := 16#0000;
#Dyn.Trolley_EndZiel := 16#0000;
#Dyn.Weichen_Ziel := 16#0000;
#Dyn.Sk.Err_Uebzeit := FALSE;
#Dyn.Status.Weiche_geschaltet := FALSE;
#Dyn.Status."Trolley ausserhalb Weiche" := FALSE;
#Dyn.Status."Trolley_fährt_rückwärts" := FALSE;
#Status2."Warten_3.V" := FALSE;
#Dyn.Error.Err_Kein_LeseErgebnis := FALSE;
#Status2."2.Lesung_aktiv" := FALSE;
#Status2."3.Lesung_aktiv" := FALSE;
#Status2."TrolleyPos_übergeben" := FALSE;
#Status2.Telegramm_gesendet := FALSE;
#Dyn.HMI.TrolleyID_Input := 0; // HMI-Zeug
GOTO mRET;
mPlus: // NW46: Naechsten Schritt aktivieren (nach Wartezeit #tWartezeit *10ms)
#Dyn.Sk.T_ok := #tWartezeit; // Wartezeit uebergeben
IF #Dyn.Sk.Err_Uebzeit THEN // Stoerung noch nicht quittiert
GOTO mRET;
END_IF;
IF #tWartezeit <> 0 THEN // sonst sofort weiter
IF #Warte_neu THEN // Wartezeit neutriggern
#Dyn.Sk.Tok_Zelle := 0;
END_IF;
IF #Warte_stop THEN // Wartezeit stoppen
GOTO mRET;
END_IF;
#Dyn.Sk.Tok_Zelle := #Dyn.Sk.Tok_Zelle + WORD_TO_INT("MW4"); // Wartezeit +10ms
IF #Dyn.Sk.Tok_Zelle < #Dyn.Sk.T_ok THEN // abgelaufen? Nein!
GOTO mRET;
END_IF;
END_IF;
#Dyn.Sk.Akt_Schritt := #Dyn.Sk.Akt_Schritt + 1; // Schritt +1
#Dyn.Sk.Terr_Zelle := 0; // Zeitwerte loeschen
#Dyn.Sk.Tok_Zelle := 0;
GOTO mRET;
mTueb: // NW47/48: Ueberwachungszeit kontrollieren (#tUebzeit *1s)
#Dyn.Sk.Ueb_akt := #Ueb_akt; // Fuer Statuskontrolle
#Dyn.Sk.T_Err := #tUebzeit; // Fuer Statuskontrolle
IF (#tUebzeit > #Dyn.Sk.Terr_Zelle) AND NOT #Dyn.Sk.Err_Uebzeit THEN
// NW48: Ueberwachungszeit +1
IF #Dyn.Sk.Ueb_akt AND "1s-Impuls" THEN
#Dyn.Sk.Terr_Zelle := #Dyn.Sk.Terr_Zelle + 1; // Ueb.zeit +1s
END_IF;
GOTO mRET;
END_IF;
IF #Ueb_akt THEN // Ueberwachungszeit aktiviert
#Dyn.Sk.Err_Uebzeit := TRUE;
END_IF;
#Dyn.Sk.Terr_Zelle := 0; // Zeitwert loeschen
GOTO mRET;
END_REGION
REGION NW50: Leser-Einheit managen (Outputs schreiben)
mRET: IF #Leser_Zugriff AND #Schleuse.Parameter_allg.Leser_eingebaut THEN
#tLeserDb := INT_TO_DINT(#Dyn.SAVE2.Leser_DB);
#tLeserBase := #Dyn.SAVE2.Leser_DD;
// Offset 4: Aktuelle Werte holen, Bits setzen, zurueckschreiben
#tByte := PEEK(area := 16#84, dbNumber := #tLeserDb, byteOffset := #tLeserBase + 4);
#tByte.%X1 := #Dyn.Leser."OUT".xInStartReading;
#tByte.%X2 := #Dyn.Leser."OUT".xInHandshakeDone;
#Dyn.Leser."OUT".xInHandshakeDone := FALSE;
#tByte.%X4 := #Dyn.Leser."OUT".xInErrQuit;
#Dyn.Leser."OUT".xInErrQuit := FALSE;
#tByte.%X5 := #Dyn.Leser."OUT".xInReset;
#Dyn.Leser."OUT".xInReset := FALSE;
POKE(area := 16#84, dbNumber := #tLeserDb, byteOffset := #tLeserBase + 4,
value := #tByte); // Veraenderte Werte zurueckschreiben
END_IF;
END_REGION
END_FUNCTION_BLOCK