BitLOG

Utolsó módosítás: 2012. május 15
Tartalom
A BitLOG program
A BitLOG használata
A BitLOG működése

Sokat megélt PLC-s szakemberek bizonyára találkoztak már azzal, amikor egy PLC-s vezérlésben időszakosan felbukkanó hibajelenség keseríti meg az ember életét. Bosszantó tud lenni, sokszor nem könnyű kifigyelni mi is a baj oka.
Fokozottan igaz ez a gyorsan lezajló folyamatokra, ezeket nehéz nyomon követni. Hiába monitorozzuk napestig, igen nagy szerencse kell ahhoz, hogy pont jókor nézzünk jó helyre hogy elcsípjük az okot. Csak a saját következtetéseinkre támaszkodhatunk sejtéseink alapján módosítva a programot és várva előjön-e a hiba. Ha a hiba megint előjön, a sejtés bizonyára nem jött be, gondolkozhatunk tovább a következő gyanúig.
A hibakeresés tehát sokszor nem könnyű, de a PLC-s fejlesztői környezetek általában, így a Simatic manager ill. a Step7 is hatékonyan támogatja a hibakeresést (akik programoztak már mikrovezérlőt is és kerestek már a fentihez hasonló hibát benne, azok biztos tudják mire gondolok).
Sokat segítene egy olyan funkció, amivel előre szabadon meghatározható bitek időbeni változását lehetne megjeleníteni.
Pl. amilyen az Omron CX programmerben a Time chart funkció:



S7 PLC-hez hasznos lehet a PLC analyzer nevű szoftver, amit nem a Siemens fejleszt, hanem egy független cég. Nem használtam még, nem tudom pontosan mire képes, de a fenti funkciót ismeri amennyire tudom. A PLC Analyzer egyrészt fizetős kereskedelmi szoftver, másrészt megoszlanak a vélemények vele kapcsolatban. Van ahol ajánlják és nincs vele semmi gond, mások óvva intenek tőle.

A BitLOG program

Mivel abba a helyzetbe keveredtem, hogy elkerülhetetlenné vált hibakereséshez egy olyan szoftver eszköz használata, ami képes adott bitek időbeni változását rögzíteni, kifejlesztettem egy megoldást, amivel célt érhetek.
Keveset tud, kicsit körülményes, de ingyen van (olyan értelemben, hogy további költséget nem okoz, ha Step7 már van). Eleinte nem gondoltam arra, hogy közzé teszem, de mivel közben igen sokat tanultam, egy kis pofozgatás-szépítgetés után érdemesnek találtam írni róla. Talán másoknak is hasznos lehet még akkor is, ha konkrétan nem is akarnak biteket logozni...

A megoldás lényege az, hogy a PLC-ben futó programot a hibakeresés idejére ki kell egészíteni egy programblokkal és egy adatblokkal, ami a PLC-ben rögzíti az megadott bitek időbeni változását. A keletkező adathalmaz DB-ben hozzáférhető.
A szóbanforgó program blokk  max. 16 bit egyidejű lekérdezését tudja elvégezni tetszőleges gyakorisággal, akár minden PLC ciklusban is rögzíthet. Az adatrögzítést addig folytatja, amíg el nem éri az ezer beolvasást, vagy meg nem szűnik a start jel.
A megfigyelt bitek állapotait egy 16000 bitet tartalmazó adatblokkba (DB) írja. A bitek állapota mellett minden rögzítéskor tárolja a rögzítés kezdete óta eltelt időt is (ms-ban).

A BitLOG programblokknak van egy #SCycle paramétere, amiben szabályozhatjuk az adatrögzítés gyakoriságát. Ha blokk hívását nem kötjük feltételhez, akkor maga a blokk minden PLC ciklusban végrehajtásra kerül.
Ha nem szükséges a bitek állapotának tárolása ilyen sűrűn, akkor ennek a paraméternek 0-nál nagyobb értéket adva ritkíthatjuk a rögíztés gyakoriságát. A paraméterben megadott szám tulajdonképpen azt jelenti, hogy a blokk hívásakor hány hívást hagyjon ki adatrögzítés nélkül. Pl. 10-es értéket megadva minden tizedik hívás során fog egyszer adatot rögzíteni.

Ha az  #SCycle paraméter nulla, akkor olyan gyakorisággal rögzíti az adatokat, amilyen gyakorisággal lefut. Így a hibakeresés során a blokk hívását feltételhez is köthetjük. Pl. impulzus sorozathoz, vagy a berendezés folyamatait vezérlő valamilyen feltételhez, amit szükség esetén egy élvezérelt impulzus utasítással megtoldva akár rendszertelen időközönként is hívhatjuk. Rendszertelen időközönkénti hívás adatainak kiértékelését 16 bitenként rögzített állapot mellé beírt időbélyeggel támogatja.
A blokkot gyorsan lezajló folyamatok megfigyelésére írtam, az időbélyeg helytakarákosság miatt integer típusú. Ezért a leghosszabb rögzítési időtartam 32.768 másodperc. Ha a rögzítés eléri ezt az időhatárt, a blokk abbahagyja a rögzítést akkor is, ha még nem érte el az ezredik adatot és a start jel még aktív.

A BitLOG egy FB és a saját instance adatblokkjába rögzít.


Az FB előnye a saját adatblokk kezelésen kívül az, hogy nem kötelező minden bemenetét felhasználni. Ha nem 16 bitet, hanem kevesebbet akarunk rögzíteni. Nem kell a blokk kihagyott bemeneteivel foglalkozni, üresen hagyható.
Alább szó lesz a blokk működéséről is, most essen szó a keletkezett adatok kiértékeléséről. A dolog nem is olyan egyszerű, mert ha az adatokkal kitöltött DB-be nézünk bele, akkor csak elég nehezen áttekinthető hogy melyik bit mikor hogyan változott meg a rögzítés ideje alatt a többihez képest.
Az adatokat egy 1000 elemű tömb tárolja, aminek minden eleme egy UDT struktúra:



A BitLOG tehát minden lefutásakor a fenti adatokat írja a DB-be. A struktúra leírása egy UDT-ben van (UDT1), az instance DB pedig a 6-os címtől fenti struktúrából ezret tartalmaz (0-999) egy LOG nevű tömbben:



A rögzített adatok elrendezése tehát az alábbi lesz a tömbben adat nézetben (data view):



A fenti csak egy részlet, az összes adat 17000 sort foglal el a DB-ben.
Látható tehát, hogy ha nagyon akarjuk, ki tudjuk silabizálni mikor melyik megfigyelt bit hogyan változott, de gyanítom, hogy annyira nem akarjuk, mivel a kiértékelésnek ez a módja elég kényelmetlen.

Ezért egy áthidaló megoldáson gondolkoztam. Először HMI-vel akartam megjeleníteni az adatokat, de sok akadályba ütköztem. Túl sok az adat, a HMI még körülményesebbé tenné az adatokhoz való hozzáférést, mert nyilván egy ilyet nem volna értelme a berendezés HMI-jébe beleintegrálni ha egyáltalán van rajta, továbbá feltéve hogy az éppen WinCC Flexible és éppen PC runtime.
Ha külön HMI project végezné a megjelenítést, ami csak erre van fenntartva, az megoldás lenne, de minden alkalommal illeszteni kellene a PLC-hez a HMI projectet, hogy kommunikálni tudjon. Pl. mert egyszer etherneten kapcsolódunk, egyszer MPI buszon, máskor profibuszon, hisz valószínűleg nem csak egy, hanem több PLC-ben is keresnénk hibát vele. Nem is beszélve arról, hogy a rögzítésre használt DB száma is lehet más és más minden használatnál, mert az amit az előzőnél használtunk épp foglalt az adott PLC-ben. Sajnos nem sikerült olyan megoldást találni, amivel a megjelenítés kellően szemléletes és áttekinthető lenne HMI-n.

Táblázatkezelő használata mellett döntöttem. Konkrétan az OpenOffice Org 3.1 Calc táblázatkezelője mellett. Nem kell nagy dologra gondolni, az OO nem tud kommunikálni a PLC-vel és nem kérdezi le a DB tartalmat, egy sokkal prózaibb megoldással azonban az adatokat át lehet bele emelni: Copy-paste módszerrel :)
A táblázatkezelő jelentősége inkább az adatok áttekinthető megjelenítésében van

A hibakereséshez tehát a következő lépéseket kell tenni:
  1. A BitLOG FB és a hozzá tartozó UDT1, valamint a DB blokk elhelyezése a hibakeresés alanyául szolgáló rendszerben. Szükség esetén a blokkok átnevezésével
  2. A BitLOG bemeneteinek kitöltése a megfigyelni kívánt bit címekkel és a hívás biztosítása, a start trigger jel megadása a blokknak
  3. A BitLOG FB és a DB blokk áttöltése a vizsgált PLC-be, valamint a hívást tartalmazó blokk áttöltése
  4. El kell végeztetni a PLC-vel azt a folyamatot, amit meg szeretnénk figyelni (aktív start jel)
  5. A BitLOG DB-t online meg kell nyitni a LAD/FBD/STL editorral (Nem a DB Param programmal)
  6. Át kell váltani Data view módba
  7. Ki kell jelölni a DB-ben a 6.0-4005.7-es címig az összes sort
  8. Át kell másolni a vágólapra a kijelölt sorokat (Edit / Copy)
  9. Meg kell nyitni OpenOffice Calc programmal a mellékelt BitLOG.ods file-t
  10. A táblázat A3-as cellájának kijelölése után a vágólap tartalmát a táblázatba kell másolni (Szerkesztés / Beillesztés)
  11. A megjelenő "Szöveg importálása" ablakban be kell kapcsolni a tabulátor elválasztójel pipáját
Az eredmény egy olyan táblázat lesz, aminek minden sorában a rögzítés elejétől eltelt idő és az egyszerre rögzített 16 bit állapota jelenik meg (az FB ki nem töltött bemeneteinek helyén mindig 0 értéket tárol el).
A könnyebb áttekinthetőség érdekében az 1 (TRUE) tartalmú bit címek sötétkék háttérrel látszanak a táblázatban. Az egyes rögzítési időpontok időben előre közvetlenül egymás alatt vannak, így látható a bitek állapotának változása egymáshoz képest is. Nagyjából egy ilyen eredményt kapunk:


A táblázat mindig 1000 sort tartalmaz. Ha az adatrögzítés leállt mielőtt a táblát teleírta volna, akkor a be nem írt sorok idő oszlopában nullákat látunk, a rögzítés teljes időtartamát pedig az utolsó még nem nulla bejegyzés idő oszlopa tartalmazza.

A BitLOG használata

Töltsük le a BitLOG.zip file-t. A ZIP egy BitLOG nevű mappát tartalmaz. A mappát (ahogy a ZIP-ben van) bontsuk ki a Step7 LIB-ek közé.

Ez alapesetben a Step7 mappából nyíló S7LIBS mappában van. Ha máshova lett beállítva, a Simatic manager Options / Customize menüjéből nyíló ablak General fülénél megnézhetjük:



Ha jól csináltuk, ebből az S7LIBS-ből fog nyílni egy BitLOG nevű mappa és abban lesz a BitLOG programblokk, a DB és az UDT.

Nem állíthatom teljes biztonsággal, hogy a blokk hibátlan, ezért mindenki saját felelősségére használja! Hogy ne merülhessen fel gyanú, hogy a benne lévő kód szándékosan kártékony, és hogy mindenki szabadon módosíthassa ha akarja, a blokk nincs védve.
Nyissuk meg a Step7 projectet, amelyikben logolni szeretnénk. javaslom, hogy a kipróbálását szimulátoron vagy ne éles rendszeren végezzük.
Nyissuk meg a BitLOG library-t. Ehhez A Simatic managerben válasszuk a megszokott módon a File menü Open parancsát, de az Open project ablakban váltsunk át a Libraries fülre. Így egy olyan listát kapunk, ami a programkönyvtárakat tartalmazza. Ha először nyitjuk meg, akkor a BitLOG még nem lesz benne, ehhez használjuk a Browse funkciót és mutassuk meg neki azt a helyet ahova az imént kibontottuk.
Ekkor megnyílik a BitLOG nevű program könyvtár, ami tartalmaz egy FB104-es program blokkot, egy DB104-es adat blokkot, és egy UDT1-es adattípus definíciót.

Jelöljük ki mindhármat és helyezzük a vágólapra (Ctrl-C), váltsunk át a célproject blokk listájára, majd illesszük be (Ctrl-V).
Ha a célprojectben is van FB104, DB104 vagy UDT1, akkor szólni fog, hogy már létezik és megkérdezi felülírja-e. Semiképp ne mondjunk neki igent, mert az a mozdulat megsemmisítené azt a blokkot a célprojectben.
Helyette válasszuk a rename funkciót és adjunk neki olyan számot, ami még nincs a projectben.
Megjegyzés: A DB104 átmásolása nem feltétlenül szükséges, a programszerkesztő generálja amikor az FB104-et paraméterezzük.

Ha a három elemet sikeresen áthelyeztük, a library ablak be is zárható.
A következő lépés az FB104 BitLOG blokk meghívása. Rendszerint erre a legjobb hely az OB1 olyan része, ami minden ciklusban lefut (nem kerüli ki ugró utasítás vagy block end).
A megszokott módon feltétellel, vagy anélkül helyezzük el a blokk hívását:


Töltsük ki az INBit paramétereket azokkal a bit címekkel, amelyeket logolni szeretnénk. Töltsük ki a Start paraméter címét is, adjuk meg az FB-nek a DB számát, amit használni fog. Ha a lib-ből a DB-t nem másoltuk át, akkor adjunk meg egy olyan DB-t, ami még nem létezik, és a szerkesztő létrehozza.

Figyelem! Semmiképpen se adjuk meg máshova tartozó, már létező DB számát, mert a működő célprojectben adatokat írhat felül és a vezérelt berendezés megállását is okozhatja!

Töltsük át a PLC-be a DB-t és az FB104-et, majd az OB1-et, amibe a hívását beleírtuk.
Megjegyzés: az UDT-t nem kell és nem is lehet a PLC-be tölteni, de a jelenlétére szükség van a DB tartalmának a helyes megjelenítéséhez és a benne lévő adatok másolásához.
Futtassuk a programot, várjuk meg amíg rögzít (miután a start jel aktív lesz). Ha a DB-be belenézünk (monitorozzuk) látható lesz, hogy van-e benne rögzített adat:
Amelyik sorba rögzített, ott  a LOG[x].TMS változó Actual value oszlopában nullánál nagyobb érték van.

Nyissuk meg az OpenOffice Calc programmal a mellékelt BitLOG.ods file-t.

Amikor a rögzítés kész, Simatic managerben nyissuk meg az online ablakot (View / Online) keressük meg az FB104 DB blokkját és nyissuk meg az online ablakban.
Jönni fog egy kérdés:



Ha korábban valamikor ezen az ablakon kivettük a pipát az "Always display this message for Open Instance DB" szöveg elől, vagy korábbi Step7 verziót használunk, akkor nem kapunk ilyen üzenetet.

Fontos, hogy az online DB blokkot az LAD/STL/FBD szerkesztővel nyissuk meg és ne a DB Param szerkesztővel, mert az utóbbival nem tudjuk az adatokat a vágólapra helyezni.
Ha a fenti kérdés nélkül magától a DB Param nyitná meg a blokkot, akkor zárjuk be, indítsuk el a LAD/STL/FBD szerkesztőt (ha még nem fut) és használjuk annak File / Open menüjét. Az Open ablakban jelöljük be az Online módot és kattintsunk a DB-re:



Amikor a blokk megnyílt, váltsuk át a nézetet Data view módba a View menü Data view pontjának használatával.
Jelöljük ki a DB tartalmát a 6.0 címmel kezdődő sortól (ez az első kijelölt sor legyen) a 4005.7 címmel kezdődő sorig (ez legyen az utolsó kijelölt sor) és másoljuk a vágólapra (Ctrl-C, vagy Edit menü Copy).
Váltsunk át OpenOffice ablakra, jelöljük ki a táblázat A3-as celláját és a vágólap tartalmát másoljuk a táblázatba (Szerkesztés / Beillesztés):



Amikor végrehajtjuk a beillesztés (Ctrl-V) parancsot, megnyílik a "Szöveg importálása" ablak:



Itt helyezzünk el pipát a Tabulátor szöveg előtt, hogy a beillesztett DB tartalom tagolása megfelelő legyen, majd nyomjuk meg az Ok gombot.
Ha a beillesztés sikeres volt, akkor a beillesztett adatok mellett a K1 cella alatt azonnal megjelenik a beillesztett adat.
A BitLOG tábla mellett AE3-AE18 sorokban kitölthetjük, hogy a PLC programban mely biteket logoltuk. Ez beíródik a BitLOG tábla fejlécébe könnyítve ezzel az adatokon való kiigazodást.



A képeken látható táblázatban és a blokk hívását mutató képen az MB255-re beállított clock memory byte egyes bitjeinek változásai láthatók.
A clock memory byte-ról az "Impulzus sorozatok egyszerűen" c. írásban lehet olvasni.

A BitLOG működése

Nézzük meg a blokkot belülről.
Azt a feladatból már lehet sejteni, hogy az adatok rögzítése (DB-be írása) indeirekt címzéssel van megoldva. A viszonylag nagy adatmennyiség miatt ez a hatékony módszer.


Az első network előállít egy start impulzust az adatrögzítés elkezdése előtti műveletek elvégzéséhez. A NW2 nullázza az #index változót, ami az adatrögzítésre szolgáló területet címzi.
Nullázza #LTime változót, ami a kezdettől eltelt időt tartalmazza. A ciklus kihagyásokat számláló változóba (#CC-be) -1 értéket tölt. A -1 re azért van szükség, hogy a #Start felfutó élekor is történjen egy adatrögzítés. Végül az SFC21 (FILL) feltölti a rögzítési adatterületet nulláva, (#null változó tartalmával, ami nulla).



NW3-ban #InProg jelzőbitet bekapcsolja a rögzítés elején a start impulzussal. #InProg törlődik, ha az adatrögzítés feltétele #Start megszűnik (FALSE lesz). Továbbá törlődik, ha az eltelt időt tartalmazó #LTime értéke eléri a 32767 értéket. A második összehasonlítás gondoskodik arról, hogy ha az #LTime túlcsordul, az adatrögzítés akkor is véget érjen. A túlcsordulás akkor történik meg, amikor a BitLOG blokk nem minden PLC ciklusban fut le, hanem ritkábban. Az #InProg tehát addig TRUE értékű, amíg az adatrögzítés tart. Ezért az #InProg SR tároló kimenete egy SAVE utasítás, ami a blokk ENO kimenetét állítja be.
A Network 4 az SFC64-el kiolvassa a rendszer által futtatott ezredmásodperc számlálót. Ez a számláló ezredmásodpercenként egyel nő. A hívás TIME típusú értéket ad vissza, ami egy 4 byte-os szám. Fontos tulajdonsága, hogy hardveres számlálásról van szó, tehát a PLC bármit is csinál, ez a számláló mindenképpen nő ezredmásodpercenként egyel. A BitLOG ezt használja az eltelt idő mérésére. A kiolvasott érték #TCKTime változóba kerül.


Az 5-ös network  feladata az eltelt idő kiszámítása a dupla egész típusú #TCKTime változásából.
Először levágja a 32 bites szám felső 17 bitjét. A maradék alsó 15 bit így csak 0-32767 értéket vehet fel. Az eredményt eltárolja #NTime (integer) változóban, majd kivonja belőle a blokk futásának előző alkalmával eltárolt értéket.
A kettő különbsége az az idő, ami eltelt a két hívás között. Ezt hozzá lehetne adni #LTime-hoz, ami a rögzítési időt méri, de még van egy csavar. Mégpedig az, hogy a TIME_TCK által visszaadott ms számláló amikor túlcsordul, akkor a számlálást kezdi elölről. A felső bitek levágása miatt ez úgy jelentkezik, hogy az #NTime eléri a 32767-es értéket, majd 0 lesz és újra nőni kezd.
A probléma akkor van, amikor a ms számláló két hívás között csordul túl. Akkor a különbség számítás hibás, negatív eredményt ad.
Pl. ha az előző híváskor még 32765 volt, de a következőnél a túlcsordulás miatt már 4, akkor 4-ből fogja kivonni 32765-öt és az eredmény -32761 lesz, vagyis negatív. A probléma egyszerűen orvosolható: Ha a különbség negatív, az eredményhez hozzá kell adni 32767-et. A művelet után az eredményt (vagyis az előző hívás óta eltelt időt) hozzáadja #LTime-hoz, majd eltárolja #PTime-ban #NTime értékét, hogy a következő lefutásnál az előző futáskor olvasott, csonkított ms számláló értéke legyen benne.
Arról is gondoskodik, hogy a rögzítés kezdetekor egyenlővé tegye az előző ciklus óta eltelt idő számításához használt #PTime és #LTime változókat.


A 6-os network ügyel arra, hogy ha a blokknak negatív cikluskihagyás számot adunk meg (#SCycle bemeneti változó), akkor 0 értékkel dolgozzon.
A 7-es network végzi a kihagyások számlálását a #CC változóban. A ciklus kihagyás működése egyszerű. A #CC változót minden ciklusban egyel növeli. Ha az értéke eléri a kihagyások számát meghatározó #SCycle bemeneti paraméterben meghatározott számot, akkor nullázza.
A következő (8-as) networkben megvizsgálja a #CC tartalmát és csak akkor engedi az adatrögzítést lefutni, ha annak tartalma 0.  A 8-as networkben lévő másik kilépési feltétel az #InProg állapota. Ha a rögzítési művelet nem aktív, akkor mindenképpen kilép a blokkból.



A 9-es network a BitLOG program lényege. Ez címzi a DB-t és helyezi el benne az adatokat. A jobb érthetőség érdekében részletesebb magyarázatot kíván.
Az első rész megvizsgálja az #Index változót ami tulajdonképpeni tömb index. Ennek a változónak a tartalma az alapja annak a címnek, ami a DB megfelelő elemét címzi az adatok beírásához.
Ezért igen fontos, hogy az #Index ne legyen nagyobb mint amekkora a tömb (999).
Ha a #Index meghaladja a 999-es értéket, a BEC utasítás kilép a blokkból. Továbbá ez a rész jelzi az #InProg jelzés törlésével, hogy az adatrögzítés befejeződött.. Ezúttal azért, mert a rögzített adatmennyiség elérte a maximumot (a tömb tele van).



A következő lépés a cím kiszámítása. Közvetlenül az #Index változóval ugyanis több okból sem címezhetjük a tömböt. Egyrészt az #Index integer, és nem pointer típusú, így a formátuma nem felel meg annak amivel címezni lehetne. Másrészt az #Index 0-tól 999-ig nő, a tömb azonban 6-os címen kezdődik és 4005-ös címen van vége, egy eleme 4 byte címet foglal el (ne feledjük, hogy S7-ben a cmzés byte alapú!).
Ezért meg kell szorozni néggyel. Ezután betölti ACCU1-be a LOG tömbre mutató pointert, majd hozzáadja a 4-el megszorzott index értékét, miután eltolta balra 3-al (Az a pointerré alakítás miatt van szükség).
A következő utasítás az eredményt az 1-es cím regiszterbe tölti. A cím regiszter alkalmas arra, hogy segítségével adatterületeket címezzünk. A LAR1 utasítás végrehajtása után a címregiszter tartalma arra a címre mutat, ahova az adatot írni kell.



Nincs más hátra, mint kiírni az adatot a megfelelő DB címre.
Először a 16 bemeneti bitet tölti majd írja a DB-be.



Végül a start óta eltelt időt írja be, majd növeli az #Index értékét egyel, hogy a következő ciklusban a a tömb következő üres elemébe történhessen az adatok tárolása, ha a tömböt még nem írta tele.



Szirty