Az RLO bit és a parajelenségek


Lássuk be, hogy ha egy program nem pontosan úgy (vagy nagyon másképpen) működik mint ahogy azt gondoltuk és ahogy ismereteink szerint várnánk, akkor sokminden eszébe jut az embernek...

Lássunk egy gyakorlatból ellesett példát.
Az alábbi program részlet rendkívül egyszerű, és az ehhez hasonló sorok gyakoriak egy S7 programban.



Egy motor indítást látunk, a motort előre és hátra nyomógombokkal lehet előre és hátra indítani.
A gombokon kívül látunk benne egy keresztbe reteszelést, ami megakadályozza hogy a két irány egyszerre kapcsoljon be.
Az első két feltétel (M102.1 és M10.4) mindkét sorban azonos. A szimbólum információkból kiderül, hogy az M102.1 a motor nyomógombokkal törénő indítási feltételei szerint veszi fel a 0 vagy 1 állapotot, az M10.4 pedig egy kiválasztás, ami akkor aktív, ha a kezelő (pl. egy operátor panelen) a 4-es szalagot választotta ki (azt akarja indítani).
Ezzel ránézésre biztosan semmi baj, nem érhet meglepetés, működnie kell, ha:
Tegyük fel, hogy minden ciklusban lefut, és máshol nem írja a program ezt a két kimenetet mégis azt tapasztaljuk, hogy a Q4.0 kimenet annak ellenére sem kapcsol be (nem lesz TRUE állapotú) hogy az előtte lévő 4 feltétel teljesül:



További furcsaság az, ami akkor történik, amikor a Network 25-öt megduplázzuk:


Meglepő módon a második példány már jól működik! Bármennyi másolatot hozunk létre, az első nem jól működik, a többi igen.

Ha valaki először lát ilyet, valószínűleg az jut az eszébe, hogy ez nem lehet!
Ez a jelenség bármikor reprodukálható bármilyen S7-300/400 PLC-n. Ez nem hardver vagy szoftver hiba!
Ha tudjuk hogyan dolgozza fel az S7 a logikai műveleteket, látni fogjuk miért.

A dolog kulcsa az RLO és az FC jelzőbit.
Mint tudjuk az S7 PLC-ben minden STL-ben történik, akármiben is írtuk meg a programunkat. Az STL-ben (és így minden S7 programban) kulcsfontosságú szerepet játszik az RLO bit.
Magas szintű (STL-nél magasabb szintű) nyelvekben mégis ritkán futunk össze vele "személyesen". Jól megbújik a háttérben, teszi a dolgát.

De mi is az az RLO bit?
Result of Logik Operation, vagyis a logikai művelet eredménye.
Az S7-ben van egy Status Word-nek nevezett állapot szó, amely bitjei az alapműveletek szempontjából fontos két állapotú információt tartalmaznak. Pl. túlcsordulás (OV bit), vagy az összehasonlítás eredményével kapcsolatos információkat tartalmazó jelzőbitek (CC 0 és CC 1).
A status word bitjeit az egyes utasítások állítják (kapcsolják ki és be), tartalmukat egyes utasítások figyelembe veszik, mások nem. A "Statement List (STL) for
S7-300 and S7-400 Programming Reference Manual" c. kézikönyv (amit a Step7 feltelepít a gépünkre) és az online help is leírja minden utasítás magyarázatánál, hogy az adott utasítás melyik jelzőbit állapotát módosítja és melyik állapotát veszi figyelembe.

Példa:

X     az utasítás a művelet eredményétől függően módosítja a jelzőbit állapotát
-      az utasítás nem módosítja a jelzőbit állapotát
0     az utasítás törli a jelzőbit állapotát
1     az utasítás beállítja a jelzőbit állapotát

Az RLO a status word 1-es bitje és a logikai műveleteket végző utasítások végrehajtása után az utasítás logikai eredményét tárolja. Egy létradiagramban rajzolt, több feltételből álló sor esetén az RLO bit tartalmazza a végrehajtás során a logikai műveletek rész eredményét (amikor a CPU az adott sort dolgozza fel).

STL-ben a logikai műveleteket végző utasításoknak csak egy operandusa van, márpedig egy logikai művelethez legalább két adat kell. A művelet egyik operandusa mindig az RLO bit.
Nézzünk egy egyszerű, soros ÉS kapcsolatokból álló sort:



A fenti sor STL-ben az alábbi:


Az első utasítás (A M 1.2) betölti az RLO-ba az M1.2-es merker bit pillanatnyi állapotát, mivel az M1.2 a sor elején van (első feltétel, ami nem függ az előtte lévőtől).
A második utasítás (A I 8.4) logikai ÉS műveletet hajt végre az RLO bit pillanatnyi tartalma és az I8.4-es bemeneti bit állapota között. Az ÉS művelet eredményét pedig az RLO-ba teszi.
Így a következő utasítás előtt az RLO tartalma csak akkor TRUE, ha az M1.2 és az I 8.4 bitek is TRUE állapotúak voltak.
A következő utasítás (AN I 8.5) ÉS-NEM műveletet hajt végre az RLO bit pillanatnyi tartalma és az I8.5 bemeneti bit állapota között, és az eredményt az RLO-ba teszi, és így tovább végig az egész soron.

Ha a fenti feltételsort létradiagramban monitorozzuk működés közben, akkor zölden mutatja azokat a szimbólumokat amelyek aktívak (TRUE) és szaggatott vonallal kékkel rajzolja az inaktívakat (FALSE).
A szimbólumok közötti vonal pedig a szimbólum által képviselt művelet eredményét, vagyis az RLO bit állapotát mutatja szintén zölddel ha TRUE és szaggatott kékkel ha FALSE.


Jól példázza ezt gy a sorba beiktatott NOT utasítás, ami az RLO állapotát az ellenkezőjére változtatja (negálja):


Ha a sor bonyolultabb és nem csak ÉS kapcsolatokból áll, akkor zárójeles STL utasításokat használ a létradiagramban (vagy FBD-ben) készült logikai kapcsolatok leírására, hogy az RLO pillanatnyi értékét, mint rész eredményt megőrizze egy ún "nesting stack"-ben. Ez nem változtat a fentieken, a lényeg bonyolult sorok monitorozásakor is ugyan az.

Nem szabad azonban elsiklani a létradiagram egyes network-jeiben lévő első szimbólum fölött (a példában ez az M1.2).
Ha újra megnézzük egy létra sor STL kódját, azt látjuk, hogy egyszerűen A vagy AN utasítással indít, pont olyannal, mint amit a további feltételek feldolgozásánál használ. De az első utasításánál nincs előző logikai művelet amit figyelembe kellene venni!
Itt jön képbe az /FC jelzőbit, az RLO testvére.

FC = First Check vagyis első vizsgálat.
Ez annyit jelent, hogy az /FC bit állapota FALSE amikor a feldolgozás egy network (vagyis egy létra/fbd blokk) elejénél tart.
Ilyenkor az A utasítások nem végez ÉS műveletet az RLO pillanatnyi tartalmával, egyszerűen beleteszi az RLO-ba az operandusként megadott bit tartalmát (AN utasítás pedig annak fordítottját).
Az A, AN, O, ON, X, XN utasítások egyúttal be is kapcsolják az /FC bitet, ezért a következő ilyen utasítás már az RLO-val végzi el a műveletet.

De mi törli az /FC bitet?
Minden "kimenet" jellegű utasítás. Vagyis minden olyan utasítás, amelyik egy logikai feltételsor eredményét (tehát az RLO állapotát) használja fel operandusként.
Ilyen pl. egy kimenet "---( )" a Set ---(S), reset ---(R), de az olyan feltételes ugró utasítások is, amelyek ugrási feltétele az RLO vagy a BR bit állapota.
Hogy pontosan melyik utasítás  miképpen állítja az /FC bitet, az online helpben megtalálható.

De térjünk vissza az eredeti problémára:
A látszólag hibás működést szemléltető képen, ahol a motor irányváltás van, nem látható az a programrész ami a problémát okozza, csak a következményeket láthatjuk a képen.

Íme a teljes kódrészlet a mumussal együtt:



No de mi ezzel a baj?
Csak érték átadások vannak a Network 25-ben, amik sem az RLO bitet, sem az /FC bitet nem befolyásolják, így nem lehet hatásuk a rosszul működő Network 26-ra.
No és mi az a //     JC    L001 ott?
Egy ugró utasítás, ami a sor elején lévő // jelek miatt már megjegyzések, tehát még annyira sem lehetnek hatással a következő network-re mint a Load és Transfer sorok.
Hogyan kerül oda az a hatástalanított ugrás?
Aki szokott STL-ben fát vágni biztosan használja azt a módszert sorok, utasítások hatástalanítására, hogy // jelet rak elé. Előnye, hogy nem lesz befordítva a kódba mert megjegyzés, de mégis bármikor visszatehetjük az így kiiktatott utasításokat a kódba, egyszerűen csak törölni kell előle a két / jelet. Nem kell tehát teljesen törölni a kiiktatáshoz és emlékezni arra mi is volt ott, amikor vissza akarjuk írni.



Látszik, hogy csak az ugrást iktatta ki a programozó és az is látszik, hogy mielőtt ezt tette, az ugrás a töltögetéseket (érték adásokat) kerülte ki akkor, amikor az M102.6-os merker bit állapota TRUE volt. Nyilván azt akarta, hogy az M102.6 állapotától függetlenül az értékadások mindig lefussanak, kiiktatta hát a feltételes ugrást a sor elé írt //-el.

Hol a baj? Ott, hogy az A M 102.6-ot viszont benne hagyta a programban.
Ameddig az ugró utasítás élt, kellett oda, hisz az ugrás ettől függött. A JC ugró utasítás törli az /FC jelzőbitet, mert az RLO állapotát használja fel. Miután azonban az ugrást hatástalanították, már nem törölte az /FC bitet, az előtte lévő A utasítás viszont beállítja az /FC-t.
Így hát amikor a CPU hozzálátott a Network 26-ban lévő első utasítás, az A M102.1 végrehajtásához, az /FC bit TRUE volt, ami az A utasításnak azt jelenti, hogy ÉS műveletet hajtson végre az RLO és az M102.1 között. De ekkor az RLO-ban a törölt JC előtt hivatkozott M102.6 bit állapota volt.

A Network 26-ban tehát ezt láttuk:

De eszerint működött:


Hogyan tudjuk az ilyesmit elkerülni?
Elsősorban úgy, hogy ha a kódból törlünk (vagy megjegyzéssé alakítunk) részleteket, akkor ezt tegyük meg azokkal a kiegészítő utasításokkal is, amelyek a törölt részhez tartoznak. Még akkor is, ha elsőre úgy tűnik, hogy nem okozhat problémát ha benne marad...
A Network 25 utolsó sorában elhelyezett CLR utasítás is helyrebillenti a rakoncátlan sor működését, mivel a CLR az RLO biten kívül az /FC bitet is törli.

Alapvetően ilyen problémába nem ütközünk, ha nem használjuk keverve az STL és létra vagy FBD nyelveket egy blokkon belül.
Néha mégis kényelmes, vagy éppen valaki így írta meg egy gép programját valamikor és nekünk kell foglalkozni vele...




Szirty