REXLANG – Volně programovatelný blok

Symbol blokuPotřebná licence: REXLANG
PIC

Popis funkce
Standardní funkční bloky systému REXYGEN řeší většinu běžných požadavků na řízení. Existují však situace, kdy je nutný nebo efektivnější uživatelsky definovaný algoritmus. Blok REXLANG je určen pro tyto případy. Umožňuje implementaci uživatelsky definovaného algoritmu pomocí skriptovacího jazyka, který se blíží jazyku C (nebo Java).

Skriptovací jazyk
Skriptovací jazyk použitý v REXLANG se podobá jazyku C, ale existují významné rozdíly a omezení:

  • Podporované datové typy zahrnují double, long a string. Typy jako int, short a bool jsou interně konvertovány na long. Typ float je konvertován na double. Typ typedef není dostupný.
  • Ukazatele a struktury nejsou implementovány. Pole definovat lze a indexace je možná pomocí operátoru [ ]. Vstupy, výstupy a parametry bloku nemohou být pole.
  • Operátor ’,’ není implementován.
  • Preprocesor podporuje příkazy jako #include, #define, #ifdef .. [#else .. ] #endif, and #ifndef .. [#else .. ] #endif. Nicméně #pragma a #if .. [#else .. ] #endif nejsou podporovány.
  • Standardní knihovny ANSI C nejsou implementovány, ale mnoho matematických funkcí z math.h a další funkce jsou dostupné (viz níže).
  • Klíčová slova input, output a parameter se používají pro odkazování na vstupy, výstupy a parametry bloku REXLANG. Jsou implementovány systémové funkce pro řízení běhu a diagnostiku.
  • Funkce main() se provádí periodicky během běhu. K dispozici jsou i další funkce jako init() (prováděná jednou při spuštění), exit() (prováděná při zastavení řídícího algoritmu) a parchange() (prováděná při změnách parametrů).
  • Ve funkcích a procedurách bez parametrů musí být v deklaraci explicitně uvedeno void.
  • Přetěžování identifikátorů není povoleno, tj. klíčová slova a vestavěné funkce nemohou sdílet názvy s identifikátory. Lokální a globální proměnné musí mít různé názvy.
  • Nelze inicializovat pole, ať už globální nebo lokální.
  • Uživatelsky definované návratové hodnoty z main(), init() a exit() jsou zapsány do výstupu iE. Hodnoty < -99 zastaví provádění algoritmu (vyžaduje vstup RESET pro další provádění). Návratové hodnoty jsou kategorizovány následovně:
    iE >= 0

    indikuje, že vykonávání je bez chyb.

    0 > iE >= -99

    znamená varování bez ovlivnění provádění funkčního bloku.

    iE < -99

    naznačuje chybu, která zastaví provádění funkčního bloku.

Syntaxe skriptovacího jazyka
Syntaxe skriptovacího jazyka je založena na jazyku C, ale s některými úpravami:

  • <typ> input(<číslo vstupu>) <název proměnné>; pro vstupní proměnné.
  • <typ> output(<číslo výstupu>) <název proměnné>; pro výstupní proměnné.
  • <typ> parameter(<číslo parametru>) <název proměnné>; pro parametrické proměnné.

Proměnné input a parameter jsou pouze pro čtení, zatímco proměnné output jsou pouze pro zápis.

Příklad:

double input(1) vstup; /* deklarace proměnné vstup typu double, která  
                          představuje hodnotu vstupu bloku u1 */  
long output(2) vystup; /* deklarace proměnné vystup typu long, která  
                          představuje hodnotu výstupu bloku y2 */  
 
vstup = 3;             //nedovolený příkaz - do vstupu nelze přiřazovat  
sum = vystup + 1;      //nedovolený příkaz - z výstupu nelze číst hodnotu  
 
if (vstup>1) vystup= 3 + vstup;  //správné použití

Dostupné funkce
Skriptovací jazyk obsahuje širokou škálu funkcí, včetně matematických výpočtů, operací s vektory, manipulace s řetězci a systémových příkazů. Funkce jsou kategorizovány a podrobně popsány následovně:

  • Matematické funkce (v souladu s knihovnou math.h ANSI C):
    Tato kategorie zahrnuje funkce jako atan, sin, cos, exp, log, sqrt, tan, asin, acos, fabs, fmod, sinh, cosh, tanh, pow, atan2, ceil, floor a abs. Všimněte si, že abs je speciálně navržen pro celočíselné hodnoty, zatímco ostatní operují s proměnnými typu double. Pro výpočet absolutní hodnoty desetinného čísla slouží funkce fabs.
  • Vektorové funkce (nejsou v ANSI C) :
    Tato sada zahrnuje specializované funkce pro manipulaci s vektory:
    double max([n,] val1, …, valn)

    Vrací maximální hodnotu mezi zadanými prvky. První parametr, označující počet prvků, je volitelný.

    double max(n, vec)

    Hledá maximální hodnotu ve vektoru vec.

    ddouble min([n,] val1, …, valn)

    Podobně jako max, ale vrací minimální hodnotu.

    double min(n, vec)

    Hledá minimální hodnotu ve vektoru vec.

    double poly([n,] x, an, …, a1, a0)

    Vypočítá hodnotu polynomu y = anxn + + a1x + a0. První parametr je volitelný.

    double poly(n, x, vec)

    Vypočítá hodnotu polynomu y = vec[n]xn + + vec[1]x + vec[0].

    double scal(n, vec1, vec2)

    Vypočítá skalární součin dvou vektorů: y = vec1[0]vec2[0] + + vec1[n-1]vec2[n-1].

    double scal(n, vec1, vec2, skip1, skip2)

    Varianta scal, která umožňuje přeskočit prvky: y = vec1[0]vec2[0]+vec1[skip1]vec2[skip2]++vec1[(n-1)skip1]vec2[(n-1)skip2]. Tato varianta je vhodná pro násobení matic, které jsou uloženy jako vektory (řádek po řádku nebo sloupec po sloupci).

    double conv(n, vec1, vec2)

    Vypočítá konvolutorní součin dvou vektorů: y = vec1[0]vec2[n-1] + vec1[1]vec2[n-2] + + vec1[n-1]vec2[0].

    double sum(n,vec)

    Sečte prvky vektoru: y = vec[0] + vec[1] + + vec[n-1].

    double sum([n,] val1, ..., valn)

    Sečte zadané hodnoty. Počet prvků je volitelný.

    []array([n,] an-1, ..., a1, a0)

    Vytvoří pole/vektor se zadanými prvky. Parametr n je volitelný. Typ vrácené hodnoty je automaticky vybrán tak, aby odpovídal typu parametrů (všechny musí být stejného typu).

    []subarray(idx, vec)

    Vrátí pole vec začínající od indexu idx. Typ vrácené hodnoty je automaticky vybrán podle pole vec.

    copyarray(count, vecSource, idxSource, vecTarget, idxTarget)

    Kopíruje count prvků pole vecSource, začínající od indexu idxSource, do pole vecTarget, začínající od indexu idxTarget. Obě pole musí být stejného typu.

    void fillarray(vector, value, count)

    Kopíruje hodnotu value do count prvků pole vector (vždy od indexu 0).

    Poznámka: Funkce max, min, poly, scal, conv a sum jsou přetížené, což znamená, že mají několik variant založených na parametrech. Parametry jsou přísně kontrolovány podle typu, vyžadující přetypování pro typy jiné než double. Například:
    double res = max(dVal, (double)iVal, 1.0, (double)2);
    přetypuje iVal na double. Pokud parametr není typu double, je hlášena chyba s textem "no function of this prototype was found".

  • Funkce pro práci s řetězci (Tato sekce pokrývá funkce analogické těm, které se nachází v knihovně string.h v ANSI C a nabízí řadu operací pro manipulaci a analýzu řetězců:)
    string strsub(str, index, len)

    Extrahuje podřetězec z str, začínající na indexu idx a pokrývající len znaků.

    long strlen(str)

    Vrací délku řetězce str, měřeno v znacích.

    long strfind(str, substr[, offset])

    Najde první výskyt substr v str a vrací jeho pozici. Prohledávání začíná od znaku s indexem offset (pokud není zadán, tak od začátku). Parametr substr může být i znak.

    long strrfind(str, substr)

    Identifikuje poslední výskyt substr v str a poskytuje jeho index.

    strreplace(str, pattern, substr)

    Nahrazuje všechny instance pattern v str řetězcem substr. Tato úprava je provedena přímo v str.

    strupr(str)

    Převede všechny znaky v str na velká písmena.

    strlwr(str)

    Převede str na malá písmena.

    strtrim(str)

    Odstraní počáteční a koncové bílé znaky z str.

    long str2long(str[, default])

    Převede str na celé číslo. Pokud konverze selže, je vrácen volitelný druhý parametr (výchozí hodnota) nebo 0, pokud není poskytnut.

    double str2double(str[, default])

    Převede str na desetinné číslo. Podobně jako str2long, vrací volitelnou výchozí hodnotu nebo 0 v případě selhání.

    string long2str(num[, radix])

    Převede celé číslo num na řetězec s volitelným parametrem radix, který určuje základ (výchozí je 10). Výstupní řetězec neudává číselný systém (bez prefixů jako 0x pro hexadecimální).

    string double2str(num)

    Převede desetinné číslo num na jeho řetězcovou reprezentaci.

    strcpy(dest, src)

    Zkopíruje obsah src do dest. Pro kompatibilitu s ANSI C dosahuje stejného výsledku dest = src.

    strcat(dest, src)

    Připojí src na konec dest. Stejně jako v ANSI C, dest = dest + src provádí stejnou operaci.

    strcmp(str1, str2)

    Porovná dva řetězce str1 a str2. Pro stejný účel lze použít konstrukci str1 == str2, což je kompatibilní s ANSI C.

    float2buf(buf, x[,endian])

    Převede reálné číslo x do pole buf čtyř prvků, z nichž každý reprezentuje jeden byte čísla uloženého ve formátu IEEE 754 single precision (známé jako float). Funkce je užitečná pro naplnění komunikačních bufferů. Volitelný 3. parametr má následující význam:

    0

    nativní endian procesoru (výchozí),

    1

    little endian,

    2

    big endian.

    double2buf(buf, x[,endian])

    Podobně jako float2buf, ale pro dvojitou přesnost, ukládá osm prvků (typ double).

    double buf2float(buf[, endian])

    Inverzní funkce k float2buf.

    double buf2double(buf[, endian])

    Inverzní funkce k double2buf.

    long RegExp(str, regexp, capture[])

    Porovnává str s regulárním výrazem regexp, ukládá zachycené skupiny do capture. Vrací počet zachycených skupin nebo záporný kód chyby. Syntaxe regulárního výrazu zahrnuje standardní konstrukce jako:

    (?i)

    Musí být na začátku regulárního výrazu. Umožňuje porovnání bez ohledu na velikost písmen.

    ̂

    Porovnává začátek řetězce

    $

    Porovnává konec řetězce

    ()

    Skupinování a zachycování podřetězců

    \s

    Porovnává bílý znak

    \S

    Porovnává ne-bílý znak

    \d

    Porovnává desetinnou číslici

    \n

    Porovnává znak nového řádku

    \r

    Porovnává znak pro posun řádku

    \f

    Porovnává znak vertikální tabulace

    \v

    Porovnává znak horizontální tabulace

    \t

    Porovnává znak horizontální tabulace

    \b

    Porovnává znak zpětného posunu

    +

    Porovnává jeden nebo vícekrát (nenasytně)

    +?

    Porovnává jeden nebo vícekrát (nenenasytně)

    *

    Porovnává nula nebo vícekrát (nenasytně)

    *?

    Porovnává nula nebo vícekrát (nenenasytně)

    ?

    Porovnává nula nebo jednou (nenenasytně)

    x|y

    Porovnává x nebo y (operátor alternace)

    \meta

    Porovnává jeden z meta znaků: ^$().[]*+?|\

    \xHH

    Porovnává bajt s hexadecimální hodnotou 0xHH, např. \x4a.

    [...]

    Porovnává jakýkoliv znak ze sady. Podporovány jsou rozsahy jako [a-z].

    [^...]

    Porovnává jakýkoliv znak kromě těch ze sady.


    Příklad:
    RegExp("48,string1,string2","̂(\\d+),([̂,]+),",capture);
    Výsledek: capture=["48,string1","48","string1"]
    long ParseJson(json, cnt, names[], values[])

    Tato funkce zpracovává json řetězec, extrahuje hodnoty specifikovaných objektů. Pole names by mělo obsahovat názvy požadovaných vlastností (přístup k podpoložkám pomocí . a indexů pole pomocí [], například "cars[1].model"). Odpovídající hodnoty jsou poté umístěny do pole values. Parametr cnt určuje počet objektů k analýze, který by měl odpovídat délce obou polí names a values. Funkce vrací celkový počet úspěšně analyzovaných hodnot nebo zápornou hodnotu, pokud dojde během analýzy k chybě.

    Poznámka: Řetězcové proměnné jsou deklarovány stejně jako v ANSI C (char <název proměnné>[<max znaků>];). Pro argumenty funkcí použijte char <název proměnné>[] nebo string <název proměnné>.

  • Systémové funkce (nejsou v ANSI C)
    Archive(arc, type, id, lvl_cnt, value)

    Tato funkce archivuje hodnotu do archivačního podsystému systému. arc slouží jako bitová maska pro určení cílových archivů (například pro archivy 3 a 5 nastavte arc = 20, což je binárně 10100 nebo 20 v desítkové soustavě). Číslování archivů začíná od 1, s maximem 15 archivů (archiv 0 je vyhrazen pro interní systémové logy). Parametr type definuje datový typ s možnostmi:

    1

    Bool

    2

    Byte (U8)

    3

    Short (I16)

    4

    Long (I32)

    5

    Word (U16)

    6

    DWord (U32)

    7

    Float (F32)

    8

    Double (F64)

    9

    Time

    10

    Large (I64)

    11

    Error

    12

    String

    17

    Bool Group

    18

    Byte Group (U8)

    19

    Short Group (I16)

    20

    Long Group (I32)

    21

    Word Group (U16)

    22

    DWord Group (U32)

    23

    Float Group (F32)

    24

    Double Group (F64)

    25

    Time Group

    26

    Large Group (I64)

    27

    Error Group


    id představuje unikátní ID archivní položky, lvl_cnt označuje úroveň poplachu nebo počet prvků pro skupinové typy a value jsou data k archivaci.
    Trace(id, val)

    Zobrazuje hodnoty id a val. Funkce je určena zejména pro účely ladění. id je uživatelem definovaná konstanta v rozsahu od 0 do 9999 pro snadnou identifikaci zprávy. val může být jakýkoliv datový typ, včetně řetězců. Výstup se objevuje v systémovém logu REXYGEN.. Pro zobrazení těchto ladících zpráv v systémovém logu je nutné je povolit. Jděte do menu
    Target Diagnostic messages a zaškrtněte políčko Information v boxu Function block messages. Logování musí být také povoleno pro daný blok zaškrtnutím políčka Enable logging v záložce Runtime v dialogu parametrů bloku. Ve výchozím stavu je toto povoleno po umístění nového bloku z knihovny. Teprve poté jsou zprávy zobrazeny v Systémovém logu.

    TraceError(id, val) TraceWarning(id, val) TraceVerbose(id, val)

    Tyto příkazy mají podobný význam jako příkaz Trace, avšak výpis se objeví v jiné skupině systémového logu (Error, Warning, Verbose). Výpisy úrovně Error se do logu zapisují vždy, nezávisle na zaškrtnutí checkboxu Enable logging daného bloku. Zprávy úrovně Warning a Verbose je potřeba nejprve povolit, stejně jako v případě příkazu Trace.

    Suspend(sec)

    Přeruší provádění kódu skriptu, pokud od jeho puštění (v dané periodě) uplynulo více času (v sekundách), než je uvedeno. Při dalším spuštění bloku se pokračuje za tímto příkazem. Při Suspend(0) dojde k přerušení vždy.

    double GetPeriod()

    Vrací vlastní periodu spouštění daného bloku ve vteřinách.

    double CurrentTime()

    Vrací aktuální čas (v interním formátu). Používá se ve spojení s funkcí ElapsedTime().

    double ElapsedTime(new_time, old_time)

    Vrací uplynulý čas v sekundách (desetinné číslo), tj. rozdíl mezi časy určenými parametry new_time a old_time, získaným z předchozího volání funkce CurrentTime().

    double Random()

    Vrací pseudonáhodné číslo z intervalu 0,1). Před voláním funkce init() se automaticky inicializuje generátor pseudonáhodného čísla, takže sekvence je vždy stejná.

    long QGet(var)

    Vrací kvalitu proměnné var (tak jak s ní pracuje systém REXYGEN, viz bloky QFC, QFD, VIN, VOUT). Funkci je možno použít jen pro vstupy, parametry a výstupy - pro vnitřní proměnné vrací vždy 0.

    void QSet(var, value)

    Nastaví kvalitu proměnné var (tak jak s ní pracuje systém REXYGEN) na hodnotu val. Funkci je možno použít jen pro výstupy - pro ostatní se nic nenastaví.

    long QPropag([n, ]val1, …, valn)

    Vrací kvalitu, která vznikne sloučením kvalit val1,…,valn. Základní pravidlo pro slučování je, že výsledná kvalita je nejhorší ze vstupních. Pokud nastavíme kvalitu výstupu bloku s použitím této funkce, tak že do parametrů dáme kvalitu všech vstupů bloku, které výstup ovlivňují, dostaneme stejné chování jako u ostatních bloků systému REXYGEN.

    double LoadValue(fileid, idx)

    Čte hodnotu ze souboru. Podporuje jak binární soubory (s hodnotami double) tak textové soubory (hodnoty na samostatných řádcích). Soubor je identifikován fileid, a idx udává index (pro binární soubory) nebo číslo řádku (pro textové soubory). V současnosti jsou podporovány následující hodnoty:

    0

    soubor na disku identifikovaný parametrem p0,

    1

    soubor na disku identifikovaný názvem bloku REXLANG a příponou .dat,

    2

    soubor na disku identifikovaný parametrem srcname, ale přípona je změněna na .dat,

    3

    soubor rexlang.dat v aktuálním adresáři,

    4-7

    stejné jako 0-3, ale formát je textový soubor. Každý řádek obsahuje jedno číslo. Index idx je číslo řádku a začíná na nule. Hodnota idx=-1 znamená další řádek (např. sekvenční zápis).

    void SaveValue(fileid, idx, value)

    Ukládá hodnotu do souboru. Parametry jsou podobné jako u LoadValue.

    void GetSystemTime(time)

    Vrací systémový čas v UTC (upravitelný prostřednictvím nastavení operačního systému). Parametr time musí být pole alespoň 8 položek typu long. Funkce vyplní pole následujícími hodnotami v daném pořadí: rok, měsíc, den (v měsíci), den v týdnu, hodiny, minuty, sekundy, milisekundy. Na některých platformách má hodnota milisekund omezenou přesnost nebo není vůbec k dispozici (funkce vrací 0 ms).

    void Sleep(seconds)

    Zastaví provádění algoritmu bloku (a celého tasku) na definovanou dobu. Používejte tento blok s extrémní opatrností a pouze v případě, že neexistuje jiná možnost, jak dosáhnout požadovaného chování algoritmu. Doba uspání by neměla překročit 900 milisekund. Nejkratší interval je asi 0,01s, přesná hodnota závisí na cílové platformě.

    long GetExtInt(ItemID)

    Vrací hodnotu vstupu/výstupu/parametru libovolného bloku v algoritmu REXYGEN. Tato externí datová položka je odkazována parametrem ItemID. Struktura řetězcového parametru ItemID je stejná jako například v parametru sc bloku GETPI. Pokud nelze hodnotu získat (např. neplatné nebo neexistující ItemID, konflikt datového typu atd.), blok REXLANG ohlásí chybu a musí být resetován.

    long GetExtLong(ItemID)

    Viz GetExtInt(ItemID).

    double GetExtReal(ItemID)

    Stejný význam jako předchozí příkazy, ale pro desetinné číslo.

    double GetExtDouble(ItemID)

    Viz GetExtReal(ItemID).

    string GetExtString(ItemID)

    Stejný význam jako předchozí příkazy, ale pro řetězce/text.

    void SetExt(ItemID, value)

    Nastaví hodnotu vstupu/výstupu/parametru libovolného bloku v REXu určeného parametrem ItemID. Tento parametr je textový a má stejný význam/strukuturu jako parametr sc bloku SETPI. Nastavuje se hodnota parametru value, přičemž typ nastavené hodnoty (long/double/string) je určen typem parametru value. Pokud hodnotu nelze nastavit (např. neexistující ItemID nebo neodpovídá datový typ) blok REXLANG skončí chybou a je potřeba ho resetovat.

    int BrowseExt(ItemID, first_subitem_index, max_count, subitems, kinds)

    Funkce prochází adresový prostor úlohy. Pokud je ItemID identifikátorem bloku (cestou k bloku), pole řetězců subitems bude obsahovat názvy všech vstupů, výstupů, parametrů a vnitřních stavů. Funkce vrací počet podpoložek nebo záporný chybový kód. Hodnoty kinds jsou: executive = 0, module = 1, driver = 2, archive = 3, level = 4, task = 5, quicktask = 6, subsystem = 7, block = 8, input = 9, output = 10, internal state = 11, parameter or state array = 12, special = 13.

    long CallExt(ItemID)

    Spustí jeden krok jakéhokoli bloku v algoritmu REXYGEN, identifikovaného pomocí ItemID. Struktura textového parametru ItemID je stejná jako například u parametru sc bloku GETPI. Doporučuje se volat pouze pozastavené bloky (nastavte zaškrtávací políčko Halt na stránce vlastností Runtime v dialogu nastavení parametrů bloku), které by měly být ve stejném úkolu jako blok REXLANG. Funkce vrací výsledkový kód volaného bloku (viz chybové kódy REXYGEN).

    long GetInArrRows(input)

    Vrací počet řádek pole připojeného ke vstupu bloku REXLANG s indexem input.

    long GetInArrCols(input)

    Vrací počet sloupců pole připojeného ke vstupu bloku REXLANG s indexem input.

    long GetInArrMax(input)

    Vrací maximální (alokovanou) velikost pole připojeného ke vstupu bloku REXLANG s indexem input.

    double GetInArrDouble(input, row, col)

    Vrací prvek pole připojeného ke vstupu bloku REXLANG s indexem input.

    long GetInArrLong(input, row, col)

    Stejně jako GetInArrDouble(...), ale hodnota je typu long.

    Void SetInArrValue(input, row, col, value)

    Nastaví prvek pole připojeného ke vstupu bloku REXLANG s indexem input.

    Void SetInArrDim(input, row, col)

    Nastaví rozměr pole připojeného ke vstupu bloku REXLANG s indexem input.

    long memrd32(hMem,offset)

    Čtení fyzické paměti. Handle se získá pomocí funkce
    Open(72,"/dev/mem",<fyzická adresa>,<velikost oblasti>).

    long memwr32(hMem, offset, value)

    Zápis do fyzické paměti. Handle se získá funkce
    OpenMemory("/dev/mem",<physical address>,<area size>).

  • Komunikační funkce (nejsou v ANSI C)

    Tento soubor funkcí usnadňuje komunikaci přes různé kanály včetně TCP/IP, UDP/IP, sériových linek (RS-232 nebo RS-485), SPI sběrnice a I2C sběrnice. Níže je stručný seznam těchto funkcí. Pro podrobné informace viz příkladové projekty v systému REXYGEN.

    long OpenFile(string filename)

    Tato funkce otevře soubor a vrátí identifikační číslo (handle) souboru. Pokud funkce vrátí zápornou hodnotu, otevření souboru nebylo úspěšné.

    long OpenCom(string comname, long baudrate, long parity)

    Otevírá sériovou linku a vrátí její handle. Od verze 3.0 REXYGEN lze jako comname specifikovat virtuální porty. Pro podrobné informace o virtuálních portech viz popis bloku UART. Pokud je vrácena záporná hodnota, otevření selhalo. Možnosti nastavení parity jsou 0 pro žádnou, 1 pro lichou a 2 pro sudou.

    long OpenUDP(string localname, long lclPort, string remotename, long remPort)

    Otevírá UDP socket a vrátí jeho handle. Pokud funkce vrátí zápornou hodnotu, otevření socketu nebylo úspěšné. Funkce může otevřít buď IPv4 nebo IPv6 socket na základě remotename, localname nebo nastavení operačního systému, pokud je použito DNS jméno. Volitelná nastavení zahrnují prázdný localname (jakékoli rozhraní), prázdný remotename nebo 0 pro remPort (nepoužívá se) a 0 pro lclPort (přiděleno UDP/IP stackem).

    long OpenTCPsvr(string localname, long lclPort)

    Tato funkce otevírá TCP socket v režimu serveru (poslechu). Vrací handle socketu a záporná návratová hodnota znamená neúspěšné otevření. Funkce může otevřít buď IPv4 nebo IPv6 socket v závislosti na remotename, localname nebo nastavení operačního systému, pokud je použito DNS jméno. Můžete nastavit prázdný localname jako jakékoli rozhraní.

    long OpenTCPcli(string remotename, long remPort)

    Otevírá TCP socket v režimu klienta a vrátí jeho handle. Záporná návratová hodnota znamená selhání otevření socketu. Funkce otevírá buď IPv4 nebo IPv6 socket na základě remotename, localname nebo nastavení operačního systému, pokud je použito DNS jméno. Všimněte si, že tato funkce nečeká na navázání spojení, což může trvat několik milisekund v místní síti nebo několik sekund pro vzdálené lokace. Pokud jsou volány Write() nebo Read() před navázáním spojení, je vrácen chybový kód -307 (chyba otevření souboru).

    long OpenI2C(string devicename)

    Otevírá I2C sběrnici a vrátí její handle. Pokud funkce vrátí zápornou hodnotu, otevření nebylo úspěšné.

    long OpenSPI(string devicename)

    Otevírá SPI sběrnici a vrátí její handle. Záporná návratová hodnota znamená neúspěšné otevření.

    long OpenDevice(string filename)

    Podobně jako OpenFile(), ale funkce Write() a Read() jsou neblokující. Pokud nelze data číst nebo zapisovat, funkce okamžitě vrátí chybový kód -1.

    long OpenMemory(string devicename, long baseaddr, long size)

    Mapuje fyzickou paměť a vrátí přidružený handle. Pokud je vrácena záporná hodnota, operace nebyla úspěšná.

    long OpenSHM(string devicename, long deviceid, long size, long flags)

    Mapuje sdílenou paměť (pouze v Linuxu, využívá ftok() a shmget()) a vrací přidružený handle. První a druhý parametr slouží k identifikaci paměťové oblasti (musí být shodné pro všechny kooperující entity). Parametr size udává velikost sdílené paměťové oblasti v bajtech. Parametr flags reprezentuje standardní linuxové příznaky a oprávnění (pokud je nastaveno na 0, což je výchozí hodnota, jsou nastavena následující práva: vytvořit oblast, pokud neexistuje, a umožnit všem čtení i zápis).

    void Close(long handle)

    Zavře socket, sériovou linku, soubor nebo jakékoli zařízení otevřené pomocí funkcí Open....

    void SetOptions(long handle, long params[])

    Nastavuje parametry socketu nebo sériové linky. Velikost pole musí být alespoň:

    22

    pro sériovou linku (na Windows parametry pro SetCommState() a SetCommTimeouts() v následujícím pořadí: BaudRate, fParity, Parity, StopBits, ByteSize, fDtrControl, fRtsControl, fAbortOnError, fBinary, fErrorChar, fNull, fDsrSensitivity, fInX, fOutX, fOutxCtsFlow, fOutxDsrFlow, fTXContinueOnXoff, ReadIntervalTimeout, ReadTotalTimeoutConstant, ReadTotalTimeoutMultiplier, WriteTotalTimeoutConstant, WriteTotalTimeoutMultiplier; linux používá odlišnou funkci, ale význam parametrů je stejný, pokud je to možné),

    2

    pro soubor (1. položka je mód: 1=vyhledání od začátku, 2=vyhledání od aktuální pozice, 3=vyhledání od konce, 4=nastavit konec souboru, 2. položka je posun pro vyhledání),

    3

    pro SPI (1. položka je režim SPI, 2. položka je počet bitů na slovo, 3. položka je maximální rychlost v Hz),

    5

    pro I2C (1. položka je adresa zařízení, 2. položka je příznak 10bitové adresy, 3. položka je příznak kontroly chyb v balíčku, 4. položka je počet pokusů, 5. položka je časový limit),

    ostatní

    typy handle nejsou podporovány

    void GetOptions(long handle, long params[])

    Načte parametry socketu nebo sériové linky a uloží je do pole params. Velikost pole musí odpovídat požadavkům daného zařízení (viz SetOptions).

    long Accept(long hListen)

    Přijme spojení na poslouchajícím socketu a vrátí handle komunikačního socketu nebo chybový kód.

    long Read(long handle, long buffer[], long count[, offset])

    Přijímá data ze sériové linky nebo socketu a vrátí počet přečtených bajtů nebo chybový kód. Parametr count definuje maximální počet bajtů k přečtení. Každý bajt příchozích dat je vložen do pole buffer typu long ve stejném pořadí. Funkce má ještě jeden (nepovinný) parametr offset, který lze použít při čtení dat z paměti, kdy je handle vytvořen pomocí OpenSHM() nebo OpenMemory().

    Lze také použít zápis
    long Read(long handle, string data[], long count) (tj. používá se řetězec místo pole dat; jeden bajt ve vstupním souboru odpovídá jednomu znaku; nelze použít pro binární soubory).
    Chybové kódy jsou:

    -1

    je nutné počkat na dokončení operace (funkce je "neblokující")

    -309

    čtení selhalo; chybový kód operačního systému se zobrazí v logu (pokud je povoleno logování bloků funkcí)

    -307

    soubor/socket není otevřen

    long Write(long handle, long buffer[], long count[, offset])

    Odesílá data přes sériovou linku nebo socket. Parametr count definuje počet bajtů k odeslání. Počet odeslaných bajtů nebo chybový kód je vrácen. Každý bajt odchozích dat je přečten z pole buffer typu long ve stejném pořadí. Funkce má ještě jeden (nepovinný) parametr offset, který lze použít pro zápis dat do paměti, kdy je handle vytvořen pomocí OpenSHM() nebo OpenMemory().

    Lze také použít formu
    long Write(long handle, string data) (tj. používá se řetězec místo pole dat; jeden bajt ve výstupním souboru odpovídá jednomu znaku; nelze použít pro binární soubory).
    Chybové kódy jsou:

    -1

    je nutné počkat na dokončení operace (funkce je "neblokující")

    -310

    zápis selhal; chybový kód operačního systému se zobrazí v logu (pokud je povoleno logování bloků funkcí)

    -307

    soubor/socket není otevřen

    long ReadLine(long handle, string data)

    Čte řádek z (textového) souboru, sériové linky nebo socketu a ukládá znaky do data až do jejich alokované velikosti. Funkce vrátí skutečnou velikost řádku nebo chybový kód.

    long DeleteFile(string filename)

    Smaže soubor. Vrací 0 pokud je soubor smazán; záporné číslo znamená chybu.

    long RenameFile(string filename, string newfilename)

    Přejmenuje soubor. Vrací 0 pokud je soubor přejmenován; záporné číslo znamená chybu.

    bool ExistFile(string filename)

    Ověří, zda soubor nebo zařízení existuje (lze otevřít pro čtení), vrátí true nebo false.

    long I2C(long handle, long addr, long bufW[], long cntW, long bufR[], long cntR)

    Zajišťuje komunikaci přes sběrnici I2C, zejména na Linuxových systémech s možností I2C (např. Raspberry Pi). Funkce odesílá a přijímá data do/z slave zařízení pomocí addr. Parametr handle je vrácen funkcí OpenI2C, jejíž parametr určuje název zařízení (podle operačního systému). Parametr bufW je buffer (pole) pro data, která se odesílají, cntW je počet bajtů k odeslání, bufR je buffer (pole) pro příchozí data a cntR je počet bajtů k přijetí. Funkce vrací 0 nebo chybový kód.

    long SPI(long handle, 0, long bufW[], long cntW, long bufR[], long cntR)

    Provede transakci přes sběrnici SPI, zejména na Linuxových systémech se sběrnicí SPI. Parametr handle je vrácen funkcí OpenSPI, jejíž parametr určuje název zařízení (podle operačního systému). Druhý parametr je vždy 0 (rezervováno pro interní použití). Parametr bufW je buffer (pole) pro data, která se odesílají, cntW je počet bajtů k odeslání, bufR je buffer (pole) pro příchozí data a cntR je počet bajtů k přijetí. Všimněte si, že komunikace přes sběrnici SPI je full-duplex, proto výsledná délka transakce SPI je dána maximem parametrů cntW a cntR, nikoli jejich součtem. Funkce vrací 0 nebo chybový kód.

    long Seek(long handle, long mode[], long offset)

    Nastaví pozici pro příkazy Read/Write. Parametr mode znamená:

    1

    posun od začátku souboru,

    2

    posun od aktuální pozice,

    3

    posun od konce souboru.

    long Recv(long handle, long buffer[], long count)

    Zastaralá funkce. Použijte Read.

    long Send(long handle, long buffer[], long count)

    Zastaralá funkce. Použijte Write.

    long crc16(data, length, init, poly, flags, offset)

    Vypočítá 16bitový cyklický redundantní kód (CRC), běžně používaný jako kontrolní součet nebo hash v různých komunikačních protokolech.

    data
    Pole bajtů (reprezentováno polem typu long) nebo řetězec, pro který se vypočítává hash.
    length
    Počet bajtů ve vstupním poli nebo textu. Použijte -1 pro zpracování celého řetězce.
    init
    Počáteční vektor pro výpočet CRC.
    poly
    Kontrolní polynom použitý ve výpočtu.
    flags
    Konfigurační příznaky:
    • 1: Obrací pořadí bitů jak ve vstupních bajtech, tak ve výsledném CRC.
    • 2: Výsledné CRC je XORováno s 0xFFFF.
    • 4: Pokud je data pole typu long, jsou zpracovány všechny 4 bajty v prvku pole (LSB první).
    • 8: Podobně jako příznak 4, ale zpracovává MSB první.
    offset
    Index prvního zpracovávaného bajtu v datovém poli (obvykle 0).

    Poznámka: Existují analogické funkce pro výpočet 32bitového a 8bitového CRC: long crc32(data, length, init, poly, flags, offset) a long crc8(data, length, init, poly, flags, offset). Počáteční vektor, kontrolní polynom a příznaky pro různé protokoly lze nalézt na https://crccalc.com/

    Příklady:

    • MODBUS: crc16("123456789", -1, 0xFFFF, 0x8005, 1, 0)
    • DECT-X: crc16("123456789", -1, 0, 0x0589, 0, 0)

    Další poznámka: Funkce crc8(...) a crc32(...) také existují, podporují výpočty 8bitových a 32bitových CRC se stejnou strukturou parametrů.

Ladění kódu, debugging
Pro ladění kódu je k dispozici příkaz Trace, viz výše. Dále lze použít výstupy bloku, které se nouužívají pro vlastní algoritmus a zapisovat do nich hodnoty různých mezivýpočtů. V závislosti na povaze algoritmu může být vhodné tyto ladící hodnoty připojit do trendu. Pokud je potřeba sledovat hodnot více, je možné do tasku přidat blok CNA (připojený na TRNDV nebo VTOR) a do hodnot v jeho poli nastavovat opět růyné mezivýsledky pomocí funkce SetExt.

Poznámky

  • Datové typy vstupů u0..u15, výstupů y0..y15 a parametrů p0..p15 jsou určeny během kompilace zdrojového kódu.
  • Chybové kódy < -99 vyžadují vstup RESET pro restartování bloku REXLANG po řešení příčiny chyby.
  • POZOR!!! Ve funkci init() je sice možné číst vstupy, ale protože ostatní bloky obvykle nenastavují v init fázi výstupy, bude tam vždy 0. Nastavovat výstupy lze, ale obvykle se to nedělá.
  • Skript může obsahovat cestu v parametru srcname; pokud ne, očekává se soubor v adresáři projektu nebo ve specifikovaných adresářích (viz parametr LibraryPath bloku PARAM).
  • Parametr srcname je možné udávat s absolutní cestou. V opačném případě se soubor hledá na aktuálním adresáři a specifikovaných adresářích (viz parametr LibraryPath bloku PARAM).
  • Parametry vektorových funkcí jsou primárně typu double, s výjimkou parametru n, který je typu long. Funkce s jedním vektorovým parametrem existují ve třech variantách:
    double function(val1,…,valn)

    Vektor je definován jako sekvence hodnot typu double.

    double function(n,val1,…,valn)

    Vektor je definován jako v prvním případě, pouze první parametr definuje počet hodnot – velikost vektoru. Tato varianta je kompatibilní s kompilátorem jazyka C. Parametr n (Volitelný parametr n vektorových funkcí musí být specifikován, pokud je vyžadována kompatibilita s kompilátorem jazyka C/C++. V takovém případě musí být implementovány také všechny nestandardní funkce a funkce s proměnným počtem parametrů musí znát počet parametrů.) musí být číslo, nikoli tzv. const proměnná, a musí odpovídat počtu následujících prvků definujících vektor.

    double function(n,vec)

    Parametr n je libovolný výraz typu long a definuje počet prvků, které funkce zohledňuje.

  • Je důležité si pamatovat, že pole v skriptovacím jazyku se chovají podobně jako pole v jazyce C: indexace začíná od 0 a neexistuje automatická kontrola hranic. Například pokud deklarujete double vec[10], x;, pole vec bude mít prvky indexované od 0 do 9. Přístup k vec[10] nevyvolá chybu syntaxe ani runtime, ale vrácená hodnota je nedefinovaná, protože leží mimo hranice pole. Navíc přiřazení hodnoty k vec[11] (např. vec[11] = x;) může být obzvlášť nebezpečné, protože může nechtěně přepsat sousední paměťová místa. To by mohlo vést k nepředvídatelnému chování nebo způsobit pád programu.
  • Během kompilačního procesu, pokud existují chyby syntaxe, kompilátor hlásí parser error spolu s číslem řádku, kde došlo k chybě. Tyto hlášení konkrétně ukazují na problémy se syntaxí. Pokud však syntaxe vypadá správně a chyba je stále hlášena, je vhodné zkontrolovat konflikty zahrnující identifikátory, klíčová slova nebo názvy funkcí, jelikož tyto mohou také způsobit chyby neokamžitě zřejmé jako chyby syntaxe.
  • Všechny skoky jsou přeloženy jako relativní, tj. odpovídající kód je omezen na 32767 instrukcí (ve formátu přenosném pro různé platformy).
  • Všechny platné proměnné a výsledky dočasných výpočtů jsou uloženy v zásobníku, který zahrnuje:
    • Globální a lokální static proměnné jsou trvale umístěny na začátku zásobníku.
    • Návratové adresy pro volání funkcí.
    • Parametry funkcí.
    • Proměnné lokální pro funkce.
    • Návratová hodnota funkce.
    • Dočasné výsledky výpočtů. Například ve výrazu a = b + c; jsou nejprve b a c vloženy na zásobník. Jejich součet je pak vypočítán, operandy jsou odstraněny ze zásobníku a výsledek je vložen na zásobník.

    Jednoduché proměnné, jako jsou long nebo double, zabírají jeden slot zásobníku. U polí záleží na celkové velikosti, bez ohledu na typ prvků.

  • Když jsou pole předávána funkcím, jsou referencována, nikoli kopírována. To znamená, že pro referenci je použit pouze jeden slot zásobníku a funkce přímo pracuje s původním polem.
  • Pokud je alokovaná velikost zásobníku nedostatečná (méně než prostor potřebný pro globální proměnné plus 10), automaticky se zdvojnásobí, s dalšími 100 sloty pro výpočetní potřeby, parametry funkcí a lokální proměnné, zejména pokud je definováno málo globálních proměnných.
  • Při základní úrovni ladění jsou během provádění skriptu prováděny různé kontroly. Ty zahrnují inicializaci čtených hodnot a kontrolu hranic indexů polí. Navíc je na začátek a konec každého deklarovaného pole vloženo několik neinicializovaných hodnot pro kontrolu hranic a do souboru *.ill jsou přidány instrukce NOP s čísly řádků zdrojového souboru.
  • Při úplné úrovni ladění je povolena další kontrola neplatných přístupů k datovým rozsahům (jako jsou přetečení zásobníku).
  • V tomto kontextu se ’instrukcí’ rozumí procesorově nezávislý mnemonický kód. Tyto kódy jsou uloženy v souboru *.ill.
  • Funkce OpenCom() nastaví binární neblokující režim bez timeoutů, 8 datových bitů, 1 stopbit, bez parity, 19200Bd. Volitelně lze upravit baudrate a parity parametr ve funkci OpenCom().
  • Přístup k textovým souborům je výrazně pomalejší než k binárním souborům. Textové soubory však mají výhodu, že jsou viditelné a upravitelné bez specializovaného software.
  • Blok automaticky nevyvolá funkci parchange(). Tato funkce musí být manuálně volána v rámci funkce init(), pokud je to potřeba.
  • Funkce OpenFile() otevírá soubory v datovém adresáři systému REXYGEN (tj. v Linuxu implicitně v \rex\data, na Windows
    C:\ProgramData\REX Controls\REX_<verze>\RexCore). Jsou dovoleny podadresáře, ale není dovoleno ..\. Linky se následují.

Ladění kódu
Použijte výše uvedený příkaz Trace.

Vstupy

HLD

Pozastavení – kód bloku se nevykonává, je-li hodnota rovna on.

Bool

RESET

Resetování chyby při náběžné hraně; blok se znovu inicializuje (vynulují se všechny globální proměnné a zavolá se funkce Init())

Bool

u0..u15

Vstupní signály, jejichž hodnoty jsou přístupné ve skriptu

Any

Výstupy

iE

Kód chyby při běhu skriptu. Pro chybové < -99 je provádění algoritmu bloku zastaveno do reinicializace vstupem RESET nebo novým spuštěním exekutivy

Error

0 ....

vše v pořádku, proběhla celá funkce main() popř. init()

-1 ...

provádění programu skončilo příkazem Suspend(), tj. vypršel čas pro výpočet; výpočet bude při dalším spuštění bloku pokračovat tam, kde skončil

< -1 .

chybový kód xxx systému REXYGEN, více viz příloha C

> 0 ..

uživatelské návratové hodnoty, běh algoritmu beze změny

y0..y15

Výstupní signály, jejichž hodnoty jsou definovány ve skriptu

Any

Parametry

srcname

Jméno souboru se skriptem  srcfile.c

String

srctype

Typ zdrojového souboru  1

Long (I32)

1: C-like 

Textový soubor s výše popisovanou syntaxí obdobnou jazyku C.

2: STL 

Textový soubor se syntaxí dle IEC61131-3. Norma je implementována se stejnými omezeními jako C-like skript (tj. žádné struktury, z typů jen INT a REAL a STRING, vstupy bloku jsou globální VAR_INPUT, výstupy bloku jsou globální VAR_OUTPUT, parametry bloku jsou globální VAR_PARAMETER, standardní funkce dle specifikace, systémové a komunikační funkce jako v C-like)

3: RLB 

Soubor v binárním formátu, který vzniká při překladu z formátu STL i C-like. Tento formát použijeme, pokud chceme předat fungující blok někomu jinému a nechceme mu dát zdrojové soubory.

4: ILL 

Textový soubor, ale zapisují se mnemonické kódy instrukcí, do kterých je překládán formát STL. Dalo by se to přirovnat k assembleru. V současnosti není tento formát podporován.

stack

Velikost zásobníku pro všechny výpočty a proměnné. Zadává se jako počet proměnných, které se mají do zásobníku vejít. Výchozí hodnota 0 znamená, že velikost zásobníku se zvolí automaticky, což ve většině případů vyhovuje.

Long (I32)

debug

Úroveň/množství ladicích kontrol a informací; větší číslo znamená více kontrol a tím pomalejší běh algoritmu; volbu bez kontroly se doporučuje nepoužívat (může vést až k pádu aplikace na cílové platformě při nesprávně napsaném kódu).  3

Long (I32)

1 ....

bez kontroly

2 ....

základní kontrola

3 ....

úplná kontrola

strs

Velikost paměti (zásobníku) pro všechny texty. Zadává se jako počet byte/znaků, které se mají do zásobníku vejít. Výchozí hodnota 0 znamená, že velikost zásobníku se zvolí automaticky, což ve většině případů vyhovuje.

Long (I32)

p0..p15

Parametry, jejichž hodnoty jsou přístupné ze skriptu

Any

Příklad C-like
Následující příklad ukazuje jednoduchý kód pro sečtení dvou vstupních signálů a také sečtení dvou uživatelsky definovaných parametrů.

double input(0) input_u0;  
double input(2) input_u2;  
 
double parameter(0) param_p0;  
double parameter(1) param_p1;  
 
double output(0) output_y0;  
double output(1) output_y1;  
 
double my_value;  
 
long init(void)  
{  
    my_value = 3.14;  
    return 0;  
}  
 
long main(void)  
{  
    output_y0 = input_u0 + input_u2;  
    output_y1 = param_p0 + param_p1 + my_value;  
    return 0;  
}  
 
long exit(void)  
{  
    return 0;  
}

Příklad STL
A zde je stejný příklad ve strukturovaném textu.

VAR_INPUT  
    input_u0:REAL;  
    input_u1:REAL;  
    input_u2:REAL;  
END_VAR  
 
VAR_OUTPUT  
    output_y0:REAL;  
    output_y1:REAL;  
END_VAR  
 
VAR_PARAMETER  
    param_p0:REAL;  
    param_p1:REAL;  
END_VAR  
 
VAR  
    my_value: REAL;  
END_VAR  
 
FUNCTION init : INT;  
    my_value := 3.14;  
    init := 0;  
END_FUNCTION  
 
FUNCTION main : INT;  
    output_y0 := input_u0 + input_u2;  
    output_y1 := param_p0 + param_p1 + my_value;  
    main := 0;  
END_FUNCTION  
 
FUNCTION exit : INT;  
    exit := 0;  
END_FUNCTION

2024 © REX Controls s.r.o., www.rexygen.com