S7 óra funkciók

Utolsó módosítás: 2012. december 18
Gyakorlatilag mindegyik S7-300 és S7-400-as CPU változatban van valós idejű óra.
Mi a valós idejű óra? Olyan óra, ami méri az idő múlását, ismeri a dátumot (év, hónap, nap) kezeli a szökő éveket, és tudja a pontos időt (óra, perc, másodperc).

Régebbi alacsonyabb kategóriás (pl. compact) típusokban szoftveres óra van, amiről annyit kell tudni, hogy ha a CPU nem kap tápfeszültséget, akkor a valós idejű óra megáll benne.
A lítiumos háttérteleppel ellátott (régebbi 300-as, illetve a 400-as) CPU típusok óráját feszültség mentes állapotban táplálja a lítium elem, így azokban olyankor is ketyeg az óra, akár egy éven keresztül is.
A teleppel nem rendelkező modernebb MMC kártyás 300-as CPU-kban egy nagy kapacitású puffer kondenzátor táplálja egy darabig az óra áramkört amikor a CPU nem kap feszültséget. Ennek áthidalási ideje kb. két nap.



Az óra jelenléte gyakran hasznos. Pl. hiba esetén a diagnosztikai pufferbe is beíródik a bejegyzés időpontja, amit ez az óra tesz lehetővé.
Ha ránézünk a diagnostic bufer tartalmára látjuk a bejegyzések időpontját:



Programból is kihasználhatjuk az órát, mivel le lehet kérdezni az időt. Segítségével kapcsoló óra funkciókat valósíthatunk meg. Elindíthatunk, vagy leállíthatunk bizonyos folyamatokat adott időpontban, ismételhetjük azt adott időközönként (akár havonta vagy évente egyszer is). Esetleg rögzíthetjük bizonyos esemény bekövetkezésének pontos időpontját, stb...
Ez az írás a valós idejű óra kezeléséről szól.

Az idővel kapcsolatos adattípusok

Először nézzük meg milyen adattípusok állnak rendelkezésre az idő kezelésére.
Az S5TIME típussal itt nem foglalkozunk, mert az eltelt vagy hátralevő idő tárolására használatosak, nem a pontos idő vagy dátum tárolására.

TIME_OF_DAY
Ez egy 32 bites (4 byte-os) előjel nélküli dupla egész, amely az adott napon 0 óra 0 perc 0 másodperc óta eltelt időt tartalmazza ezred másodpercben.
A konstans formátuma és ábrázolási tartomány: TOD#0:0:0.0 – TOD#23:59:59.999

DATE_AND_TIME
Ez egy 8 byte-os komplex típus, tulajdonképpen egy adatstruktúra. Emiatt hivatkozni rá csak a kezdetével lehet (illetve a szimbolikus nevével, lásd később).
Figyelem! Minden szám BCD ábrázolású!

ByteTartalomTartomány
0Év90-89(1990-2089)
1Hónap1-12
2Nap1-31
3Óra0-23
4Perc0-59
5Másodperc0-59
6Ezred másodperc felső 2 digitje0-99
7Ezred másodperc alsó digitje
és a hét napjai
0-9
1-7 (1=vasárnap)

Mivel complex típus, az ilyen DATE_AND_TIME változót nem lehet monitorozni, a tartalma nem jelenik meg pl. ha egy DB blokkot monitorozunk:



Ha mindenképpen meg akarjuk nézni mi van benne, akkor kénytelenek vagyunk byte-onként vizsgálni a tartalmát. Erre alkalmas pl. a VAT tábla. Mivel BCD számok vannak benne, a HEX formátumú megjelenítés fogja a helyes decimális megjelenést hozni:



A fenti képen a CPU_TOD változó tartalma tehát: 2012. December 17 17 óra 19 perc, 38 másodperc, 608 ezred másodperc, hétfő
DATE
16 bites (2 byte-os) előjel nélküli egész. Dátum 1 napos lépésekben, 1990 január 1-től számítva.
Ábrázolási tartomány: D#1990-1-1 – D#2168-12-31

TIME
32 bites (4 byte-os) előjel nélküli dupla egész, amely az időt ezred másodpercben tárolja.
Ebből a szempontból nagyon hasonló a TIME_OF_DAY típushoz, de a TIME nem csak maximum 24 óra idő tárolására képes.
Ábrázolási tartomány: 0D_0H_0M_0S_0MS - 24D_20H_31M_23S_647MS

A rendszer idő kiolvasása

A rendszer óra kiolvasására több lehetőségünk is van.
Minden OB blokk tartalmaz egy DATE_AND_TIME típusú előre deklarált TEMP változót, ami az OB legutóbbi futásának időpontját tartalmazza. vagyis a PLC operációs rendszere ide beírja a valós idejű óra pillanatnyi tartalmát, amikor a blokkot meghívja (futtatja).
Ennek a változónak a neve OBxxx_DATE_TIME ahol xxx az OB száma. Mivel az OB1-et a rendszer minden ciklusban meghívja, ott mindig a pontos időt találjuk, az egyik módszer tehát ennek a kiaknázása úgy, hogy ezt a változót átmásoljuk célszerűen eegy DB blokkban deklarált DATE_AND_TIME típusú változóba. A másolás azért szükséges, mert valószínűleg nem csak az OB-ből akarjuk elérni a pontos időt, ám az OB1_DATE_TIME lokális változó, így csak az OB1-ből érhető el. Ha másoljuk, akkor a másolat mindenhonnan elérhető lesz.



Az a tény, hogy a DATE_AND_TIME komplex típus okozni fog egy kis problémát. Ez elsőt a másolásnál, mivel a MOVE utasításnak nem adhatunk meg komplex típust.
Ezért vagy két részletben másoljuk, két duplaszavas másolással, vagy BLKMOV hívással, ami képes komplett struktúrák másolására is.
Nézzük a duplaszavas megoldást. Ez sajnos kicsit "hekker" módszer, mert közvetlen címmel bele kell címeznünk a változó közepébe is:



A másolás célja a DB1.DBB6 címen lévő (kezdődő) DATE_AND_TIME típusú változó, ahogy azt a 3. képen is látni lehet. A szimbolikus neve CPU_DT (ennek alább lesz jelentősége).
Látható az OB1 interface-ében, hogy az OB1_DATE_TIME változó a 12-es címen kezdődik. Tudjuk, hogy mértee 8 bíte, ahogy azt is, hogy egy duplaszó 4 bíte mérető. A Network 1 ezért két duplaszó méretű részletben másolja. Az első duplaszót az LD12-es címről olvassa, a másodikat az LD16-os címről.

A másik, már említett módja a másolásnak a BLKMOV (SFC20) rendszerhívás használata.
Szerencsére az SFC20-nak átadható a változó szimbolikus neve is, így a címmel nem kell törődnünk. Keletkezik azonban egy visszatérési érték, ami a művelet sikerességét jelzi, Ezért hozzunk létre egy SFCRV nevű integer TMP változót és adjuk meg azt az SFC20 RET_VAL kimeneténél. Ennek az #SFCRV-nek a tartalmát programból vizsgálhatjuk ha nagyon fontos hog a másolás sikertelensége kiderüljön, de mivel közvetlen címeket adtunk meg a rendszerhívásnak (és nem számított, indirekt címet), ha azok léteznek, akkor a másolás biztos hogy sikeres lesz.



A CPU óráját a programban kiolvashatjuk az SFC1 hívással is. Az SFC1 ("READ_CLK") is DATE_AND_TIME típusú adatokat ad vissza.



Az #SFCRV változóban (integer) nulla lesz ha a kiolvasás sikeres és hibakód ha sikertelen. A sikertelenség oka általában az, hogy a megadott cím ahova az időt akarjuk lerakni nem létezik, vagy kifut egy DB blokkból.

A rendszer idő felhasználása

Szoftveres összehasonlítás

Amikor valamilyen funkciót az óra egy meghatározott állásakor szeretnénk elvégezni, akkor nem csak kiolvasni kell a CPU órát, hanem a kiolvasott adatokat fel is kell használni.
Akár az OB1 változójából szerezzük meg az időt, akár SFC1 meghívásával, DATE_AND_TIME formában kapjuk meg az időt és dátumot. Ahogy az a típus leírásánál szerepel, ebben BCD formátumú számok vannak. Ezt nem szabad elfelejteni, mert könnyen belefutunk abba a hibába, hogy az időpont figyelése nem jól működik.

Gyakori, hogy impulzusra van szükség, ami minden perc, óra vagy nap elején aktív. Ilyet egyszerű összehasonlítással létre tudunk hozni. Pl. az órás impulzushoz azt kell figyelni mikor 0 a perc számláló tartalma.
Ha a lekérdezett DATE_AND_TIME formátumú idő a DB1.DBB6 címen van (CPU_DT), akkor ki kell számolni melyik byteon van a perc számláló.



Ebben az esetben a percet a DB1.DBB10 címen találjuk:





Az M1.1 merker biten előáll az egy órás impulzus, ami a CPU órája szerint minden egész óra 0. másodpercében keletkezik.
Persze ha nem minden óra nulladik percében, hanem mondjuk a 30-adik percében akarunk órás impulzusokat, akkor az összehasonlítás alsó értékét B#16#0-ról át kell írni B#16#30-ra. (mivel a perc (is) BCD-ben van, hexadecimálisan kell megadnunk a decimális 30-at!).
Az óra állítása bekavarhat ennek a módszernek (is).
Pl. rosszul jár és az előre állított óra átlépi az összehasonlításban beállított időt, akkor abban az órában kimarad egy impulzus. Vagy ha visszafele kell állítani és ezt akkor tesszük, amikor az épp átlépte az összehasonlítás időpontját a visszaállítás során pedig megint elé kerül a pontos idő, akkor abban az órában kétszer is létre fog jönni az impulzus.
Hogy ez várhatóan mekkora problémát okoz, az attól függ mire használjuk ezeket az impulzusokat. Ha az impulzus duplázódása komolyabb problémát okoz, mint a kimaradása, akkor használhatunk két összehasonlítást és egy RS tárolót az impulzus előállítására:



Ha adott idő intervallumot akarunk figyelni pl. minden nap 6:00-8:00-ig kell egy aktív jel, akkor célszerű az időt átkonvertálni egy könnyebben kezelhető formára. Ha a dátum figyelése nem szükséges, akkor a dátum adatokat (év, hónap, nap) érdemes elhagyni és csak az óra:perc.másodperc adatokat figyelni. Ha ezt DATE_AND_TIME formátumú idővel valósítjuk meg, akkor több összehasonlításra van szükség.
A DATE_AND_TIME  formátumból a standard lib-ben lévő FC8  DT_TOD IEC funkcióblokk kibányássza nekünk az óra, perc másodpercet és a könnyebben kezelhető TOD típusban adja vissza. A TOD-ot közvetlenül használhatjuk DINT típusú összehasonlításban (ha kikapcsoljuk a programszerkesztőben a típusvizsgálatot, lásd alább).



A fenti network a korábban már bemutatott SFC1-el történő óra lekérdezés bővített változata, ahol a DATE_AND_TIME formátumból az említett IEC funkció kialakítja a DB1-ben a TOD formátumú időt. (a konverzió természetesen alkalmazható az OB1-ből kinyert adatok átalakításához is).
Az FC8-at A standard library-ből húzhatjuk elő:



Ha a programunkban van már FC8, akkor természetesen átszámozhatjuk.
Az átalakított idő adatot már könnyen lehet kezelni a CMP utasításokkal:


Az == összehasonlítással itt vigyázni kell, mert a TOD formátim az ezredmásodpercet is összehasonlítja és az == csak teljes egyezésnél ad TRUE eredményt!
A CPU órája a PLC programtól függetlenül telik, a ciklus idő meg valószínűleg nagyobb lesz 1 ms-nál. Ennek pedig az a következménye, hogy az összehasonlítás rendszeresen le fog maradni a teljes egyezésről, mert az egyik lefutáskor az időpont előtt, a következőnél meg már utána hasonlít össze.
Ilyenkor az ezredmásodpercre pontos összehasonlítás helyett használjunk inkább kisebb, nagyobb relációt, vagy idő intervallumokat (tól-ig).
Lássunk ez utóbbira is egy példát:



Figyelem!
A fenti példák önfeledt és zavartalan reprodukálásához a fejlesztői környezetben ki kell kapcsolni a típus ellenőrzést. Ellenkező esetben az egész számok összehasonlítására való CMP >=D, CMP <D stb utasítások nem fogják elfogadni a TOD típust, mivel az nem DINT.

Az említett típus vizsgálat a programszerkesztő Options / Customize menüjéből elérhető ablak LAD/FBD fülén található Type Check of Addresses kapcsoló kikapcsolásával hatástalanítható.



Megjegyezném ugyanakkor, hogy ennek az opciónak a kikapcsolása sokkal engedékenyebbé teszi a programszerkesztőt, mert az nem fogja figyelni hogy a megfelelő adattípust adtuk-e meg az utasításoknak. ha nem vagyunk elég figyelmesek (és gyakorlottak) komoly szívás lehet belőle. Csak akkor kapcsoljuk ki, ha tényleg tudjuk mit csinálunk!

Megszakítás (Time-of-day interrupt)

Sok CPU lehetővé teszi, hogy egy előre beállított időpontban megszakítást hajtsanak végre, ami egy OB blokk meghívását jelenti.
Ezt a HW configban kell eszközölni, az időpont bekövetkezését és a hívást maga a PLC operációs rendszere végzi el, nekünk csak azt kell leprogramozni mi történjen, amikor az időpont elérkezik.
Bizonyos CPU típusok egy, mások egyszerre több ilyen megszakítást is tudnak kezelni.



A Time-of-day interrupt kezelésére vannak rendszerhívások is, hiszen meglehetősen problémás lenne, ha az időpont megváltoztatásakor újra kellene töltenia  HW configot (ami a CPU leállításával jár).
Ezekkel a rendszerhívásokkal változtathatunk az időponton illetve a hívás ismétlődésén (SFC 28 "SET_TINT"), inaktivvá tehetjük a megszakítást, hogy ne következzen be (SFC 29 "CAN_TINT") aktiválhatjuk amikor inaktív (SFC 30 "ACT_TINT") illetve lekérdezhetjük egy ilyen megszakítás állapotát (SFC 31 "QRY_TINT") amiből meg lehet tudni aktív-e-egyáltalán van-e hozzá tartozó OB blokk, stb.
Egy más okból végrehajtott HW config újratöltés módosíthatja a futás közben módosított megszakítási paramétereket!

A rendszer idő átállítása a megszakításos időkezelésnél is okozhat problémákat!

A rendszer idő beállítása

A rendszer óra számítógépről és programból, rendszerhívással is állítható.

Az óra beállítása PC-ről

Erre a fejlesztői környezet biztosít lehetőséget.
Ha Simatic managerben kiválasztjuk a PLC menüből a Diagnostic/Setting / Set Time of Day pontot, a megjelenő ablakban látható a CPU órája a Module time szöveg mellett.
Figyelem, ez a menüpont csak akkor aktív, ha a project fában valamelyik PLC ki van választva!



Itt át is állítható a CPU órája, amire két lehetőségünk van. Ha kikapcsoljuk a Take from PG/PC pipát, akkor kézzel beírhatjuk a dátumot és időt. ha bekapcsoljuk, akkor a CPU óráját beállítja a PC-nk órájához, ami meg is jelenik a PG/PC time szöveg mellett.

Az óra beállítása programból

Az óra beállítsára az SFC0 funkció biztosít lehetőséget. (Setting the TOD with SFC 0 "SET_CLK").
A hívás bemenő paramétere (PDT) DATE_AND_TIME formátumban az idő amire az órát szeretnénk beállítani. Kimenő paramétere egy visszatérési érték, ami nulla értéket vesz fel ha a beállítás sikeres volt és hibakódot ad, ha sikertelen.


A fenti példában a 8080-as (hexa) hibakódot az okozta, hogy a bemeneti paraméterben megadott változóban 99. hónap volt megadva ami érvénytelen hónap szám.
SFC0-t rendszerint akkor használunk, amikor a CPU óráját egy másik órához akarjuk szinkronizálni szoftveresen, vagy ha pl. operátor panelről akarjuk kézzel beállítani az időt.
Arra természetesen figyelni kell, hogy az SFC0-t csak egyszer hívjuk meg és ne minden ciklusban, különben megáll az óra a PLC-ben, hiszen pár ezredmásodpercenként újra és újra beáll az idő ugyanarra az időpontra.. A fenti példában ezt a -(P)- impulzus képző biztosítja.
Álljon itt egy példa az operátorpanelről történő beállításra. Szükséges egy DATE_AND_TIME típusú TAG, egy hozzá tartozó I/O field és egy nyomógomb, ami egy bitet bekapcsol:


A programban egy kényelmi funkció is van, ami dátum TAG-be belemásolja a CPU aktuális óráját, amit állítani akarunk, amikor az OP megjeleníti ezt a képernyőtartalmat. Így nem kell megadni a teljes dátumot és időt minden alkalommal és nem az esetleg hónapokkal ezelőtt beállított idő lesz az input mezőben, hanem az az idő, amit át szeretnénk állítani. Így jó eséllyel csak az órát vagy a percet kell módosítani.



A #NormSCR és az azt követő összehasonlítás állapítja meg, hogy az OP-n az időbeállító kép (502-es screen) van megjelenítve (erről részletesebben a Képernyő szám átadása a PLC-nek című írásban lehet olvasni)
Amikor erre a képernyőre váltunk a menüből, végrehajtásra kerül az SFC20 (BLKMOV) másolás, ami az IO field TAG-be másolja az aktuális CPU időt.
A "Beírás" nyomógomb az M28.5 merker bitet bekapcsolja (SetBit funkcióval). Amikor ez megtörténik, az SFC0 beállítja a CPU óráját arra az időpontra, amit a DATE_AND_TIME típusú I/O mezőbe írtunk be, majd kikapcsolja az M28.5-öt, hogy többször az SFC0 ne fusson le.
Érdemes az operátorpanel óráját automatikusan szinkronizálni a CPU órához, mert akkor a két óra együtt fog járni, az alarm bejegyzések időbélyegzői helyesek lesznek. (Részletesebben lásd a WinCC Flexible: OP órájának szinkronizálása c. írásban)

Óra szinkronizálása hálózatról

Az ethernettel (profinettel) is rendelkező (PN-es) CPU-k HW configjában beállítható, hogy az óra NTP segítségével (Network Time Protocol) automatikusan szinkronizálódjon adott időközönként.
A beállítás rendkívül egyszerű, meg adni a time szerver címét és a szinkronizálás gyakoriságát:




Figyelem!
Ha a PLC-ben futó program használ Time of day interruptot (vagyis olyan megszakítás van beállítva, ami egy adott időpontban történik meg) és a PLC órájának állításával átlépjük ezt az időpontot, akkor egy time error hiba fog keletkezni.Ha nincs hozzá tartozó OB, akkor a CPU leáll!


Kapcsolódó írások:
S7-300/400 címtartományok, adattípusok
Az idő mérése
S7 300/400 időzítők és számlálók
Képernyő szám átadása a PLC-nek
WinCC Flexible: OP órájának szinkronizálása


Szirty