Výukový seriál o programování PLC pokračuje třetím dílem, který seznamuje s programovými organizačními jednotkami uživatelského programu PLC (funkce, funkční bloky, program) a vysvětluje, jak používat jednotlivé objekty programu PLC: identifikátory, klíčová slova, komentáře, typy dat, literály a deklarace proměnných.
Programové organizační jednotky (POU)
Při programování podle normy IEC/EN 61131-3 je základním pojmem programová organizační jednotka (POU – Program Organization Unit). Je to nejmenší nezávislá jednotka uživatelského programu PLC. Obvykle ji vytváří uživatel PLC pro svou aplikaci, některé může dodávat výrobce řídicího systému se svým vývojovým systémem (např. jako knihovny funkcí a funkčních bloků). Jednotlivé POU mohou volat další POU a při tom si mohou vzájemně předávat potřebné parametry. Existují tři typy POU: funkce, funkční blok a program.
Funkce
Funkce je nejjednodušší typ programové organizační jednotky. Zpracovává vstupní parametry a předává jediný výstupní parametr – ten je závislý jen na aktuální hodnotě vstupních parametrů, nezávisle na dřívějších aktivacích nebo na čase. Při opakovaném volání se stejnými parametry předává funkce stejný výsledek (výstupní parametr). POU typu funkce je možné přirovnat ke kombinační logické funkci nebo k integrovanému obvodu, který ji realizuje (např. logického součinu AND, multiplexoru nebo dekodéru). V oboru spojitých a číslicových systémů je analogickým prvkem statický systém bez vlastní dynamiky, např. zesilovač, korekční člen. Norma popisuje široký sortiment standardních funkcí:
-
funkce pro konverzi typu dat,
-
numerické funkce jedné proměnné (absolutní hodnota, odmocnina, exponenciální a logaritmické funkce, sinus, kosinus, tangens a k nim inverzní funkce),
-
numerické funkce dvou a více proměnných (sčítání, násobení, odčítání, podíl a dělení modulo, obecná mocnina),
-
funkce prováděné s řetězci bitů (rotace, booleovské funkce AND, OR, XOR, NOT),
-
funkce výběru (multiplexor, maximum, minimum, omezovač),
-
porovnávání (zobecnění relací nerovnosti větší, větší nebo rovno, menší, menší nebo rovno, rovnost, neshoda),
-
funkce pro řetězce znaků,
-
funkce s typy datum a čas,
-
funkce s výčtem.
Uživatel si může vytvářet své vlastní (uživatelské) funkce, může je získat i od výrobce PLC nebo vývojového systému v knihovnách problémově orientovaných POU ([1], [4], [12]). Deklarovaná funkce je v paměti programu obsažena jen v jednom exempláři a při volání se nevytvářejí její kopie – funkce se pouze provede a předá svou výstupní hodnotu.
Funkční bloky
Funkční blok je obecnější organizační jednotka než funkce. Může zpracovávat více vstupních parametrů a předávat více výstupních parametrů. Ve svých vnitřních proměnných může uchovávat informace o stavu z posledního volání. Je obvyklé, že při opakovaném volání se shodnými hodnotami vstupních proměnných předává funkční blok odlišné hodnoty výstupních proměnných (např. u čítače nebo časovače) . Funkční blok lze přirovnat k sekvenční logické funkci nebo k integrovanému obvodu, který ji realizuje, např. klopnému obvodu, čítači nebo časovači. V oboru spojitých nebo číslicových systémů jsou analogickými prvky systémy s vlastní dynamikou nebo jejich programové modely, regulátory nebo číslicové filtry.
Norma nabízí několik typů standardních funkčních bloků:
-
bistabilní prvky (klopné obvody SR s dominantním nastavením a RS s dominantním mazáním),
-
detekce náběžné (R_TRIG) a sestupné hrany (F_TRIG),
-
čítače (dopředný CTU, zpětný CTD a oboustranný CTUD),
-
časovače (pulzní TP, zpoždění náběžné a sestupné hrany – TON a TOF).
Uživatel si může vytvářet své vlastní (uživatelské) funkční bloky, může je získat i od výrobce PLC nebo vývojového systému v knihovnách problémově orientovaných funkčních bloků ([1], [4], [12]). Vzhledem k jejich paměťovému charakteru existují funkční bloky ve dvou formách: deklarace a instance.
Deklarací se vytvoří obecná matrice funkčního bloku se specifikací všech jeho proměnných (vstupních, výstupních a vnitřních proměnných) a s programem, který popisuje jeho činnost. Deklarace funkčního bloku je pouze předpisem, ve kterém je deklarována struktura dat spolu s algoritmy, které se budou s těmito daty provádět. V místě každého použití deklarovaného funkčního bloku se provede jeho instance – vytvoří jeho pojmenovaná kopie s doplněním jmen konkrétních proměnných a hodnot parametrů. Každé instanci je přiřazeno unikátní jméno funkčního bloku. Deklarovaný funkční blok je v paměti programu uložen v jednom exempláři, ale (na rozdíl od funkce) na místě každého použití se ještě doplní jeho instance.
Obrazně je možné definovaný funkční blok přirovnat k razítku s volnými kolonkami a instanci k jeho otisku s individuálně doplněnými údaji. Jakýkoliv funkční blok, který byl již deklarován, může být použit v deklaraci jiného funkčního bloku.
Programy
Program je vrcholnou programovou jednotkou v uživatelském programu. V normě je definován jako „logický souhrn programovacích jazyků a konstrukcí nutných pro zamýšlené zpracování signálů, které je vyžadováno pro zamýšlené řízení stroje nebo procesu systémem programovatelného automatu“. Jinak řečeno, funkce lze přirovnat k podprogramům a funkční bloky k makrům (subroutines), zatímco POU typu program je hlavní program (main program). Programy mohou volat funkce a funkční bloky, nikoliv naopak. Centrální jednotka PLC může zpracovávat více programů. Rovněž program je třeba považovat za definici, ke které je třeba vytvořit instanci – k tomu je určen aparát konfiguračních prvků, konfigurací, zdrojů a úloh. Zde se jimi nebudeme zabývat, základní způsob aktivace je obvykle předdefinován ve vývojovém systému ([1], [4], [12]).
Deklarace všech POU mají obdobnou strukturu. Začínají deklarací jména POU, následuje deklarační část se jmény vstupních, výstupních a lokálních proměnných, pak výkonná část (tělo POU) s příkazy programu, popř. s voláním dalších POU, a na závěr je napsáno klíčové slovo END s uvedením typu POU (obr. 8). Deklarace programu může mít např. tuto podobu:
PROGRAM Rizeni_Linky (*jméno programu*)
(*deklarační část*)
VAR_INPUT
pocetDavek : UINT; (*vstupní proměn- né*)
pocetKusu : UINT;
END_VAR
VAR
pomoc, odloz REAL;(*lokální proměnné*)
priznak BOOL;
END_VAR
(*výkonná část*)
priznak := (pocetDavek <> 0) AND (pocetKu- su <> 0);
IF priznak THEN ….
…..
END_IF
…..
…..
END_PROGRAM (*konec programu*)
Identifikátory
Identifikátory (identifiers) se používají jako jména konstant, proměnných, návěští, odvozených datových typů, funkcí, funkčních bloků, programů a úloh. Identifikátor je řetězec malých a velkých písmen anglické abecedy, číslic a podtržítek (_). Musí začínat písmenem nebo podtržítkem a nesmí obsahovat mezery. Znaky národních abeced (např. s čárkami a háčky) nejsou v identifikátorech povoleny. Umístění podtržítka v identifikátoru je významné (např. ZBL_BL, ZBLB_L, Z_BLBL jsou různé identifikátory). Více podtržítek za sebou není přípustné. Velikost písmen se v identifikátorech nerozlišuje. Zápisy MOTOR_ON, motor_on, Motor_On, Motor_on, motor_ON představují shodné identifikátory a mohou označovat stejnou proměnnou. Příklady platných a neplatných identifikátorů uvádí tab. 1.
Klíčová slova
Klíčová slova (keywords) jsou standardní identifikátory, které norma předurčuje pro specifické použití, např. FUNCTION, BOOL, TRUE, REAL, INT, VAR, VAR_INPUT, END_VAR, AND, IF, THEN, TON. Klíčová slova se nesmějí používat pro vytváření jakýchkoliv uživatelských jmen. Pro jejich zápis mohou být použita malá i velká písmena – pro odlišení od ostatních identifikátorů se však často píšou velkými písmeny (není to ale nutné). Ke klíčovým slovům patří především jména elementárních datových typů, standardních funkcí a funkčních bloků, a jména jejich vstupních a výstupních parametrů, prvky textových jazyků IL a ST.
Komentáře
Komentáře (comments) nemají syntaktický ani sémantický význam, jsou však důležité k dokumentování programu a k jeho zpětnému pochopení. Lze je zapsat všude tam, kde je možné zapsat znak mezera. Při překladu programu jsou komentáře ignorovány. Proto mohou obsahovat libovolné znaky, včetně znaků národních abeced, např. znaky s háčky a čárkami. Překladač rozeznává dva typy komentářů: obecné a řádkové. Obecné komentáře jsou řetězce znaků uvozené otevírací závorkou a hvězdičkou (* a zakončené hvězdičkou a uzavírací závorkou *). Mohou být i víceřádkové, např.:
(* takto může vypadat obecný komentář
Může být víceřádkový a může obsahovat libovolné znaky české abecedy
Vyplatí se nešetřit výstižnými komentáři,
protože vynaložené úsilí se vrátí ve formě lepší čitelnosti programu
a ušetří čas i stres při ladění a úpravách programů
…. a takto obecný komentář končí *)
(*Obecným komentářem lze označit i části programu, které se z určitých důvodů nemají překládat, ale přesto mají zůstat zachovány a zůstat viditelné, např:
motor_1 := start OR motor_1 AND NOT stop;
alarm := sz_a AND (sz_b OR sz_c) OR sz_b AND sz_c);
… konec ignorovaného programu *)
Řádkové komentáře začínají dvojicí znaků // (lomítek) a končí s koncem řádku.
Typy dat
Typy dat zlepšují přehlednost programu a jsou prevencí chyb programátora. Typ je nutné definovat pro každý použitý objekt (proměnné, data). V první části seriálu budeme nejčastěji pracovat s jednotlivými dvouhodnotovými proměnnými (bitovými, booleovskými). Ty mají v normě určen formát BOOL (Boolean). Pro skupiny (řetězce) bitových proměnných používá norma typy:
-
BYTE pro sekvence osmi bitů,
-
WORD (slovo) pro sekvence16 bitů,
-
DWORD (double word, dvojité slovo) pro sekvence 32 bitů,
-
LWORD (Long Word, dlouhé slovo) pro sekvence 64 bitů.
Pro různé typy celočíselných objektů jsou definovány typy uvedené v tab. 2 a pro čísla s pohyblivou desetinnou čárkou lze použít typy specifikované v tab. 3. Samostatné typy jsou vyhrazeny pro časové údaje (tab. 4). Pro celočíselné objekty (se znaménkem i bez znaménka) platí, že řádová tečka se u nich sice neuvádí, ale je předpokládána na pevné pozici za poslední číslicí. Číselné objekty se znaménkem (SINT, INT, DINT) mají poloviční číselný rozsah, oproti odpovídajícím objektům bez znaménka (USINT, UINT, UDINT), protože pro zobrazení čísla je k dispozici formát o jeden bit kratší – jeden bit je vyhrazen pro zobrazení znaménka (znaménkový bit). U objektů s pohyblivou (plovoucí) řádovou tečkou je situace složitější. Podle zvolené přesnosti je pro formát čísla vyhrazena délka 32 bitů (REAL) nebo 64 bitů (LREAL). V tomto rozsahu jsou uloženy dva číselné údaje – mantisa (ve které je zakódován číselný údaj v normalizovaném rozsahu) a exponent (řád mocniny, kterou je třeba násobit mantisu, aby byla získána skutečná hodnota čísla). Zjednodušeně lze říci, že mantisa určuje numerickou hodnotu čísla a exponent polohu řádové tečky. Podrobnosti jsou uvedeny např. v [1], [4]. Počítání v pohyblivé řádové tečce je výhodné, jestliže se pracuje s necelými (zlomkovými) čísly nebo při provádění složitějších výpočetních operací (např. násobení, dělení a složitější funkce). Počítání v pevné řádové tečce (s čísly celočíselného formátu) je účelné pouze tehdy, jestliže se s celými čísly (se znaménkem nebo bez znaménka) provádějí nejjednodušší výpočetní operace sčítání, odčítání a porovnávání.
Znakovým řetězcům je vyhrazen typ STRING (String, řetězec, max. 255 znaků). Uvedené typy jsou označovány jako elementární datové typy. Kromě nich norma definuje ještě rodové datové typy, které popisují celou skupinu (rod) typů, a dále odvozené datové typy (jednoduché, pole, struktury dat a jejich kombinace).
Literály
Pro přímou reprezentaci hodnot proměnných se používají literály (numerické, řetězce znaků, časové). Mohou udávat přímo hodnotu (např. 14, –18.5, nebo 0.123_4) nebo je na začátku literáru uvedeno jméno datového typu (INT#14, REAL#–18.5, REAL#0.123_4). U časových literálů je uvedení typu povinné, např. TIME#12h20m33s. Na rozdíl od češtiny, se v literálech uvádí řádová tečka, nikoliv čárka.
Numerické literály
Numerický literál je zápis číselné hodnoty (konstanty) v desítkové soustavě nebo v soustavě o jiném základu (např. dvojkové, osmičkové, šestnáctkové). Základ soustavy se uvádí na začátku a od číselného údaje je oddělen znakem #. Základ desítkové soustavy se neuvádí. Příklady numerických literálů pro příslušné typy dat jsou uvedeny v tab. 2 a tab. 3.
Například hodnotu 215 (v desítkové soustavě) lze zapsat těmito způsoby: 215, 2#1101_0111, 8#327, 16#D7. Mezi číslicemi smí být pro přehlednost použit znak podtržítka, jehož umístění nemá vliv na číselnou hodnotu. Podle číselného typu se rozlišují literály typu integer s pevnou řádovou čárkou (zde tečkou), např. 14, INT#14, –123, 12_345_678, a typu real s pohyblivou řádovou tečkou, např. –12.3, 0.123_4, REAL#8.5). Pravdivostní hodnota logické (booleovské) proměnné se zadává literálem FALSE nebo BOOL#0 pro logickou nulu (nepravdu) a TRUE nebo BOOL#1 pro logickou jedničku (pravdu).
Řetězce znaků
Řetězec znaků (string) je posloupnost znaků (jednoho, více, popř. žádného – prázdný řetězec), uzavřená mezi apostrofy, ’’ např. ’teplota=’, ’°C’, prázdný znak se zapíše dvojicí apostrofů: ’’. Jako prefix pro zadání znaků v osmibitovém kódu ASCII se používá znak $ (dolar), např. řetězec dvou znaků CR (Enter, šestnáctkově 0D) a LF (odřádkování, šestnáctkově 0A) se zapíše ‚$0D$0A‘. Znak $ uvozuje ale i speciální znaky v řetězcích, např. $$ pro znak $ (dolar) nebo $‘ pro znak ’(apostrof). Literály řetězce znaků (string) se používají především při programování textů pro operátorské panely, textová hlášení (např. pro SMS nebo e-maily, pro vizualizaci ve SCADA nebo pro webové stránky) a pro výměnu textů mezi různými PLC a počítači v distribuovaném systému.
Časové literály
Při řízení technologických procesů, ale i technických zařízení budov a energetických zařízení jsou často potřebné časové údaje dvou typů. Prvním z nich je údaj o době trvání, která uběhla či má uběhnout od určité události. Ve druhém případě je to údaj o „absolutním čase“, tedy o datu podle kalendáře a o čase v rámci dne. Příklady časových literálů pro příslušné typy dat jsou uvedeny v tab. 4. Časový literál pro dobu trvání je uvozen některým z klíčových slov T#, t#, TIME# nebo time#. Časový údaj je vyjádřen v časových jednotkách: hodinách (h, H), minutách (m, M), sekundách (s, S) a milisekundách (ms, MS) – zkratky mohou být vyjádřeny malými a velkými písmeny, mezi údaji mohou být použita podtržítka, např. TIME#5h_35m_5s (trvání 5 hodin, 35 minut a 5 sekund), T#45ms (trvání 45 milisekund). Časový literál pro datum a pro denní čas reprezentuje údaje o kalendářním datu (DATE#, D#, např. DATE#2011-08-25, dne 25. 8. 2011) a o čase v rámci dne (TIME_OF_DAY#13:25:15.7 nebo rovnocenně TOD#13:25:15.7, v 13 hodin, 25 minut a 15,7 sekund). Pro souhrnný údaj o „absolutním“ čase se používá kombinovaný zápis, např. DATE_AND_TIME#2011-08--25-13:25:15.7 nebo rovnocenně DT#2011--08-25-13:25:15.7, dne 25. 8. 2011 v 13 hodin, 25 minut a 15,7 sekund. Velikost písmen opět není rozlišována.
Proměnné
Podle normy jsou proměnné určeny pro identifikaci datových objektů, jejichž obsah se obvykle mění, např. dat přiřazeným ke vstupům, výstupům nebo k vnitřní paměti PLC. Proměnná může být deklarována některým z elementárních nebo odvozených (uživatelských) datových typů. Proměnné jsou identifikátory, zvolené programátorem, které jsou obvykle určeny k rezervování místa v paměti pro uložení dat. Součástí deklarace proměnných může být i údaj o jejich počáteční hodnotě (inicializace). Stejnou formu jako deklarace proměnných ovšem mají i deklarace konstant. Každá deklarace programové organizační jednotky (POU, tedy programu, funkčního bloku nebo funkce) by měla v úvodu obsahovat alespoň jednu deklarační část, která definuje jména a datové typy proměnných používaných v této POU.
Deklarační část je zahájena klíčovými slovy VAR (pro vnitřní proměnné POU), popř. některým klíčovým slovem, které začíná VAR_, např.:
-
VAR_TEMP pro vnitřní proměnné přechodného typu,
-
VAR_INPUT pro vstupní proměnné,
-
VAR_OUTPUT pro výstupní proměnné,
-
VAR_IN_OUT pro vstupní a výstupní proměnné.
Deklarační část končí klíčovým slovem END_VAR. Proměnné platí vždy pouze uvnitř té POU, v níž jsou deklarovány (jsou zde lokální), a nejsou přístupné pro ostatní POU (nejsou z vnějšku POU „viditelné“). Výjimkou jsou proměnné pro předávání parametrů mezi POU a jejím okolím – vstupní proměnné, do kterých lze z vnějšku zapisovat (VAR_INPUT), výstupní proměnné (VAR_OUTPUT), které lze z vnějšku číst, a proměnné pro obousměrný přístup (vstupní a výstupní proměnné - VAR_IN_OUT).
Proměnné deklarované jako VAR mají vyhrazeno pevné místo v paměti a mají dlouhodobou platnost. Skončí-li aktivace POU, pamatují si poslední hodnotu, která je pak použita jako výchozí při opětovné aktivaci POU. Naproti tomu proměnné deklarované jako VAR_TEMP mají přechodný charakter, při ukončení aktivace POU zanikají (jejich místo v paměti se uvolní) a při opětovné aktivaci se znovu vytvoří s nulovým nebo jinak iniciovaným obsahem.
Existují ale i proměnné s všeobecnou (globální) platností – VAR_GLOBAL. Jsou deklarovány vně POU (obvykle před programem) a jsou dostupné pro všechny POU v programu. Za klíčovým slovem VAR_GLOBAL může být ještě uveden kvalifikátor RETAIN (tedy VAR_GLOBAL RETAIN), který označuje zálohované proměnné, nebo CONSTANT pro označení konstantního obsahu proměnné, tedy pro deklaraci konstanty. Celý blok deklarací tedy může mít tvar:
VAR_GLOBAL RETAIN
RemanentniBit BOOL;
RemanentniPamet BYTE := 123;
DalsiRemanent BYTE := 63;
END_VAR
V uvedeném příkladu jsou všechny tři proměnné deklarovány jako globální a remanentní. Po zapnutí (horkém restartu) se obnovuje jejich poslední obsah, který měly těsně před vypnutím. Bitová (booleovská) paměť RemanentniBit není iniciována, zatímco proměnné RemanentniPamet a DalsiRemanent jsou po prvním zapnutí a po studeném restartu iniciovány – nastavovány na hodnotu 123 a 63 (obě v desítkové soustavě).
Podobnou vlastnost mohou mít proměnné deklarované jako VAR_EXTERNAL. Zde je ale situace složitější. Obecně jsou takto deklarovány proměnné, které pocházejí z externího zdroje. V systému Mosaic jsou takto označeny proměnné definované v původním jazyku mnemokódů pro PLC systémy Tecomat. V jiných vývojových systémech to může být jinak.
Ladislav Šmejkal
Obr. 8. Ukázka definice jednoduchého funkčního bloku, funkce a programu v jazyce ST
Tab. 1. Příklady platných a neplatných identifikátorů
Tab. 2. Typy dat pro celočíselné objekty
Tab. 3. Typy dat pro objekty s pohyblivou desetinnou čárkou
Tab. 4. Typy dat pro časové údaje