235 lines
9.7 KiB
Markdown
235 lines
9.7 KiB
Markdown
# 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 1–2 Separatoren, 0–2 Weichen, 1–4 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. |