REXLANG – Volně programovatelný blok

Symbol blokuPotřebná licence: REXLANG
PIC

Popis funkce
V některých případech se může stát, že je do řídícího algoritmu nutné implementovat funkci, kterou nelze efektivně vytvořit z dostupné množiny bloků. Pro takový účel byl vyvinut blok REXLANG, který implementuje algoritmus definovaný skriptovacím jazykem. Je použit skriptovací jazyk velice podobný jazyku C (nebo Java).

Skriptovací jazyk
Jak již bylo řečeno, skriptovací jazyk vychází z jazyka C a je mu velmi podobný, nicméně existují určité rozdíly a omezení:

Syntaxe skriptovacího jazyka
Syntaxe skriptovacího jazyka vychází z jazyka C, přičemž nejsou podpořeny pointery a jiné typy než long a double. Navíc jsou definována klíčová slova input, output a parameter, která slouží pro odkazování na vstupy, výstupy a parametry bloku. Syntaxe je následující:

Proměnné typu input a parameter lze pouze číst a do proměnných typu output lze pouze přiřazovat. Napří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
Ve skriptovacím jazyce je možné používat následující funkce:

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

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

unknown

Výstupy

iE

Kód chyby při běhu skriptu (kromě kódu 0 a -1 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

xxx ..

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

y0..y15

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

unknown

Parametry

srcname

Jméno souboru se skriptem  srcfile.c

string

srctype

Typ zdrojového souboru  1

long

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

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

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

p0..p15

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

unknown

Příklad
Následující příklad implementuje lineární model procesu definovaný vahovou funkcí (filtr typu FIR) doplněný o saturaci na vstupu. Příklad je napsán tak, aby ukazoval různé konstrukce použitého skriptovacího jazyka. Algoritmus by bylo možné realizovat i jednodušším postupem.

double input(0) vstup;  //promenna ’vstup’ predstavuje hodnotu u0  
double output(0) vystup; //promenna ’vystup’ predstavuje prirazeni do y0  
double stav[20], param[20];  
const long count=20;  
 
long init(void)  
{  
    long i;  
    const double a=0.95;  
    param[0]=0.2;param[5]=0.2;param[10]=0.2;param[12]=0.2;param[15]=0.2;  
    for(i=0;i<count;i++)  
    {  
        param[i]=param[i]+exp(-i*a)/a;  
        Trace(1,param[i]);  
    }  
    return 0;  
}  
 
long main(void)  
{  
    long i;  
    double soucet=0.0;  
    for(i=0;i<count-1;i++)  
        stav[i]=stav[i+1];  
    if(fabs(vstup)>1)  
        stav[count-1]=(vstup>0)? 1 : -1;  
    else  
        stav[count-1]=vstup;  
    for(i=0;i<count;i++)  
    {  
        soucet+=stav[i]*param[count-1-i];  
        Suspend(0.1);  
    }  
    vystup=soucet;  
    return 0;  
}  
 
long exit(void){return 0;}

a tentýž příklad v STL syntaxi:

VAR_INPUT  
  vstup:REAL;  //promenna ’vstup’ predstavuje hodnotu u0  
END_VAR  
 
VAR_OUTPUT  
  vystup:REAL; //promenna ’vystup’ predstavuje prirazeni do y0  
END_VAR  
 
VAR_PARAMETER  
  tt:REAL; //promenna ’tt’ predstavuje hodnotu parametru p0  
END_VAR  
 
VAR  
  param, stav : ARRAY[0 .. 19] OF REAL;  
END_VAR  
 
VAR CONSTANT  
  count:INT := 20;  
END_VAR  
 
FUNCTION init : INT;  
VAR  
  i:INT;  
END_VAR  
 
VAR CONSTANT  
    a:REAL := 0.95;  
END_VAR  
    param[0]:=0.2; param[5]:=0.2; param[10]:=0.2; param[12]:=0.2; param[15]:=0.2;  
    FOR i:=0 TO count-1 DO  
        param[i] := param[i] + EXP(-i*a)/a;  
        Trace(1,param[i]);  
    END_FOR  
 
    init := 0;  
END_FUNCTION  
 
 
FUNCTION main : INT;  
VAR  
  i:INT;  
  soucet:REAL := 0.0;  
END_VAR  
 
    FOR i:=0 TO count-2 DO  
        stav[i] := stav[i+1];  
    END_FOR  
 
    IF abs(vstup)>1 THEN  
IF vstup>0.0 THEN  
            stav[count-1] := 1;  
ELSE  
    stav[count-1] := -1;  
END_IF  
    ELSE  
        stav[count-1] := vstup;  
    END_IF  
 
    FOR i:=0 TO count-1 DO  
        soucet := soucet+stav[i]*param[count-1-i];  
     IF tt>0.0 THEN  
           Suspend(tt);  
        ELSE  
           Suspend(0.1);  
END_IF  
    END_FOR  
 
    vystup := soucet;  
    main := 0;  
END_FUNCTION  
 
FUNCTION exit : INT;  
    exit := 0;  
END_FUNCTION