Az idő mérése

(1., 2., 3., 4., 5. rész)

Ez a cikk különböző megoldásokat mutat be az idő mérésére S7-300/400 PLC-vel
A cikk alapját a Siemens web oldalán található példaprogram képezi, de az írás nem annak fordítása és kisebb-nagyobb változtatásokat tartalmaz és bővítettem is (A 7-es és a 8-as példa nem szerepel a siemenstől letölthető projectben.)

Tartalom:
Időmérés timerrel
Időmérés IEC timerrel
Időmérés 16 bites üzemóra számlálóval
Mérés 32 bites üzemóra számlálóval (RTM)
Időmérés az SFC64 segítségével (TIME_TCK)
Időmérés a valós idejű órával (READ_CLK)
Időmérés a clock memory bitek felhasználásával
Mérés a cyclic interrupt segítségével

Minden példa egy-egy külön FC blokkban kapott helyet. A példákhoz néhány bit előkészítése szükséges, a szükséges programrész az OB1 elején található:



A fenti programrész előállítja a start és stop impulzusokat és a mérési folyamatot jelző bitet, amiket a példaprogramok használnak fel.

1. példa: Időmérés timerrel

Időzítésre a leggyakrabban használt megoldás a timer (időzítő) használata. A timer arra való, hogy egy esemény bekövetkezése után egy előre megadott idő múlva jelzést adjon. Tehát nem kifejezetten az idő mérésére, hanem időzítésre szolgál.
Az idő mérése annyiban tér el az időzítéstől, hogy nem egy előre meghatározott idővel dolgozunk, hanem meg akarjuk tudni, hogy két esemény között mennyi idő telik el.
Mivel a timer pillanatnyi tartalma kiolvasható, ez a feladat is megoldható vele.

A példaprogram lokális változói:








Az M0.0 felfutó éle elindítja a mérést, az M0.2 felfutó éle pedig leállítja.
A mérés ideje alatt a #T_BIN és a #T_BCD tartalma folyamatosan csökken (visszaszámlálás). Az M0.2 felfutó élénél a számlálás leáll, az érték "befagy" és M0.0 újabb felfutó éléig tárolja az értéket.
A visszaszámlálás az időzítő TV paraméterében megadott időtől indul.
A visszaszámlálás sebessége a timer időalapjától függ, amit a TV-ben megadott időkonstans határoz meg a következő táblázat szerint:

Időalap TV paraméter értéke Szorzó
10 ms 0-999ms (0 - 9.99s) 1
100ms 10s-99.9s (10s -1m 39s 900ms) 10
1s 100s-999s (1m 40s - 16m 39s) 100
10s 1000s-9990s (16m 40s - 2h 64m 30s) 1000

Az időalap az az idő amennyi idő eltelése után újra és újra csökkenti a timer az időszámlálót amíg el nem éri a nullát.
A start (M0.0) és a stop (M0.2) jel között eltelt időt úgy kapjuk meg, hogy az M0.2 felfutó éle után kiolvassuk a #T_BIN-ből az időtag értékét, kivonjuk a TV paraméterben megadott kiindulási értékből, majd az időtag által használt időalap szerint, a fenti táblázatban látható szorzóval megszorozzuk (#szorzo). Az eredményt MD20-ban, század másodpercben kapjuk.
Az MD20-at akkor kell kiolvasni amikor az időmérés leállt, azaz az M0.2 felfutó éle után.

A timer a BCD kimenő paraméterében visszaadja a pillanatnyi állapotát BCD számként. Ez a #T_BCD lokális változóba kerül. A BCD érték az időn kívül az első digiten tartalmazza az időalap kódját is (a fenti táblázat szerint). A #T_BCD word változó szerkezete az alábbi:



A szorzó megállapításához a program a 12-13-as biteket használja fel. Először kimaszkolja egy AND művelettel, majd jobbra rotálja, hogy a 0-1 bitekre kerüljön ez a két bit. Egy összehasonlítás sorozattal a kapott érték tartalma szerint feltölti a #szorzo változót.

Fontos!

2-es példa: Időmérés IEC timerrel

Amennyiben az időt Time formátumban szeretnénk mérni, a méréshez használjuk az IEC timer funkciót, amit S7-ben az SFB4 valósít meg.
Az idő mérése ms pontosságú, a legnagyobb mérhető időtartam 24 nap,20 óra, 31 perc 23 másodperc, 647 ezred másodperc.
Az időszámlálót a timerrel ellentétben az IEC timer növeli, nem csökkenti.
Az eredmény TIME típusú duplaszóban képződik ami lényegében olyan DINT, ami ezredmásodpercben eltelt időt tartalmaz.



Ha az SFB4 blokk PT paraméterénél megadott idő letelik az IN (M1.0) bekapcsolt állapota mellett, akkor a timer bekapcsolja a Q kimenetét.
A timer tartalmát egy MOVE utasítás a mérés ideje alatt folyamatosan másolja az MD68 duplaszóba. Amikor az idő mérését leállítjuk, a másolás leáll, az MD68-ban az M1.0 bekapcsolásának időtartamát kapjuk, vagyis a mérés eredményét, TIME formátumban.
A másolásra azért van szükség, mert az IEC timer tartalma nulla lesz, amikor a mérés végén az IN bemenete logikai nullává válik. Másolás nélkül a mérési eredmény ezért elveszne.

Fontos!
  • A másolás közvetlenül a timer előtt legyen, mert csak így biztosítható az utolsó timer tartalom kiolvasása a timer leállításakor
  • Ha a példaprogramot PLCSIM PLC szimulátorral próbáljuk ki, nézzük meg milyen verziójú, mert a PLCSIM V5.3+SP1 verzió hibás! Ebben az IEC timer vagy nem működik, vagy nem jól számolja az időt (a PT-nél megadott értéktől függ hogy melyik eset következik be), órák telnek el másodpercek alatt.

3-as példa: Időmérés 16 bites üzemóra számlálóval (Runt Time Meter)

Amikor nagyon hosszú időt akarunk mérni kis felbontással, használhatjuk az S7 beépített üzemóra számlálóját (run time meter).
Az üzemóra számláló kezelésére külön rendszerhívások szolgálnak:
SFC2 (SET_RTM) - A számláló beállítása és nullázása
SFC3 (CTRL_RTM) - A számláló elindítása és leállítása
SFC4 (READ_RTM) - A számláló tartalmának kiolvasása

A 16 bites üzemóra számláló egy integerben adja vissza az órák számát. A számláló start paranccsal indítható, stop paranccsal leállítható. A számlálás start után kezdődik stop hatására leáll. Újabb start jelre a számlálás folytatódik. A számláló állapota lekérdezhető (hogy éppen start vagy stop állapotban van-e). A számlálás a háttérben zajlik a számláló növelését a rendszer elvégzi a programunkban azzal nem kell törődnünk, csak az indításával, kiolvasásával, leállításával, stb.
Ezzel a módszerrel egy óra felbontással mérhetünk kb. 3.5 évet.




A számláló értéke az idő telésével nő. Amikor eléri az integer típus ábrázolási tartományának végét (32767 óra után), a számlálás leáll és az SFC4 a CQ kimenetén túlcsordulást jelez..

4-es példa: Mérés 32 bites üzemóra számlálóval (RTM)

Ha a három és fél éves határ nem elég az idő mérésére, mérhetünk 32 bites üzemóra számlálóval is időt. Valószínű hogy ez elegendő lesz, hiszen 245 146 évig ketyeg mire túlcsordul. Nem minden CPU ismeri azonban az SFC101-es funkciót. (Ez a tipp segít megállapítani)
Ezzel a módszerrel is 1 órás felbontásban mérhetünk időt.

A 16 bites üzemóra számlálóval szemben a 32 bites kezelése eltér kissé. Itt nincs minden RTM funkcióra külön blokk, hanem az összes funkciót ugyanaz a hívás bonyolítja le.
Egy MODE paraméteren keresztül kell közölni a funkcióval, hogy mit szeretnénk az üzemóra számlálótól.
A példa ehhez egy lokális változót használ, amibe a kívánt funkcióhoz tartozó üzemmódot teszi MOVE utasítással, majd meghívja az FC101-et.




A 32 bites számláló is növeli az értékét, akár a 16 bites.
Az eltelt idő at MD110-be kerül, értéke órát jelent. Az M10.7 jelzi a számláló aktivitását.

Fontos!
(Megjegyzés: E cikk írásának idején nem tudtam olyan CPU-t szerezni amin kipróbálhattam volna a 32 bites RTM példáját hogy a példa 100%-osan működőképes-e, így tapasztalatok nélkül tettem a cikkbe)
Ui: Ha valaki küldene egy S7-400 CPU414-et ajándékba, kipróbálnám :)

5-ös példa: Időmérés az SFC64 segítségével (TIME_TCK)

Az S7 CPU-ban van egy szabadonfutó számláló, amit a rendszer adott időközönként növel. A számláló 32 bites, 1 vagy 10ms-onként nő. Amikor eléri a 32 bites érték maximumát, a számlálást újrakezdi és ismét nő.
Ezt a számlálót az SFC64 (TIME_TCK) rendszerhívással lehet kiolvasni.
Az 5-ös példa ezt a számlálót használja fel az idő mérésére oly módon, hogy minden ciklusban kiolvassa az értéket  a számlálóból és egy belső időhöz hozzáadja az előző hívás és a pillanatnyi számlálóérték különbségét.
Mivel a két kiolvasás között ez a belső számláló átfordulhat (vagyis eléri a maximumot és a számlálás újrakezdődik) ezt az esetet is kezelni kell, hogy az időméréskor visszaadott érték ilyenkor is helyes legyen.
Ezért a TIME_TCK-val működő időmérés az FB1 blokkban kapott helyet. Az FB1 SCL-ben írt blokk, a siemens oldalról letölthető példa projectben megtalálható. HTML file-ként itt is megtekinthető.

A CPU üzemmód hatással van a TIME_TCK számlálójára, ezért azt mindegyik restart OB-ban inicializálni kell a RESET bemeneten keresztül.
Ezzel elkerülhető, hogy a CPU-t STOP majd RUN üzemmódba helyezve az FB1 hibás értéket adjon.



Ha S7-400-as PLC-t használunk, a fenti hívást bele kell tenni az OB101 és OB102 blokkokba is.

Az idő méréséhez az alábbi hívás kell:



A mérés eredménye az MD114-ben áll elő TIME formátumban.
A legnagyobb mérhető idő a TIME típus ábrázolási tartományának megfelelően 4 nap, 20 óra, 31 perc, 23 másodperc, 647 ezred másodperc. Ennek túllépésekor a blokk bekapcsolja az M10.5 bitet, ami túlcsordulást jelez.
A mérés felbontása 1 vagy 10 ezred másodperc.

Fontos:

6-os példa: Időmérés a valós idejű órával (READ_CLK)

Mindegyik CPU rendelkezik valós idejű órával. (Némelyik régi típus, főként IFM vagy compact csak szoftveres órát tartalmaz, ezek kikapcsolt állapotban nem mérik az időt.)
Ez is felhasználható az idő mérésére.
A módszer lényege az, hogy bizonyos időközönként (akár minden PLC ciklusban) lekérdezzük a valós idejű óra állását az SFC1 rendszerhívással (READ_CLK) és elraktározzuk egy változóban. A következő hívásnál kiszámoljuk mennyi idő telt el az előző hívás óta, vagyis megnézzük az eltárolt és a most lekérdezett rendszeridő különbségét. Ezzel a különbséggel mindig növelünk egy átmeneti változót, ami egyben az eltelt időt fogja tartalmazni.

Ez látszólag egyszerű, de a dolog számos problémát vet fel, némelyik igencsak riasztó :)
Nézzük mik is ezek.
Először is a rendszer óra év, hónap nap, óra, perc, másodperc, ezredmásodperc adatokat szolgáltat.
Ha a mérési eredményt TIME formátumban akarjuk megkapni, akkor a két dátum különbségének meghatározásához át kell számolni ezredmásodpercre. Ráadásul az SFC1 BCD-ben adja meg az időt.
További probléma, hogy kezelni kell a hónapok napjainak különbségét, hiszen míg minden perc 60 másodperc, minden nap 24 óra, addig nem minden hónap 30 vagy 31 nap, hanem hol annyi, hol ennyi. Ha az idő mérése keresztezi a hónapok határát (pl. január 29-én indítottuk, és február 1-én állítjuk le a mérést, csak akkor adhat helyes eredményt, ha figyelembe vesszük hány napos a január. A szökő éveket is figyelni kell.

A siemenstől letölthető példában ezt az FB2-vel oldották meg, amely SCL-ben kezeli ezeket a problémákat. A blokk használata az alábbi:



Az eredmény az MD118-ban képződik, TIME formában.
Ha a mért idő meghaladja a TIME típus ábrázolási tartományát, akkor az M10.6 TRUE állapotú lesz.

Ennek a módszernek legnagyobb előnye az, hogy ha az idő mérésének indítása után a PLC-t kikapcsolják, visszakapcsolás után a kikapcsolva eltöltött időt is beleméri az eredménybe (mivel a valós idejű óra olyankor is jár). Kivételt képeznek természetesen a szoftveres órával rendelkező CPU-k.
A hátrány az, hogy az SCL-ben írt FB2 elég nyakatekert dolgokat tartalmaz (részlet):



A teljes SCL forrás
Ez nagy STL kódot produkál. Érdemes belenézni az STL forrásba is. Szöveges file-ban itt található.

7-es példa: Időmérés a clock memory bitek felhasználásával

Egy szabályos, 1 másodperces gyakoriságú óraimpulzus sorozat felfutó éleinél növelünk egy számlálót.
Ehhez be kell állítani a CPU hardver configban a clock memory funkciót a 255-ös merker byte-ra:



Természetesen a beállítás után a hardver configot át is kell tölteni a PLC-be (a szimulátorba is ha épp azzal próbáljuk ki).
A clock memory impulzus sorozatairól részletesebb leírás található az "Impulzus sorozatok egyszerűen" c. írásban.



A módszer másodperc alapú mérést tesz lehetővé. A felbontása is ennek megfelelő. A legnagyobb mérhető időtartam 2147483647 másodperc, vagyis kb 68 év.
Az egy másodperces impulzusokat előállíthatjuk időtaggal is. A módszer hosszú távú pontosságáról nincs információm.

8-as példa: Mérés a cyclic interrupt segítségével

Az idő mérésére lehetőség van az egyik CPU által kínált funkció kihasználásával, a ciklikus megszakítással.
Ez csak annyiban tér el a 7-es példától, hogy itt az 1 másodperces impulzus sorozatot nem egy merker bit adja, hanem a ciklikus megszakítás.
A dolog feltétele az, hogy a hardver konfigban a Cyclic Interrupts fülön az egyik ciklikus megszakítást 1 másodpercesre állítsuk.



A számlálást az OB35-ben kell megírni, az OB35 fog egyszer lefutni minden másodpercben:



Az M11.3 megakadályozza hogy a számláló átforduljon amikor az eléri a dint ábrázolási tartományának felső határát. Egyúttal a túlcsordulást is jelzi.
A ciklusmagban (tehát ciklusonként lefutó blokkban) gondoskodunk a túlcsordulás figyeléséről és a számláló lenullázásáról:



A módszer itt is másodperc alapú mérést tesz lehetővé. A felbontása is ennek megfelelő. A legnagyobb mérhető időtartam 2147483647 másodperc, vagyis kb 68 év.
Ha a hardver konfigban átállítjuk a cyclic interrupt idejét, akkor eltérő időalapot kapunk.

A project file

A Step7 project file tartalmazza az összes fenti példát. Minden példa egy külön FC-ben kapott helyet. Némelyikhez azonban más blokkokban is vannak részletei (lásd fent).
A projectben van egy VAT tábla is, ami segít kipróbálni a módszereket:



Megtalálható benne az FB1 és FB2 SCL-ben írt (siemens-től letöltött) blokk STL-be fordított változata is.
A project file ZIP arhívban letölthető innen: Time6.zip


Kapcsolódó cikkek:
Impulzus sorozatok egyszerűen
S7 300/400 időzítők és számlálók
Egy tipp arra, hogyan lehet megnézni hogy egy CPU milyen beépített funkciókat ismer



Szirty