Jste zde

LABJACK U3 – KROK ZA KROKEM IV

V minulém díle jsme skončili u zpracování výjimek a událostí. Dnes budeme v tomto tématu pokračovat a ukážeme si další metody odchytu chybových stavů. Protože se ale nejedná o náročnou oblast, vrátíme se už dnes zpět k tomu hlavnímu, nastavení periferií a sběru naměřených dat.

Úvodem

Ukázali jsme si, jak ošetřit chybové události zjištěné časovačem kanálů. Stejnou metodou můžeme zjišťovat chyby také pokud pro čtení / zápis hodnot používáme proudu (streem) . Ne všechny chyby jsou ale tímto způsobem odhalitelné, protože ne všechny se nám projeví v okně COMMAND/ALERT.

Téměř každá funkce v prostředí DAQFactory poskytuje návratovou hodnotu nesoucí informaci o úspěšnosti požadovaného úkonu. V případě, že proces byl úšpěsný vrací funkce hodnotu:

LJE_NOERROR (0)

Hodnotu můžeme samozřejmě použít jako výraz při větvení a cyklení programu. LJE_NOERROR s hodnotou 0 má tedy význam FALSE. V nejjednodušším případě pak můžeme ukládat návratové hodnoty všech požadovaných funkcí a dle nich větvit další průběh skriptu. Ve velkém množství prováděných funkcí se ale tento postup stává zdlouhavým a podstatným způsobem znepřehledňuje a zvětšuje množství potřebného kódu.

Prostředí DAQFactory nám ale umožňuje i tuto činnost zjednodušit a to funkcí GetNextError(). Níže uvedený příklad je převzat z manuálu k prostředí DAQFactory:

AddRequest(0, LJ_ioPUT_CONFIG, LJ_chAIN_RESOLUTION, 14, 0, 0)
AddRequest(0, LJ_ioPUT_AIN_RANGE, 2, LJ_rgBIP5V, 0, 0)
AddRequest(0, LJ_ioPUT_AIN_RANGE, 3, LJ_rgBIP5V, 0, 0)
GoOne(0)
private err
private ch
private io
while(GetNextError(0,@io,@ch,@err))
    ? Format("Error occurred on channel type: %d, io type: %d, code: %d",ch,io,err)
endwhile

Proměnné err, ch, io jsme si deklarovali pouze pro účely uchování informací o každé jednotlivé chybě, kterou nám GetNextError() vrátí. Cyklus while zcela podle očekávání popíše všechny chyby s uvedením kanálu, zařízením a zněním chybového hlášení. První tři řádky pouze nastiňují, v jaké souvislosti může být výpis chybových hlášení použit. V samotné funkci GetNextError() je nutné myslet na to, že parametry musí být adresy proměnných (stejně jako například v jazyce C), a proto je před proměnnými uveden zavináč. Není nutné snad poznamenat, že uvedený kód je často využívám a proto se vyplatí je uvést v samostatné funkci.

Vraťme se k měření...

V případě měření a sběru dat prostřednictvím LabJacku a PC musíme rozlišovat dva typy měření :

  • Jednotlivá měření
  • Hromadná (dávková) měření

Dohady o správnosti terminologie ponechme stranou, pro nás je důležitý význam. Jednotlivá měření jsou taková měření, kdy každému úkonu jednoznačně předchází povel řídícího členu (v tomto případě PC). Naměřené hodnoty jsou ihned po naměření přeneseny žadateli a ten s nimi naloží dle uvážení. Z této situace je myslím jasné, že rychlost sběru dat bude omezena nejenom rychlostí části provádějící měření, ale také rychlostí žadatele. V případě, že je žadatelem PC, musíme uvažovat, že operační systém má na starosti nejen naši aplikaci, ale také další. A i v případě, že by obsluhoval pouze naši aplikaci, je i v ní na zpracování úloh více (aktualizace GUI například)

V prostředí DAQFactory jsme proto v tomto režimu omezeni rychlostí sběru dat, která je rovna stovce vzorků za sekundu. V případě pěti kanálů, pak například každý můžeme měřit 20x za sekundu. Příklad takového měření si můžeme ukázat. Vytvoříme si proto nový projekt a na rozdíl od předchozích prací nebudeme vytvářet žádný kanál pro měření (alespoň ne vizuálně).

Vytvoříme si dva skripty:

StartUp

// standardni prikazy, kterej jsme jiz pouzivali:
using("device.labjack.")
include("c:\program files\labjack\drivers\labjackud.h")

// globalni promenna ID, hodi se nam... (prvni nalezeny LABJACK)
global ID = 0

// takhle si zaridime, ze budeme mit tovarni nastaveni
ePUT(ID, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0)

// spustime mereni
beginseq(Mereni)

a Mereni

// nastavi kanal 0 jako analogovy vstup ePut(ID, LJ_ioPUT_ANALOG_ENABLE_BIT,0, 1, 0) private err private val private string message while(1) err = eGet(ID, LJ_ioGET_AIN,0,@val,0) if (err) ErrorToString(err, @message) ? message else ? val endif delay(1) endwhile

Máte-li vše dobře sepsáno, neměl by být problém s bezchybným spuštěním skriptů. K prvnímu z nich není téměř co vysvětlovat. První dva řádky jsme již využili. Jde o připojení hlavičkového souboru a použití jmenného prostoru.

global ID = 0

Výše uvedený řádek pouze deklaruje a nastaví proměnnou ID, kterou budeme používat jako Handler (více později).

ePUT(ID, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0)

Toto jsme také už dělali – jde o nastavení JabJacku do továrního nastavení. To je dobré dělat, abychom při následném nastavování mohli očekávat, v jakém že se to stavu zařízení nachází.

beginseq(Mereni)

Toto dnes používáme poprvé, jde o funkci spouštějící další sekvenci (Měření). Ta obsahuje hned na prvním řádku zajímavý kód:

ePut(ID, LJ_ioPUT_ANALOG_ENABLE_BIT,0, 1, 0)

Funkci ePut jsme si zmínili již minule, přesto by bylo dobré si podrobněji představit, jaký význam mají jednotlivé parametry:

  • ID – nahrazuje tzv. Handler – odkaz na zařízení, které budeme používat. V tomto případě je handler 0 – budeme tedy pracovat s prvním LabJackem, který bude nalezen.
  • LJ_ioPUT_ANALOG_ENABLE_BIT – tento parametr je u fce ePut obecně nazýván IO type. Říkáme jí, jakou činnost chceme provádět. V tomto přpadě chceme povolit jeden ze vstupů jako vstup pro analogové veličiny.
  • Dalším parametrem sdělujeme co chceme měnit – v tomto případě kanál
  • Čtvrtý parametr určuje, jaké hodnoty nabyde měněná veličina (tedy 1)
  • Pátý je volitelný parametr. V případě čtení říká, kolik toho budeme číst.
V některých případech přibývají další nepovinné parametry, což si ukážeme jakmile k tomu bude příležitost.

Ve výkladu kódu postupujeme k měřicímu cyklu. V něm je prvním zajímavým řádkem

err = eGet(ID, LJ_ioGET_AIN,0,@val,0)

Tento řádek uloží do proměnné val naměřenou hodnotu z kanálu 1. Zároveň ale uloží do proměnné err návratovou hodnotu funkce, která nám říká, zda byla provedena úspěšně, nebo zda nastala nějaká chyba. Podle úspěšnosti buďto vypíšeme získanou hodnotu, nebo chybové hlášení (okno COMMAND/ALERT):

0.4283105658833
0.4313138204161
0.4319144713227
0.42891121679
0.4253073113505
0.425907962257
0.4283105658833

Jak je vidět, za pomoci funkce eGet jsme schopni realizovat poměrně jednoduše měření. Pokud bychom chtěli měřit 3 kanály, byl by možný zápis:

eGet(0, LJ_ioGET_AIN, 1, @val1, 0)
eGet(0, LJ_ioGET_AIN, 2, @val2, 0)
eGet(0, LJ_ioGET_AIN, 3, @val3, 0)

Oproti tomu zápis s AddRequest, GoOne a GetResult:

AddRequest(0, LJ_ioGET_AIN, 1, 0, 0, 0)
AddRequest(0, LJ_ioGET_AIN, 2, 0, 0, 0)
AddRequest(0, LJ_ioGET_AIN, 3, 0, 0, 0)
GoOne(0)
GetResult(0, LJ_ioGET_AIN, 1, @val1)
GetResult(0, LJ_ioGET_AIN, 2, @val2)
GetResult(0, LJ_ioGET_AIN, 3, @val3)

Je zřejmé, že druhý použitý zápis je výrazně delší a proto by se mohlo zdát, že použití prvního je výhodnější. Pokud nechceme kontrolovat možné chybové stavy, pak je tomu skutečně tak. Pokud nám záleží na návratových hodnotách, situace se mění. eGet nám totiž neumožňuje využití funkce GetNexError(), kterou jsme si uvedli na začátku a tak musíme každé jeho použití obalit podmínkami s testem na chybu. Naproti tomu trojice konkurenčních příkazů tuto možnost má. Ve složitejších případech použití uvedené trojice výsledný kód zkracuje a zjednodušuje jeho čitelnost.

Přecházíme na vyšší rychlost

Chceme-li využívat vyšší rychlost měření, je již nutné nechat časování na samotném LabJacku. V tomto případě budou naměřené hodnoty z několika cyklů měření přeposlány PC jako blok dat a PC je tím ušetřeno od neustálých požadavků na nastavování a měření. Labjack podporuje streaming obou typů vstupů, analogových i digitálních.

Přestože se streaming v DAQFactory liší od metody popisované manuálem LabJacku, není na škodu si ukázat jak na to. V jednom z následujících dílů bychom si měli vytvořit aplikaci pod prostředím .NET, kde uvidíme rozdíl mezi jednotlivými metodami. V DAQFactory je vhodné využít nastavení kanálů a krátkých skriptů.

V tomto případě využijeme hotový příklad dodaný spolu DAQFactory:

LJGuideSamples\BasicStream.ctl

V tomto příkladě jsou vytvořeny dva analogové kanály:

ChannelA	LabJack		A to D		Chn: 2		Timming 0		History:3600
ChannelB	LabJack		A to D		Chn: 3		Timming 0		History:3600

Nastavení je myslím si po absolvování předchozích lekcí jasné. Máme obsazeny dva kanály (FIO2, FIO3) nastaveny jsou jako analogové vstupy, s historií na 3600 vzorků. Dále budeme pokračovat vytvořením skriptů pro nastavení a spuštění streamingu. Prvním bude, jako již tradičně, StartUp:

using("device.labjack.")
include("c:\program files\labjack\drivers\labjackud.h")

global ID = 0
ePut(ID, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0)

Skript je totožný s tím uvedeným pro LOW-speed verzi, v tomto ohledu se nic nemění. Opět je zde připojení knihovního souboru, využití jmenného prostoru, nastavení ID a reset periferií LabJacku do továrního nastavení. Nově nám přibyl skript (funkce) ErrorHandler:

function ErrorHandler(ljID)
   private err
   private ch
   private io
   private string message
   while(GetNextError(ljID,@io,@ch,@err))
      ErrorToString(err,@message)
            ? Format("Error occurred on io type: %d, channel type: %d, code: %d: %s",io,ch,err,message)   
endwhile

Opět zde není uvedeno nic převratného, funkce vypíše všechny chyby, spolu s chybovými hlášeními a chybovými kódy. Je volána pracovními skripty vždy, pokud je předpoklad, že by mohlo dojít k chybě. Vzhledem ke vstupnímu parametru může být funkce použita pro více zařízení, jsou-li připojena. Budeme ji tedy využívat i v dalších příkladech. Nyní se ale pustíme do hlavního úkolu, nastavení a spuštění sběru dat. O to se stará skript StartStream:

// nastaví streamovací frekvenci na 100Hz
AddRequest(ID, LJ_ioPUT_CONFIG, LJ_chSTREAM_SCAN_FREQUENCY, 100, 0, 0)

// pro LabJack U3 musíme povolit použití analogových kanálů (2,3)
AddRequest(ID, LJ_ioPUT_ANALOG_ENABLE_BIT, 2, 1, 0, 0)
AddRequest(ID, LJ_ioPUT_ANALOG_ENABLE_BIT, 3, 1, 0, 0)

// nejprve smažeme seznam všech streamovaných kanálů
// a pak je jednotlivě přidáme, abychom měli jistotu
// že streamujeme opravdu jen to co chceme
AddRequest(ID, LJ_ioCLEAR_STREAM_CHANNELS, 0, 0, 0, 0)
AddRequest(ID, LJ_ioADD_STREAM_CHANNEL, 2, 0, 0, 0)
AddRequest(ID, LJ_ioADD_STREAM_CHANNEL, 3, 0, 0, 0)

// provedeme požadavky
GoOne(ID)
// v případě chyby vypíšeme chybové hlášení
ErrorHandler(ID)

global scanrate = 0
//spustíme stremování a přečteme aktuální streamovací frekvenci.
eGet(ID,LJ_ioSTART_STREAM, 0, @scanrate, 0)
ErrorHandler(ID)

V příkladu je vytvořena stránka s rozhraním, kde se naměřená data ukládají do grafu. Jak je z obrázku vidět, naměřených dat bude opravdu mnoho. Jejich počet si můžeme prohlédnout také v tabulce kanálu, kde si můžeme ověřit, že na 1s připadá opravdu 100 naměřených vzorků.

grafLJ4.png

Odkazy a Download

Hodnocení článku: