Doku und erster Vorschlag aus dem Fortna Extrakt dazu

This commit is contained in:
2026-07-21 11:59:14 +02:00
parent c7c50190cb
commit e901857869
8 changed files with 2751 additions and 1 deletions
+235
View File
@@ -0,0 +1,235 @@
# Vorschlag: Vereinheitlichung der MainTRO-Bausteine (`FB_ILS_MTRO`)
Stand: 2026-07-13
## Ausgangslage
Die Anlage verwendet derzeit **sieben verschiedene MainTRO-Bausteine**, die aus dem
SPS-Code extrahiert wurden:
| Typ | Separatoren | Weichen | Eingänge | Ausgänge (Richtungen) | Prio-Manager | Scanner | Besonderheit |
|---|---|---|---|---|---|---|---|
| `FB_ILS_MTRO_1Sep` | 1 | 0 | 1 | 1 (Exit2) | 1 | 1 | Borner/Dummy-Handling |
| `FB_ILS_MTRO_1Sep_SSCC` | 1 | 0 | 1 | 1 | 1 | 2 (+SSCC) | Endmess-Sensor |
| `FB_ILS_MTRO_1Sep1Swi` | 1 | 1 | 1 | 2 (Exit2/3) | 2 (Dir1/2) | 1 | 2. Kreisel |
| `FB_ILS_MTRO_1Sep2Swi` | 1 | 2 | 1 | 3 (Exit2/3/4) | 1 | 1 | 2. Kreisel |
| `FB_ILS_MTRO_2Sep1Swi` | 2 | 1 | 2 | 2 | 4 (Dir1-4) | 2 | 2 Eingänge, 2 Kreisel |
| `FB_ILS_MTRO_Vario` | 1 | 0 (Vario) | 1 | 1 (+Finger-Jam) | 1 | 1 | Kettenförderer, Finger-/Pos-Sensoren, Motorschutz |
| `FB_ILS_MTRO_PinStore_Auto` | 1 + 21 | n | 1 | n Stationen | 1 | 1 | **Ausreißer** — Lagerblock, Encoder, Lagerlinien |
## Kernerkenntnis
Alle MainTRO-Varianten basieren auf **demselben Grundgerüst**: ein `FB_StateManager`
mit identischer Schrittkette
(`WaitForTrolley → Scan → CheckLoad → CheckSep → GetDirection → CheckJam → CheckSwitch → ReleaseSep → Buchen`),
plus zusammengesetzte Sub-TRO-Bausteine (`FB_ILS_STRO_Sep`, `FB_ILS_STRO_Switch`,
`FB_ILS_STRO_Vario`, `FB_BarcodeReaderCognex`).
Was sich zwischen den Typen unterscheidet, ist fast ausschließlich die **Anzahl**
einiger Sub-Module und die entsprechende Zahl an Staubereichen/Richtungen. Das
Namensschema `<nSep>Sep<nSwi>Swi` bringt es auf den Punkt: Es sind keine 7 Verhaltensweisen,
sondern **ein Verhalten**, instanziiert mit 12 Separatoren, 02 Weichen, 14 Richtungen.
Der skalare Teil der Schnittstelle ist **überall identisch**: `stInSettings` (Borner,
Jam-Src/Dest, `bSepType`, Timings), `nInMainTroNo`, `xInSftyOk`, `xInAllRdyToStart`,
`xInTestMode`, `xInCancel`, `xInAreaStopActive`, `xInRelease`, dazu die Ausgänge
`xOutCorrection / nOutStateLast / nOutScanResult / xOutNewScan` und die In-Outs
`stInOutMachineState / stInOutCognexInterface / stInOutHMI`. Lediglich die
*wiederholten* Elemente werden von Hand vervielfältigt und durchnummeriert
(`...1`, `...2`, `Dir1..Dir4`, `Exit2..Exit4`).
## Vorschlag: ein einziger Baustein `FB_ILS_MTRO`
Die von Hand nummerierten Member werden durch **Arrays von zusammengesetzten UDTs**
ersetzt, plus einen **Konfigurations-/Routing-Deskriptor**, der angibt, wie viele
Elemente jeder Art existieren und wie jede Richtung verdrahtet ist. Der skalare Kern
bleibt unverändert.
### 1. Vereinheitlichte TRO-Typdefinition (ersetzt die 7 `fbType`-Namen)
```json
{
"$def": "FB_ILS_MTRO",
"description": "Single MainTRO block, shaped by config instead of by type name",
"config": {
"nNoOfSeparators": { "type": "USInt", "range": [1, 2] },
"nNoOfSwitches": { "type": "USInt", "range": [0, 2] },
"nNoOfCarousels": { "type": "USInt", "range": [1, 2] },
"nNoOfDirections": { "type": "USInt", "range": [1, 4] },
"xScannerPlugged": { "type": "Bool" },
"xSsccPlugged": { "type": "Bool" },
"xVarioMode": { "type": "Bool" }
},
"arrays": {
"arInSeparator": "Array[1..2] of UDT_MTRO_SeparatorIf",
"arInSwitch": "Array[1..2] of UDT_MTRO_SwitchIf",
"arInDirection": "Array[1..4] of UDT_MTRO_DirectionIf",
"arInPriorityManager": "Array[1..4] of UDT_Response",
"arInCarouselRun": "Array[1..2] of Bool",
"arInOutJamEntr": "Array[1..2] of UDT_JamArea",
"arInOutJamExit": "Array[1..4] of UDT_JamArea"
},
"scalarCore": [
"stInSettings", "nInMainTroNo", "xInSftyOk", "xInAllRdyToStart",
"xInTestMode", "xInCancel", "xInAreaStopActive", "xInRelease",
"stInOutMachineState", "stInOutHMI"
]
}
```
### 2. Die zusammengesetzten UDTs, die als Array geführt werden
```json
{
"UDT_MTRO_SeparatorIf": {
"stSenInSep": "UDT_Sensor", "stSenSepLeft": "UDT_Sensor",
"stSenPart": "UDT_Sensor", "stSenStartScan": "UDT_Sensor",
"stSenJamExit": "UDT_Sensor",
"Settings": "SettingsSeparator",
"bSepType": "Byte", "xIsBorner": "Bool", "nBornerDest": "Int"
},
"UDT_MTRO_SwitchIf": {
"stSenExit3": "UDT_Sensor", "stSenExit4": "UDT_Sensor",
"Settings": "SettingsSwitch"
},
"UDT_MTRO_DirectionIf": {
"xPrioRelevant": "Bool",
"nSepIndex": "USInt", "nSwitchIndex": "USInt", "nSwitchPos": "USInt"
},
"UDT_JamArea": {
"arCarrier": "Array[*] of stCarrier", "stData": "stJamData"
}
}
```
### 3. Per-Instanz-Konfiguration, die jeden alten Typ reproduziert (die "Anreicherung")
```json
{
"instances": [
{
"name": "TRO101", "replaces": "FB_ILS_MTRO_1Sep",
"config": { "nNoOfSeparators": 1, "nNoOfSwitches": 0,
"nNoOfCarousels": 1, "nNoOfDirections": 1,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": false },
"direction": [ { "nSepIndex": 1, "nSwitchIndex": 0, "nSwitchPos": 0, "xPrioRelevant": false } ]
},
{
"name": "TRO102", "replaces": "FB_ILS_MTRO_1Sep_SSCC",
"config": { "nNoOfSeparators": 1, "nNoOfSwitches": 0,
"nNoOfCarousels": 1, "nNoOfDirections": 1,
"xScannerPlugged": true, "xSsccPlugged": true, "xVarioMode": false }
},
{
"name": "TRO103", "replaces": "FB_ILS_MTRO_1Sep1Swi",
"config": { "nNoOfSeparators": 1, "nNoOfSwitches": 1,
"nNoOfCarousels": 2, "nNoOfDirections": 2,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": false },
"direction": [
{ "nSepIndex": 1, "nSwitchIndex": 1, "nSwitchPos": 3, "xPrioRelevant": true },
{ "nSepIndex": 1, "nSwitchIndex": 1, "nSwitchPos": 4, "xPrioRelevant": true }
]
},
{
"name": "TRO104", "replaces": "FB_ILS_MTRO_1Sep2Swi",
"config": { "nNoOfSeparators": 1, "nNoOfSwitches": 2,
"nNoOfCarousels": 2, "nNoOfDirections": 3,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": false }
},
{
"name": "TRO105", "replaces": "FB_ILS_MTRO_2Sep1Swi",
"config": { "nNoOfSeparators": 2, "nNoOfSwitches": 1,
"nNoOfCarousels": 2, "nNoOfDirections": 4,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": false }
},
{
"name": "TRO106", "replaces": "FB_ILS_MTRO_Vario",
"config": { "nNoOfSeparators": 1, "nNoOfSwitches": 0,
"nNoOfCarousels": 1, "nNoOfDirections": 1,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": true }
}
]
}
```
### 4. Einbindung in die bestehende `units[]`-Skeleton-Struktur
Heute schreibt `create_skel.py` einen `fbType`-String pro Einheit. Im Vorschlag wird
dieses eine Feld zu `fbType: "FB_ILS_MTRO"` plus ein `config`-Objekt, das der Generator
aus den gezählten Rollen füllt:
```json
{
"unit": "M0101",
"fbType": "FB_ILS_MTRO",
"config": {
"nNoOfSeparators": 1, "nNoOfSwitches": 1,
"nNoOfCarousels": 2, "nNoOfDirections": 2,
"xScannerPlugged": true, "xSsccPlugged": false, "xVarioMode": false
},
"io": {
"sensorInSep": ["BG0101"],
"switchOutput": ["MB0102"],
"stopperOutput": ["MB0101"],
"sensorJam": ["BG0103"]
}
}
```
`guess_fbtype()` (liefert heute einen der 7 Namen, siehe `lib/create_skel.py:558-563`)
würde stattdessen `"FB_ILS_MTRO"` zurückgeben plus einen zählenden Regelsatz:
```json
{
"configRules": {
"nNoOfSeparators": "count(roles == 'sensorInSep')",
"nNoOfSwitches": "count(roles == 'switchOutput')",
"nNoOfDirections": "count(roles == 'switchOutput') + 1",
"xScannerPlugged": "any(role == 'sensorStartScan')",
"xVarioMode": "has(roles, 'sensorFinger') or has(roles, 'sensorCarrInPos')"
}
}
```
## Abbildung der alten Typen auf den neuen Baustein (Übersicht)
| Alter Typ | Konfiguration, die ihn reproduziert |
|---|---|
| `1Sep` | Sep=1, Swi=0, Car=1, Dir=1 |
| `1Sep_SSCC` | Sep=1, Swi=0, Dir=1, `xSsccPlugged=TRUE` |
| `1Sep1Swi` | Sep=1, Swi=1, Car=2, Dir=2 |
| `1Sep2Swi` | Sep=1, Swi=2, Car=2, Dir=3 |
| `2Sep1Swi` | Sep=2, Swi=1, Car=2, Dir=4 |
| `Vario` | Sep=1, Swi=0, Dir=1, `xVarioMode=TRUE` |
Sieben Bausteine → **ein Baustein + ein Konfigurationsdatensatz pro Instanz**.
## Was separat bleibt
- **`FB_ILS_MTRO_PinStore_Auto`** ist ein echter Ausreißer — 21 Linien-Separatoren,
Encoder-Positionserfassung, Lagerlinien-Daten (`arInOutStorageLines`),
Auslager-Stationen. Es ist ein *Lager*-Controller, kein Routing-TRO. Die übrigen
sechs werden in `FB_ILS_MTRO` zusammengeführt; PinStore bleibt eigenständig
(oder wird zu `FB_ILS_STORE`).
- **Vario** ist ein Grenzfall: Es tauscht die Weiche gegen einen Kettenförderer mit
Finger-/Positionssensoren. Es passt als `xVarioMode` (ein Sub-Modul-Schalter), weil
es weiterhin denselben Separator + State-Manager nutzt. Falls die Finger-Schrittkette
zu stark abweicht, ist ein dünner Wrapper über den gemeinsamen Kern der Mode-Flag
vorzuziehen.
## Abwägung
- **Pro:** ein Baustein zum Testen/Versionieren/Dokumentieren; `create_skel.py` wird
deutlich einfacher (kein `FBTYPE_TEMPLATE`-Mapping, ein Aufruf-Template); das in der
Standardisierungsanalyse markierte "Versionschaos" entfällt.
- **Contra:** Arrays mit `nNoOf...`-Guards sind weniger selbsterklärend als ein
benannter `1Sep1Swi`; ungenutzte Array-Elemente kosten pro Instanz weiterhin
DB-Speicher. Multi-Instanz-Sub-FB-Arrays und `Array[*]`-In-Outs werden auf dem
Zielsystem (CPU 1518F) gut unterstützt — es gibt keinen Plattform-Blocker.
## Nächste Schritte (offen)
1. `FB_ILS_MTRO.scl`-Skelett prototypisieren (mit `FOR`-Schleifen-Aufrufen der Sub-TROs
und einer datengetriebenen Richtungs-Tabelle).
2. `create_skel.py` anpassen, sodass es den einzelnen Baustein mit `config`-Block
ausgibt statt der sieben Templates.