Konfigurace Scriptable pluginu

ScriptablePlugin umožňuje provádět nad piny složitější operace a dá se rovněž použít pro generování různých funkcí na výstupech. Celý plugin dokáže emulovat funkčnost většiny ostatních pluginů s vyjímkou těch, které přímo komunikují s HW (ISESCardPlugin, ISESProCardPlugin, PCI1202CardPlugin). Interface dostupný přímo z MeasureServeru je minimální a většina operací se provádí pomocí scriptu uloženého v samostatném souboru.

Dialog v MeasureServeru

Pomocí tohoto dialogu jdou měnit základní parametry. Jakákoliv změna parametru vyžaduje restart MeasureServeru.

V dialogu MeasureServeru (viz. hlavní dokumentace) je nejdůležitější řádek pro volbu souboru se scriptem, který popisuje chování pluginu, dostupné piny a ostatní použité pluginy.

V případě, že script používá i jiné pluginy, je možné pomocí dalšího prvku umístěného v dialogu, nastavovat jejich parametry.

Script

Scripty jsou textové soubory s koncovkou psc. Tyto scripty jsou načteny při startu MeasureServeru. Případné změny v nich provedené se projeví až při dalším spuštění MeasureServeru. Syntaxe použítá ve scriptu nejvíce připomíná programovací jazyk C s některými prvky z jiných jazyků. Všechny proměnné jsou reálná čísla (typ double v C), jiný datový typ není přímo podporovaný. Rozlišují se velká a malá písmena! Všechny operace prováděnné scriptem jsou synchronní s celým během serveru (dokud běží script, tak server nemůže provádět nic jiného).

Struktura scriptu je částečně fixní s tím, že většina částí je nepovinná, ale pokud jsou uvedeny tak musí být ve správném pořadí.

Struktura scriptu je následující:

  1. Hlavička - povinná
  2. Definice importu - nepovinná
  3. Definice proměnných - nepovinná
  4. Definice pinů a speciálních handlerů - nepovinná
  5. Definice burst experimentů - nepovinná

Na většině míst v textu je možno používat komentáře uvedené znakem '#'. Cokoliv od tohoto znaku do konce řádku je ignorováno.

Hlavička

Hlavička má následující povinný formát

version 1.0
name example_generator
Kde:

Definice importu

Popisuje jaké piny a z kterých pluginů budou použity. Piny se ve zbytku scriptu chovají jako proměnné. Zápis do takovéto proměnné zapíše hodnotu do pinu druhého pluginu. Čtení z takovéto proměnné přečte hodnotu z pinu druhého pluginu. Tato sekce má dvě části, jejichž pořadí je pevně dáno. První část definuje další pluginy, které jsou použity, včetně jména jejich konfigurace. Formát této části je následující:

using plugin_id "path_to_plugin" config_id
Kde: Příklad definice:
using hw_lib "Plugins\ISESProCardPlugin.ldp" config1

Druhá část pak identifikuje piny z pluginů definovaných v první části, které jsou scriptem používány. Formát této části je následující:

import pin_id plugin_id "pin_name" [filter]
Kde: Příklad definice:
import output_a hw_lib "Write D/A 1"

Definice proměnných

Popisuje globální proměnné dostupné v celém scriptu. Proměnné vzniknou při startu serveru a nastaví se na hodnotu uvedenou v jejich definici. Následně může script jejich hodnoty libovolně číst a měnit. Formát definice proměnné je následující:

variable variable_id = value
Kde: Příklad definice:
variable sfrequency = 1.345

Definice pinů a speciálních handlerů

Tato část obsahuje výkonnou činnost scriptu. Celá je tvořena z bloků které mají následující syntaxi:

block_type [block_id] { operations }
Kde:

Typy bloků

Handlery on_each_second a on_user_change

Operace asociované s jedním z těchto handlerů se spustí, pokud nastane operace asociovaná s handlerem.

Operace asociované s on_each_second se spusti přibližně každou sekundu.

Operace asociované s on_user_change se spustí, když dojde ke změně uživatele nebo odpojení posledního uživatele.

V případě, že je v souboru scriptu definováno několik handlerů stejného typu, se všechny provedou v pořadí uvedeném ve scriptu.

Piny pin_read a pin_write

Operace asociované s těmito piny se spustí pří přečtení nebo žápisu hodnoty pinu jménem block_id. Je možné mít v jednom scriptu pin_read i pin_write se stejným block_id, ale není možné mít ve scriptu několik pin_read/pin_write se stejným block_id.

Neexistuje žádné omezení z jakých pinů z ostatních pluginů je možné v rámci bloku číst nebo na které je možné zapisovat. Čtecí handler pro pin může klidně zapisovat na pin jiného pluginu. To umožňuje tvorbu generátorů signálu jak je uvedeno v kapitole Příklady

V případě, že běží handler pin_write, je dostupná speciální proměnna new_value s hodnotou, která se má zapsat do pinu.

V případě, že běží handler pin_read, je dostupná speciální proměnná time, která obsahuje čas v sekundách od posledního zápisu do tohoto pinu popřípadě od startu serveru pokud k žádnému zápisu dosud nedošlo. V případě, že odpovídající pin_write handler neexistuje, je zápis na tento pin ignorován, ale k restartu času dojde. Dále je zde dostupná speciální proměnná result, do níž by měl pin uložit hodnotu, která se vrátí jako hodnota přečtená z pinu. Defaultně je v této proměnné na začátku bloku uložena hodnota 0. Dále je dostupná proměnná reset_time, která (pokud je na konci nastavena na kladnou hodnotu), způsobi restart hodnoty time. V případě experimentů, jejichž server běží dlouhodoběji, je potřeba jednou za čas provést tento restart, jinak dojde ke ztrátě přesnosti času uloženého v proměnné time. V závislosti na HW počítače a velikosti hodnoty proměnné time může být čas vyjádřen až s přesností na desetinu milisekundy.

Experiment

Úvod

Tento blok representuje krátkodobý experiment (aktuálně je limitovaný na maximálně 10s), který vyžaduje vysokou vzorkovací frekvenci záznamu a případně i vysokou přesnost výstupu. Příkladem je experiment volného pádu nebo přechodového děje v cívce. block_id je jméno, pod kterým je experiment dostupný klientovi. Experiment je složen z následujících tří povinných částí: celá struktura popisu experimentu vypadá následovně:
experiment foo {
  init { operations }
  on_sample plugin_id { operations }
  finalize { operations }
}

Průběh experimentu

Oproti běžným handlerům obsahují bloky experimentů speciální podporu pro předávání dat mezi bloky. Obsah dočasných proměnných (t0-t99) se přenáší mezi voláními bloků (například hodnota zapsaná do proměnné t50 v init bloku v ní bude dostupná i v průběhu on_sample bloku).

V blocích init a on_manual_sample je možné používat funkci write_output, která zapíše aktuální stav burst_out_* proměnných do seznamu dat posílaných na výstup v případě init bloku nebo do záznamu experimentu v případě on_manual_sample bloku. V případě init bloku je možné zapsat až 1000000 vzorků. V případě on_manual_sample je možné zapsat desetinásobek naměřeného množství HW vzorků (uložené v sample_count).

Blok on_sample/on_manual_sample na začátku dostane v proměnných sample_index, burst_in_time a burst_in_0-burst_in_7 parametry HW vzorku pro který je právě volán. Hodnota burst_out_time je nastavena na stejnou hodnotu jako burst_in_time. V rámci bloku je možné použít funkce sample a isample pro načtení parametrů i jiných naměřených vzorků. Volání jedné z těchto funkcí naplní hodnoty burst_in_time a burst_in_0-burst_in_7 hodnotami pro příslušný vzorek. Ostatní proměnné, hlavně burst_out_time a sample_index, zůstanou nezměněnné.

Operace

Operace asociované s blokem popisují, co se má stát, když se blok zpracovává. Jsou podporovány základní matematické operace jako je sčítání, odčítání, násobení, dělení, zbytek po dělení. Script také obsahuje několik goniometrických funkcí a nástroje pro tvorbu jednoduchých podmínek. V operacích je možné používat všechny proměnné uvedené v předchozích sekcích a dále je možno použít 100 dočasných proměnných, které platí pouze po dobu běhu bloku a na jeho začátku jsou nastavené na hodnotu 0.

Každý blok může mít libovolný počet operací. Každá operace může být jedno z následujícího:
Přiřazení:

Y = expression ;

Podmínka:
if ( if_expression ) {
  operations
}
[ else { operations } ]

Cyklus:
while ( if_expression ) {
  operations
}

Řídící funkce (viz níže):
exit ;

Možné řídící funkce:

ZápisVýznam
exitFunkce ukončí běh bloku.
stopFunkce má význam pouze v on_sample/on_manual_sample bloku burst experimentu. Ukončí zpracování naměřených vzorků po dokončení zpracování aktualního vzorku.
write_outputFunkce má význam pouze v on_sample/on_manual_sample/init bloku burst experimentu. Vygeneruje nový výstupní vzorek na základě aktualního stavu výstupních proměnných.
sample( expression )Funkce má význam pouze v on_sample/on_manual_sample bloku burst experimentu. Načte do vstupních proměnných hodnotu vzorku s indexem ( sample_index + expression ). Hodnota se před přístupem zaokrouhlí na nejbližší celé číslo. Pokud je index mimo naměřený rozsah, použije se nejbližší naměřená hodnota.
isample( expression )Podobné funkci sample, ale desetinná část je použita pro lineární interpolaci mezi dvěma vzorky, mezi které ( sample_index + expression ) padne.
rotate( start, end, ammount )Orotuje dočasné proměnné (t0-t99) v rozsahu o ammount kroků. Například parametry (0,2,1) způsobí že proměnná t2 bude obsahovat předchozí obsah proměnné t1. t1 bude obsahovat předchozí obsah t0. t0 bude obsahovat předchozí obsah t2.

Expression

Expression je výraz, který může obsahovat libovolnou syntakticky platnou kombinaci proměnných, explicitních číselných konstant (např. 2.4), operací a funkcí uvedených níže. V příkladech uvedených níže jsou pismena A a B jména proměnných.

Základní matematické operace

ZnaménkoOperacePříklad
+Sčítání5 + A
-Odčítání5 - A
-Změna znaménka-A
*Násobení5 * A
/DěleníA/3. V případě, že dojde k dělení nulou, vraci hodnotu 0
%Zbytek po děleníA % 3. V případě, že dojde k dělení nulou, vraci hodnotu 0

Podporované matematicé funkce

FunkcePříkladPopis
clamp( x, minum, maximum )clamp( A, -5, 10.0 )Zajistí, aby vrácená hodnota byla pouze v uvedeném rozsahu. Pokud je minimum > maximum, je vrácena hodnota minimum.
min( x, minum )min( A, 0.0 )Vrací minimum z obou hodnot.
max( x, maximum )max( A, 0.0 )Vrací maximum z obou hodnot.
pow( x, y )pow( A, 2.0 )Spočítá x^y
cmp( x, treshold, result_a, result_b )cmp( A, 0.0, 1.0, 0.0 )Vraci result_a pokud x > treshold a jinak vraci result_b
cmps( x, treshold, result_a, result_b )cmps( A, 0.0, 1.0, 0.0 )Vraci result_a pokud x >= treshold a jinak vraci result_b
cmp( x, treshold )cmp( A, 0.0 )Zkratka pro cmp( x, treshold, 1.0, 0.0 )
cmps( x, treshold )cmps( A, 0.0 )Zkratka pro cmps( x, treshold, 1.0, 0.0 )
atan2( x, y )atan2( A, B )Vrací arc tangent v radiánech z hodnoty X / Y v radiánech včetně správného určení kvadrantu.
asin( x )asin( A )Vrací arc sinus v radiánech z hodnoty oříznuté do rozsahu <-1,1>.
acos( x )acos( A )Vrací arc cosinus v radiánech z hodnoty oříznuté do rozsahu <-1,1>.
sin( x )sin( A )Vrací sinus hodnoty v radiánech
cos( x )cos( A )Vrací cosinus hodnoty v radiánech
remap( x, s0, s1, s2, d0, d1, d2 )remap( A, 100, 200, 300, 0, 0.5, 1.0 )Přemapuje hodnoty z rozsahu <s0,s1,s2> do rozsahu <d0,d1,d2> s tím že s1 se přemapuje na d1. Vstupní hodnoty mimo platný rozsah se oříznou do rozsahu <s0,s2>
fraction( x )fraction( 3.5 )Vrací desetinou část vstupní hodnoty. Použitelné například pro generování signálu typu pila.
floor( x )floor( 3.5 )Zaokrouhlí hodnotu na nejbližší nižší celé číslo
ceil( x )ceil( 3.5 )Zaokrouhlí hodnotu na nejbližší vyžší celé číslo
round( x )round( 3.5 )Zaokrouhlí hodnotu na nejbližší celé číslo
abs( x )abs( -3.5 )Vrací absolutní hodnotu parametru

If_expression

Tento typ výrazu může být použit pouze v podmínce typu if. Oproti normálnímu výrazu je ještě rozšířen o následující užitečné zkratky.

ZkratkaVýznam
expression_a>expression_bcmp( expression_a, expression_b )
expression_a>=expression_bcmps( expression_a, expression_b )
expression_a<expression_bcmp( expression_b, expression_a )
expression_a<=expression_bcmps( expression_b, expression_a )

Příklady

Příklad 1: Jednoduchý generátor sinusového výstupního signálu

Plugin je možné použit pro generování signálu přes ISES následujícím postupem.

Ukázka jednoduchého scriptu generujícího sinusový přůběh s nastavitelnou frekvencí

version 1.0
name sin_signal

# Importovani pinu do kterého budeme zapisovat.

using card_lib "plugins\ISESProCardPlugin.ldp" card_config_1
import output card_lib "Write D/A 1"

# Frequence generované křivky v HZ.

variable set_frequency = 1.0

# Pin jehož čtení generuje výstup.

pin_read generator {

     # Generovani hodnoty pro aktuální okamžik.

     result = sin( time * set_frequency * 6.28 ) * 2048 + 2048 ;
}

# Pin sloužící pro nastavení generované frequence.

pin_read frequency {
     result = set_frequency ;
}

pin_write frequency {
     set_frequency = new_value ;
}

Příklad 2: Generátor sinusového nebo pilového výstupního signálu

Tento příklad je součástí CD ISESWebControl. Výpis scriptu generator_example.psc:
# Script generujici sinusovou krivku nebo pilu s uzivatelsky nastavitelnou
# frekvenci.
#
# Script ma nasledujici piny:
# frequency .. cteni vraci aktualne nastavenou frekvenci v Hz.
# frequency .. zapis nastavi novou frekvenci v Hz.
# measured_value .. cteni vraci hodnotu prectenou z prvniho analogoveho vstupu
#                   ISESu.
# generator .. precteni tohoto pinu vygeneruje na vystup jednu hodnotu. Pro
#              spravnou funkci generatoru je potreba mit u tohoto pinu zapnuty
#              fastlog s rozume vysokou vzorkovaci frekvenci.

# Verze scriptovaciho jazyka.

version 1.0

# Nazev scriptu. Tato polozka se pouzije jako nazev pluginu v MeasureServeru.

name example_generator

# Reference na HW plugin, ktery se bude pouzivat pro vystup a vystup.

using card_lib "plugins\ISESProCardPlugin.ldp" card_config_1

# Importovani pinu, do kterého budeme zapisovat vystup.

import output card_lib "Write D/A 1"

# Importovani pinu, ze ktereho budeme cist namerene hodnoty.

import vstup_1 card_lib "Read A/D 1"

# Typ generovane krivky.
#
# Hodnota >= 0.0 odpovida sinusove krivce.
# Hodnota < 0.0 odpovida pile.

variable output_type = 1.0 

# Frequence generované křivky v Hz.

variable generated_frequency = 1.0

# Promenna pouzita pro zastaveni generovani, kdyz neni komunikace
# s klientem. 

variable watchdog_counter = 0.0

# Pin, jehož čtení generuje výstup.

pin_read generator {

     # Generovani hodnoty pro aktuální okamžik. Pokud je generovani
     # zapnute, tak se spocita skutecna hodnota, jinak se pouzije
     # hodnota odpovidajici nule.

     if ( watchdog_counter > 0.0 ) {
     
         # Vygenerovani zvoleneho typu krivky jako hodnoty
         # v rozsahu <-1,1>
     
         if ( output_type >= 0.0 ) {
             t0 = sin( time * generated_frequency * 6.28 ) ;
         }
         else {
             t0 = fraction( time * generated_frequency ) * 2 - 1 ;
         }
         
         # Prepocet na vystupni rozsah 0 az 4095 (odpovida 12bitovemu rozliseni
         # ADDA karty a vystupnimu rozsahu <-5V,5V> tj. 0-4095 binarne)
         
         t0 = t0 * 2048 + 2048 ;
         
         # Vyslani spocitane hodnoty na vystup. Normalni experiment by mohl
         # spocitanou hodnotu vyslat i kdyz se nic negeneruje. Protoze vsak
         # ostatni ukazkove experimenty pouzivaji vystup, tak by takoveto
         # chovani tohoto prikladu zpusobilo nefunkcnost jejich vystupu.       
          
         output = t0 ;
     }
     else {
         t0 = 2048 ;

         # Nasledujici radek vynuti restart promenne time. Vsechny vypocty v
         # tomto scriptu se provadeji pomoci 64bitovych cisel s pohyblivou
         # desetinou carkou. Dusledkem je, ze u prilis velkych hodnot dochází
         # ke ztrátě přesnosti hodnoty. Pokud by se reset neprovedl, experiment
         # by po delsi dobe zacal generovat cim dal "zubatejsi" krivku.  

         reset_time = 1 ;
     }

     # Jeji vraceni jako hodnoty tohoto pinu. 
     
     result = t0 ;
}

# Pin, jehoz precteni nacte hodnotu z prvniho HW vstupu. 

pin_read measured_value {
     result = vstup_1 ;
}

# Pin sloužící pro cteni a nastavovani generovane frekvence.

pin_read frequency {
     result = generated_frequency ;
     
     # V ukazkove strance je applet, ktery periodicky cte tento pin (a zaroven
     # tento pin neni logovan), takze se tento pin cte prave kdyz je funkcni 
     # spojeni s klientem.
     # Pri kazdem precteni se nastavi promena watchdog_counter na vhodne
     # zvolenou hodnotu. Hodnota teto promenne je kazdou sekundu snizena 
     # o 1 (viz on_each_second nize) a generovani se zastavi pokud bude mensi
     # nez nula nebo rovna nule (viz. generator nahore).
     # Dusledkem je, ze generovani se zastavi pokud si tento pin nekdo neprecte
     # po odpovidajici pocet sekund.
     
     watchdog_counter = 5 ;     
}

pin_write frequency {
     generated_frequency = new_value ;
}

# Pin slouzici na nastavovani typu generovaneho vystupu.

pin_write type {
     output_type = new_value ;
}

# Nasledujici funkce je volana kazdou sekundu.

on_each_second {

    # Odpocet casu do zastaveni generovani pokud uz toto nebylo zastaveno.

    if ( watchdog_counter > 0.0 ) {
        watchdog_counter = watchdog_counter - 1 ; 
    }
}

# Kdyz se zmeni uzivatel, nastavime zpatky pocatecni frekvenci a
# typ krivky.

on_user_change {
    generated_frequency = 1.0 ;
    output_type = 1.0 ;
}