From 3bf291fdf808cf1e6f5caaef6118748e0a553324 Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Mon, 29 Jun 2026 10:24:45 +0200 Subject: [PATCH] =?UTF-8?q?Claude=20Session=20mit=20Empfehlungen=20zur=20S?= =?UTF-8?q?tandardisierung=20der=20Library=20hinzugef=C3=BCgt.=20Manuelle?= =?UTF-8?q?=20Pr=C3=BCfung=20jedes=20Bausteins=20noch=20n=C3=B6tig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _CommonLib/DIFF_ANALYSE.md | 162 ++++++++++++++ .../400_BasicFunctions/FC/FC_Int2String.scl | 25 +++ .../FB_FortnaTele_Placeholder.scl | 36 +++ .../TCP-Logger/FB_CommunicationLogger.scl | 207 ++++++++++++++++++ .../970_Visu/FB_Visu_Jam.scl | 200 +++++++++++++++++ .../970_Visu/FB_Visu_JamStorage.scl | 197 +++++++++++++++++ .../970_Visu/FC_CarrierManipulator.scl | 159 ++++++++++++++ .../FC_GET_PROFINET_DEVICE_STATES.scl | 27 +++ .../Programmbausteine/Programming error.scl | 32 +++ .../SCADA/FB-OPC_UA_System-Stat.scl | 72 ++++++ _CommonLib/Programmbausteine/_IBN/FC_S7.scl | 62 ++++++ .../_PerformanceMeasurement_/FB_PerfTest.scl | 104 +++++++++ _CommonLib/TIA_BIBLIOTHEK_ANLEITUNG.md | 159 ++++++++++++++ 13 files changed, 1442 insertions(+) create mode 100644 _CommonLib/DIFF_ANALYSE.md create mode 100644 _CommonLib/Programmbausteine/400_BasicFunctions/FC/FC_Int2String.scl create mode 100644 _CommonLib/Programmbausteine/900_Communications/FB_FortnaTele_Placeholder.scl create mode 100644 _CommonLib/Programmbausteine/900_Communications/TCP-Logger/FB_CommunicationLogger.scl create mode 100644 _CommonLib/Programmbausteine/970_Visu/FB_Visu_Jam.scl create mode 100644 _CommonLib/Programmbausteine/970_Visu/FB_Visu_JamStorage.scl create mode 100644 _CommonLib/Programmbausteine/970_Visu/FC_CarrierManipulator.scl create mode 100644 _CommonLib/Programmbausteine/PROFINET/FC_GET_PROFINET_DEVICE_STATES.scl create mode 100644 _CommonLib/Programmbausteine/Programming error.scl create mode 100644 _CommonLib/Programmbausteine/SCADA/FB-OPC_UA_System-Stat.scl create mode 100644 _CommonLib/Programmbausteine/_IBN/FC_S7.scl create mode 100644 _CommonLib/Programmbausteine/_PerformanceMeasurement_/FB_PerfTest.scl create mode 100644 _CommonLib/TIA_BIBLIOTHEK_ANLEITUNG.md diff --git a/_CommonLib/DIFF_ANALYSE.md b/_CommonLib/DIFF_ANALYSE.md new file mode 100644 index 0000000..05a1bf0 --- /dev/null +++ b/_CommonLib/DIFF_ANALYSE.md @@ -0,0 +1,162 @@ +# Diff-Analyse P1-Bausteine — HundM_Fortna + +**Stand:** 2026-06-29 +**Analysiert:** 22 Bausteine die in allen 5 Konfigurationen (UH01–UH05) vorhanden sind +**Methode:** Vollständiger Inhaltsvergleich aller Versionen + +--- + +## Ergebnis-Übersicht + +| Baustein | Gruppe | UH01 | UH02 | UH03 | UH04 | UH05 | Aktion | +|---|---|:---:|:---:|:---:|:---:|:---:|---| +| `FC_GET_PROFINET_DEVICE_STATES` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `FB-OPC_UA_System-Stat` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `FC_S7` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `FC_CarrierManipulator` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `FC_Int2String` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `FB_FortnaTele_Placeholder` | **A** | ✅ | ✅ | ✅ | ✅ | ✅ | In CommonLib → Projektbibliothek | +| `Programming error` (OB) | **B** | ✅ | ⚠️ | ✅ | ✅ | ✅ | UH02 bereinigen (VAR_TEMP entfernen) | +| `FB_PerfTest` | **B** | ✅ | ✅ | ⚠️ | ✅ | ✅ | UH03 Default-Wert klären/entfernen | +| `FB_CommunicationLogger` | **B** | ✅ | ⚠️ | ✅ | ✅ | ✅ | connectionID + JAM-Ref. beachten! | +| `FB_Visu_Jam` | **B** | ⚠️ | ✅ | ✅ | ✅ | ✅ | UH01 cleanup: nInJamCount entfernt, REGION vereinheitlicht | +| `FB_Visu_JamStorage` | **B** | ✅ | ✅ | ⚠️ | — | — | UH03 hat HMI-Block auskommentiert (nur UH01/02/03) | +| `FB_Main` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Nicht standardisierbar — TRO-Nummern, Topologie | +| `FB_PreMain` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Nicht standardisierbar — EStop, Monitoring | +| `FB_CallSensors` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Nicht standardisierbar — Sensor-IDs, Hardware | +| `FB_Visu` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Nicht standardisierbar — TRO-Ranges, Config | +| `FB_CommunicationWCSBL` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | ConnectionID 10/20/30/40/50, Logik je UH reduziert | +| `FC_Call_Jams` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Jam-Bereichsnummern je UH (0100/1100/2100/4000/5000) | +| `FC_Direction` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Weichen-Nummern je UH | +| `FB_Visu_Jams` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | Jam-Instanzen je UH | +| `FC_CARR_GLOB_CORRECTION` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | 568–5826 Zeilen je UH (Faktor 10!) | +| `FC_BARCODE_SEARCH` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | UH01: 2 Lagerbereiche, UH02–UH05: 12 | +| `FC_Jam` | **D** | ❌ | ❌ | ❌ | ❌ | ❌ | UH02/UH03 mit erweiterter Storage-Logik | + +**Legende:** ✅ = identisch mit Referenz | ⚠️ = kleine Abweichung | ❌ = topologie-spezifisch | — = nicht vorhanden + +--- + +## Gruppe A — 100% identisch (6 Blöcke) + +### FC_GET_PROFINET_DEVICE_STATES +- **Typ:** FC, 28 Zeilen +- **Funktion:** Liest PROFINET-Gerätezustände (vorhanden/gestört) via `DeviceStates()` +- **Status:** Alle 5 Versionen byte-identisch +- **Kanonische Version:** UH01 (gleichwertig) + +### FB-OPC_UA_System-Stat +- **Typ:** FB, 73 Zeilen +- **Funktion:** Übersetzt internen Anlagenstatus in OPC-UA SCADA-Statuscodes +- **Status:** Alle 5 Versionen byte-identisch +- **Kanonische Version:** UH01 (gleichwertig) + +### FC_S7 +- **Typ:** FC, 63 Zeilen +- **Funktion:** S7-PUT Wrapper für CPU-zu-CPU-Datenaustausch +- **Status:** Alle 5 Versionen byte-identisch +- **Kanonische Version:** UH01 (gleichwertig) + +### FC_CarrierManipulator +- **Typ:** FC, 159 Zeilen +- **Funktion:** HMI-gesteuerte Carrier-Manipulation in Jam-Listen (Löschen, Verschieben, HyperJam) +- **Status:** Alle 5 Versionen byte-identisch (MD5 identisch) +- **Kanonische Version:** UH01 (gleichwertig) + +### FC_Int2String +- **Typ:** FC, 25 Zeilen +- **Funktion:** Wandelt INT in String, entfernt führendes "+" (Autor: Christian Forkl, 28.07.2021) +- **Status:** Alle 5 Versionen byte-identisch +- **Kanonische Version:** UH01 (gleichwertig) + +### FB_FortnaTele_Placeholder +- **Typ:** FB, 37 Zeilen (nur Variablendeklaration, kein Code) +- **Funktion:** Platzhalter-Baustein mit allen Fortna WES/WCS UDT-Instanzen zur Typ-Aktivierung +- **Status:** Alle 5 Versionen byte-identisch +- **Kanonische Version:** UH01 (gleichwertig) + +--- + +## Gruppe B — Kleine Abweichungen (5 Blöcke) + +### Programming error (OB) +- **Typ:** OB (Organization Block), 33 Zeilen +- **Funktion:** Fehlerbehandlung bei Programmierfehler, schreibt Fehlerinfo in DB_Error +- **Abweichung UH02:** Hat zusätzliche `VAR_TEMP` Sektion mit ungenutzter `Temp_1 : Bool` +- **Entscheidung:** UH01-Version ist korrekt. UH02-VAR_TEMP ist redundant und sollte entfernt werden. +- **CommonLib-Version:** UH01 (ohne VAR_TEMP) + +### FB_PerfTest +- **Typ:** FB, 105 Zeilen +- **Funktion:** Leistungsmessung — zählt Trolley-Releases und protokolliert Zeitstempel +- **Abweichung UH03:** `nInGoalFlags : Int := 498;` (Default-Wert = 498 = Array-Größe 500 minus 2) +- **Abweichung UH03:** Eine fehlende Leerzeile nach `END_IF` +- **Entscheidung:** Default-Wert in UH03 war vermutlich temporär für Tests gesetzt. UH01-Version (kein Default) ist der Standard. Falls UH03 den Default bewusst nutzt, muss dieser nach TIA-Import im Instanz-DB gesetzt werden. +- **CommonLib-Version:** UH01 (kein Default-Wert für `nInGoalFlags`) + +### FB_CommunicationLogger +- **Typ:** FB, 229 Zeilen +- **Funktion:** TCP-Logger Kommunikation zu Fortna WCSBL, empfängt GOHDRespM-Telegramme +- **Abweichung UH02:** `connectionID := 100` (UH01/UH03/UH04/UH05 = 99) +- **Wichtig:** `connectionID` muss je PLC eindeutig sein! Dies ist KEIN Fehler in UH02, sondern möglicherweise bewusst. +- **Weitere Abweichung:** Zeilen 171–179 (Jam-Referenz auf `"DB_JamArea0102"`) sind UH01-spezifisch +- **Entscheidung:** CommonLib-Version nimmt UH01 als Basis mit explizitem Kommentar: + - `connectionID` muss beim Import in UH02–UH05 angepasst werden + - Jam-Referenz `"DB_JamArea0102"` bei anderen PLCs auskommentieren oder ersetzen +- **CommonLib-Version:** UH01 mit Hinweis-Kommentaren + +### FB_Visu_Jam +- **Typ:** FB, 207 Zeilen +- **Funktion:** HMI-Listenverwaltung für Jam-Carrier-Anzeige (Scroll, Carrier-Manipulation) +- **Abweichung UH01:** Hat ungenutzten `VAR_INPUT nInJamCount : UInt` — in UH02/UH03/UH04/UH05 nicht vorhanden +- **Abweichung UH01:** REGION-Name "Carrier Manipulation" — in anderen UH "FC_CAR_MOVE" +- **Bereinigungen in CommonLib-Version:** + - `VAR_INPUT` Sektion vollständig entfernt (`nInJamCount` war unbenutzt) + - REGION umbenannt zu "FC_CAR_MOVE" (einheitlich mit UH02–UH05) +- **CommonLib-Version:** Bereinigt + +### FB_Visu_JamStorage +- **Typ:** FB, 200 Zeilen +- **Funktion:** HMI-Listenverwaltung für Lager-Jam-Carrier-Anzeige (nur in UH01/UH02/UH03) +- **Nicht vorhanden in:** UH04, UH05 +- **Abweichung UH03:** HMI-REGION (Zeilen 193–196) ist auskommentiert — `nCapacitySetHMI`-Zuweisung deaktiviert +- **Entscheidung:** UH01-Version ist die vollständigste (aktive HMI-Logik). UH03 hat bewusst deaktiviert. +- **CommonLib-Version:** UH01 (aktive HMI-Logik) + +--- + +## Gruppe D — Topologie-spezifisch (11 Blöcke) + +Diese Blöcke können **nicht ohne vollständiges Redesign** standardisiert werden, da sie +hartcodierte Werte enthalten, die die physikalische Anlagentopologie abbilden. + +| Baustein | Hartcodierte Topologie-Werte | Größenunterschied | +|---|---|---| +| `FB_Main` | TRO-Nummern (100er/200er/300er/400er/500er), Workstations, Carousel-IDs, UDT-Referenzen | 1835–9293 Zeilen | +| `FB_PreMain` | EStop-Konstanten (10–31 je UH), Monitoring-Instanzen, Befeuerungs-Konfiguration (1x/2x/4x) | 491–2373 Zeilen | +| `FB_CallSensors` | Sensor-IDs (BG0280/BG3240 etc.), Schaltschrank-State-Referenzen | 769–11649 Zeilen | +| `FB_Visu` | TRO-Ranges, Schaltschrank-IDs, EStop-Array-Größen | 70–1796 Zeilen | +| `FB_CommunicationWCSBL` | ConnectionID 10/20/30/40/50 je UH, Telegramm-Logik je UH verschieden | — | +| `FC_Call_Jams` | Jam-Bereichsnummern (0100er/1100er/2100er/4000er/5000er) | — | +| `FC_Direction` | Weichen-Nummern (cSwi107/cSwi202/cSwi313/cSwi405/cSwi505) | — | +| `FB_Visu_Jams` | Jam-Instanzen (Anzahl und Art je UH) | 32–52 KB | +| `FC_CARR_GLOB_CORRECTION` | Jam-Bereiche, Stationsnummern | 568–5826 Zeilen | +| `FC_BARCODE_SEARCH` | Lagerbereiche: UH01=2, UH02–UH05=12 | — | +| `FC_Jam` | UH02/UH03 mit erweiterter `CarrierStatisticsStorage`-Logik | 85–203 Zeilen | + +### Empfehlung für Gruppe-D-Blöcke + +Langfristig könnten diese Blöcke durch **Code-Generierung** aus einer zentralen +Topologie-Konfigurationsdatei (z.B. UDT-Array oder JSON) erstellt werden. +Kurzfristig: Getrennte Pflege je UH bleibt notwendig. + +--- + +## Entscheidungsstatus FC_StorageLines (Sonderfall) + +`FC_StorageLines` war zunächst als P1-Kandidat eingestuft: +- **UH01, UH03, UH05:** identisch (gleiches MD5) +- **UH02, UH04:** abweichend (unterschiedliche Storage-Strukturen) + +Da nicht alle 5 UH identisch sind, wurde dieser Block **nicht** in die CommonLib aufgenommen. +Möglichkeit: Separate CommonLib-Instanz nur für UH01/UH03/UH05 — bei Bedarf ergänzen. diff --git a/_CommonLib/Programmbausteine/400_BasicFunctions/FC/FC_Int2String.scl b/_CommonLib/Programmbausteine/400_BasicFunctions/FC/FC_Int2String.scl new file mode 100644 index 0000000..b84d686 --- /dev/null +++ b/_CommonLib/Programmbausteine/400_BasicFunctions/FC/FC_Int2String.scl @@ -0,0 +1,25 @@ +FUNCTION "FC_Int2String" : String +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_INPUT + nInNumber : Int; + END_VAR + + VAR_TEMP + sTmp : String; + END_VAR + + +BEGIN + // Funktion wandelt Int zu String. Im Gegensatz zu "Int_To_String" wird das "+" entfernt. Bei negativen Zahlen bleibt das "-" erhalten. + // Autor: Christian Forkl + // 28.07.2021 + + #sTmp := INT_TO_STRING(#nInNumber); + IF #nInNumber >= 0 THEN + #FC_Int2String := RIGHT(IN := #sTmp, L := (LEN(#sTmp) - 1)); + ELSE + #FC_Int2String := #sTmp; + END_IF; +END_FUNCTION + diff --git a/_CommonLib/Programmbausteine/900_Communications/FB_FortnaTele_Placeholder.scl b/_CommonLib/Programmbausteine/900_Communications/FB_FortnaTele_Placeholder.scl new file mode 100644 index 0000000..1674d70 --- /dev/null +++ b/_CommonLib/Programmbausteine/900_Communications/FB_FortnaTele_Placeholder.scl @@ -0,0 +1,36 @@ +FUNCTION_BLOCK "FB_FortnaTele_Placeholder" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR + Static_1 : "UDT_Payload_CRCanM"; + Static_2 : "UDT_Payload_CReqM"; + Static_3 : "UDT_Payload_CRRespM"; + Static_4 : "UDT_Payload_CSRespM"; + Static_5 : "UDT_Payload_CTMP"; + Static_6 : "UDT_Payload_ECNT"; + Static_7 : "UDT_Payload_GOHDReqM"; + Static_8 : "UDT_Payload_GOHDRespM"; + Static_9 : "UDT_Payload_GOHDUM"; + Static_10 : "UDT_Payload_INDX"; + Static_11 : "UDT_Payload_UNLDResp"; + Static_12 : "UDT_Payload_WSAD"; + Static_13 : "UDT_Telegram_CRCanM"; + Static_14 : "UDT_Telegram_CReqM"; + Static_15 : "UDT_Telegram_CRRespM"; + Static_16 : "UDT_Telegram_CSRespM"; + Static_17 : "UDT_Telegram_CTMP"; + Static_18 : "UDT_Telegram_ECNT"; + Static_19 : "UDT_Telegram_GOHDReqM"; + Static_20 : "UDT_Telegram_GOHDRespM"; + Static_21 : "UDT_Telegram_GOHDUM"; + Static_22 : "UDT_Telegram_INDX"; + Static_23 : "UDT_Telegram_UNLDResp"; + Static_24 : "UDT_Telegram_WSAD"; + Static_25 : "UDT_Header"; + Static_26 : "UDT_Workstation"; + END_VAR + + +BEGIN +END_FUNCTION_BLOCK + diff --git a/_CommonLib/Programmbausteine/900_Communications/TCP-Logger/FB_CommunicationLogger.scl b/_CommonLib/Programmbausteine/900_Communications/TCP-Logger/FB_CommunicationLogger.scl new file mode 100644 index 0000000..72a46b1 --- /dev/null +++ b/_CommonLib/Programmbausteine/900_Communications/TCP-Logger/FB_CommunicationLogger.scl @@ -0,0 +1,207 @@ +FUNCTION_BLOCK "FB_CommunicationLogger" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_IN_OUT + fbInOutSendFIFO : "LGF_FIFO"; + arFifoSendBuffer : Array[1..100] of "UDT_TelegramData_Send"; + END_VAR + + VAR + fbTeleHandler : "FB_TCP_LCOM_TeleHandler"; + xReset : Bool; + xSendTele : Bool; + stTelegramToSend : "UDT_TelegramData_Send"; + nState : Int; + xRetVal : Bool; + stNewTelegram { S7_SetPoint := 'False'} : "UDT_TelegramData"; + stTeleGOHDRespM : "UDT_Telegram_GOHDRespM"; + arPayloadHelp : Array[0..200] of Byte; + cnt : UInt; + LStream_JsonDeserializer_Instance : "LStream_JsonDeserializer"; + typeElement { S7_SetPoint := 'False'} : Array[0..10] of "LStream_typeElement" := [(2, 'DecisionPoint', (), (), ()), (3, 'GIN', (), (), ()), (2, 'Barcode', (), (), ()), (1, 'Actions', (), (), true), ((), (), (), (), ()), ((), (), (), (), ()), ((), (), (), (), ()), ((), (), (), (), ()), ((), (), (), (), ()), ((), (), (), (), ()), ((), (), (), (), ())]; + xDone : Bool; + rTrigConnectionActive {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG; + xSendHeartbeat : Bool; + tOnHeartbeat {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME; + END_VAR + + VAR_TEMP + xStart : Bool; + test : "UDT_TelegramData_Send"; + END_VAR + + +BEGIN + REGION Info + // Kommunikation zu Fortna WCSBL + // Telegramme: + // Senden: + // GOHDReqM (Zielanfrage) | Von Schönenberger -> Fortna WCSBL + // GOHDUM (Update) | Von Schönenberger -> Fortna WCSBL + // Empfangen: + // GOHDRespM (Antwort auf Zielanfrage) | Von Fortna WCSBL -> Schönenberger + END_REGION + + REGION Call TeleHandler + // hardware identifier of the local interface, PLC tags--Default tag table--System constant default value: PROFINET_interface_1 = 64 + #fbTeleHandler.stInTcpTypeConfig.connection.interfaceID := "Local~PN-Interface_SchSy"; //"Local"~PN-Interface_Customer"; + // WICHTIG: connectionID muss je PLC eindeutig sein! + // UH01=99, UH02=100 (absichtlich verschieden -- pro PLC anpassen) + #fbTeleHandler.stInTcpTypeConfig.connection.connectionID := 99; + //used protocol: 1=TCP protocol, 2=LCom protocol + #fbTeleHandler.stInTcpTypeConfig.connection.comService := "LCOM_TCP_CONNECTION"; + //FALSE: passive (server), TRUE: active connection establishment (client) + #fbTeleHandler.stInTcpTypeConfig.connection.isClient := TRUE; + //TRUE: accept requests from all partners, FALSE: only specified partner is allowed in case of server + #fbTeleHandler.stInTcpTypeConfig.connection.acceptUnknownPartner := TRUE; + //local port number (possible values: 1...49151; caution: some may be reserved for internal use; recommended values: 2000...5000) + #fbTeleHandler.stInTcpTypeConfig.connection.localPort := 4711; + //partner port number, use only in case of client or specified partner (possible values: 1...49151; recommended values: 2000...5000) + #fbTeleHandler.stInTcpTypeConfig.connection.partnerPort := 4711; + + //partner IP address xxx.xxx.xxx.xxx = [1].[2].[3].[4], use only in case of client or specified partner + #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[1] := 192; + #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[2] := 168; + #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[3] := 3; + #fbTeleHandler.stInTcpTypeConfig.connection.partnerIP.ADDR[4] := 245; + + #fbTeleHandler.stInTcpTypeConfig.connection.connectType := "LCOM_CON_TYPE_IPV4"; + + // Telegramdefinition + #fbTeleHandler.stInTelegramDefinition.sStartMarker := '$02'; + #fbTeleHandler.stInTelegramDefinition.sEndMarker := '$03'; + #fbTeleHandler.stInTelegramDefinition.sStartMarkerSend := '$02'; + #fbTeleHandler.stInTelegramDefinition.sEndMarkerSend := '$03'; + #fbTeleHandler.stInTelegramDefinition.bSeparatorByte := '$1D'; //','; + #fbTeleHandler.stInTelegramDefinition.nLength := 0; + #fbTeleHandler.stInTelegramDefinition.nTelegramIDDataField := 0; + #fbTeleHandler.stInTelegramDefinition.xTelegramIDIsNumber := FALSE; + + #fbTeleHandler(xInReset := #xReset, + xInSendTele := true, + xInOutSendTele := #xSendTele, + stInTelegramSend := #stTelegramToSend, + fbInOutSendFIFO:= #fbInOutSendFIFO, + arFifoSendBuffer:=#arFifoSendBuffer); + END_REGION + + REGION Reset SequenceNumber + #rTrigConnectionActive(CLK:=#fbTeleHandler.xOutConnectionActive); + + IF #rTrigConnectionActive.Q THEN + "DB_CommunciationParametersLogger".nSeqNum := 0; + END_IF; + END_REGION + + REGION Send Heartbeat + (* IF #fbTeleHandler.xOutConnectionActive THEN + #xSendHeartbeat := TRUE; + + IF #tOnHeartbeat.Q THEN + #xSendHeartbeat := FALSE; + "FC_Send_HB"(sInPLCID := "cPLCID", + FIFO := "DB_LGF_FIFO_CommLogger", + BUFFER := "DB_Buffer_CommunicationLogger".BUFFER, + nInOutSequenceNumber:="DB_CommunciationParametersLogger".nSeqNum); + END_IF; + ELSE + #xSendHeartbeat := FALSE; + END_IF; + + #tOnHeartbeat(IN := #xSendHeartbeat, + PT := t#15s); *) + END_REGION + + REGION Empfangen + //Wird nicht benötigt + CASE #nState OF + 0: // Waiting + //New Telegram + IF #fbTeleHandler.xOutTelegramAvailable THEN + #fbTeleHandler.xInGetFirst := TRUE; + #nState := 100; + END_IF; + 100: // Get new Telegram + #stNewTelegram := #fbTeleHandler.stOutNewTelegram; + #fbTeleHandler.xInGetFirst := FALSE; + #nState := 200; + 200: //Analyze Telegram + #stTeleGOHDRespM.stHeader.sPlcId := #stNewTelegram.arDataString[1]; + #stTeleGOHDRespM.stHeader.sSeqNum := #stNewTelegram.arDataString[2]; + #stTeleGOHDRespM.stHeader.sMessageType := #stNewTelegram.arDataString[3]; + + IF #stTeleGOHDRespM.stHeader.sMessageType = 'GOHDRespM' THEN + + Strg_TO_Chars(Strg := #stNewTelegram.arDataString[4], + pChars := 0, + Cnt => #cnt, + Chars := #arPayloadHelp); + + #typeElement[0].type := 2; + #typeElement[0].key := 'DecisionPoint'; + #typeElement[1].type := 3; + #typeElement[1].key := 'GIN'; + #typeElement[2].type := 2; + #typeElement[2].key := 'Barcode'; + #typeElement[3].type := 1; + #typeElement[3].key := 'Actions'; + + #xStart := TRUE; + + IF #xDone THEN + #xStart := FALSE; + + #stTeleGOHDRespM.stPayload.sDecisionPoint := #typeElement[0].value; + + STRG_VAL(IN := #typeElement[1].value, + FORMAT := 0, + P := 1, + OUT => #stTeleGOHDRespM.stPayload.nGin); + + STRG_VAL(IN := #typeElement[2].value, + FORMAT := 0, + P := 1, + OUT => #stTeleGOHDRespM.stPayload.nBarcode); + + #stTeleGOHDRespM.stPayload.arActions[0] := #typeElement[4].value; + #stTeleGOHDRespM.stPayload.arActions[1] := #typeElement[5].value; + #stTeleGOHDRespM.stPayload.arActions[2] := #typeElement[6].value; + #stTeleGOHDRespM.stPayload.arActions[3] := #typeElement[7].value; + #stTeleGOHDRespM.stPayload.arActions[4] := #typeElement[8].value; + + // WICHTIG: "DB_JamArea0102" ist UH01-spezifisch! + // Beim Einsatz in anderen PLCs diesen Block anpassen oder parametrisieren. + IF #stTeleGOHDRespM.stPayload.sDecisionPoint = 'GOH.Rec.01' THEN + IF "DB_JamArea0102".stJam0102_4.arCarrier[1].nBarcode = #stTeleGOHDRespM.stPayload.nBarcode THEN + IF #stTeleGOHDRespM.stPayload.arActions[0] = '1' THEN + "DB_JamArea0102".stJam0102_4.arCarrier[1].nDestination := "cDestInboundOut"; + ELSIF #stTeleGOHDRespM.stPayload.arActions[0] = '-1' THEN + "DB_JamArea0102".stJam0102_4.arCarrier[1].nDestination := "cDestClearing"; + END_IF; + END_IF; + END_IF; + + #xDone := FALSE; + + #nState := 0; + END_IF; + + ELSE + #nState := 0; + END_IF; + END_CASE; + END_REGION + + REGION LStream + #LStream_JsonDeserializer_Instance(execute := #xStart, + tree := #typeElement, + raw := #arPayloadHelp); + + IF #LStream_JsonDeserializer_Instance.done THEN + #xDone := TRUE; + END_IF; + END_REGION + + +END_FUNCTION_BLOCK + diff --git a/_CommonLib/Programmbausteine/970_Visu/FB_Visu_Jam.scl b/_CommonLib/Programmbausteine/970_Visu/FB_Visu_Jam.scl new file mode 100644 index 0000000..282e1ee --- /dev/null +++ b/_CommonLib/Programmbausteine/970_Visu/FB_Visu_Jam.scl @@ -0,0 +1,200 @@ +FUNCTION_BLOCK "FB_Visu_Jam" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_IN_OUT + arInOutJam : Array[*] of "stCarrier"; // Jam Daten + stInOutHMIJam : "UDT_Visu_Jam_List"; + stInOutHMIData : "UDT_HMI_JamData"; // Jam Daten HMI Schnittstelle + END_VAR + + VAR + xReInit : Bool; + nUpperBound : Int; + END_VAR + + VAR_TEMP + nIdx : Int; + nIdxMerker : Int; + END_VAR + + +BEGIN + // Hier werden die Carrierlisten für die Visu erstellt + // Auf Knopfdruck am HMI werden Aktionen durchgeführt, um die Liste zu scrollen + // Aktuell werden immer 10 Carrier gleichzeitig angezeigt + + #stInOutHMIJam.#upperBound := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1)); + #nUpperBound := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1)); + REGION Jam Daten Liste + // Beim ersten Aufruf nach reinit ausführen, damit Daten drinstehen + IF NOT #xReInit THEN + #stInOutHMIJam.nIndex := 1; + #nIdxMerker := #stInOutHMIJam.nIndex; + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #xReInit := TRUE; + END_IF; + + // Wenn nichts an der Liste gemacht wird, Daten nur aktualisieren + IF NOT #stInOutHMIJam.#DecOne AND NOT #stInOutHMIJam.#DecFive AND NOT #stInOutHMIJam.#IncOne AND NOT #stInOutHMIJam.#IncFive AND NOT #stInOutHMIJam.#ScrollEnd AND NOT #stInOutHMIJam.#ScrollStart THEN + #nIdxMerker := #stInOutHMIJam.nIndex; + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + END_IF; + + // Liste um eins nach oben bewegen + IF #stInOutHMIJam.#DecOne THEN + #stInOutHMIJam.#nIndex -= 1; + IF #stInOutHMIJam.#nIndex < 1 THEN + #stInOutHMIJam.#nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#DecOne := FALSE; + END_IF; + + // Liste um fünf nach oben bewegen + IF #stInOutHMIJam.#DecFive THEN + #stInOutHMIJam.#nIndex -= 5; + IF #stInOutHMIJam.#nIndex < 1 THEN + #stInOutHMIJam.#nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#DecFive := FALSE; + END_IF; + + // Liste um eins nach unten bewegen + IF #stInOutHMIJam.#IncOne THEN + #stInOutHMIJam.#nIndex += 1; + IF #stInOutHMIJam.#nIndex > #stInOutHMIJam.#upperBound - 9 THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex <= 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#IncOne := FALSE; + END_IF; + + // Liste um fünf nach unten bewegen + IF #stInOutHMIJam.#IncFive THEN + #stInOutHMIJam.#nIndex += 5; + IF #stInOutHMIJam.#nIndex > #stInOutHMIJam.#upperBound - 9 THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex < 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#IncFive := FALSE; + END_IF; + + // Zum Listenanfang springen + IF #stInOutHMIJam.#ScrollStart THEN + #stInOutHMIJam.#nIndex := 1; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#ScrollStart := FALSE; + END_IF; + // Zum Listenende springen + IF #stInOutHMIJam.#ScrollEnd THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex < 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#ScrollEnd := FALSE; + END_IF; + END_REGION + + REGION FC_CAR_MOVE + + // "FC_CARR_MOVE"(nInCommand := #stHMIJam.stCarMove.nCommand, + // nInJamNr := #nInJamNr,//braucht nicht von HMI zu kommen - #stHMIJam.stCarMove.nJamNr, + // nInTarget := #stHMIJam.stCarMove.nTarget, + // xInStart := #stHMIJam.stCarMove.xStart, + // xOutError => #stHMIJam.stCarMove.xError); + + // #stInOutHMIJam.stCarMove.xStart := FALSE; + + "FC_CarrierManipulator"(stInOutHMIJamData := #stInOutHMIData, + stInOutHMIJamList := #stInOutHMIJam, + arInOutJam := #arInOutJam, + arInOutHyperJam := "DB_HyperJam".stHyperJam.arCarrier); + + #stInOutHMIJam.stCarMove.xStart := FALSE; + + END_REGION + + REGION Manuelle Zielvergabe für Jam + IF #stInOutHMIData.stStatus.bByte.%X7 THEN //%X7: Manuelle Zielvergabe aktiviert + #arInOutJam[1].nDestination := #stInOutHMIData.stJamConfig.nManualDest; //Sorgt dafür, dass Carrier ein festes Ziel bekommen + END_IF; + END_REGION +END_FUNCTION_BLOCK + diff --git a/_CommonLib/Programmbausteine/970_Visu/FB_Visu_JamStorage.scl b/_CommonLib/Programmbausteine/970_Visu/FB_Visu_JamStorage.scl new file mode 100644 index 0000000..eb9e2dd --- /dev/null +++ b/_CommonLib/Programmbausteine/970_Visu/FB_Visu_JamStorage.scl @@ -0,0 +1,197 @@ +FUNCTION_BLOCK "FB_Visu_JamStorage" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_INPUT + nInJamCount : UInt; + END_VAR + + VAR_IN_OUT + arInOutJam : Array[*] of "stCarrier"; // Jam Daten + stInOutHMIJam : "UDT_Visu_Jam_List"; + stInOutHMIData : "UDT_HMI_StorageData"; // Jam Daten HMI Schnittstelle + END_VAR + + VAR + xReInit : Bool; + nUpperBound : Int; + END_VAR + + VAR_TEMP + nIdx : Int; + nIdxMerker : Int; + END_VAR + + +BEGIN + // Hier werden die Carrierlisten für die Visu erstellt + // Auf Knopfdruck am HMI werden Aktionen durchgeführt, um die Liste zu scrollen + // Aktuell werden immer 10 Carrier gleichzeitig angezeigt + + #stInOutHMIJam.#upperBound := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1)); + #nUpperBound := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1)); + REGION Jam Daten Liste + // Beim ersten Aufruf nach reinit ausführen, damit Daten drinstehen + IF NOT #xReInit THEN + #stInOutHMIJam.nIndex := 1; + #nIdxMerker := #stInOutHMIJam.nIndex; + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #xReInit := TRUE; + END_IF; + + // Wenn nichts an der Liste gemacht wird, Daten nur aktualisieren + IF NOT #stInOutHMIJam.#DecOne AND NOT #stInOutHMIJam.#DecFive AND NOT #stInOutHMIJam.#IncOne AND NOT #stInOutHMIJam.#IncFive AND NOT #stInOutHMIJam.#ScrollEnd AND NOT #stInOutHMIJam.#ScrollStart THEN + #nIdxMerker := #stInOutHMIJam.nIndex; + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + END_IF; + + // Liste um eins nach oben bewegen + IF #stInOutHMIJam.#DecOne THEN + #stInOutHMIJam.#nIndex -= 1; + IF #stInOutHMIJam.#nIndex < 1 THEN + #stInOutHMIJam.#nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#DecOne := FALSE; + END_IF; + + // Liste um fünf nach oben bewegen + IF #stInOutHMIJam.#DecFive THEN + #stInOutHMIJam.#nIndex -= 5; + IF #stInOutHMIJam.#nIndex < 1 THEN + #stInOutHMIJam.#nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#DecFive := FALSE; + END_IF; + + // Liste um eins nach unten bewegen + IF #stInOutHMIJam.#IncOne THEN + #stInOutHMIJam.#nIndex += 1; + IF #stInOutHMIJam.#nIndex > #stInOutHMIJam.#upperBound - 9 THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex <= 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#IncOne := FALSE; + END_IF; + + // Liste um fünf nach unten bewegen + IF #stInOutHMIJam.#IncFive THEN + #stInOutHMIJam.#nIndex += 5; + IF #stInOutHMIJam.#nIndex > #stInOutHMIJam.#upperBound - 9 THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex < 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + #stInOutHMIJam.#IncFive := FALSE; + END_IF; + + // Zum Listenanfang springen + IF #stInOutHMIJam.#ScrollStart THEN + #stInOutHMIJam.#nIndex := 1; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#ScrollStart := FALSE; + END_IF; + // Zum Listenende springen + IF #stInOutHMIJam.#ScrollEnd THEN + #stInOutHMIJam.#nIndex := #stInOutHMIJam.#upperBound - 9; + IF #stInOutHMIJam.nIndex < 0 THEN + #stInOutHMIJam.nIndex := 1; + END_IF; + + #nIdxMerker := #stInOutHMIJam.nIndex; + + FOR #nIdx := 1 TO 10 DO + #stInOutHMIJam.arJamList[#nIdx - 1] := #arInOutJam[#nIdxMerker]; + #nIdxMerker += 1; + IF #nIdx >= #nUpperBound OR #nIdxMerker > #nUpperBound THEN + EXIT; + END_IF; + END_FOR; + + #stInOutHMIJam.#ScrollEnd := FALSE; + END_IF; + END_REGION + + REGION FC_CAR_MOVE + + // "FC_CARR_MOVE"(nInCommand := #stHMIJam.stCarMove.nCommand, + // nInJamNr := #nInJamNr,//braucht nicht von HMI zu kommen - #stHMIJam.stCarMove.nJamNr, + // nInTarget := #stHMIJam.stCarMove.nTarget, + // xInStart := #stHMIJam.stCarMove.xStart, + // xOutError => #stHMIJam.stCarMove.xError); + + #stInOutHMIJam.stCarMove.xStart := FALSE; + + END_REGION + + REGION HMI + IF #stInOutHMIData.stStatus.bByte.%X7 THEN //%X7: Manuelle Zielvergabe aktiviert + #arInOutJam[1].nDestination := #stInOutHMIData.stConfig.nCapacitySetHMI; //Sorgt dafür, dass Carrier ein festes Ziel bekommen + END_IF; + END_REGION +END_FUNCTION_BLOCK + diff --git a/_CommonLib/Programmbausteine/970_Visu/FC_CarrierManipulator.scl b/_CommonLib/Programmbausteine/970_Visu/FC_CarrierManipulator.scl new file mode 100644 index 0000000..35686f8 --- /dev/null +++ b/_CommonLib/Programmbausteine/970_Visu/FC_CarrierManipulator.scl @@ -0,0 +1,159 @@ +FUNCTION "FC_CarrierManipulator" : Void +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_IN_OUT + stInOutHMIJamData : "UDT_HMI_JamData"; // Jam Daten HMI + stInOutHMIJamList : "UDT_Visu_Jam_List"; // Jam Liste HMI + arInOutJam : Array[*] of "stCarrier"; // Jam SPS + arInOutHyperJam : Array[*] of "stCarrier"; + END_VAR + + VAR_TEMP + tmpEmptyCarr : "stCarrier"; + nCounter : DInt; + nArrayMax : Int; + nIdx : Int; + nStatus : Int; + xResult : Bool; + END_VAR + + VAR CONSTANT + cFirstAhead : Int := 1; // Carrier weiterbuchen + cLastBack : Int := 2; // Carrier zurückbuchen + cSwapFirstLast : Int := 3; // Ersten und letzten Carrier im Jam tauschen + cDeleteAll : Int := 4; // Alle Jam Daten löschen (macht Sinn, wenn Jam unklar und man einfach bereinigen will) + cDeletePos : Int := 5; // Position, falls bestimmter Carrier gelöscht werden soll (macht Sinn, wenn man Carrier entnimmt) + cPutToHyperJam : Int := 6; // Position, falls bestimmter Carrier zum HyperJam soll (macht Sinn, wenn Carrier nicht auffindbar) + END_VAR + + +BEGIN + REGION Info + (* + Funktionen + + - Alle carrier daten in einem jam leeren - check + - bestimmten carrier löschen - check + + MUBEA bereits gemacht: + - Carrier in Hyper-Jam - check + - Weiterbuchen + - Zurückbuchen + - Tauschen (erster und letzter) + *) + END_REGION + + REGION Array-Grenzen + #nArrayMax := DINT_TO_INT(UPPER_BOUND(ARR := #arInOutJam, DIM := 1)); + END_REGION + + REGION Befehl ausführen + CASE #stInOutHMIJamList.stCarMove.nCommand OF + #cDeleteAll: + REGION Jam bereinigen + IF #stInOutHMIJamList.stCarMove.xStart THEN + IF NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN + #stInOutHMIJamList.stCarMove.xStart := FALSE; + RETURN; + END_IF; + + FOR #nIdx := 1 TO #nArrayMax DO + IF #arInOutJam[#nIdx].bStatus.%X0 THEN + #arInOutJam[#nIdx] := #tmpEmptyCarr; // Carrierdaten löschen/überschreiben + ELSE + EXIT; //fertig, nichts mehr zu tun + END_IF; + END_FOR; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + END_IF; + END_REGION + + #cDeletePos: + REGION Bestimmten Carrier löschen + IF #stInOutHMIJamList.stCarMove.xStart THEN + + IF #stInOutHMIJamList.stCarMove.nPosDeleteCarrier < 1 OR #stInOutHMIJamList.stCarMove.nPosDeleteCarrier > #nArrayMax OR NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN + //Wenn Positionsangabe zu klein oder zu groß ist, oder in Jam ist gar kein Carrier online, dann beende + #stInOutHMIJamList.stCarMove.nPosDeleteCarrier := 1; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + RETURN; + END_IF; + + //lösche den ausgewählten + #arInOutJam[#stInOutHMIJamList.stCarMove.nPosDeleteCarrier] := #tmpEmptyCarr; + IF #stInOutHMIJamList.stCarMove.nPosDeleteCarrier < #nArrayMax THEN + //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war + #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam, + COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosDeleteCarrier), + SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosDeleteCarrier, + DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosDeleteCarrier - 1, + DEST => #arInOutJam); + //letztes löschen damit dort nichts doppeltes drinsteht + #arInOutJam[#nArrayMax] := #tmpEmptyCarr; + END_IF; + //fertig, setze Startbefehl zurück und Position auf Default + #stInOutHMIJamList.stCarMove.nPosDeleteCarrier := 1; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + END_IF; + END_REGION + + #cPutToHyperJam: + REGION Carrier zum Hyper-Jam + + IF #stInOutHMIJamList.stCarMove.xStart THEN + IF #stInOutHMIJamList.stCarMove.nPosTransferHj < 1 OR #stInOutHMIJamList.stCarMove.nPosTransferHj > #nArrayMax OR NOT #arInOutJam[1].bStatus.%X0 OR NOT #stInOutHMIJamData.stStatus.bByte.%X2 OR NOT #stInOutHMIJamData.stStatus.bByte.%X3 THEN + //Wenn Positionsangabe zu klein oder zu groß ist, oder in Jam ist gar kein Carrier online, dann beende + #stInOutHMIJamList.stCarMove.nPosTransferHj := 1; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + RETURN; + END_IF; + + IF #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj].nBarcode > 2 THEN + REGION normale Barcodes + //Füge Carrier am Ende des Hyperjams ein nur wenn nicht Dummy oder BadRead, also nur bei normalem Code + "FC_TSHR_AddAtEnd"(stInTrolley := #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj], + nOutCounter => #nCounter, + xOutResult => #xResult, + arTSHR := #arInOutHyperJam); + //lösche den ausgewählten + #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj] := #tmpEmptyCarr; + IF #stInOutHMIJamList.stCarMove.nPosTransferHj < #nArrayMax THEN + //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war + #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam, + COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosTransferHj), + SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj, + DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj - 1, + DEST => #arInOutJam); + //letztes löschen damit dort nichts doppeltes drinsteht + #arInOutJam[#nArrayMax] := #tmpEmptyCarr; + END_IF; + //fertig, setze Startbefehl zurück und Position auf Default + #stInOutHMIJamList.stCarMove.nPosTransferHj := 1; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + END_REGION + ELSE + REGION Dummy oder unbekannt + //Falls doch Dummy oder unbekannter Barcode, lösche nur + #arInOutJam[#stInOutHMIJamList.stCarMove.nPosTransferHj] := #tmpEmptyCarr; + IF #stInOutHMIJamList.stCarMove.nPosTransferHj < #nArrayMax THEN + //Rücke danach auf um Lücke zu beseitigen aber nur wenn es nicht die letzte Stelle war + #nStatus := MOVE_BLK_VARIANT(SRC := #arInOutJam, + COUNT := INT_TO_UDINT(#nArrayMax - #stInOutHMIJamList.stCarMove.nPosTransferHj), + SRC_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj, + DEST_INDEX := #stInOutHMIJamList.stCarMove.nPosTransferHj - 1, + DEST => #arInOutJam); + //letztes letztes löschen damit dort nichts doppeltes drinsteht + #arInOutJam[#nArrayMax] := #tmpEmptyCarr; + END_IF; + //fertig, setze Startbefehl zurück und Position auf Default + #stInOutHMIJamList.stCarMove.nPosTransferHj := 1; + #stInOutHMIJamList.stCarMove.xStart := FALSE; + END_REGION + END_IF; + END_IF; + END_REGION + + END_CASE; + END_REGION +END_FUNCTION + diff --git a/_CommonLib/Programmbausteine/PROFINET/FC_GET_PROFINET_DEVICE_STATES.scl b/_CommonLib/Programmbausteine/PROFINET/FC_GET_PROFINET_DEVICE_STATES.scl new file mode 100644 index 0000000..a50925c --- /dev/null +++ b/_CommonLib/Programmbausteine/PROFINET/FC_GET_PROFINET_DEVICE_STATES.scl @@ -0,0 +1,27 @@ +FUNCTION "FC_GET_PROFINET_DEVICE_STATES" : Void +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_TEMP + nRetValExist : Int; + nRetValFaulty : Int; + END_VAR + + +BEGIN + REGION Device States + + REGION Get MODE Exist + #nRetValExist := DeviceStates(LADDR := "Local~PROFINET_IO-System", // IO-System + MODE := 4, // vorhanden / nicht vorhanden + STATE := "DB_PROFINET_DEVICE_STATES".arPN_DEV_STATE_EXIST); // Status + END_REGION + + REGION Get MODE Fault + #nRetValFaulty := DeviceStates(LADDR := "Local~PROFINET_IO-System", // IO-System + MODE := 2, // Störung + STATE := "DB_PROFINET_DEVICE_STATES".arPN_DEV_STATE_FAULTY); // Status + END_REGION + + END_REGION +END_FUNCTION + diff --git a/_CommonLib/Programmbausteine/Programming error.scl b/_CommonLib/Programmbausteine/Programming error.scl new file mode 100644 index 0000000..1707bdc --- /dev/null +++ b/_CommonLib/Programmbausteine/Programming error.scl @@ -0,0 +1,32 @@ +ORGANIZATION_BLOCK "Programming error" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + +BEGIN + "DB_Error".BlockNr := #BlockNr; + "DB_Error".Reaction := #Reaction; + "DB_Error".Fault_ID := #Fault_ID; + "DB_Error".BlockType := #BlockType; + "DB_Error".Area := #Area; + "DB_Error".DBNr := #DBNr; + "DB_Error".Csg_OBNr := #Csg_OBNr; + "DB_Error".Csg_Prio := #Csg_Prio; + "DB_Error".Width := #Width; + "DB_Error".xErrorActive := TRUE; //Wird am Anfang von OB1 wieder auf FALSE gesetzt + CASE #BlockType OF + 16#01: + //Fehler in OB + "DB_Error".sErrorText := CONCAT_STRING(IN1 := 'Programming Error in OB ', IN2 := UINT_TO_STRING(#BlockNr)); + 16#02: + //Fehler in FC + "DB_Error".sErrorText := CONCAT_STRING(IN1 := 'Programming Error in FC ', IN2 := UINT_TO_STRING(#BlockNr)); + 16#03: + //Fehler in FB + "DB_Error".sErrorText := CONCAT_STRING(IN1 := 'Programming Error in FB ', IN2 := UINT_TO_STRING(#BlockNr)); + 16#06: + //Fehler in DB + "DB_Error".sErrorText := CONCAT_STRING(IN1 := 'Programming Error in DB ', IN2 := UINT_TO_STRING(#BlockNr)); + END_CASE; + +END_ORGANIZATION_BLOCK + diff --git a/_CommonLib/Programmbausteine/SCADA/FB-OPC_UA_System-Stat.scl b/_CommonLib/Programmbausteine/SCADA/FB-OPC_UA_System-Stat.scl new file mode 100644 index 0000000..68fe683 --- /dev/null +++ b/_CommonLib/Programmbausteine/SCADA/FB-OPC_UA_System-Stat.scl @@ -0,0 +1,72 @@ +FUNCTION_BLOCK "FB-OPC_UA_System-Stat" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_INPUT + nInSystemStat : Int; // Main State + xInFireAlarm : Bool; // Feueralarm + xInSafetyStop : Bool; // Not-Halt + xInError : Bool; // Störung + xInCommunicationError : Bool; // Kommunikationsstörung + END_VAR + + VAR_OUTPUT + nOutScadaStatus : Int; + END_VAR + + +BEGIN + //Priority Chain + //Emergency + //Fault/Restore + //Manual + //Energy Saving + //Cleaning / Warning + //Running/Stopped + + IF #xInFireAlarm THEN + #nOutScadaStatus := 1; + ELSIF #xInSafetyStop THEN + #nOutScadaStatus := 3; + ELSIF #xInError THEN + #nOutScadaStatus := 5; + ELSIF #xInCommunicationError THEN + #nOutScadaStatus := 23; + ELSIF #nInSystemStat = "E_DeviceState.eExecute" THEN + #nOutScadaStatus := 19; + ELSIF (#nInSystemStat = "E_DeviceState.eStopped") OR (#nInSystemStat = "E_DeviceState.eIdle") THEN + #nOutScadaStatus := 17; + END_IF; + + (* CASE #nInSystemStat OF + + "E_DeviceState.eStopped": + #nOutScadaStatus := 17; + + "E_DeviceState.eIdle": + #nOutScadaStatus := 17; + + "E_DeviceState.eExecute": + #nOutScadaStatus := 19; + + "E_DeviceState.eHolding": + #nOutScadaStatus := 3; + + "E_DeviceState.eHeld": + #nOutScadaStatus := 13; + + "E_DeviceState.eSuspended": + #nOutScadaStatus := 13; + + "E_DeviceState.eStarting", + 120, + "E_DeviceState.eUnholding", + "E_DeviceState.eUnsuspending", + "E_DeviceState.eStopping": + #nOutScadaStatus := 7; + + ELSE + #nOutScadaStatus := 5; + + END_CASE; *) +END_FUNCTION_BLOCK + diff --git a/_CommonLib/Programmbausteine/_IBN/FC_S7.scl b/_CommonLib/Programmbausteine/_IBN/FC_S7.scl new file mode 100644 index 0000000..d6099ce --- /dev/null +++ b/_CommonLib/Programmbausteine/_IBN/FC_S7.scl @@ -0,0 +1,62 @@ +FUNCTION "FC_S7" : Void +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_INPUT + wInID : Word; + END_VAR + + VAR_IN_OUT + xInOutStart : Bool; + xInOutError : Bool; + wInOutStatus : Word; + InOutAddr : Remote; + InOutOrigin : Variant; + END_VAR + + VAR_TEMP + xDone : Bool; + xError : Bool; + wStatus : Word; + END_VAR + + +BEGIN + + + REGION PUT + + + + "PUT_DB"(REQ := #xInOutStart, + ADDR_1 := #InOutAddr,//P#DB99.DBX68.0 BYTE 1,//Partner CPU, + SD_1 := #InOutOrigin,//Eigene CPU + ID := #wInID); + + IF "PUT_DB".ERROR THEN + #xInOutError := "PUT_DB".ERROR; + END_IF; + IF "PUT_DB".STATUS <> 0 THEN + #wInOutStatus := "PUT_DB".STATUS; + END_IF; + IF "PUT_DB".DONE THEN + #xInOutStart := FALSE; + END_IF; + END_REGION + + // REGION GET + // #rTrigGET(CLK := "DB_S7".xGetStart); + // IF #rTrigGET.Q THEN + // "DB_Test".rTimeResult := RUNTIME("DB_Test".rTimeMem); + // END_IF; + // "GET_DB"(REQ := "DB_S7".xGetStart, + // NDR => #xTemp, + // ADDR_1 := P#DB99.DBX2.0 DINT 1,//Partner CPU + // RD_1 := "DB_S7".arCarrier[1].nBarcode, //Eigene CPU + // ID := W#16#117); + // IF "GET_DB".NDR THEN + // "DB_Test".rTimeResult := RUNTIME("DB_Test".rTimeMem); + // "DB_S7".xGetStart := FALSE; + // END_IF; + // END_REGION +END_FUNCTION + diff --git a/_CommonLib/Programmbausteine/_PerformanceMeasurement_/FB_PerfTest.scl b/_CommonLib/Programmbausteine/_PerformanceMeasurement_/FB_PerfTest.scl new file mode 100644 index 0000000..b80fd68 --- /dev/null +++ b/_CommonLib/Programmbausteine/_PerformanceMeasurement_/FB_PerfTest.scl @@ -0,0 +1,104 @@ +FUNCTION_BLOCK "FB_PerfTest" +{ S7_Optimized_Access := 'TRUE' } +VERSION : 0.1 + VAR_INPUT + nInSepNo : Int; // Nummer welche hinter Sep-Konstante steckt + xInSepFlag : Bool; // Flanke vom Release pro MiniTrolley + xInReset : Bool; + tInTimeMeasurement : Time := T#86400s; // Default 24h + nInGoalFlags : Int; // Anzahl der Releases welche Messung stoppen + END_VAR + + VAR + tOnTimer {InstructionName := 'TON_TIME'; LibVersion := '1.0'; S7_SetPoint := 'False'} : TON_TIME; + xTestActive : Bool; // true = Messung läuft + xTimerRun : Bool; // Signal für Timer + nCount : Int; // MiniTrolleys pro Sep während Messung + Date_And_TimeStart : Date_And_Time; // Beginn mit erstem MiniTrolley + Date_And_TimeLap : Date_And_Time; // Zeit bei jedem weiteren MiniTrolley + tTimeResult : Time; // jeweiliges Ergebnis + rTrigRun {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG; + fTrigRun {InstructionName := 'F_TRIG'; LibVersion := '1.0'} : F_TRIG; + fTrigSepFlag {InstructionName := 'F_TRIG'; LibVersion := '1.0'} : F_TRIG; + END_VAR + VAR RETAIN + arTrolley : Array[1..500] of Struct + nCountNo : Int; // Aktuelle Schaltung + tTimeEvent : Date_And_Time; // Zeitstempel bei Release + tTimeResult : Time; // Differenz seit Start + END_STRUCT; + nTrolleyNo : Int; // aktuelle Zeile in Array in welche geschrieben wird + END_VAR + + VAR_TEMP + nTmpTimeReturn : Int; + nIdx : Int; + END_VAR + + +BEGIN + IF #nTrolleyNo = 0 THEN + #nTrolleyNo := 1; + END_IF; + + REGION Flanken erfassen + #rTrigRun(CLK := #xTestActive); + #fTrigRun(CLK := #xTestActive); + #fTrigSepFlag(CLK := #xInSepFlag); + END_REGION + + REGION Nullen bei neuer Messung + IF #xInReset THEN + #Date_And_TimeLap := DT#1990-01-01-00:00:00; + #Date_And_TimeStart := DT#1990-01-01-00:00:00; + #tTimeResult := T#0s; + #nTrolleyNo := 1; + FOR #nIdx := 1 TO 500 DO + #arTrolley[#nIdx].nCountNo := 0; + #arTrolley[#nIdx].tTimeEvent := DT#1990-01-01-00:00:00; + #arTrolley[#nIdx].tTimeResult := T#0s; + END_FOR; + ELSIF #rTrigRun.Q THEN + #Date_And_TimeLap := DT#1990-01-01-00:00:00; + #Date_And_TimeStart := DT#1990-01-01-00:00:00; + #tTimeResult := T#0s; + #nTrolleyNo := 1; + #xTimerRun := TRUE; + END_IF; + END_REGION + + REGION Sep-Flanken während Messung erfassen + //Während Messtimer läuft und 1. Flanke kommt, ermittle Zeit und schreibe sie weg und erhöhe Pos für nächste Zeile. + //Danach so weiter machen aber dann immer die Zeitdifferenz wegschreiben + IF #tOnTimer.ET > T#0s AND #tOnTimer.ET < #tInTimeMeasurement AND #fTrigSepFlag.Q THEN + IF #nTrolleyNo = 1 THEN //Nur beim ersten Trolley die Startzeit ermitteln + #nTmpTimeReturn := RD_SYS_T(#Date_And_TimeStart); + END_IF; + #nTmpTimeReturn := RD_SYS_T(#Date_And_TimeLap); //Flankenzeitpunkt für Differenz aus diesem und Startzeitpunkt + #tTimeResult := T_DIFF(IN1 := #Date_And_TimeLap, IN2 := #Date_And_TimeStart); + //Daten wegschreiben + #arTrolley[#nTrolleyNo].nCountNo := #nTrolleyNo; + #arTrolley[#nTrolleyNo].tTimeEvent := #Date_And_TimeLap; + #arTrolley[#nTrolleyNo].tTimeResult := #tTimeResult; + //erhöhen für nächste Zeile oder beende Messung + IF #nTrolleyNo <= #nInGoalFlags THEN + #nTrolleyNo += 1; + ELSIF #tOnTimer.ET >= #tInTimeMeasurement OR #fTrigRun.Q OR #nTrolleyNo > #nInGoalFlags THEN + #xTimerRun := FALSE; + #xTestActive := FALSE; + END_IF; + + END_IF; + IF #tOnTimer.ET >= #tInTimeMeasurement OR #fTrigRun.Q OR #nTrolleyNo > #nInGoalFlags THEN + #xTimerRun := FALSE; + #xTestActive := FALSE; + END_IF; + END_REGION + + REGION Timer + #tOnTimer(IN := #xTimerRun, + PT := #tInTimeMeasurement); + END_REGION + +END_FUNCTION_BLOCK + diff --git a/_CommonLib/TIA_BIBLIOTHEK_ANLEITUNG.md b/_CommonLib/TIA_BIBLIOTHEK_ANLEITUNG.md new file mode 100644 index 0000000..e2c1f4a --- /dev/null +++ b/_CommonLib/TIA_BIBLIOTHEK_ANLEITUNG.md @@ -0,0 +1,159 @@ +# TIA Portal Projektbibliothek — Anleitung + +**Projekt:** HundM_Fortna +**Stand:** 2026-06-29 +**Ziel:** Kanonische Bausteine aus `_CommonLib/` in die TIA Portal Projektbibliothek übernehmen + +--- + +## Voraussetzungen + +- TIA Portal V17 oder höher +- Alle 5 PLCs (UH01–UH05) im selben TIA Portal Projekt geöffnet +- `_CommonLib/Programmbausteine/` als Referenz-Ordner vorhanden (dieses Repository) + +--- + +## Schritt 1: SCL-Datei in einen PLC importieren + +Für jeden Baustein aus `_CommonLib/` einmalig: + +1. Im TIA Portal Projektbaum: Beliebigen PLC auswählen (z.B. UH01) +2. `Programmbausteine` → Rechtsklick → **"Externe Quelldatei einfügen"** +3. SCL-Datei aus `_CommonLib/Programmbausteine//` auswählen +4. Der Baustein erscheint unter `Programmbausteine` → **Kompilieren** (F11) +5. Sicherstellen: Keine Kompilierfehler + +**Gruppe-A-Blöcke (direkt importierbar, keine Anpassung nötig):** + +| SCL-Datei | PLC-Pfad nach Import | +|---|---| +| `PROFINET/FC_GET_PROFINET_DEVICE_STATES.scl` | PLC → Programmbausteine → PROFINET | +| `SCADA/FB-OPC_UA_System-Stat.scl` | PLC → Programmbausteine → SCADA | +| `970_Visu/FC_CarrierManipulator.scl` | PLC → Programmbausteine → 970_Visu | +| `400_BasicFunctions/FC/FC_Int2String.scl` | PLC → Programmbausteine → 400_BasicFunctions | +| `900_Communications/FB_FortnaTele_Placeholder.scl` | PLC → Programmbausteine → 900_Communications | +| `_IBN/FC_S7.scl` | PLC → Programmbausteine → _IBN | + +**Gruppe-B-Blöcke (vor Import Hinweise beachten → siehe Abschnitt "Gruppe B"):** + +| SCL-Datei | Besonderheit | +|---|---| +| `Programming error.scl` | OB — direkt importierbar | +| `_PerformanceMeasurement_/FB_PerfTest.scl` | Kein Default-Wert; falls gewünscht im Instanz-DB setzen | +| `900_Communications/TCP-Logger/FB_CommunicationLogger.scl` | connectionID anpassen! Jam-Referenz prüfen! | +| `970_Visu/FB_Visu_Jam.scl` | VAR_INPUT `nInJamCount` entfernt — Aufrufe prüfen | +| `970_Visu/FB_Visu_JamStorage.scl` | Nur für UH01/UH02/UH03 relevant | + +--- + +## Schritt 2: Baustein in Projektbibliothek speichern + +Nachdem der Baustein in einem PLC kompiliert wurde: + +1. Baustein im Projektbaum markieren +2. Rechtsklick → **"In Projektbibliothek kopieren"** +3. Im Dialog: + - Bibliotheksname: `HundM_CommonLib` + - Typ: **Typ** (nicht Instanz) + - Version: `V1.0.0` +4. Bestätigen → Baustein erscheint unter **Projektbibliothek → Typen** + +--- + +## Schritt 3: Lokale Kopien in anderen PLCs ersetzen + +Für jeden weiteren PLC (UH02–UH05): + +1. Lokalen Baustein in diesem PLC **löschen** (Rechtsklick → Löschen) + - TIA Portal warnt, falls der Baustein noch aufgerufen wird — dann erst Aufrufe anpassen +2. In der **Projektbibliothek** (linkes Panel): `HundM_CommonLib → Typen` +3. Baustein per **Drag & Drop** in `Programmbausteine` des Ziel-PLCs ziehen +4. TIA Portal erstellt automatisch eine Bibliotheksreferenz (kein lokaler SCL-Code mehr) +5. **Kompilieren** und Konsistenzprüfung durchführen + +--- + +## Schritt 4: Konsistenzprüfung aller PLCs + +Nach Abschluss aller Blöcke: + +1. **Gesamtprojekt kompilieren:** Menü → Kompilieren → Alle Bausteine +2. **Konsistenzprüfung:** Extras → Konsistenz prüfen +3. Alle 5 PLCs müssen ohne Fehler kompilieren + +--- + +## Gruppe B: Besondere Hinweise vor dem Import + +### FB_CommunicationLogger — connectionID + +Die `connectionID` in diesem Block ist ein TCP-Verbindungsparameter, der je PLC eindeutig sein muss: + +| PLC | Aktuelle connectionID | +|---|---| +| UH01 | 99 | +| UH02 | 100 (bewusst verschieden!) | +| UH03 | 99 | +| UH04 | 99 | +| UH05 | 99 | + +**Empfehlung:** Nach Übernahme in die Projektbibliothek die `connectionID` als FB-Parameter +herausziehen (VAR_INPUT), damit jeder PLC seinen eigenen Wert im Aufruf setzen kann. +Alternativ: Im Instanz-DB der jeweiligen PLC nach dem Drag & Drop anpassen. + +**Zusätzlich:** Zeile mit `"DB_JamArea0102"` ist UH01-spezifisch. In anderen PLCs +diesen Abschnitt anpassen oder auskommentieren. + +### FB_Visu_Jam — VAR_INPUT entfernt + +Die CommonLib-Version hat `nInJamCount : UInt` aus VAR_INPUT entfernt (war unbenutzt). +Falls bestehende Aufrufe in UH01 diesen Parameter übergeben: +→ Den Aufruf in UH01 anpassen (Parameter entfernen) + +--- + +## Git-Workflow nach TIA-Export + +Nach erfolgter Bibliotheksintegration und erneutem TIA Portal Export: + +``` +# Erwartete Git-Änderungen: +# - Lokale .scl Dateien in UH01-UH05 werden ersetzt durch TIA-interne Library-Referenz +# - Möglicherweise erscheinen neue .liblink Dateien für die CommonLib-Blöcke + +git status +# Geänderte/gelöschte .scl Dateien überprüfen +# _CommonLib/*.scl bleiben unverändert (Quelle der Wahrheit) + +git add _CommonLib/ +git commit -m "CommonLib angelegt: 11 standardisierte P1/P2-Bausteine" +``` + +**Regel:** Änderungen an standardisierten Blöcken **immer** in `_CommonLib/` beginnen, +dann in TIA Portal aktualisieren, dann exportieren und committen. + +--- + +## Übersicht: Was wurde standardisiert + +### Gruppe A (6 Blöcke — 100% identisch) +- `FC_GET_PROFINET_DEVICE_STATES` — PROFINET-Gerätezustände +- `FB-OPC_UA_System-Stat` — OPC-UA Statusübersetzung +- `FC_S7` — S7 PUT-Wrapper (CPU-zu-CPU) +- `FC_CarrierManipulator` — HMI Carrier-Manipulation +- `FC_Int2String` — String-Konvertierung +- `FB_FortnaTele_Placeholder` — Fortna UDT-Platzhalter + +### Gruppe B (5 Blöcke — bereinigt) +- `Programming error` (OB) — UH02-VAR_TEMP entfernt +- `FB_PerfTest` — Default-Wert bereinigt +- `FB_CommunicationLogger` — connectionID-Hinweis ergänzt +- `FB_Visu_Jam` — nInJamCount entfernt, REGION vereinheitlicht +- `FB_Visu_JamStorage` — UH01 als kanonische Version + +### Nicht standardisiert (Gruppe D — 11 Blöcke) +Topologie-spezifische Blöcke (FB_Main, FB_PreMain, FB_CallSensors, FB_Visu, +FB_CommunicationWCSBL, FC_Call_Jams, FC_Direction, FB_Visu_Jams, +FC_CARR_GLOB_CORRECTION, FC_BARCODE_SEARCH, FC_Jam) +bleiben je UH individuell — Pflege weiterhin getrennt.