diff --git a/CLAUDE.md b/doc/CLAUDE.md similarity index 100% rename from CLAUDE.md rename to doc/CLAUDE.md diff --git a/doc/Json_Layout-Konzept.md b/doc/Json_Layout-Konzept.md new file mode 100644 index 0000000..ff65109 --- /dev/null +++ b/doc/Json_Layout-Konzept.md @@ -0,0 +1,993 @@ +# JSON Layout-Konfiguration fuer HundM_Fortna SCL-Code-Generierung + +## Kontext + +Die 5 SPS-Konfigurationen (UH01-UH05) enthalten tausende Zeilen repetitiven SCL-Code in `FB_Main`, `FB_CallSensors`, `FC_Direction` und `FC_Call_Jams`. Dieser Code folgt festen Mustern pro Element-Typ und unterscheidet sich nur in den konkreten Parametern (Adressen, Sensor-IDs, TRO-Nummern, Timing-Werte). Eine JSON-Konfigurationsdatei koennte als **Single Source of Truth** dienen, aus der der gesamte topologie-spezifische SCL-Code generiert wird. + +## Identifizierte Element-Typen (aus FB_Main UH01) + +| Typ | FB-Typ | Anzahl UH01 | Kennzeichen | +|---|---|---|---| +| Conveyor/Carousel | `FB_Conveyor` | 13 | Motor, Grid-Sensor, Schaltschrank | +| TRO 1Sep | `FB_ILS_MTRO_1Sep` | ~15 | 1 Separator, Entry/Exit Jam | +| TRO 1Sep + Scanner | `FB_ILS_MTRO_1Sep` | 5 | + Cognex Barcode-Reader | +| TRO 1Sep1Swi | `FB_ILS_MTRO_1Sep1Swi` | 4 | + Switch mit Direction-Logik | +| TRO 1Sep SSCC | `FB_ILS_MTRO_1Sep_SSCC` | 2 | + SSCC-Scanner + DReqM Telegramm | +| TRO Vario | `FB_ILS_MTRO_Vario` | 9 | Ketten-/Variofuerderer | +| EmptyCarrBuffer | `FB_EmptyCarrBuffer` | 2 | Mehrzeiliger Puffer + Weichen | +| LoadingBoom | `FB_LoadingBoom_INBOUND` | 2 | Komplex: Boom, Fuss, Stopper, Tilt, Distance | +| Sensor | `FB_SensorInput` | ~200 | Pro physischem Sensor | + +--- + +## Vorschlag fuer eine standardisierte TRO-Liste + +### Uebersicht aller TROs nach Steuerung + +Insgesamt wurden **237 TROs** ueber alle 5 Steuerungen identifiziert. Die TRO-IDs folgen dem Schema `TRO` (z.B. TRO100-TRO134 fuer UH01). + +| Steuerung | TRO-Bereich | Anzahl TROs | Schwerpunkt | +|---|---|---|---| +| UH01 | TRO100-TRO134 | 21 | Inbound, Loading Booms, SSCC-Scanner, Empty Carrier Buffer | +| UH02 | TRO200-TRO275 | 76 | 3x PinStore-Bloecke (automatisiertes Lager) | +| UH03 | TRO301-TRO386 | 84 | 3x PinStore-Bloecke (2.1, 2.2, 2.3) + F2H | +| UH04 | TRO402-TRO424 | 24 | 3x Work Stations (manuelle Arbeitsplaetze) | +| UH05 | TRO500-TRO531 | 32 | Laengenmessung + Verteilsystem | + +### FB-Typ-Verteilung ueber alle Steuerungen + +| FB-Typ | Beschreibung | UH01 | UH02 | UH03 | UH04 | UH05 | Gesamt | +|---|---|---|---|---|---|---|---| +| `FB_ILS_MTRO_1Sep` | Standard-Separator | ~15 | ~20 | ~25 | ~8 | ~10 | ~78 | +| `FB_ILS_MTRO_Vario` | Kettenfoerderer (variabel) | 9 | ~15 | ~18 | 4 | ~12 | ~58 | +| `FB_ILS_MTRO_1Sep1Swi` | Separator + 1 Weiche | 4 | ~8 | ~12 | 3 | 5 | ~32 | +| `FB_ILS_MTRO_1Sep2Swi` | Separator + 2 Weichen | 0 | ~5 | ~6 | 0 | 0 | ~11 | +| `FB_ILS_MTRO_PinStore_Auto` | Automatisches Pin-Lager | 0 | ~20 | ~18 | 0 | 0 | ~38 | +| `FB_ILS_MTRO_1Sep_SSCC` | SSCC-Barcode-Scanner | 2 | 0 | 0 | 0 | 0 | 2 | +| `FB_ILS_MTRO_Vario_workStation` | Manueller Arbeitsplatz | 0 | 0 | 0 | 3 | 0 | 3 | +| `FB_EmptyCarrBuffer` | Leertablar-Puffer | 2 | 0 | 0 | 0 | 0 | 2 | + +### Detaillierte TRO-Liste UH01 + +| TRO | FB-Typ | Scanner | Switch | Prio | Besonderheit | +|---|---|---|---|---|---| +| TRO100 | 1Sep | - | - | releaseOk | Eingang Kreisel | +| TRO101_IN | 1Sep | - | - | releaseOk | Eingang Empty Buffer rechts | +| TRO101 | EmptyCarrBuffer | - | - | Manager | 5-Zeilen Leertablar-Puffer rechts | +| TRO102_IN | 1Sep | - | - | releaseOk | Eingang Empty Buffer links | +| TRO102 | EmptyCarrBuffer | - | - | Manager | 5-Zeilen Leertablar-Puffer links | +| TRO103 | 1Sep | - | - | releaseOk | Zufahrt Loading Boom 1 | +| TRO104 | 1Sep | BX1103 | - | releaseOk | Stopper vor Boom 1 + Barcode | +| TRO105 | 1Sep_SSCC | BX1104 + BX1107 | - | releaseOk | SSCC-Scanner Boom 1 + WCS DReqM | +| TRO106 | 1Sep | - | - | Manager | Abfahrt Boom 1 | +| TRO107 | 1Sep1Swi | - | cSwi107.1 | Dir2 Manager | Weiche Boom 1 (LS / Clearing) | +| TRO108 | 1Sep | - | - | releaseOk | Zufahrt Loading Boom 2 | +| TRO109 | 1Sep | BX1105 | - | releaseOk | Stopper vor Boom 2 + Barcode | +| TRO110 | 1Sep_SSCC | BX1106 + BX1108 | - | releaseOk | SSCC-Scanner Boom 2 + WCS DReqM | +| TRO111 | 1Sep | - | - | Manager | Abfahrt Boom 2 | +| TRO112 | 1Sep1Swi | - | cSwi112.1 | Dir2 Manager | Weiche Boom 2 (LS / Clearing) | +| TRO113 | 1Sep | BX1101 | - | releaseOk | RFID + Barcode vor Ausfahrt | +| TRO114 | 1Sep1Swi | - | cSwi114.1 | - | Weiche Inbound Out / Clearing | +| TRO115 | Vario | - | - | releaseOk | Loaded to Storage (Kette) | +| TRO116 | 1Sep | - | - | releaseOk | Separator vor Clearing | +| TRO117 | 1Sep | BX1100 | - | Manager | Clearing Station + Barcode | +| TRO120 | Vario | - | - | releaseOk | Highway Vario | +| TRO121 | Vario | - | - | releaseOk | Highway Vario | +| TRO122 | 1Sep | - | - | releaseOk | Highway Separator | +| TRO123 | Vario | - | - | releaseOk | Highway Vario | +| TRO124 | 1Sep1Swi | - | cSwi124.1 | Manager | Weiche Highway (Storage / Inbound) | +| TRO125 | 1Sep | - | - | Manager | Highway Separator | +| TRO126 | Vario | - | - | releaseOk | Empty to Storage (Kette) | +| TRO127 | Vario | - | - | releaseOk | Empty to Inbound (Kette) | +| TRO128 | Vario | - | - | releaseOk | Loaded to AMR (Kette) | +| TRO129 | 1Sep | - | - | Manager | Highway Separator | +| TRO130 | 1Sep | - | - | Manager | Highway Separator | +| TRO131 | Vario | - | - | releaseOk | Highway Vario | +| TRO132 | 1Sep | - | - | releaseOk | Highway Separator | +| TRO133 | Vario | - | - | releaseOk | Highway Vario | +| TRO134 | Vario | - | - | releaseOk | Highway Vario | + +### Spezial-Elemente je Steuerung + +| Feature | UH01 | UH02 | UH03 | UH04 | UH05 | +|---|---|---|---|---|---| +| SSCC-Scanner | TRO105, TRO110 | - | - | - | - | +| Cognex Barcode | BX1100-BX1108 | - | - | BX4103 | BX5101 | +| PinStore (autom. Lager) | - | 3 Bloecke | 3 Bloecke (2.1-2.3) | - | - | +| Work Station (manuell) | - | - | - | TRO421-423 | - | +| Laengenmessung | - | - | - | - | TRO500 | +| Empty Carrier Buffer | TRO101, TRO102 | - | - | - | - | +| Loading Boom | Boom1, Boom2 | - | - | - | - | +| Borner (Einschleusung) | TRO101, TRO102 | TRO200, 240, 270, 272 | - | - | TRO500, 502 | +| F2H (Floor-to-Hub) | - | - | TRO308, 383, 386 | - | - | + +### Namenskonvention fuer standardisierte JSON-Konfiguration + +Um eine einheitliche JSON pro Steuerung zu erzeugen, wird folgendes Schema empfohlen: + +``` +TRO-ID: TRO z.B. TRO115, TRO207, TRO315 +Separator-Nr: cSep.1 z.B. cSep115.1 +Switch-Nr: cSwi.1 z.B. cSwi107.1 +MainTroNo: cMainTro z.B. cMainTro115 +JamArea-DB: DB_JamArea<4-stellig> z.B. DB_JamArea0107 +Scanner-ID: cScannerBX<4-stellig> z.B. cScannerBX1104 +HMI-Pfad: DB_Interface_HMI.stTRO.TRO +``` + +--- + +## Vorgeschlagene JSON-Struktur + +### 1. Projekt-Header & SPS-Konfiguration + +```json +{ + "$schema": "hmf-layout-v1.schema.json", + "version": "1.0", + "project": "HundM_Fortna", + + "plc": { + "id": "UH01", + "configName": "=A01+UH01-KF00", + "plcId": "cPLCID", + "connectionIdWCSBL": 10 + }, + + "controlUnits": [ + { + "id": "OF1", + "safetySignal": "DB_InterfaceSafety.stFromSafety.EStopMainOF1.Q", + "mainContactors": [ + "DB_InterfaceSafety.stFromSafety.stMainContactorsUH01.Q", + "DB_InterfaceSafety.stFromSafety.stMainContactorsUC0110.Q", + "DB_InterfaceSafety.stFromSafety.stMainContactorsUC0111.Q" + ], + "machineState": "DB_MachineGlobal.stStateMainOF1" + }, + { + "id": "OF2", + "safetySignal": "DB_InterfaceSafety.stFromSafety.EStopMainOF2.Q", + "mainContactors": [ + "DB_InterfaceSafety.stFromSafety.stMainContactorsUC011.Q" + ], + "machineState": "DB_MachineGlobal.stStateMainOF2" + } + ] +} +``` + +### 2. Sensoren (erzeugt `FB_CallSensors`) + +```json +"sensors": [ + { + "id": "BG0280", + "constant": "cInBG0280", + "hwInput": "BG0280", + "controlUnit": "OF1", + "comment": "TRO104 Sep Sensor" + }, + { + "id": "BG0282", + "constant": "cInBG0282", + "hwInput": "BG0282", + "controlUnit": "OF1", + "comment": "LoadingBoom1 Stopper1" + } +] +``` + +### 3. Conveyors / Carousels (erzeugt REGION Conveyor in `FB_Main`) + +#### Standard-Conveyor (Carousel mit Grid-Sensor) + +```json +"conveyors": [ + { + "id": "Carousel0101", + "instanceName": "fbCarousel0101", + "comment": "Eingangskreisel", + "controlUnit": "OF1", + "settings": { + "energySafeTime": "cTimeEnergySafe", + "gridActive": true, + "motorProtectName": "FC0060", + "gridSenName": "BG3347" + }, + "io": { + "enabled": "cTodoTRUE", + "gridSensor": "cInBG3347", + "gridQuit": ["SF0031", "SF0002"], + "motorProtection": "FC0060", + "powerContactor": "MA0060", + "hmiPath": "DB_Interface_HMI.stConveyors.stCarousel.stCar0101" + }, + "requestRunSources": [ + { "type": "startupCounter", "value": 100 }, + { "type": "restart" }, + { "type": "troCarouselReq", "tro": "TRO100" }, + { "type": "troCarouselReq", "tro": "TRO101_IN" }, + { "type": "troCarouselReq", "tro": "TRO102_IN" } + ] + } +] +``` + +#### Buersten-Conveyor (Subtype brush) + +```json +{ + "id": "Conveyor4103_B", + "instanceName": "fbConveyor4103_B", + "comment": "Buersten Highway Loaded to Storage", + "controlUnit": "OF2", + "subtype": "brush", + "settings": { + "energySafeTime": "T#90s", + "gridActive": false, + "motorProtectName": "FC0152" + }, + "io": { + "motorProtection": "FC0152", + "powerContactor": "MA0152", + "hmiPath": "DB_Interface_HMI.stConveyors.stCarousel.stCar4103_B" + }, + "brushConfig": { + "triggerSensor": "cInBG3140", + "jamSensor": "cInBG3143", + "fullSensor": "cInBG3142", + "taktTime": "T#1s" + } +} +``` + +### 4. TROs (Transfer Route Objects) + +#### TRO 1Sep — Standard-Separator + +```json +"tros": [ + { + "id": "TRO100", + "type": "1Sep", + "fbType": "FB_ILS_MTRO_1Sep", + "mainTroNo": "cMainTro100", + "controlUnit": "OF1", + "comment": "Eingang Kreisel", + "separator": { + "no": "cSep100.1", + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#600ms", + "handlingTime": "T#200ms", + "jamTime": "TimeForSepJam", + "senFree": "T#1500ms", + "senWait": "T#4000ms", + "plugged": { + "jam": true, + "part": false, + "scanner": false + }, + "sensorInSep": "cInBG3242" + }, + "sensorJam2": "cInBG3243", + "priority": { "releaseOk": true }, + "call": { + "carouselRun": "fbCarousel0101.xOutConveyorFullSpeed", + "release": "DB_TRO_TEST.TRO100" + }, + "jamAreas": { + "entry": "DB_JamArea0100.stJam0100_1", + "exit": "DB_JamArea0101.stJam0101_1" + }, + "outputs": { + "stopper1": "MB3242" + }, + "hmi": "DB_Interface_HMI.stTRO.TRO100" + } +] +``` + +#### TRO 1Sep1Swi — Separator + Switch mit Direction-Logik + +```json +{ + "id": "TRO107", + "type": "1Sep1Swi", + "fbType": "FB_ILS_MTRO_1Sep1Swi", + "mainTroNo": "cMainTro107", + "controlUnit": "OF1", + "comment": "Switch Boom 1", + "separator": { + "no": "cSep107.1", + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#100ms", + "handlingTime": "T#50ms", + "jamTime": "TimeForSepJam", + "plugged": { "jam": true, "part": false, "scanner": false }, + "sensorInSep": "cInBG3306" + }, + "sensorJam2": "cInBG3305", + "sensorJam3": "cInBG3330", + "switch": { + "no": "cSwi107.1", + "pluggedExSen3": false, + "pluggedExSen4": false, + "nTo1Destinations": 3 + }, + "settings": { + "prioDir2": true + }, + "priority": { + "managerDir2In": "DB_Prozessdaten.stPriorityManager.udt_TRO107.TroIn", + "managerDir2Out": "DB_Prozessdaten.stPriorityManager.udt_TRO107.TroOut" + }, + "call": { + "carouselRun1": "fbCarousel0102.xOutConveyorFullSpeed", + "release": "true" + }, + "jamAreas": { + "entry": "DB_JamArea0102.stJam0102_1", + "exit2": "DB_JamArea0103.stJam0103_1", + "exit3": "DB_JamArea0102.stJam0102_2" + }, + "outputs": { + "stopper1": "MB3306", + "sw1ExTo3": "MB3304" + }, + "hmi": "DB_Interface_HMI.stTRO.TRO107", + "direction": { + "switchNo": "cSwi107.1", + "carrierSource": "DB_JamArea0102.stJam0102_1.arCarrier[1]" + } +} +``` + +#### TRO Vario — Kettenfoerderer + +```json +{ + "id": "TRO115", + "type": "Vario", + "fbType": "FB_ILS_MTRO_Vario", + "mainTroNo": "cMainTro115", + "controlUnit": "OF1", + "comment": "Loaded To Storage Vario", + "separator": { + "no": "cSep115.1", + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#800ms", + "handlingTime": "T#300ms", + "jamTime": "TimeForSepJam", + "senFree": "T#2000ms", + "senWait": "T#5000ms", + "plugged": { "jam": false, "part": false, "scanner": false }, + "sensorInSep": "cInBG3025" + }, + "vario": { + "continousEmptying": false, + "waitForJog": "T#300ms", + "convEmpty": "T#45000ms", + "countCarrier": 1, + "waitForStop": "T#3s", + "carrierInPosDelay": "T#1200ms", + "carrierInPosEdgeDelay": "T#100ms", + "rasterHigh": "T#5s", + "rasterLow": "T#5s", + "jamSenDelayActive": true, + "jamSenDelay": "T#2s", + "sensors": { + "carrInPos": "cInBG3026", + "finger": "cInBG3027", + "lastPos": "cInBG3000", + "jam": "cInBG3001" + } + }, + "settings": { "isBorner": true }, + "priority": { "releaseOk": true }, + "call": { + "motorProtection": "FC0145", + "automatic": "#t_Automatik_OF1 AND SF0120", + "errorQuit": "SF0002", + "release": "DB_TRO_TEST.TRO115" + }, + "jamAreas": { + "entry": "DB_JamArea4104.stJam4104_1", + "finger": "DB_JamArea4103.stJam4103_1" + }, + "outputs": { + "stopper": "MB3025", + "varioMotor": "MA0145" + }, + "hmi": "DB_Interface_HMI.stTRO.TRO115" +} +``` + +#### TRO 1Sep_SSCC — SSCC-Scanner + WCS-Telegramm + +```json +{ + "id": "TRO105", + "type": "1Sep_SSCC", + "fbType": "FB_ILS_MTRO_1Sep_SSCC", + "mainTroNo": "cMainTro105", + "controlUnit": "OF1", + "comment": "SSCC Scanner Boom 1", + "separator": { + "no": "cSep105.1", + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#600ms", + "handlingTime": "T#200ms", + "jamTime": "TimeForSepJam", + "senFree": "T#1500ms", + "senWait": "T#4000ms", + "plugged": { "jam": true, "part": false, "scanner": true }, + "sensorInSep": "cInBG3280" + }, + "sensorJam2": "cInBG3281", + "scanner": { + "id": "cScannerBX1104", + "prefix": "bx1104", + "hwResults": "BX1104~Ergebnisse_-_64_Bytes_1", + "checkASCII": true, + "timeout": "T#3000ms" + }, + "ssccScanner": { + "prefix": "bx1107", + "hwResults": "BX1107~Ergebnisse_-_64_Bytes_1", + "checkASCII": true, + "timeout": "T#3s", + "sensorEndMeasurement": "cInBG3281" + }, + "priority": { "releaseOk": true }, + "call": { + "carouselRun": "true", + "release": "FB_CommunicationWCSBL_DB.fbTeleHandler.xOutConnectionActive OR IBN.xFahrenOhneTcpPartner" + }, + "jamAreas": { + "entry": "DB_JamArea0104.stJam0104_3", + "exit": "DB_JamArea0106.stJam0106_2" + }, + "outputs": { "stopper1": "MB3280" }, + "hmi": "DB_Interface_HMI.stTRO.TRO105", + "correction": { + "station": 0, + "carrierExpect": "DB_JamArea0104.stJam0104_3.arCarrier[1]" + }, + "wcsTelegram": { + "type": "DReqM", + "decisionPoint": "cDP_DOCK_01", + "dockDoor": "1", + "ssccReq": true, + "lengthReq": false, + "dockDoorReq": true + } +} +``` + +### 5. Loading Booms + +```json +"loadingBooms": [ + { + "id": "LoadingBoom1", + "instanceName": "fbLoadingBoom1", + "controlUnit": "OF1", + "comment": "Ladeschleife 1", + "relatedTro": "TRO104", + "controls": { + "btnReleaseMT1": "SF0305", + "switchLoadingPos2": "SF0306", + "btnBack": null, + "btnForth": null, + "btnReleaseMT2": "SF0332", + "switchFootUp": null, + "switchFootDown": null, + "switchLightOnOff": "SF0041", + "btnBoomActive": "SF0044", + "btnReset": ["SF0043", "SF0002", "IBN.xQuit"], + "switchFootManual": "SF0025" + }, + "boom": { + "motorProtection": ["FC0070", "FC0072"], + "limitForth": "cInBG3343", + "limitForthEmergency": "SF0051", + "limitBack": "cInBG3344", + "limitBackEmergency": "SF0050", + "bumperOk": true + }, + "foot": { + "motorProtection": "FC0321", + "limitUp": "SF0322", + "limitDown": "SF0323" + }, + "timings": { + "boomInput": "T#5s", + "wheelInput": "T#5s", + "senWaitStopper1": "T#100ms", + "waitAfterReleaseStopper1": "T#1200ms", + "waitBeforeSwitchStopper2": "T#4000ms", + "trailingStopper2": "T#150ms" + }, + "tilt": { + "analogInput": "wTiltSensorLS1", + "hmiBasePath": "DB_Interface_HMI.stLoadingBoom.stDataBoom1" + }, + "distance": { + "analogInput": "wDistanceSensorLS1", + "startSlow": 2510, + "startFast": 2520, + "hmiBasePath": "DB_Interface_HMI.stLoadingBoom.stDataBoom1" + }, + "callSensors": { + "sen2mThreshold": "cInBG0287", + "senJamEntr": "cInBG0286", + "senJamExit1": "cInBG0285", + "senJamExit2": "cInBG3276", + "senStopper1": "cInBG0282", + "senStopper2": "cInBG0283" + }, + "jamAreas": { + "stopper": "DB_JamArea0104.stJam0104_2", + "exit": "DB_JamArea0104.stJam0104_3" + }, + "outputs": { + "light": "QA0012", + "boomActive": "PF0044", + "ledMovement": "PF0287", + "stopper1Clamp": "MB0282", + "stopper1Finger": "MB0284", + "stopper2": "MB0283", + "boomForth1": "QA0071", + "boomForth2": "QA0073", + "boomBack1": "MA0070", + "boomBack2": "MA0072", + "footUp": "DQ0322", + "footDown": "DQ0323", + "footSpeed1": "DQ0324" + }, + "hmi": "DB_Interface_HMI.stLoadingBoom.stDataBoom1" + } +] +``` + +### 6. Empty Carrier Buffers (mehrzeiliger Puffer) + +```json +"emptyCarrBuffers": [ + { + "id": "TRO101", + "instanceName": "TRO101", + "mainTroNo": "cMainTro101", + "controlUnit": "OF1", + "comment": "Empty Buffer rechts", + "numberOfLines": 5, + "storageDb": "DB_JamBuffer101", + "inTro": { + "id": "TRO101_IN", + "separator": { + "no": 999, + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#100ms", + "handlingTime": "T#50ms", + "jamTime": "TimeForSepJam", + "sensorInSep": "cInBG3246" + }, + "isBorner": true, + "bornerDest": "cDestInboundLS", + "carouselRun": "fbCarousel0101.xOutConveyorFullSpeed", + "jamEntry": "DB_JamArea0101.stJam0101_1", + "stopper": "MB3246", + "hmi": "DB_Interface_HMI.stTRO.TRO101_In" + }, + "separatorLines": [ + { "line": 1, "jamLength": 5, "sensor": "cInBG3320", "handlingTime": "T#200ms", "trailingTime": "T#500ms", "senFree": "T#1500ms", "senWait": "T#3000ms" }, + { "line": 2, "jamLength": 7, "sensor": "cInBG3321", "handlingTime": "T#200ms", "trailingTime": "T#500ms", "senFree": "T#1500ms", "senWait": "T#3000ms" }, + { "line": 3, "jamLength": 10, "sensor": "cInBG3322", "handlingTime": "T#200ms", "trailingTime": "T#500ms", "senFree": "T#1500ms", "senWait": "T#3000ms" }, + { "line": 4, "jamLength": 10, "sensor": "cInBG3323", "handlingTime": "T#200ms", "trailingTime": "T#500ms", "senFree": "T#1500ms", "senWait": "T#3000ms" }, + { "line": 5, "jamLength": 10, "sensor": "cInBG3324", "handlingTime": "T#200ms", "trailingTime": "T#500ms", "senFree": "T#1500ms", "senWait": "T#3000ms" } + ], + "jamSensors": ["cInBG3250", "cInBG3251", "cInBG3252", "cInBG3253", "cInBG3254"], + "switchLineOutputs": ["MB3250", "MB3251", "MB3252", "MB3253", "MB3254"], + "separatorStoreOutputs": ["MB3320", "MB3321", "MB3322", "MB3323", "MB3324"], + "exitJam": "DB_JamArea0102.stJam0102_2", + "exitSensor": "cInBG3330", + "priority": { + "managerIn": "DB_Prozessdaten.stPriorityManager.udt_TRO101.TroIn", + "managerOut": "DB_Prozessdaten.stPriorityManager.udt_TRO101.TroOut" + }, + "hmi": "DB_Interface_HMI.stTRO.TRO101" + } +] +``` + +### 7. Routing / FC_Direction (erzeugt CASE-Statement) + +```json +"routing": { + "switches": [ + { + "switchNo": "cSwi107.1", + "comment": "Switch 107.1 Boom 1", + "rules": [ + { "destination": "cDestInboundLS", "direction": 1, "comment": "LINKS - zu Ladeschleife" }, + { "destinations": ["cDestClearing", "cDestInboundOut", "cDestInboundLS_Extra"], "direction": 2, "comment": "RECHTS - Clearing/Inbound verlassen" } + ], + "default": 2 + }, + { + "switchNo": "cSwi112.1", + "comment": "Switch 112.1 Boom 2", + "rules": [ + { "destinations": ["cDestInboundLS", "cDestInboundLS_Extra"], "direction": 1, "comment": "LINKS - zu Ladeschleife" }, + { "destinations": ["cDestClearing", "cDestInboundOut"], "direction": 2, "comment": "RECHTS - Clearing/Inbound verlassen" } + ], + "default": 2 + }, + { + "switchNo": "cSwi114.1", + "comment": "Switch 114.1", + "rules": [ + { "destination": "cDestInboundOut", "direction": 1, "comment": "LINKS - Inbound verlassen" }, + { "destination": "cDestClearing", "direction": 2, "comment": "RECHTS - Clearing-Station" } + ], + "default": 0 + }, + { + "switchNo": "cSwi124.1", + "comment": "Switch 124.1", + "rules": [ + { "destination": "cDestHighwayStorage", "direction": 1, "comment": "LINKS - zum Storage" }, + { "destination": 0, "direction": 2, "comment": "RECHTS - zum Inbound (Standard)" } + ], + "default": 2 + } + ] +} +``` + +### 8. Jam Areas + +```json +"jamAreas": [ + { + "id": "JamArea0100", + "db": "DB_JamArea0100", + "slots": [ + { "name": "stJam0100_1", "capacity": 5 } + ] + }, + { + "id": "JamArea0101", + "db": "DB_JamArea0101", + "slots": [ + { "name": "stJam0101_1", "capacity": 5 }, + { "name": "stJam0101_2", "capacity": 5 } + ] + }, + { + "id": "JamArea0102", + "db": "DB_JamArea0102", + "slots": [ + { "name": "stJam0102_1", "capacity": 5 }, + { "name": "stJam0102_2", "capacity": 5 }, + { "name": "stJam0102_3", "capacity": 5 }, + { "name": "stJam0102_4", "capacity": 5 }, + { "name": "stJam0102_5", "capacity": 5 }, + { "name": "stJam0102_6", "capacity": 5 } + ] + } +] +``` + +### 9. Scanners (Cognex Barcode-Reader) + +```json +"scanners": [ + { + "id": "BX1100", + "constant": "cScannerBX1100", + "prefix": "bx1100", + "hwResults": "BX1100~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO117" + }, + { + "id": "BX1101", + "constant": "cScannerBX1101", + "prefix": "bx1101", + "hwResults": "BX1101~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO113" + }, + { + "id": "BX1103", + "constant": "cScannerBX1103", + "prefix": "bx1103", + "hwResults": "BX1103~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO104" + }, + { + "id": "BX1104", + "constant": "cScannerBX1104", + "prefix": "bx1104", + "hwResults": "BX1104~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO105" + }, + { + "id": "BX1105", + "constant": "cScannerBX1105", + "prefix": "bx1105", + "hwResults": "BX1105~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO109" + }, + { + "id": "BX1106", + "constant": "cScannerBX1106", + "prefix": "bx1106", + "hwResults": "BX1106~Ergebnisse_-_64_Bytes_1", + "usedByTro": "TRO110" + }, + { + "id": "BX1107", + "constant": "cScannerBX1107", + "prefix": "bx1107", + "hwResults": "BX1107~Ergebnisse_-_64_Bytes_1", + "comment": "SSCC Scanner Boom 1", + "usedByTro": "TRO105" + }, + { + "id": "BX1108", + "constant": "cScannerBX1108", + "prefix": "bx1108", + "hwResults": "BX1108~Ergebnisse_-_64_Bytes_1", + "comment": "SSCC Scanner Boom 2", + "usedByTro": "TRO110" + } +] +``` + +### 10. Sonderlogik — Hybrid-Ansatz (customCode fuer seltene Einzelfaelle) + +Haeufige Muster werden als eigene JSON-Felder modelliert (scanner, ssccScanner, wcsTelegram, brushConfig, correction). Seltene Einzelfaelle werden als `customCode`-Bloecke eingebettet: + +```json +{ + "id": "TRO117", + "type": "1Sep", + "fbType": "FB_ILS_MTRO_1Sep", + "mainTroNo": "cMainTro117", + "controlUnit": "OF1", + "comment": "Clearing Station", + "separator": { + "no": "cSep117.1", + "delayToNextItem": "TimeForSepWaiting_Short", + "trailingTime": "T#100ms", + "handlingTime": "T#50ms", + "jamTime": "TimeForSepJam", + "plugged": { "jam": true, "part": true, "scanner": true }, + "sensorInSep": "cInBG3300" + }, + "sensorJam2": "cInBG3304", + "scanner": { + "id": "cScannerBX1100", + "prefix": "bx1100", + "hwResults": "BX1100~Ergebnisse_-_64_Bytes_1", + "checkASCII": true, + "timeout": "T#5s" + }, + "correction": { + "station": 0, + "carrierExpect": "DB_JamArea0102.stJam0102_6.arCarrier[1]" + }, + "customCode": { + "beforeCall": [ + "#rTrig_ClarificationButton(CLK := \"SF0032\");" + ], + "releaseExpression": "#rTrig_ClarificationButton.Q", + "afterCall": [ + "// Clearing-Station: Trolley loeschen", + "IF NOT \"DB_Inputs\".Sensors[\"cInBG3300\"].xDirectSensor AND \"DB_Interface_HMI\".stClearingStation.xDeleteTrolley THEN", + " \"DB_JamArea0102\".stJam0102_6.arCarrier[1] := #stEmptyCarrier;", + " \"DB_Interface_HMI\".stClearingStation.xDeleteTrolley := FALSE;", + " #TRO117.nState := 100;", + "END_IF;", + "", + "// Clearing-Station: Ladung loeschen", + "IF NOT \"BG3301\" AND \"DB_Interface_HMI\".stClearingStation.xDeleteLoad THEN", + " \"DB_JamArea0102\".stJam0102_6.arCarrier[1].bStatus.%X1 := FALSE;", + " \"DB_Interface_HMI\".stClearingStation.xDeleteLoad := FALSE;", + "END_IF;", + "", + "// HMI-Anzeige aktualisieren", + "\"DB_Interface_HMI\".stClearingStation.stFirstCarrierInStation := \"DB_JamArea0102\".stJam0102_6.arCarrier[1];", + "\"DB_Interface_HMI\".stClearingStation.xTrolleyInStation := \"DB_Inputs\".Sensors[\"cInBG3300\"].xDbncdSensor;" + ] + } +} +``` + +--- + +### 11. Connections — Physische Topologie (TRO-Verkettung) + +Jede Verbindung beschreibt den Pfad: Quell-TRO + Exit-Slot → JamArea → Ziel-TRO + Entry-Slot. +Switch-Ausgaenge haben nummerierte Exit-Slots (`exit2`, `exit3`); normale TROs haben nur `exit`. + +```json +"connections": [ + { "from": "TRO100", "exitSlot": "exit", "jamArea": "DB_JamArea0101.stJam0101_1", "to": "TRO101_IN", "entrySlot": "entry", "comment": "Eingang → Entry Buffer" }, + { "from": "TRO100", "exitSlot": "exit", "jamArea": "DB_JamArea0101.stJam0101_1", "to": "TRO101", "entrySlot": "entry", "comment": "Parallel: direkt in EmptyBuffer" }, + { "from": "TRO101", "exitSlot": "exit", "jamArea": "DB_JamArea0102.stJam0102_2", "to": "TRO107", "entrySlot": "entry", "comment": "EmptyBuffer → Switch Boom1" }, + { "from": "TRO102", "exitSlot": "exit", "jamArea": "DB_JamArea0102.stJam0102_1", "to": "TRO107", "entrySlot": "entry" }, + { "from": "TRO107", "exitSlot": "exit2", "jamArea": "DB_JamArea0103.stJam0103_1", "to": "TRO103", "entrySlot": "entry", "direction": 1, "comment": "Dir1=LS1" }, + { "from": "TRO107", "exitSlot": "exit3", "jamArea": "DB_JamArea0102.stJam0102_2", "to": "TRO112", "entrySlot": "entry", "direction": 2, "comment": "Dir2=weiter" }, + { "from": "TRO103", "exitSlot": "exit", "jamArea": "DB_JamArea0104.stJam0104_1", "to": "TRO104", "entrySlot": "entry" }, + { "from": "TRO104", "exitSlot": "exit", "jamArea": "DB_JamArea0104.stJam0104_2", "to": "LoadingBoom1", "entrySlot": "stopper" }, + { "from": "TRO106", "exitSlot": "exit", "jamArea": "DB_JamArea0102.stJam0102_2", "to": "TRO112", "entrySlot": "entry", "comment": "LS1 Rueckleitung" }, + { "from": "TRO112", "exitSlot": "exit2", "jamArea": "DB_JamArea0107.stJam0107_1", "to": "TRO108", "entrySlot": "entry", "direction": 1, "comment": "Dir1=LS2" }, + { "from": "TRO112", "exitSlot": "exit3", "jamArea": "DB_JamArea0102.stJam0102_3", "to": "TRO113", "entrySlot": "entry", "direction": 2, "comment": "Dir2=Clearing" }, + { "from": "TRO111", "exitSlot": "exit", "jamArea": "DB_JamArea0102.stJam0102_3", "to": "TRO113", "entrySlot": "entry", "comment": "LS2 Rueckleitung" }, + { "from": "TRO113", "exitSlot": "exit", "jamArea": "DB_JamArea0102.stJam0102_4", "to": "TRO114", "entrySlot": "entry" }, + { "from": "TRO114", "exitSlot": "exit2", "jamArea": "DB_JamArea4104.stJam4104_1", "to": null, "entrySlot": null, "direction": 1, "comment": "Dir1=InboundOut→WCS" }, + { "from": "TRO114", "exitSlot": "exit3", "jamArea": "DB_JamArea0102.stJam0102_5", "to": "TRO116", "entrySlot": "entry", "direction": 2, "comment": "Dir2=Clearing" } +] +``` + +**Mehrwert `connections`**: + +- Topologie-Validierung: Generator prueft ob jede in `tros[].jamAreas` genannte JamArea auch in `connections` erscheint +- Topologie-Diagramme: Aus `connections` wird automatisch ein Mermaid-Flowchart erzeugt +- Cross-Config-Vergleich: `connections` von UH01 vs UH04 direkt vergleichbar + +--- + +### 12. Destinations — Abstrakte Routing-Tabelle + +Beschreibt pro Carrier-Ziel: welche Switches wie geschaltet werden, den vollstaendigen TRO-Pfad und die Endaktion. +Ermoeglicht automatische Generierung von `FC_Direction` ohne manuelles Pflegen von `routing.switches`. + +```json +"destinations": [ + { + "id": "cDestInboundLS", + "constant": 100, + "description": "Carrier in Ladeschleife beladen (Loading Station 1 oder 2)", + "routes": [ + { + "id": "route_LS1", + "description": "Weg zur Loading Station 1 (Boom 1)", + "switchDecisions": [ + { "tro": "TRO107", "switch": "cSwi107.1", "direction": 1 }, + { "tro": "TRO112", "switch": "cSwi112.1", "direction": 2 } + ], + "path": ["TRO107", "TRO103", "TRO104", "LoadingBoom1", "TRO105", "TRO106"], + "terminal": { "type": "loadingBoom", "element": "LoadingBoom1" } + }, + { + "id": "route_LS2", + "description": "Weg zur Loading Station 2 (Boom 2)", + "switchDecisions": [ + { "tro": "TRO107", "switch": "cSwi107.1", "direction": 2 }, + { "tro": "TRO112", "switch": "cSwi112.1", "direction": 1 } + ], + "path": ["TRO107", "TRO112", "TRO108", "TRO109", "LoadingBoom2", "TRO110", "TRO111"], + "terminal": { "type": "loadingBoom", "element": "LoadingBoom2" } + } + ], + "wcsTelegram": { "type": "DReqM", "decisionPoints": ["cDP_DOCK_01", "cDP_DOCK_02"] } + }, + { + "id": "cDestClearing", + "constant": 200, + "description": "Carrier zur Clearing-/Error-Station", + "routes": [ + { + "id": "route_clearing", + "switchDecisions": [ + { "tro": "TRO107", "switch": "cSwi107.1", "direction": 2 }, + { "tro": "TRO112", "switch": "cSwi112.1", "direction": 2 }, + { "tro": "TRO114", "switch": "cSwi114.1", "direction": 2 } + ], + "path": ["TRO107", "TRO112", "TRO113", "TRO114", "TRO116", "TRO117"], + "terminal": { "type": "clearingStation", "element": "TRO117" } + } + ] + }, + { + "id": "cDestInboundOut", + "constant": 300, + "description": "Carrier verlaesst das Inbound-System", + "routes": [ + { + "id": "route_exit", + "switchDecisions": [ + { "tro": "TRO114", "switch": "cSwi114.1", "direction": 1 } + ], + "path": ["TRO113", "TRO114"], + "terminal": { "type": "wcsTelegram", "action": "cSTRAIGHT", "decisionPoint": "cDP_INBOUND_OUT" } + } + ] + }, + { + "id": "cDestHighwayStorage", + "constant": 400, + "description": "Carrier faehrt zum Storage ueber Highway", + "routes": [ + { + "id": "route_storage", + "switchDecisions": [ + { "tro": "TRO124", "switch": "cSwi124.1", "direction": 1 } + ], + "path": ["TRO113", "TRO114", "TRO120", "TRO121", "TRO122", "TRO123", "TRO124"], + "terminal": { "type": "wcsTelegram", "action": "cSTORAGE", "decisionPoint": "cDP_HIGHWAY" } + } + ] + } +] +``` + +**Auswirkung auf bestehende Abschnitte**: + +| Abschnitt | Auswirkung | +|---|---| +| `routing.switches[].rules` | Kann aus `destinations[].routes[].switchDecisions` abgeleitet werden (Single Source of Truth) | +| `tros[].jamAreas` | Bleibt explizit fuer Debugging; Generator validiert Konsistenz gegen `connections[]` | +| `FC_Direction` (generiert) | Wird kuenftig aus `destinations` statt aus `routing.switches` generiert | + +**Mehrwert `destinations`**: + +- `FC_Direction` auto-generieren: Switch-Regeln kommen direkt aus `switchDecisions` +- Dokumentation: vollstaendiger Carrier-Pfad pro Ziel als Planungsgrundlage +- Simulation: Carrier-Fluss kann ohne SPS per Graph-Traversal simuliert werden + +--- + +## Welche SCL-Bausteine werden daraus generiert? + +| Ziel-Baustein | Generiert aus JSON-Abschnitt | +|---|---| +| `FB_Main` VAR-Deklaration | `conveyors[]`, `tros[]`, `loadingBooms[]`, `emptyCarrBuffers[]` | +| `FB_Main` REGION Conveyor | `conveyors[]` — Settings + Call-Pattern je Subtype | +| `FB_Main` REGION TRO | `tros[]` — Separator-Settings + Call je fbType | +| `FB_Main` REGION LoadingBoom | `loadingBooms[]` — Controls/Boom/Foot/Call/Outputs | +| `FB_Main` REGION EmptyCarrBuffer | `emptyCarrBuffers[]` — Lines/Jams/Call | +| `FB_Main` REGION Reinitialisieren | alle `tros[].mainTroNo` + `emptyCarrBuffers[].mainTroNo` | +| `FB_CallSensors` | `sensors[]` — repetitiver Call-Block pro Sensor | +| `FC_Direction` | `routing.switches[]` — CASE-Statement | +| `FC_Call_Jams` | `jamAreas[]` — Jam-Aufrufe | +| `FC_CARR_GLOB_CORRECTION` | TROs mit `correction`-Feld | +| Konstanten-Tabelle | Alle `constant`-Felder — TIA-Konstantenliste | + +--- + +## Vorteile + +1. **Single Source of Truth**: Aenderung an einem Ort (JSON) statt in 5 verschiedenen 3000-9000 Zeilen SCL-Dateien +2. **Fehlerreduktion**: Kein Copy-Paste mehr zwischen UH01-UH05 +3. **Review**: Topologie-Aenderungen sind als JSON-Diff lesbar +4. **Neues Projekt**: Nur neue JSON-Datei anlegen, Code wird generiert +5. **Validierung**: JSON-Schema kann Pflichtfelder, gueltige Typen etc. pruefen + +--- + +## Sonderlogik-Behandlung (Hybrid-Ansatz) + +| Muster | Haeufigkeit | Behandlung | +|---|---|---| +| Scanner + Correction | 5x pro UH | Eigene JSON-Felder (`scanner`, `correction`) | +| SSCC-Scanner + WCS-Telegramm | 2x pro UH | Eigene JSON-Felder (`ssccScanner`, `wcsTelegram`) | +| Buersten-Taktlogik | 4x in UH01 | Eigenes JSON-Feld (`brushConfig`) | +| Priority Manager | ~10x pro UH | Eigenes JSON-Feld (`priority`) | +| Clearing-Station (Delete-Buttons) | 1x in UH01 | `customCode.afterCall` | +| Laengenmessung DReqM | 1x in UH01/UH05 | `customCode.afterCall` | + +--- + +## Offene Designentscheidungen + +1. **Ausdruck-Sprache**: Felder wie `release` enthalten SCL-Ausdruecke (`#fbLoadingBoom1.xOutReady AND ...`). Diese werden als Strings durchgereicht. + +2. **Generator**: Falls gewuenscht, Python + Jinja2-Templates als `bin/generate_scl.py` im Repository. + +3. **JamArea-Kapazitaeten**: Koennten vollstaendig in die JSON aufgenommen werden, um auch die JamArea-DBs zu generieren. + +4. **Topologie-Verbindungen**: Die JSON beschreibt aktuell jedes Element isoliert. Optional koennte ein `connections`-Abschnitt die Verkettung (TRO100 -> JamArea0101 -> TRO101_IN -> Buffer -> TRO101 -> JamArea0102 -> ...) explizit machen. \ No newline at end of file diff --git a/SCL_Analyse_Standardisierung.md b/doc/SCL_Analyse_Standardisierung.md similarity index 100% rename from SCL_Analyse_Standardisierung.md rename to doc/SCL_Analyse_Standardisierung.md