A programozás nyelvtana, nyelvfüggetlenül — és a három POU-típus, amelynek összekeverése a leggyakoribb kezdő hiba.
- 10.1 Változó, deklaráció, hatókör
- 10.2 Elemi adattípusok — röviden
- 10.3 Mi marad meg újraindításkor? —
RETAINésPERSISTENT - 10.4 Globális és lokális változók
- 10.5 A POU fogalma
- 10.6
FUNCTION— állapotmentes, visszatérési értékkel - 10.7
FUNCTION_BLOCK— példányosítható, saját állapottal - 10.8
PROGRAM— állapotos, de példány nélküli - 10.9 A három típus egymás mellett
- 10.10 A legfontosabb kezdő buktató
- 10.11 Akciók, metódusok, öröklés — áttekintés
- 10.12 A task és a POU-k hívási lánca
- Összefoglalás
- Gyakorlatok
- Ellenőrző kérdések
- Tudáspróba
- A fejezet forrásai
Ez a fejezet nyelvfüggetlen. Mindegy, hogy strukturált szövegben vagy létradiagramban dolgozol: a változók, a hatókör és a POU-típusok ugyanazok.
A fejezet magja a 10.6–10.10. alfejezet: a három POU-típus pontos szétválasztása. Ez az a különbség, amit a kezdők a leggyakrabban elrontanak — és amely a 17. és 18. fejezet minden gyakorlatában visszaköszön.
10.1 Változó, deklaráció, hatókör
Minden változót deklarálni kell, mielőtt használnád: meg kell mondani a nevét és a típusát. A deklaráció egy kulcsszópárba kerül, és a kulcsszó dönti el a változó hatókörét: ki látja, ki írhatja, meddig él.
VAR blokk tartalma kívülről nem írható, a VAR_IN_OUT viszont a hívó változóját változtatja meg.A leggyakrabban használt kulcsszavak:7 3 4
| Kulcsszó | Mit jelent? |
|---|---|
VAR |
„a POU összes lokális változója … ezeknek nincs külső kapcsolatuk, más szóval kívülről nem írhatók”7 |
VAR_INPUT |
„a POU bemeneti változóiként szolgáló változók”7 |
VAR_OUTPUT |
„a POU kimeneti változói. Ezek az értékek tehát visszakerülnek a hívó POU-hoz.”7 |
VAR_IN_OUT |
„bemeneti és kimeneti változók”; az átadott változó „értéke megváltozik (mutatóként adódik át, call-by-reference)”7 |
VAR_GLOBAL |
„az egész projektben ismert” változók7 |
És a ritkábban használtak, áttekintésül:7
| Kulcsszó | Mit jelent? |
|---|---|
VAR_TEMP |
„minden POU-híváskor újrainicializálódik”; csak programban és funkcióblokkban használható |
VAR_STAT |
funkcióblokkban, metódusban és függvényben használható; „az első híváskor inicializálódik” |
VAR_EXTERNAL |
„a POU-ba importált globális változók” |
VAR_INST |
példányváltozó: „nem a metódus veremén, hanem a funkcióblokk-példány veremén tárolódik” |
A VAR_INPUT egy másolatot ad át: ha a POU átírja, a hívó változója nem változik. A
VAR_IN_OUT viszont mutatóként adja át — a POU a hívó saját változóját módosítja.
Ez hatékony, de veszélyes: ha egy funkcióblokk mellékhatásként átír egy változót, azt a hibakeresésnél nagyon nehéz megtalálni. Használd, ha tudod, mit csinálsz.
A fenti kulcsszóleírások egy CODESYS-alapú, de más gyártótól származó környezet
dokumentációjából valók, mert a CODESYS saját összefoglaló lapja nem volt elérhető. A
VAR_INPUT és a VAR_OUTPUT jelentését a CODESYS saját súgója is megerősíti.3 4
A ritkább kulcsszavak viselkedését érdemes a saját CODESYS-verziódban ellenőrizni.
10.2 Elemi adattípusok — röviden
Az elemi adattípusokat, a bitszélességüket és az értékkészletüket a 4. fejezet tárgyalta részletesen. Itt csak a legfontosabb emlékeztető:
| Csoport | Típusok |
|---|---|
| Logikai | BOOL |
| Bitmintázat | BYTE, WORD, DWORD, LWORD |
| Előjeles egész | SINT, INT, DINT, LINT |
| Előjel nélküli egész | USINT, UINT, UDINT, ULINT |
| Lebegőpontos | REAL, LREAL |
| Idő és dátum | TIME, LTIME, DATE, TIME_OF_DAY, DATE_AND_TIME |
| Karakterlánc | STRING, WSTRING |
A kezdők hajlamosak mindenre DINT-et vagy REAL-t használni, „hogy biztos beleférjen”. Ez
két bajt okoz: fölösleges memóriafoglalást, és — a REAL esetében — kerekítési hibákat ott,
ahol egész számokkal pontosan lehetne dolgozni (4. fejezet, 0.1 + 0.2 ≠ 0.3).
A jó szabály: a legszűkebb típus, amelybe a feladat összes lehetséges értéke belefér.
Kezdőérték és konstans
Deklarációkor kezdőérték is adható:
VAR iDarab : INT := 0; rHatarertek : REAL := 12.5; sNev : STRING := 'szalag1'; END_VAR VAR CONSTANT MAX_DARAB : INT := 500; END_VAR
A CONSTANT módosítóval jelölt változó értéke futás közben nem módosítható. Használd
minden olyan értékhez, amely a programban „varázsszámként” jelenne meg: a 500 önmagában
semmit nem mond, a MAX_DARAB mindent.
10.3 Mi marad meg újraindításkor? — RETAIN és PERSISTENT
Ez a fejezet egyik legfontosabb — és a gyakorlatban legtöbb bosszúságot okozó — része.
Alapesetben minden változó újrainicializálódik, amikor a vezérlő újraindul. Ha egy értéknek túl kell élnie az újraindítást (például egy darabszámláló vagy egy üzemóra-számláló), akkor remanens változóra van szükség.
A deklaráció szintaxisa:8
VAR RETAIN iDarabszam : DINT; END_VAR
VAR_GLOBAL RETAIN gDarabszam : DINT; END_VAR
A PERSISTENT ugyanígy írható (VAR PERSISTENT, VAR_GLOBAL PERSISTENT), illetve külön,
a perzisztenciaszerkesztővel kezelt listában.8
Mi mit él túl? A CODESYS súgójának élettartam-táblázata — és ugyanezt a táblázatot egy másik, szintén CODESYS-alapú környezet dokumentációja is szó szerint megadja:6 8
PERSISTENT még az új letöltést is túléli.| Művelet | VAR |
VAR RETAIN |
VAR PERSISTENT |
|---|---|---|---|
| Online Change | megmarad | megmarad | megmarad |
| Reset Warm (meleg indítás) | törlődik | megmarad | megmarad |
| Reset Cold (hideg indítás) | törlődik | törlődik | megmarad |
| Download (új letöltés) | törlődik | törlődik | megmarad |
| Reset Origin (gyári visszaállítás) | törlődik | törlődik | törlődik |
Emlékszel a CC100 üzemmódkapcsolójára a 7. fejezetből? A meleg indítás (2–7 másodperc) a retain változókat megtartja, a hideg indítás (7 másodpercnél hosszabb) viszont azokat is visszaállítja.
Ez pontosan a fenti táblázat két sora. A WAGO hardveres kapcsolóállása és a CODESYS online parancsa ugyanazt a két szintet valósítja meg — nem véletlenül, hanem mert a szabvány ugyanezt a fogalompárt írja elő.
A gyártói dokumentáció szó szerint figyelmeztet:8
„Ha nincs megfelelő memóriatartomány, a
VAR RETAINvagyVAR PERSISTENTváltozók értékei elvesznek áramkimaradás esetén!”
A megmaradáshoz a vezérlőn „megfelelő memóriatartomány (NVRAM, UPS)” kell. Vagyis a
RETAIN kulcsszó kérés, nem garancia: a hardvernek is támogatnia kell.
Hogy a saját eszközöd mit tud, azt a gyártói adatlapból kell ellenőrizni — a könyv erre nem ad ígéretet. Ha egy értéknek biztosan túl kell élnie az áramkimaradást, mérd meg: írj bele egy értéket, húzd ki a tápot, dugd vissza, nézd meg.
10.4 Globális és lokális változók
Lokális (VAR) |
Globális (VAR_GLOBAL) |
|
|---|---|---|
| Hol él? | egy POU-ban | az egész projektben |
| Ki éri el? | csak az adott POU | bárki |
| Hol deklarálod? | a POU deklarációs részében | globális változólistában (GVL) |
| Előny | átlátható, biztonságos | egyszerű megosztás |
| Kockázat | – | bárki átírhatja, és nehéz megtalálni, ki tette |
Egy globális változót a projekt bármely pontjáról lehet írni. Ha egy érték „magától” megváltozik, és nem érted, miért, a válasz szinte mindig ugyanaz: valahol máshol is írja valaki.
Gyakorlati szabály: a globális változókat használd állapotmegosztásra (üzemmód, riasztási állapot, közös alapjelek), de ne dolgozzon rajtuk több POU is íróként. Egy írjon, a többi olvasson.
10.5 A POU fogalma
„A POU típusú objektum egy »programming organization unit« a CODESYS-projektben. A vezérlő programjának forráskódját POU-kban írjuk.”2
Háromféle POU van: PROGRAM, FUNCTION és FUNCTION_BLOCK.2 A következő négy alfejezet ezeket járja végig — és ha ezt megérted, a könyv többi része sokkal könnyebb lesz.
10.6 FUNCTION — állapotmentes, visszatérési értékkel
A gyártói megfogalmazás egyértelmű:3
„A függvényeknek nincs belső állapotinformációjuk, ami azt jelenti, hogy a függvények nem mentik el a változóik értékét a következő hívásig.”
Ebből minden más következik:3
- pontosan egy adatelemet ad vissza (ez lehet tömb vagy struktúra is), és a kimeneti változó maga a függvény neve;
- a deklaráció alakja:
FUNCTION <név> : <adattípus>; - nem használhat globális változókat és címeket — épp az állapotmentesség miatt.
FUNCTION Atlag : REAL VAR_INPUT r1 : REAL; r2 : REAL; r3 : REAL; END_VAR Atlag := (r1 + r2 + r3) / 3.0;
Hívása:
rEredmeny := Atlag(20.0, 22.0, 24.0);
„CODESYS V3-ban nem keverhető az explicit és az implicit paraméterátadás egyetlen függvényhívásban.”3
Vagyis vagy sorrend szerint adod meg az összes paramétert:
rEredmeny := Atlag(20.0, 22.0, 24.0);
vagy név szerint az összeset:
fun(in1 := 1, in2 := 2, out1 => loc1, out2 => loc2);
A kettő keverése fordítási hiba.
Amikor a feladat matematikai: adott bemenetekből számol egy eredményt, és nincs szüksége semmilyen emlékre. Skálázás, mértékegység-átváltás, határérték-ellenőrzés, átlagolás.
Egy jó teszt: ha kétszer meghívod ugyanazokkal a bemenetekkel, ugyanazt kell kapnod. Ha nem, akkor nem függvény kell.
10.7 FUNCTION_BLOCK — példányosítható, saját állapottal
A funkcióblokk a másik véglet:4
„Mindig példányon keresztül hívja a funkcióblokkot, amely a funkcióblokk másolata.”
„A kimeneti változók és a belső változók értéke a végrehajtás után a következő végrehajtásig változatlan marad.”
A példány deklarálása: <példánynév> : <funkcióblokk>;4
PROGRAM Prog VAR inst1 : FB1; END_VAR inst1.iVar1 := 33; inst1(); ires := inst1.out1;
Amit kívülről elérhetsz:4
„A funkcióblokk-példányon kívülről csak a be- és kimeneti változók érhetők el, a belső változók nem.”
Ez nem korlátozás, hanem védelem: a blokk belső működése a blokk dolga. Ez az, amit programozásban egységbezárásnak neveznek.
Amikor a feladatnak emlékeznie kell valamire: időzítés, számlálás, élfigyelés, szabályozás, állapotgép. És különösen akkor, ha több példányban is szükség lehet rá.
A könyvben eddig használt TON, CTU, R_TRIG, SR — mind funkcióblokk, és mind ezért az.
10.8 PROGRAM — állapotos, de példány nélküli
A harmadik típus a legkülönösebb. Van állapota — de nincs példánya.5
„Minden érték változatlan marad a program végrehajtása után a következő végrehajtásig.”
„A programoknak nincsenek példányai.”
És a kulcsmondat, amely az egészet megmagyarázza:5
„Ha egy POU meghív egy programot, és ennek hatására a program értékei megváltoznak, akkor ezek a változások megmaradnak a következő programhívásig. A program értékei akkor is megmaradnak, ha a következő hívást egy másik POU végzi. Ez különbözik a funkcióblokk hívásától: a funkcióblokk hívásakor csak az adott példány értékei változnak.”
A programok hívási sorrendjét a task-objektumok határozzák meg.5
10.9 A három típus egymás mellett
| FUNCTION | FUNCTION_BLOCK | PROGRAM | |
|---|---|---|---|
| Állapot a hívások között | nincs3 | van4 | van5 |
| Példányosítás | nincs | kötelező4 | nincs példánya5 |
| Visszatérési érték | pontosan egy (a függvény neve)3 | nincs; kimeneti változókon át | nincs; kimeneti változókon át |
| Globális változó, cím | nem használható3 | használható | használható |
| Kívülről elérhető | a visszatérési érték | csak VAR_INPUT / VAR_OUTPUT4 |
a változói (pl. PLC_PRG.out2)5 |
| Több „másolat” egyszerre | – | igen, külön állapottal | nem: egyetlen, közös állapot |
| Objektumorientált elemek | – | EXTENDS, IMPLEMENTS2 |
– |
1. Kell-e emlékeznie? Ha nem: FUNCTION.
2. Ha igen: kell-e belőle több, egymástól független? Ha igen: FUNCTION_BLOCK.
Ha csak egy van belőle, és a taskok hívják: PROGRAM.
10.10 A legfontosabb kezdő buktató
Ez az a hiba, amit szinte mindenki elkövet egyszer.
Tegyük fel, hogy két késleltetésre van szükséged: a lámpa 2 másodperc múlva gyulladjon ki, a motor 10 másodperc múlva induljon el.
Helyesen:
VAR tonLampa : TON; tonMotor : TON; END_VAR tonLampa(IN := bIndit, PT := T#2S); tonMotor(IN := bIndit, PT := T#10S); bLampa := tonLampa.Q; bMotor := tonMotor.Q;
Hibásan — egyetlen példányt használva két helyen:
VAR ton1 : TON; END_VAR ton1(IN := bIndit, PT := T#2S); bLampa := ton1.Q; ton1(IN := bIndit, PT := T#10S); (* felülírja az előzőt! *) bMotor := ton1.Q;
A második hívás ugyanazon a példányon dolgozik: felülírja a PT-t, és ugyanazt az eltelt
időt használja. Az eredmény: egyik késleltetés sem működik helyesen.
Az állapot nem a funkcióblokkban lakik, hanem a példányban. Ahány független működésre van szükséged, annyi példányt kell deklarálnod.
És figyeld meg a különbséget a programmal szemben: egy PROGRAM esetében minden hívó
ugyanazon az állapoton dolgozik.5 Ott nincs mód „két példányra” — ha két független
működés kell, funkcióblokkot kell választanod.
10.11 Akciók, metódusok, öröklés — áttekintés
A POU-khoz további programozási objektumok is rendelhetők: „metódus, akció és egyebek”.2
| Elem | Mire jó? |
|---|---|
| Akció (action) | a POU-hoz tartozó, külön nevesített kódrészlet, amely ugyanazokon a változókon dolgozik |
| Metódus (method) | objektumorientált hívható egység, saját paraméterekkel |
EXTENDS |
öröklés: egy funkcióblokk átveszi egy másik tulajdonságait2 |
IMPLEMENTS |
interfész megvalósítása; ilyenkor a metódusok automatikusan generálódnak2 |
Az EXTENDS és az IMPLEMENTS csak funkcióblokknál áll rendelkezésre — a függvénynél és a
programnál nem.2
Nem feltétlenül. A szakképesítés az alapszintű programozást kéri. Ezt az alfejezetet azért érdemes elolvasni, hogy felismerd a fogalmakat, ha meglátod őket egy meglévő projektben — és hogy tudd: az IEC 61131-3 harmadik kiadása óta a szabvány objektumorientált elemeket is tartalmaz.
10.12 A task és a POU-k hívási lánca
Ki hívja meg az első POU-t? A task.
„A task az IEC-programod időbeli végrehajtási egysége. A task definiálja a POU-k hívási láncát (hívási hierarchiáját).”1
Ez zárja be a kört a 8. fejezettel: ott állítottad be a task típusát és intervallumát, itt derül ki, mit is indít el vele. A lánc jellemzően így néz ki:
Task (pl. MainTask, ciklikus, t#20ms)
└─ PLC_PRG (PROGRAM)
├─ Szallitoszalag() (FUNCTION_BLOCK példány)
├─ Adagolo() (FUNCTION_BLOCK példány)
└─ rSkalazott := Skalaz(...) (FUNCTION)A következő fejezet — a lineáris és strukturált programfelépítés — pontosan erről a láncról szól: mikor éri meg felbontani a programot, és hogyan.
Összefoglalás
- A deklarációs kulcsszó dönti el a hatókört.
VAR= lokális, kívülről nem írható;VAR_INPUT/VAR_OUTPUT= a POU be- és kimenetei;VAR_GLOBAL= az egész projektben ismert. - A
VAR_IN_OUTmutatóként adja át a változót: a POU a hívó saját változóját módosítja. - A
CONSTANTmódosítóval jelölt érték futás közben nem módosítható — használd varázsszámok helyett. - Remanencia: a
RETAINtúléli a meleg indítást, aPERSISTENTa hideg indítást és az új letöltést is. Mindkettőt törli a gyári visszaállítás. - A
RETAINkulcsszó nem garancia: megfelelő memóriatartomány (NVRAM, UPS) nélkül az értékek áramkimaradáskor elvesznek. - POU = a program szervezési egysége. Három típusa van.
FUNCTION: nincs állapota, egy visszatérési értéke van, globális változót nem használhat.FUNCTION_BLOCK: példányosítható, minden példánynak saját állapota van; kívülről csak a be- és kimeneti változói érhetők el.PROGRAM: van állapota, de nincs példánya — minden hívó ugyanazon dolgozik.- A leggyakoribb kezdő hiba: egy példány két helyen. Ahány független működés kell, annyi példány.
- A task definiálja a POU-k hívási láncát.
Gyakorlatok
Egy adagolóberendezés programjához a következő adatokra van szükség. Döntsd el mindegyikről, milyen deklarációs kulcsszóval és milyen típussal vennéd fel, és indokold: (a) a szalag pillanatnyi sebessége, amit csak a szabályozó POU használ; (b) az üzemmód (kézi/automata), amit három POU is olvas; (c) egy skálázó függvény bemeneti nyersértéke; (d) az összes legyártott darab száma a gép élettartama alatt; (e) a megengedett legnagyobb hőmérséklet, ami sosem változik.
Melyik POU-típust választanád? Indokold egy-egy mondattal. (a) 4–20 mA-es jel átváltása mérnöki egységre; (b) egy szállítószalag teljes vezérlési logikája, amelyből három egyforma van a gépsoron; (c) a fő program, amelyet a ciklikus task hív; (d) két szám közül a nagyobb visszaadása; (e) egy adagolószelep állapotgépe.
Az alábbi kódrészlet két különböző jelet akar késleltetni. Mi a hiba, és hogyan javítanád?
VAR tmr : TON; END_VAR tmr(IN := bJel1, PT := T#3S); bKeslelt1 := tmr.Q; tmr(IN := bJel2, PT := T#5S); bKeslelt2 := tmr.Q;
Deklarálj egy VAR RETAIN és egy VAR PERSISTENT számlálót. Töltsd le a programot, futtasd,
hogy legyen bennük érték, majd végezd el sorban: meleg indítás, hideg indítás, majd egy
új letöltés. Minden lépés után jegyezd fel mindkét változó értékét, és hasonlítsd össze a
10.2. ábra táblázatával.
Végül húzd ki a vezérlő tápját, és dugd vissza. Mit tapasztalsz? Mit mond ez a készülék memóriájáról?
Írj egy FUNCTION-t, amely egy 0–27 648 tartományú nyersértéket 0–100 %-ra skáláz. Utána írj
egy FUNCTION_BLOCK-ot, amely ugyanezt csinálja, de emlékszik az eddigi legnagyobb mért
értékre is. Fogalmazd meg egy mondatban, miért nem lehetett volna a másodikat függvénnyel
megoldani.
Ellenőrző kérdések
- Mi a különbség a
VARés aVAR_GLOBALközött? - Miben más a
VAR_IN_OUT, mint aVAR_INPUT? Mi ennek a veszélye? - Mikor inicializálódik újra a
VAR_TEMP, és mikor aVAR_STAT? - Mire való a
CONSTANTmódosító? - Melyik remanens változó éli túl a hideg indítást, és melyik nem?
- Mit törölhet mindkét remanens változófajtából?
- Miért nem elég önmagában a
RETAINkulcsszó az áramkimaradás túléléséhez? - Mi a POU, és mi a három típusa?
- Miért nem használhat egy
FUNCTIONglobális változót? - Mit jelent az, hogy a funkcióblokkot példányon keresztül hívjuk?
- Mely változói érhetők el kívülről egy funkcióblokk-példánynak?
- Miben más a
PROGRAMaFUNCTION_BLOCK-tól az állapot szempontjából? - Hány
TON-példány kell három független késleltetéshez? Miért? - Mi definiálja a POU-k hívási láncát?
Tudáspróba
Válaszd ki az egyetlen helyes választ!
1. A VAR … END_VAR blokkban deklarált változó:
a) lokális, kívülről nem írható;
b) az egész projektben látható;
c) minden ciklusban újrainicializálódik;
d) csak függvényekben használható.
2. A VAR_IN_OUT paraméter átadása:
a) másolattal történik;
b) mutatóval (call-by-reference) történik;
c) csak konstansokra működik;
d) nem megengedett funkcióblokkban.
3. A VAR_TEMP változó:
a) az első híváskor inicializálódik;
b) sosem inicializálódik;
c) minden POU-híváskor újrainicializálódik;
d) csak függvényben használható.
4. Melyik változófajta éli túl az új letöltést?
a) VAR
b) VAR RETAIN
c) egyik sem
d) VAR PERSISTENT
5. A meleg indítás (Reset Warm) után:
a) a RETAIN és a PERSISTENT megmarad;
b) minden változó törlődik;
c) csak a PERSISTENT marad meg;
d) semmi nem változik.
6. A FUNCTION:
a) példányosítható;
b) nincs belső állapota, és nem használhat globális változót;
c) több visszatérési értéke lehet;
d) csak ST nyelven írható.
7. A funkcióblokk-példányon kívülről elérhető: a) minden változója; b) csak a belső változói; c) csak a bemeneti és kimeneti változói; d) semmi.
8. A PROGRAM:
a) példányosítható, mint a funkcióblokk;
b) nem hívható taskból;
c) nincs állapota;
d) van állapota, de nincs példánya.
9. Három független késleltetéshez szükséges TON-példányok száma:
a) 3
b) 2
c) 1
d) attól függ, milyen hosszúak
10. Az EXTENDS és az IMPLEMENTS kulcsszó:
a) minden POU-típusnál használható;
b) csak funkcióblokknál;
c) csak függvénynél;
d) csak programnál.
A megoldókulcs a B függelékben található.
A fejezet forrásai
-
CODESYS Online Help: Task Configuration. CODESYS GmbH. (2026-07-29) A task definiálja a POU-k hívási láncát. ↩
-
CODESYS Online Help: Object: POU (V3.5.22.0). CODESYS GmbH. (2026-07-29) ↩↩↩↩↩↩↩
-
CODESYS Online Help: Object: Function (V3.5.22.0). CODESYS GmbH. (2026-07-29) ↩↩↩↩↩↩↩↩
-
CODESYS Online Help: Object: Function Block (V3.5.22.0). CODESYS GmbH. (2026-07-29) ↩↩↩↩↩↩↩↩
-
CODESYS Online Help: Object: Program (V3.5.22.0). CODESYS GmbH. (2026-07-29) ↩↩↩↩↩↩↩
-
CODESYS Online Help: Data Persistence (V3.5.22.0). CODESYS GmbH. (2026-07-31) A RETAIN/PERSISTENT élettartam-táblázat. ↩
-
EcoStruxure Machine Expert V2.1: Variable Types. Schneider Electric. (2026-07-31) CODESYS-alapú környezet dokumentációja; a CODESYS saját összefoglaló lapja nem volt elérhető. ↩↩↩↩↩↩↩
-
Automation Builder 2.2: Remanent Variables – RETAIN, PERSISTENT. ABB. (2026-07-31) A CODESYS élettartam-táblázatának második, független megerősítése, valamint az áramkimaradásra vonatkozó figyelmeztetés forrása. ↩↩↩↩