Obsługa urządzeń pomiarowych z interfejsem GPIB w środowisku LabVIEW.

Spis treści :
| 1. Biblioteki I/O interfejsu GPIB. 2. Sesja urządzeniowa. 3. Szeregowanie operacji urządzeniowych. 4. Praca w warunkach współdzielenia zasobów pomiarowych. 5. Programowanie zdalne urządzeń. 5.a Separator części ułamkowej zapisu liczby. | 5.b Sygnalizacja końca komunikatu. 5.c Stosowanie poleceń złożonych. 6. Odczyt danych z urządzeń. 7. Technika synchronizacji; wykorzystanie SRQ w aplikacji. 8. Argumenty i dane binarne komunikatów urządzeniowych. 9. Literatura.

1. Biblioteki I/O interfejsu GPIB.

Platformę komunikacyjną systemu pomiarowego stanowi określony typ interfejsu sprzęgającego jego urządzenia (RS232, GPIB, VXI, PCI itd.). Obejmuje ona medium transmisyjne oraz realizację sprzętową interfejsu w poszczególnych urządzeniach (np. kartę GPIB w komputerze sterującym systemem). Realizację typowych operacji w obrębie określonej platformy interfejsowej zapewnia odpowiednia biblioteka I/O. Jej celem jest uwolnienie projektanta aplikacji od szczegółów obsługi konkretnej platformy interfejsowej przez dostarczenie gotowych, uniwersalnych funkcji pozwalających aplikacji w sposób prosty komunikować się z wybranym urządzeniem pomiarowym. Aplikacja może korzystać też z tzw. drajwerów przyrządowych. Ich zadaniem jest dostarczenie gotowych procedur obsługi różnych typów urządzeń pomiarowych a celem jest uwolnienie programisty od szczegółów obsługi konkretnego typu urządzenia. Drajwer przyrządowy korzysta z określonej biblioteki I/O.

Środowiska projektowe nastawione na tworzenie aplikacji pomiarowych, między innymi LabVIEW, dysponują bibliotekami I/O dotyczącymi podstawowych platform interfejsowych a także możliwością dołączania nowych. To samo dotyczy drajwerów przyrządowych. I tak LabVIEW oferuje w grupie bibliotek przyrządowych :

- Dwie biblioteki dotyczące platform interfejsowych:
  - VISA - interfejs GPIB i VXI (oznaczenie VISA) oraz interfejs szeregowy RS232 (oznaczenie SERIAL);
  - NI488 - interfejs GPIB (oznaczenie 488);
- Dwie grupy bibliotek obejmujących drajwery przyrządowe IVI:
  - Instr. Lib. - specyficzne drajwery przyrządowe IVI zgodne z klasami przyrządowymi (drajwery kilku konkretnych urządzeń);
  - IVI - drajwery przyrządowe IVI klas przyrządowych.

Rys.1.Rozwinięta paleta funkcji biblioteki VISA dla interfejsu GPIB.

Interfejs GPIB jest wsparty przez dwie różne biblioteki. Biblioteka NI488 jest podstawową biblioteką firmy NI obsługującą jej karty GPIB. Cechuje się bardzo korzystnymi własnościami i była powszechnie stosowana do czasu powstania biblioteki VISA.

VISA powstała w wyniku umowy unifikacyjnej producentów sprzętu pomiarowego VXIplug&play Systems Alliance. Jest biblioteką I/O obejmującą wszystkie platformy interfejsowe stosowane w systemach pomiarowych i posiadającą jednakowe API w odniesieniu do różnych platform interfejsowych, rozwiązań kart interfejsowych oraz środowisk pracy (Windows, Unix itd.). Konkretna realizacja biblioteki VISA jest unikalna w odniesieniu do danego systemu operacyjnego oraz rozwiązań sprzętowych danego producenta, ale jej funkcje obejmują wymienione rodzaje interfejsów a jej API odpowiada realizacjom biblioteki VISA innych producentów. Dzięki przyjętej unifikacji użytkownik końcowy jest niezależny od producenta sprzętu i oprogramowania co znacznie ułatwia projektowanie aplikacji. Jednolita biblioteka I/O pozwoliła zunifikować dostarczane przez firmy drajwery przyrządowe. Drajwery VXIplug&play oraz IVI wykorzystują bibliotekę VISA. Biblioteka VISA dla środowiska LabVIEW jest nieco inna w porównaniu z podobną biblioteką dla tekstowych środowisk projektowych [2] (Tablica 1).

Tablica 1. Zestaw funkcji biblioteki VISA dla środowisk tekstowych (C) i graficznych (LabView):

ANSI C | GWIN98 | Opis
Funkcje rozpoznania zasobów oraz sterowania czasem życia sesji :
viOpenDefaultRM |  | Otwarcie sesji menadżera zasobów.
viFindRsrc | VISA Find Resource | Szukanie zasobów.
viFindNext |  | Zwraca kolejny zasób z listy rozpoznanych.
viOpen | VISA Open | Otwarcie sesji urządzeniowej.
viClose | VISA Close | Zamknięcie sesji urządzeniowej.
viTerminate |  | Przerwanie asynchronicznej operacji I/O.
Funkcje pomocnicze :
viStatusDesc | VISA Status Description | Zwraca tekstowy opis błędu operacji VISA.
viParseRsrc |  | Sprawdza poprawność nazwy zasobu.
Funkcje obsługi atrybutów sesji :
viGetAttribute | Property Node | Dostarcza wartość wybranego atrybutu sesji.
viSetAttribute | Property Node | Ustawia wartość wybranego atrybutu sesji.
Funkcje sposobu udostępniania zasobu :
viLock | VISA Lock | Zajęcie zasobu.
viUnlock | VISA Unlock | Zwolnienie zasobu.
Funkcje obsługi zdarzeń :
viEnableEvent | VISA Enable Event | Uaktywnienie wykrywania zdarzeń.
viDisableEvent | VISA Disable Event | Zakończenie wykrywania zdarzeń.
viDiscardEvents | VISA Discard Events | Odrzucenie zdarzenia.
viWaitOnEvent | VISA Wait on Event | Oczekiwanie na zdarzenie.
viEventHandler |  | Prototyp funkcji obsługi zdarzeń.
viInstallHandler |  | Zainstalowanie funkcji obsługi zdarzeń.
viUninstallHandler |  | Odinstalowanie funkcji obsługi zdarzeń.
Funkcje obsługi urządzeń programowanych komunikatami tekstowymi oraz funkcje sterujące :
viRead | VISA Read | Odczyt komunikatu z urządzenia.
viReadAsync |  | Asynchroniczny odczyt komunikatu z urządzenia.
viWrite | VISA Write | Zapis komunikatu do urządzenia.
viWriteAsync |  | Asynchroniczny zapis komunikatu do urządzenia.
viReadToFile | VISA Read To File | Odczyt komunikatu urządzenia z zapisem do pliku.
viWriteFromFile | VISA Write From File | Zapis do urządzenia komunikatów pobranych z pliku.
viSetBuf | VISA Set I/O Buffer Size | Ustawia rozmiar bufora dla formatowanych operacji I/O.
viFlush | VISA Flush I/O Buffer | Opróżnienie bufora dla formatowanych operacji I/O.
viBufWrite |  | Zapis komunikatu do bufora formatowanych operacji I/O.
viBufRead |  | Odczyt z pośrednictwem bufora formatowanych operacji I/O.
viPrintf / viVPrintf |  | Zapis do urządzenia z formatowaniem danych wej. (buf. form. oper. I/O).
viSPrintf / viVSPrintf |  | Zapis do bufora I/O z formatowaniem danych wej.
viScanf / viVScanf |  | Odczyt z urządzenia z formatowaniem danych wyj. (buf. form. oper. I/O).
viSScanf / viVSScanf |  | Odczyt z bufora I/O z formatowaniem danych wyjściowych.
viQueryf / viVQueryf |  | Zapis i odczyt z formatowaniem (buf. form. oper. I/O).
viReadSTB | VISA Read STB | Odczyt bajtu statusowego.
viAssertTrigger | VISA Assert Trigger | Wyzwolenie akcji urządzenia.
viClear | VISA Clear | Zerowanie urządzenia.
Funkcje obsługi urządzeń rejestrowych VXI oraz funkcje specyficzne dla VXI :
viIn8 / viIn16 / viIn32 | VISA In8 / 16 / 32 | Odczyt 8/16/32 bitowy z określonego adresu pamięci.
viOut8 / viOut16 / viOut32 | VISA Out 8 / 16 / 32 | Zapis 8/16/32 bitowy do określonego adresu pamięci.
viMoveIn8 / viMoveIn16 / viMoveIn32 | VISA Move In 8 / 16 / 32 | Przenosi blok danych z pamięci VXI do lokalnej.
viMoveOut8 / viMoveOut16 / viMoveOut32 | VISA Move Out 8 / 16 / 32 | Przenosi blok danych z pamięci lokalnej do VXI.
viMove | VISA Move | Przenosi blok danych w przestrzeni adresowej.
viMoveAsync |  | Przenosi asynchronicznie blok danych w przestrzeni adresowej.
viMapAddress | VISA Map Address | Mapuje pamięć do przestrzeni adresowej procesu.
viUnmapAddress | VISA Unmap Address | Likwiduje mapowanie pamięci (viMapAddress).
viPeek8 / viPeek16 / viPeek32 | VISA Poke 8 / 16 / 32 | Odczyt 8/16/32 bitowy z adresu (viMapAddress).
viPoke8 / viPoke16 / viPoke32 | VISA Peek 8 /16 / 32 | Zapis 8/16/32 bitowy do adresu (viMapAddress).
viMemAlloc | VISA Memory Allocation | Alokuje pamięć w regionie pamięci urządzenia.
viMemFree | VISA Memory Free | Zwalnia pamięć (viMemAlloc).
viAssertIntrSignal | VISA Assert Interrupt Signal | Wystawia wybrane przerwanie lub sygnał.
viAssertUtilSignal | VISA Assert Utility Signal | Ustawia/likwiduje SYSFAIL lub SYSRESET.
viMapTrigger | VISA Map Trigger | Mapuje linię źródła wyzwalania do określonej linii.
viUnmapTrigger | VISA Unmap Trigger | Likwiduje mapowanie linii wyzwalania.
viVxiCommandQuery | VISA VXI Cmd or Query | Wysyła rozkazy/zapytania lub odczytuje odpowiedź.
Funkcje specyficzne interfejsu GPIB :
viGpibControlREN | VISA GPIB Control REN | Steruje linią REN.
viGpibControlATN | VISA GPIB Control ATN | Steruje linią ATN.
viGpibSendIFC | VISA GPIB Send IFC | Steruje linią IFC.
viGpibPassControl | VISA GPIB Pass Control | Przekazuje kontrolę nad magistralą GPIB.
viGpibCommand | VISA GPIB Command | Wysyła adresy / rozkazy interfejsowe.

Zasadnicze różnice występują w grupie funkcji obsługi urządzeń programowanych komunikatami tekstowymi. W środowisku LabView nie ma funkcji I/O z formatowaniem danych i buforowaniem pośrednim oraz asynchronicznych funkcji I/O. Brak funkcji z formatowaniem oznacza konieczność stosowania dodatkowych funkcji do tworzenia tekstów komunikatów wysyłanych do urządzenia (Format Into String) oraz przetwarzania odbieranych numerycznych komunikatów tekstowych do postaci numerycznej typu int, float, double itp. (Scan From String).

2. Sesja urządzeniowa.

W bibliotece VISA urządzenie pomiarowe stanowi zasób (resource) przyrządowy względem, którego można realizować różne funkcje użytkowe. Każdy zasób jest identyfikowany nazwą zasobu (instrument descriptor), w której jest określony rodzaj używanego interfejsu, identyfikator interfejsu w systemie, adres urządzenia w interfejsie oraz klasa zasobu. Przyjęto następującą składnię dla nazw zasobów:

Interface_Type[Board_Index]::Address::VISA_Class
gdzie:

- Interface_Type - rodzaj stosowanego interfejsu;
- Board_index - identyfikator karty interfejsu w systemie komputerowym;
- Address - adres (numer) urządzenia w interfejsie magistralowym;
- VISA_Class - klasa zasobu, określenie grupy dostępnych operacji (funkcji biblioteki).

Przykłady :

- GPIB[board]::primary_address[::secondary_address][::INSTR], np.:
  - GPIB0::9::3::INSTR - określa urządzenie działające w interfejsie GPIB realizowanym przez kartę GPIB o numerze logicznym 0 w systemie komputerowym. Urządzenie wykorzystuje adresowanie dwubajtowe (numer podstawowy na magistrali 9 i rozszerzający 3).
- ASRL[board][::INSTR], np.:
  - ASRL1::INSTR - określa urządzenie działające w interfejsie szeregowym realizowanym przez port szeregowy COM1 systemu komputerowego.
- GPIB-VXI[board]::VXI logical address[::INSTR], np.:
  - GPIB-VXI0::10::INSTR - określa urządzenie kasety VXI o adresie logicznym 10 udostępniane poprzez moduł sterujący GPIB kasety. Jest odpowiednikiem GPIB[board], ale pozwala stosować adresy logiczne VXI.
- VXI[board]::VXI_logical_address[::INSTR], np.:
  - VXI::9::INSTR - określa urządzenie VXI o adresie logicznym 9 udostępniane wbudowanemu kontrolerowi kasety VXI.
- TCPIP::Numer_IP::GPIB[board],primary_address [,secondary_address]::INSTR, np.:
  - TCPIP::156.17.45.29::GPIB0,9,3::INSTR - określa urządzenie działające w interfejsie GPIB realizowanym przez kartę GPIB o numerze logicznym 0 w systemie komputerowym o numerze IP 156.17.45.29, udostępniane w sieci LAN poprzez protokół TCP/IP (standard VXI-11). Urządzenie wykorzystuje adresowanie dwubajtowe (numer podstawowy na magistrali 9 i rozszerzający 3).

Funkcje użytkowe biblioteki VISA są niezależne od typu stosowanego interfejsu. Przykładowo funkcja zapisu stringu ASCII do urządzeń obsługiwanych tekstowo jest identyczna w przypadku interfejsu szeregowego, GPIB i VXI. Zadaniem funkcji jest wypracowanie odpowiedniego stringu oraz wywołanie na podstawie nazwy zasobu odpowiedniej funkcji drajwera obsługującego dany interfejs, w tym przypadku realizującej transfer komunikatu. W przypadku obsługi urządzenia na interfejsie szeregowym wywoła odpowiednią funkcję systemu operacyjnego, natomiast dla urządzenia GPIB funkcję drajwera karty GPIB (np. funkcję ibwrite biblioteki NI-488.2 dla karty firmy NI). Wybranej funkcji zostaną przekazane również inne potrzebne dane, jak np. adres urządzenia.

Konstrukcja biblioteki VISA zakłada stosowanie wskaźnika sesji uzyskanego w wyniku operacji otwarcia sesji komunikacyjnej z wybranym zasobem przyrządowym. Realizuje to specjalna funkcja otwarcia sesji - viOpen/VISA Open, która otrzymuje nazwę zasobu jako argument i tworzy wskaźnik otwartej sesji.

Rys.2. Konfigurowanie węzła Property Node dla sesji typu TCPIP::INSTR.

Wraz z otwarciem sesji zostaje utworzony zespół danych opisujących własności tej sesji (adresy, terminator, timeout itp. ), który jest wykorzystywany przez funkcje użytkowe realizujące operacje do urządzenia związanego z daną sesją. Dane charakteryzujące sesję, zwane atrybutami sesji, można odczytywać a także modyfikować. W środowiskach tekstowych służą do tego funkcje viSetAttribute i viGetAttribute. W LabView służy do tego węzeł Property Node, który po odpowiednim skonfigurowaniu pozwala odczytać dane wybranych atrybutów sesji lub zmodyfikować ich ustawienia (rys.2). Zakres i rodzaj dostępnych atrybutów zależy od rodzaju stosowanego interfejsu oraz typu sesji. Przykładowo dla sesji TCPIP::INSTR dostępne są grupy własności pokazane na rys.2. W grupie Message Based Settings dostępne są atrybuty:

- File Opened Enable - określa czy operacja VISA Read To File dopisuje lub zastępuje dane w pliku.
- Send End Enable - uaktywnia lub blokuje wystawianie komunikatu END z ostatnim bajtem komunikatu dla każdej operacji VISA Write ( domyślnie True ).
- Termination Character - określa kod znaku terminalnego, który kończy operację odczytu (VISA Read); domyślnie obowiązuje znak NL (0x0A).
- Termination Character Enable - uaktywnia lub blokuje używanie znaku terminalnego w operacjach odczytu (domyślnie False).

Funkcje użytkowe biblioteki korzystają z wskaźnika sesji, który pozwala dotrzeć im do atrybutów sesji określających szczegóły sposobu ich realizacji. Stąd aplikacja może współpracować z określonym zasobem dopiero po otwarciu sesji komunikacyjnej. W tekstowych środowiskach projektowania aplikacji trzeba jawnie otworzyć sesję urządzeniową. Stąd ogólny szkielet aplikacji dotyczącej współpracy z urządzeniem musi mieć postać:

- ViSession vi, viDefaultRM; // Identyfikatory sesji
- ViChar rdResponse[100]; // Inne zmienne
- ViUInt32 retCount;
- // Otwarcie sesji z zarządcą, który między innymi inicjalizuje system VISA dla aplikacji.
- viOpenDefaultRM(&viDefaultRM);
- // Zarządca otrzymuje nazwę zasobu i otwiera sesję komunikacyjną do niego.
- viOpen(viDefaultRM, "TCPIP::156.17.45.27::GPIB0,1::INSTR",0 ,0, &vi);
- // Operacje urządzeniowe; korzystają z identyfikatora sesji 'vi'.
- viWrite( vi, "*idn?", 5, &retCount );
- viRead( vi, rdResponse, 60, &retCount );
- viClose(vi); //Zamknięcie sesji komunikacyjnej.

Rys.3. Niejawne i jawne otwarcie sesji urządzeniowej.

W środowisku LabView projektant aplikacji może zrezygnować z jawnego otwierania sesji urządzeniowej, ponieważ funkcje biblioteki VISA zakładają dostarczenie im nazwy zasobu i jeśli sesja nie jest otwarta następuje jej otwarcie w trybie domyślnym, czyli między innymi bez zajęcia zasobu na wyłączność (rys.3). Jeśli aplikacja wymaga zajęcia zasobu na wyłączność, wówczas trzeba jawnie użyć funkcji VISA Open z odpowiednimi argumentami jej wywołania.

3. Szeregowanie operacji urządzeniowych.

Sterowanie urządzenia pomiarowego wymaga wykonania pewnej sekwencji działań, np. w stosunku do multimetru wybrania funkcji pomiarowej, ustalenia sposobu wyzwolenia pomiaru, zainicjowanie pomiaru, stwierdzenie gotowości wyniku i odbiór wartości zmierzonej. W przypadku wykorzystywania kilku urządzeń, np. generatora i multimetru najpierw trzeba ustawić parametry generowanego sygnału (amplitudę, częstotliwość) i dopiero wtedy przejść do obsługi multimetru. W środowisku programowania tekstowego wymaganą kolejność operacji zapewnia sekwencja wywołań odpowiednich funkcji. Graficzne środowisko programowania wykorzystujące sterowanie przepływem danych zakłada przepływ danych między kolejno wykonywanymi węzłami diagramu. Tymczasem atomistycznie traktowane operacje urządzeniowe nie muszą przekazywać sobie danych i to jeszcze identycznego typu. Stąd trudno sekwencję operacji zapisu i odczytu zrealizować przepływem danych. Wprawdzie funkcja zapisu zwraca liczbę wysłanych znaków a funkcja odczytu wykorzystuje wejście określające liczbę odczytywanych znaków (obie dane są typu int), ale dane te nie są ze sobą związane logicznie. Można zastosować konstrukcję sekwencji i w kolejnych jej ramkach umieszczać wymagane operacje. Takie rozwiązanie jest jednak nieoptymalne i mało czytelne. Z tych powodów funkcje biblioteki VISA podobnie jak operacje plikowe lub innego typu wymagające zachowania określonej kolejności są zbudowane w specyficzny sposób umożliwiający sterowanie przepływem danych. Wykorzystują one dodatkowe dane określonych typów przekazywane z wejścia na wyjście po wykonaniu operacji przez węzeł stanowiący funkcję biblioteki VISA.

Każdy węzeł funkcji VISA posiada terminal wejściowy Error In oraz terminal wyjściowy Error Out. Dane o błędzie są strukturą (cluster) wykorzystaną do raportowania zakończenia działania węzła i dostarczenia kodu błędu. Struktura błędu zawiera trzy pola (rys.4):

- Wskaźnik błędu (boolean); Uzyskuje wartość TRUE jeśli operacje węzła zakończą się błędem.
- Numeryczny kod błędu (int);
  - Wartości mniejsze od zera oznaczają błąd (wtedy wskaźnik błędu przyjmie wartość TRUE).
  - Wartość zero oznacza poprawne wykonanie operacji węzła.
  - Wartości większe od zera oznaczają poprawne wykonanie operacji z pewnym zastrzeżeniem (ostrzeżenie).
- Opis błędu (string) określa nazwę węzła i programu VI (subVI), w którym wystąpił.

Ostrzeżenie oznacza sytuację odbiegającą od normy, która może skutkować błędnym działaniem aplikacji (rys.4). Przykładowo węzeł VISA Read wymaga podania liczby znaków odczytywanego komunikatu. Jeśli zadeklarowana liczba jest mniejsza od długości komunikatu znajdującego się w buforze wyjściowym urządzenia, węzeł VISA Read zgłosi ostrzeżenie 'odebrano zadeklarowaną liczbę znaków'. Oznacza to, że odebrano niekompletny komunikat z urządzenia i może to prowadzić do błędów w jej działaniu. Dodatkowo w urządzeniu zgodnym z specyfikacją IEEE488.2 wystąpi błąd 'Querry interrupted', jeśli nie odebrano kompletnego komunikatu odpowiedzi i zrealizuje się operację zapisu.

Rys.4. Wyjście błędu w węzłach VISA.

Funkcje VISA nie realizują swoich zasadniczych operacji, jeśli terminal Error In dostanie daną sygnalizującą wystąpienie błędu (rys.5). W takim przypadku funkcja przenosi tylko daną o błędzie do terminala Error Out. Jeśli funkcja dostaje zerową daną o błędzie wtedy realizuje swoje zadania a informacja wyjściowa o błędzie reprezentuje status wykonania tej funkcji. Wykorzystanie terminali błędów pozwala przenieść informację o zaistniałym błędzie na poziom najwyższy aplikacji z wyłączeniem wykonywania następujących po nim operacji VISA. Jednocześnie we/wy błędu dostarcza węzłom VISA możliwości szeregowania działania połączonych tą daną węzłów (sterowanie przepływem danej o błędzie).

Rys.5. Idea konstrukcji węzłów VISA (jeśli wejście 'Error in' zgłasza błąd węzeł nie wykonuje właściwych sobie operacji).

Dodatkowo węzły VISA posiadają terminal wejściowy nazwy zasobu oraz terminal wyjściowy dostarczający duplikatora nazwy zasobu. Wyjątkiem jest tylko węzeł VISA Close zamykający sesję, który nie ma terminala wyjściowego nazwy zasobu oraz funkcja VISA Find Resource, której zadaniem jest znalezienie zasobów przyrządowych systemu komputerowego i stosuje inne wejścia i wyjścia. Terminal wyjściowy dostarcza wartość odpowiadającą wejściowej po wykonaniu węzła (niezależnie od błędu). Podobnie jak w przypadku we/wy błędu terminale nazwy zasobu mogą być zastosowane do uzależnienia kolejności wykonania węzłów VISA od przepływu tej specyficznej danej.

W praktyce połączenia między we/wy nazwy zasobu wykorzystuje się do szeregowania operacji VISA w odniesieniu do określonego zasobu, natomiast we/wy błędu można wykorzystać dodatkowo do określenia kolejności wykonania operacji na różnych zasobach przyrządowych.

Rys.6. Wykorzystanie przepływu danych do uzyskania odpowiedniej kolejności wykonania węzłów VISA.

Aplikacja z rys.6 wykonuje operacje przyrządowe tylko w przypadku zakończonej powodzeniem operacji otwarcia sesji komunikacyjnych do dwóch urządzeń (wartość TRUE na wejściu selektora konstrukcji CASE). Sesje dotyczą generatora (GPIB0::1) i multimetru (GPIB0::2). Najpierw musi nastąpić ustawienie parametrów sygnału generatora, potem pomiar multimetrem napięcia z obiektu zasilanego sygnałem generatora i na końcu zamknięcie obu sesji. Diagram konstrukcji CASE rozpoczyna się węzłem VISA Write do generatora. Po jego wykonaniu podejmie działanie węzeł VISA Write do multimetru , który zainicjuje wykonanie pomiaru. Podaną kolejność zapewnia przepływ danej o błędzie pomiędzy obu węzłami. Teraz dane dostarczone przez węzeł VISA Write (dvm) zainicjują działanie węzła VISA Read, który odczyta wynik pomiaru z multimetru. Nazwa zasobu dostarczona do węzła VISA Close (Dvm) spowoduje zamknięcie sesji związanej z multimetrem. Dana o błędzie wpływająca do drugiego węzła VISA Close spowoduje jego wykonanie i zamknięcie drugiej sesji. Jak widać wszystkie operacje wykonają się w wymaganej kolejności uzyskanej z przepływu danych.

Wejście błędu węzła VISA może pozostać niepołączone, co odpowiada dostarczeniu mu zerowej wartości domyślnej. Dlatego węzeł VISA Write do generatora zawsze podejmie próbę wykonania operacji zapisu. Dalsze przekazanie danej o błędzie zapewni nie tylko odpowiednią kolejność wykonania operacji ale także zablokuje wykonanie operacji następnych węzłów w przypadku niepowodzenia wykonania operacji przez poprzedzający węzeł VISA. Operacje zamknięcia sesji powinny zostać wykonane w każdych warunkach, dlatego wejście błędu pierwszego węzła VISA Close jest puste.

4. Praca w warunkach współdzielenia zasobów pomiarowych.

Współdzielenie zasobów może dotyczyć kilku procesów realizowanych współbieżnie w systemie komputerowym dysponującym lokalnymi zasobami pomiarowymi (np. karta GPIB plus dołączone do niej urządzenia pomiarowe) lub procesów realizowanych przez różne stacje komputerowe, ale korzystające z wspólnego serwera pomiarowego.

Aplikacje wykorzystujące współdzielone zasoby, takie jak przyrządy pomiarowe, wymagają stosowania mechanizmu ich blokowania w celu zabezpieczenia sekcji krytycznych realizowanego procesu. Sekcją krytyczną jest obszar aplikacji, w którym proces wymaga wyłączności w korzystaniu z danego zasobu, np. programowanego generatora. Aplikacja wykonująca pomiar charakterystyki częstotliwościowej obiektu musi zablokować na czas jej realizacji możliwość używania generatora innym procesom, aby nie dopuścić do zmiany jego ustawień przez konkurencyjne procesy.

Dany proces zajmuje urządzenie na swoje potrzeby (lock-blokada) zabraniając w ten sposób innym procesom dostępu do wybranego urządzenia. Blokada powinna obowiązywać przez okres czasu potrzebny do wykonania zadania. W tym czasie inne procesy nie są w stanie wykonać żadnych działań na zajętym urządzeniu łącznie z próbą zajęcia urządzenia dla własnych potrzeb.

Biblioteka VISA dla środowiska LabView dysponuje dwoma węzłami odpowiedzialnymi za zajmowanie zasobu. Węzeł VISA Lock Async.vi realizuje operację zajmowania zasobu na wyłączność natomiast Visa Unlock zwalniania zasób. Oba są skonstruowane zgodnie z ogólnymi zasadami przyjętymi dla węzłów VISA ( we/wy nazwy zasobu oraz we/wy błędu). VISA Lock Async.vi dysponuje wejściem pozwalającym zadeklarować czas oczekiwania ( w msek.) na uzyskanie zajęcia urządzenia. Jeśli w tym czasie nie uda się uzyskać zajęcia zasobu na wyłączność (zasób zajęty przez inny proces) węzeł zakończy działanie i zgłosi błąd.

Rys.7. Węzły VISA realizujące odpowiednio operację zajmowania zasobu na wyłączność (VISA Lock Async.vi) i zwalniania zasobu (Visa Unlock).

Operację zajęcia zasobu można też zrealizować podczas otwierania sesji urządzeniowej. Wejście 'access mode' węzła VISA Open pozwala zadeklarować potrzebę zajęcia zasobu bezpośrednio po otwarciu sesji (wartość 1 wybiera zajęcie na wyłączność). Jeśli zajęcie zasobu jest niemożliwe sesja zostaje zamknięta i węzeł zgłosi błąd. Wejście 'timeout' określa maksymalny okres czasu ( w msek.) na wykonanie operacji węzła. Jeśli w tym czasie nie uda się zrealizować przewidzianych operacji węzeł zgłosi błąd.

Rys.8. Węzeł VISA Open; argument 'access mode' o wartości 1 oznacza zajęcie zasobu na wyłączność.

Zwolnienie zasobu (VISA Unlock) jest też wykonywane podczas zamykania sesji (VISA Close), jeśli wcześniej nie zrealizowano tego w sposób jawny. Programista ma więc do dyspozycji różne możliwości zajmowania zasobów. Może uznać, że cała część programu dotycząca operacji przyrządowych stanowi sekcję krytyczną i wtedy wykorzysta węzły VISA Open i VISA Close nie tylko do otwarcia i zamknięcia sesji ale także do zajęcia zasobów na wyłączność i ich zwolnienia wraz z zamknięciem sesji. Jeśli uzna za część krytyczną pewien fragment diagramu wtedy ma do dyspozycji węzły odpowiedzialne tylko za zajmowanie i zwalnianie zasobów (VISA Lock Async.vi i Visa Unlock).

W warunkach pracowni studenckiej proponuje się uznanie całej części pomiarowej za sekcję krytyczną i otwieranie sesji łącznie z zajmowaniem zasobów na wyłączność. Otwarcie sesji do dwóch urządzeń można wtedy zrealizować w sposób pokazany na rys.9. Ramka zerowa sekwencji realizuje zamknięcie otwartych sesji, które z jakiś powodów nie zostały zamknięte. Ramka pierwsza wykonuje otwarcie żądanych sesji. Węzły VISA Open realizują kolejno otwarcie sesji do urządzeń łącznie z zajęciem zasobów na wyłączność. Jeśli pierwszy węzeł zakończy swoje operacje niepowodzeniem drugi pominie otwieranie sesji i cała operacja zakończy się błędem. Żadna sesja nie będzie otwarta a wyjścia sekwencji dostarczą odpowiednich informacji o stanie jej wykonania. Wyjście 'Open OK' można wykorzystać w dalszej części programu do warunkowego wykonania diagramu realizującego obsługę urządzeń, gdy otwarcie obu sesji powiodło się. Jeśli błędem zakończy się wykonanie drugiego węzła VISA Open, nastąpi wykonanie operacji zamykającej sesję pierwszą (ramka False konstrukcji CASE) i w efekcie po wykonaniu sekwencji nie będzie otwarta żadna sesja. Do zamykania otwartych sesji wykorzystano tutaj tablicę wskaźników otwartych sesji VISA w systemie komputerowym (Array of Refnums), którą automatycznie tworzy środowisko wykonawcze LabView. Tylko w przypadku powodzenia obu operacji otwarcia sesji sekwencja dostarczy na wyjściu 'Open OK' wartość prawdziwą.

Rys.9. Przykład otwarcia dwóch sesji urządzeniowych wraz z zajęciem zasobów na wyłączność.

Dla sesji urządzeniowych ( ::INSTR) zajęcie dotyczy określonego urządzenia pomiarowego. Oznacza to, że w przypadku zasobów GPIB pracujących na jednej magistrali inne procesy mogą korzystać z pozostałych urządzeń dołączonych do tej magistrali. Obowiązuje to również w odniesieniu do zasobów sieciowych GPIB, dostępnych na serwerach pomiarowych. Stacje użytkowe mogą równolegle realizować aplikacje pomiarowe na danym serwerze pomiarowym pod warunkiem wykorzystywania różnych urządzeń.

5. Programowanie zdalne urządzeń.

Przez programowanie zdalne urządzenia rozumie się tutaj przesłanie do niego komunikatu tekstowego polecającego wykonanie pewnej operacji (zerowania, inicjacji pomiaru itp.) lub ustawienie jego zasobu funkcjonalnego (kształtu lub częstotliwości generowanego sygnału itp.). Operację przesłania komunikatu realizuje się za pomocą węzła VISA Write. Argument wejściowy 'VISA Resource Name' określa urządzenie do, którego komunikat zostanie wysłany a argument 'write buffer' dostarcza węzłowi tekst komunikatu. Wyjście 'return count' zwraca liczbę informującą ile znaków tekstu komunikatu zostało wysłanych. Operacja VISA Write realizuje wyłącznie wysłanie komunikatu. Nie wykonuje żadnych operacji na treści komunikatu. Musi on być dostarczony w postaci gotowej, takiej jaka jest wymagana przez urządzenie.

Rys.10. Węzeł VISA Write.

Problemem nie jest samo wysłanie komunikatu ale jego przygotowanie. Potrzebna jest znajomość formatów i postaci poleceń stosowanych w danym urządzeniu oraz sposób ich wytworzenia w środowisku LabView. Programista może spotkać się z trzema kategoriami urządzeń pomiarowych GPIB stosujących różne formaty komunikatów :

- Urządzenia zgodne z specyfikacją IEEE488.1 (urządzenia produkowane przed 1987 r.);
- Urządzenia zgodne z specyfikacją IEEE488.2;
- Urządzenia zgodne z specyfikacją SCPI.

Specyfikacja IEEE488.1 nie określała w zasadzie formatu poleceń urządzeniowych. Stąd każde urządzenie jest programowane w sposób całkowicie unikalny wymyślony przez jego producenta. Zwykle zakładano zastosowanie krótkiego nagłówka literowego (najczęściej jednoznakowego) oraz dołączonego do niego argumentu numerycznego, np.:

- R2 - ustawienie drugiego podzakresu pomiarowego (nagłówek R od Range; argument numeryczny ustalony arbitralnie np. od 1 do 4, numery odpowiadają podzakresom od 0.1V do 100V).
- AXX.XX - ustawienie napięcia wyjściowego źródła w voltach (nagłówek A od Amplitude; argument numeryczny prezentujący w ustalonym stałym formacie wartość napięcia).

Koniec komunikatu sygnalizuje END lub dodatkowo pewien znak terminalny, najczęściej NL. W przypadku łączenia prostych komunikatów w jeden złożony nie stosowano znaków rozgraniczających. Jego rolę pełni kolejny nagłówek literowy.

Specyfikacja IEEE488.2 definiuje formaty komunikatów. Określa budowę nagłówka i argumentów polecenia oraz separator nagłówek-argumenty, separator argumentów oraz separator komunikatów. Definiuje też dopuszczalne znaki terminalne komunikatu. Nie są jednak określone słowa kluczowe nagłówków w odniesieniu do określonych zasobów funkcjonalnych urządzeń. Stąd polecenia urządzeniowe są dalej unikalne (nazewnictwo nagłówków) w podobnych urządzeniach pochodzących od różnych producentów; mają jednak podobną budowę. Standard wprowadza grupę poleceń wspólnych dotyczących zasobów funkcjonalnych, które występują we wszystkich urządzeniach, np. *cls, *rst itp.

Dopiero specyfikacja SCPI wprowadza szersze unormowanie dotyczące nazewnictwa zasobów funkcjonalnych urządzeń. Przyjmuje wszystkie ustalenia specyfikacji IEEE488.2 i wprowadza wspólne nazewnictwo do podobnych zasobów funkcjonalnych niezależnie od rodzaju urządzenia pomiarowego.

Programista przystępując do opracowania aplikacji musi poznać dokładnie sposób programowania wykorzystywanych urządzeń. Potrzebne informacje znajdzie w dokumentacji urządzeń. W przypadku najstarszych urządzeń unikalne formaty oraz specyficzna postać argumentów będzie z pewnością dużym utrudnieniem dla procesu projektowania. Urządzenia współczesne stosujące SCPI ułatwią proces projektowania. Głównie z powodu nazewnictwa (można przewidzieć nazwę nagłówka) oraz swobodnego formatu większości argumentów.

Rys.11. Przykład operacji programowania generatora.

W zasadzie programista będzie stosował jeden z dwóch sposobów ustalenia treści komunikatu:

- Komunikat o treści arbitralnej , czyli ustawiającej zasób funkcjonalny urządzenia w ustalony sposób niezależny od danych wypracowywanych w aplikacji, np. ustawienie na stałe generacji sygnału sinusoidalnego o określonej częstotliwości. W tej sytuacji wystarczy wykorzystać stałą tekstową z odpowiednio zdefiniowaną treścią.
- Komunikat o treści uzależnionej od danych wypracowywanych w aplikacji, np. ustawienie częstotliwości sygnału stosownie do wartości uzyskanej z obliczeń. W tej sytuacji musi wykorzystać funkcję formatującą dane numeryczne do postaci tekstowej i dołączyć ten tekst do tekstu nagłówka. W urządzeniach SCPI może stosować formatowanie domyślne, w innych może zaistnieć potrzeba zastosowania określonego sposobu formatowania. Gorzej, jeśli specyficznego formatu nie daje się uzyskać prostymi środkami.

Przykład z rys.11 pokazuje ustawianie częstotliwość generatora według logarytmicznego doboru wartości w granicach od From do To z liczbą punktów Step w dekadzie oraz oba sposoby wytworzenia komunikatu programującego. Pierwszy i trzeci węzeł VISA Write realizuje arbitralne polecenie, odpowiednio ustawienie generatora do generacji sygnału sinusoidalnego i polecenie pytające o aktualnie ustawioną częstotliwość generowanego sygnału. Drugi węzeł VISA Write realizuje ustawienie częstotliwości sygnału na podstawie danej typu DBL uzyskanej z formuły. Do uzyskania tekstu komunikatu wykorzystano węzeł Format Into String z konwersją typu zmiennoprzecinkowego (domyślna liczba znaków, minimum 8 w tym zawsze 6 znaków części ułamkowej). Przesłany do urządzenia argument może mieć zbyt dużą precyzję i wobec tego niepotrzebnie traci się czas na transfer nadmiarowych znaków. Zatem jeśli wystarcza ustawienie częstotliwości z dokładnością do 0.1Hz można zastosować formatowanie z żądaną precyzją (np. %.1f). Z podobnych powodów formatowanie %f może być nieodpowiednie dla bardzo dużych i bardzo małych wartości. Można posłużyć się wtedy formatowaniem %g lub %e, które produkuje zapisy wartości numerycznych w postaci wykładniczej. Urządzenie SCPI przyjmie argument numeryczny w każdym zapisie zarówno stałoprzecinkowym jak i wykładniczym.

Przykład z rys.12 pokazuje programowanie urządzenia wymagającego ściśle określonego formatu zapisu liczby stanowiącej argument polecenia. Do uzyskania żądanej postaci komunikatu przekazanego funkcji VISA Write wykorzystano węzeł Format Into String z stringiem formatującym w postaci "A%+06.2f>". Znak plus wymusza wyprodukowanie zapisu liczby ze znakiem. Znak 0 zapewnia stosowanie zer nieznaczących zapisu zamiast spacji. 6.2 określa długość zapisu i precyzję (liczbę znaków części ułamkowej). Do tekstu zapisu liczby są dodane jeszcze znaki A i >. Pierwszy stanowi nagłówek polecenia określający źródło zasilacza (posiada dwa źródła A i B), drugi kończy polecenie i jest traktowany przez urządzenie jako polecenie ustawienia napięcia. Węzeł Expression zabezpiecza operację przed próbą ustawienia napięcia wykraczającego poza dopuszczalny zakres (+/-30V).

Rys.12. Przykład operacji programowania zasilacza BM572.

Rys.13 prezentuje programowanie podzakresu pomiarowego multimetru V553. Komunikat stosuje jednoznakowy nagłówek wybierający programowanie podzakresu (Y) oraz argument, którym jest arbitralnie ustalona cyfra przypisana do danego podzakresu. Węzeł Expression ustala na podstawie dostarczonej mu wartości spodziewanej numer podzakresu. Konwersja tej liczby zgodnie z formatem "Y%d" pozwala uzyskać żądaną postać komunikatu tekstowego.

Rys.13. Przykład operacji programowania podzakresu pomiarowego multimetru V553.

Separator części ułamkowej zapisu liczby: Wszystkie dostępne w środowisku projektowym operacje konwersji wartości numerycznych do zapisu tekstowego (jak również konwersje odwrotne) stosują narodowe ustalenia dotyczące zapisu liczb określone w systemie operacyjnym. Dla polskiej wersji systemów Windows domyślnie przyjmowany jest przecinek do oddzielenia części całkowitej od ułamkowej. Tymczasem urządzenia pomiarowe stosują kropkę. W tej sytuacji podane przykłady realizowane w polskiej wersji systemu tworzą zapisy liczb z zastosowaniem przecinka. Polecenie w takiej postaci wysłane do urządzenia kończy się katastrofą. Urządzenie nie rozumie poleceń i raportuje błędy. Rozwiązaniem tego problemu jest modyfikacja ustawień narodowych systemu w zakresie znaku dziesiętnego lub zastosowanie dodatkowych operatorów formatowania w operacjach przekształcania danych numerycznych do tekstowych i tekstowych do numerycznych:

- "%.;" - ustawia kropkę jako separator części ułamkowej.
- "%,;" - ustawia przecinek jako separator części ułamkowej.
- "%;" - powrót do ustawienia systemowego.

Pokazane kody określają wyłącznie rodzaj separatora i nie wymagają żadnych dodatkowych wejść lub wyjść dla węzłów realizujących konwersje. Zmiana obowiązuje dla wszystkich późniejszych operacji aż do jawnego odwołania.

Sygnalizacja końca komunikatu : Dla sesji z zasobem GPIB (lokalnym lub sieciowym) z domyślnie ustawionym atrybutem Send End Enable (rys.2) wraz z ostatnim transmitowanym znakiem jest wystawiony END (linia EOI) sygnalizujący koniec komunikatu. Większości urządzeń GPIB implementuje ten sposób rozpoznania końca odbieranego komunikatu. Istnieją jednak urządzenia, w których nie zastosowano tej możliwości wprowadzając w zamian stosowanie określonego znaku terminalnego. W takiej sytuacji trzeba dołączyć do tekstu komunikatu określony znak terminalny, ponieważ węzeł VISA Write nie wykonuje już żadnych operacji na dostarczonym tekście komunikatu (nie ma opcji automatycznego dołączania znaku terminalnego). Urządzenia SCPI powszechnie rozpoznają koniec komunikatu na podstawie znaku terminalnego NL oraz komunikatu END. Komunikat wysyłany do takich urządzeń może kończyć się znakiem NL lub musi się nim kończyć, jeśli atrybut Send End Enable blokuje wystawianie END.

Rys.14. Przykłady kreowania tekstów poleceń z dołączeniem znaku terminalnego NL(\n).

Rys.14 pokazuje sposób wytworzenia tekstów poleceń do urządzenia, które traktuje znak NL jako terminator poleceń. W podanych przykładach zostaną wytworzone teksty (\s - spacja):

1. freq\s100.000000;:volt\s1.000000\n
2. freq\s100.000000\nvolt\s1.000000\n
3. freq\s100;:volt\s1.0\n
4. freq\s100;:volt\s1.0\n

W przypadku wykorzystania węzła Format Into String można bezpośrednio wpisywać oznaczenia kodów znaków sterujących LF, CR itp. stosowanych najczęściej jako znaki terminalne w stałej definiującej string formatujący. Dla ustawień arbitralnych można stosować węzeł Concatenate Strings łączący stałe stringowe. Dołączenie określonego znaku terminalnego wymaga dołączenia zdefiniowanej stałej, np. Line Feed Constant lub ustawienia węzła stałej w trybie wpisywania kodów zastępczych znaków ASCII ('\' Codes Display) i wpisania jego oznaczenia.

Przykład 'b' pokazuje wytworzenie tekstu polecenia, które zostanie wysłane w jednej operacji VISA Write ale zostanie potraktowane przez urządzenie jako dwa osobne polecenia programujące. Uzyskano to przez rozdzielenie poleceń znakiem terminalnym NL zamiast znakiem separatora poleceń jednostkowych (;).

Stosowanie poleceń złożonych : Operacja programowania urządzenia składa się z co najmniej dwóch węzłów konstruowanego diagramu (Format Into String i VISA Write). Z powodu ograniczonych rozmiarów okna prezentującego graficzny zapis programu oraz jego czytelności należy konstruować w miarę proste diagramy. Oznacza to konieczność oszczędnego stosowania węzłów i optymalnego ich wykorzystania. W odniesieniu do operacji urządzeniowych optymalne wykorzystanie węzła VISA Write polega na przesłaniu za jego pomocą możliwie wielu poleceń jednocześnie. Jest to możliwe, ponieważ urządzenia akceptują polecenia złożone, czyli składające się z wielu poleceń elementarnych. Polecenia złożone współczesnych urządzeń stosują średnik jako separator poleceń elementarnych. W przypadku urządzeń starszych trzeba dostosować się do wymogów konkretnego urządzenia.

Rys.15. Przykład operacji VISA Write przesyłającej polecenie złożone.

Przykład pokazuje ustawienie kilku parametrów generatora oraz sprawdzenia poprawności ich wykonania przy wykorzystaniu jednej operacji przesłania polecenia złożonego. Polecenie realizuje następujące zlecenia:

- *rst;*cls - zerowanie generatora i czyszczenie kolejki zarejestrowanych błędów;
- :outp:load 50 - określenie obciążenia źródła (50 ohm);
- :func:shap SIN - ustawienie generacji sygnału sinusoidalnego;
- :volt %f - ustawienie amplitudy zgodnie z wartością otrzymaną z nastawnika Amplituda;
- :freq %f - ustawienie częstotliwości zgodnie z wartością otrzymaną z nastawnika Częstotliwość;
- syst:err? - zapytanie o błąd wykryty przez urządzenie (np. spowodowany błędem zapisu polecenia lub jego argumentu).

Zapytanie o błąd (syst:err?) stanowi tutaj osobne polecenie, co uzyskano przez wstawienie przed nim znaku terminatora NL. Takie postępowanie jest w pełni uzasadnione, jeśli urządzenie ma dostarczyć odpowiedź o ewentualnym błędzie polecenia w każdych warunkach a więc także, gdy błędnie zostanie podany nagłówek jednego z wcześniejszych poleceń jednostkowych. Urządzenia zgodne z IEEE488.2 a więc także SCPI w takim wypadku rejestrują błąd polecenia i pomijają następne polecenia aż do najbliższego terminatora (NL). Jeśli zapytanie jest ostatnim elementem polecenia złożonego nie zostanie wykonane w przypadku błędnej nazwy jednego z poprzedzających poleceń. Wtedy też operacja odczytu danych o błędzie zakończy się błędem przeterminowania.

6. Odczyt danych z urządzeń.

Odczyt danych realizuje się za pomocą węzła VISA Read. Operacja odczytu jest wykonywana bez jakiegokolwiek przetwarzania odbieranego komunikatu. Oznacza to, że na wyjściu 'read buffer' otrzymuje się surowy tekst komunikatu, taki jaki wysyła w danej sytuacji urządzenie. Wejście liczby znaków 'byte count' określa maksymalną liczbę znaków, którą operacja może odczytać z urządzenia. Operacja odczytu kończy się, gdy zostanie spełniony jeden z wymienionych niżej warunków :

- Zostanie rozpoznany koniec komunikatu (END - w GPIB odpowiedni stan linii EOI).
- Zostanie odebrany ustalony znak terminalny (zwykle NL; opcjonalny warunek zakończenia, który można zablokować lub uaktywnić; atrybuty sesji - rys.2).
- Po odebraniu zadeklarowanej liczby znaków.

Rys.16. Węzeł VISA Read.

W praktyce należy odbierać całe komunikaty. Oznacza to, że do wejścia liczby odbieranych znaków należy doprowadzić wartość co najmniej odpowiadającą długości odczytywanego komunikatu. Współczesne urządzenia mogą dostarczać różnorodnych danych i komunikaty z nimi mogą mieć różną długość. Dane dotyczące ich długości można znaleźć w dokumentacji urządzeń. W wielu przypadkach można przewidzieć orientacyjnie ich długość a dla pewności deklarować wartości odpowiednio duże.

Operację odczytu można realizować wtedy, gdy urządzenie dysponuje komunikatem w swoim buforze wyjściowym. Musi zatem poprzedzać ją pewna operacja skierowana do urządzenia, której wynikiem jest przygotowanie określonego komunikatu, np. zainicjowanie pomiaru. Bezpośrednio po wysłaniu takiego polecenia można przejść do odczytu, nawet jeśli komunikat nie jest jeszcze gotowy. Węzeł VISA Read podobnie jak inne węzły realizujące transfer danych czeka z jego realizacją przez czas określony timeout'em dla operacji transmisji. Jeśli czas przygotowania komunikatu przez urządzenie jest krótszy od zadeklarowanego timeoutu wówczas operacja VISA Read poczeka chwilę i z małym opóźnieniem odczyta komunikat. W przeciwnym razie zakończy się błędem przeterminowania. W sytuacji, gdy nie można oszacować czasu potrzebnego na przygotowanie przez urządzenie danych, trzeba zastosować specjalne środki pozwalające synchronizować aplikację z urządzeniem.

Akcje inicjujące przygotowanie komunikatów wyjściowych są różnie realizowane. Generalnie zależy to od standardu według, którego urządzenie zostało wykonane. Urządzenia starszej generacji, zgodne ze standardem IEEE488.1 wysyłają tylko jeden typ danych - wynik pomiaru. Dotyczy to urządzeń mierzących określone wielkości i dla nich poleceniem przygotowania danej jest inicjalizacja pomiaru, najczęściej rozkaz GET. Urządzenia stymulujące - źródła sygnałów - wykonywano jako urządzenia przyjmujące nastawy. Zwykle nie wydają one żadnych komunikatów danych. W roku 1979 firma Tektronix wprowadziła koncepcję zapytań, która pozwoliła zaimplementować w urządzeniach możliwość wydawania różnego rodzaju danych. Koncepcja to upowszechniła się po roku 1987 po wprowadzeniu standardu IEEE488.2 a później ustaleń SCPI. Zgodnie z nią dane są przygotowywane tylko w odpowiedzi na zapytanie. Obowiązuje też zasada, że po poleceniu zawierającym zapytania bezwzględnie trzeba odczytać cały komunikat. Bez wcześniejszego zapytania bufor wyjściowy urządzenia jest pusty i operacja odczytu zakończy się błędem przeterminowania.

Rys.17. Inicjowanie wydania odpowiedzi w urządzeniach pomiarowych.

Węzeł VISA Read dostarcza tekst komunikatu. W przypadku wyników pomiarów lub innych danych liczbowych trzeba za pomocą dodatkowych środków zrealizować ich konwersję do typu int, float, double itp., aby można było realizować na nich obliczenia. Można zastosować do tego celu węzeł Scan From String lub podobny. Operacje konwersji dotyczą stringów numerycznych zawierających dowolny, poprawny zapis wartości liczbowych (tekst musi rozpoczynać się zapisem liczby). Tymczasem komunikaty z danymi numerycznymi mogą mieć nagłówki tekstowe, mogą być komunikatami złożonymi itp. Uzyskanie poprawnej konwersji wymaga od programisty znajomości formatu odebranego komunikatu tak, aby konwersji do postaci numerycznej poddać fragmenty tekstu zawierające poprawne zapisy tekstowe liczb.

W przypadku odpowiedzi dostarczającej daną liczbową poprzedzoną nagłówkiem tekstowym (rys.18) trzeba zastosować format, który najpierw wybierze początkowe znaki nagłówka (%[ *A-Z]) i przekaże na wyjście tekstowe a następnie przetworzy (%f) pozostałą część odpowiedzi (zapis liczby) do danej numerycznej typu double przekazanej na wyjście DBL. Jeśli nagłówek ma w każdej sytuacji stałą długość można uprościć konwersję korzystając z wejścia określającego pozycję w stringu, od której rozpoczyna się zapis liczby (wejście 'initial scan location') i od której rozpocznie się analizowanie stringu podczas konwersji. Jest to domyślnie wejście i bez doprowadzenia danej ma wartość zero. W przedstawionym przykładzie należy wprowadzić na to wejście wartość 4 i zastosować string formatujący %f.

Rys.18. Konwersja komunikatu liczbowego z nagłówkiem tekstowym do typu double.

Urządzenia bardzo często wydają odpowiedzi numeryczne bez nagłówków lub można ustawić w urządzeniu format odpowiedzi (z lub bez nagłówka). W tej sytuacji konwersja staje się prosta. Można też spotkać się z sytuacją, gdy odpowiedź zawiera kilka danych liczbowych. Jest tak jeśli polecenie poprzedzające odczyt zawiera kilka zapytań. Wtedy po odebraniu całej odpowiedzi, komunikat zawiera kilka danych liczbowych oddzielonych średnikami (rys.19). Konwersję do typu numerycznego np. DBL można wykonać za pomocą węzła Scan From String z stringiem formatującym "%f;%f". Dane wyjściowe są dostępne na osobnych wyjściach węzła. Można też wykorzystać węzeł Spreadsheet String To Array. Wówczas dane będą dostępne w tablicy typu DBL. Dla węzła należy określić separator danych, string formatujący oraz określić wymiar tablicy wyjściowej.

Rys.19. Konwersja złożonego komunikatu liczbowego do typu double.

Ostatni sposób konwersji jest bardziej przydatny w sytuacji, gdy urządzenie wydaje np. tablicę danych pomiarowych uzyskanych w wyniku jednej akwizycji. Wówczas separatorem poszczególnych danych są przecinki i schemat z rys.19 trzeba nieco zmodyfikować.

7. Technika synchronizacji; wykorzystanie SRQ w aplikacji.

W procesie obsługi urządzeń często istnieje konieczność zapewnienia synchroniczności działania programu z działaniem urządzeń. Prostym przykładem tego jest sekwencja wydania polecenia wykonania pomiaru przez urządzenie i odbiór wyniku pomiaru. Realizuje to sekwencja operacji VISA Write (wysyła np. polecenie "meas:volt:ac?") i operacji VISA Read odczytująca uzyskany wynik. Najczęściej realizuje się to w sposób pokazany na rys.17. Sekwencja operacji VISA stosuje tu niejawną synchronizację wykorzystującą timeout zdefiniowany dla operacji transferu danych. Urządzenie realizuje pomiar w czasie krótszym od zadeklarowanego czasu przeterminowania dla sesji VISA, wobec czego węzeł VISA Read poczeka na dane i z opóźnieniem odczyta je. Operacja zakończy się sukcesem. Problemy wystąpią, gdy czas wykonania pomiarów jest długi i dodatkowo uzależniony od wielu czynników i w rezultacie trudny do oszacowania. W tej sytuacji potrzebne są środki zapewniające prosty i pewny sposób rozwiązania zasygnalizowanego problemu. Wspomniana sytuacja może mieć miejsce także podczas programowania urządzenia, gdy następne polecenie może być wysłane do urządzenia po wykonaniu poprzedniego [3].

W GPIB wykorzystuje się do tego celu zgłaszanie żądań obsługi przez urządzenia (SRQ) oraz system raportowania stanu urządzeń, którym dysponują urządzenia tego standardu [4]. Możliwości wykorzystania zgłaszania obsługi są bardzo zróżnicowane w zależności od generacji urządzeń. W najstarszych urządzeniach (zgodnych z IEEE488.1) zwykle stosowano zgłaszanie stanu operacji: wykonuje pomiar - wynik gotowy oraz ewentualnie unikalnie zdefiniowane inne stany. Urządzenia stymulujące (źródła) lub komutatory najczęściej nie dysponowały możliwością zgłaszania SRQ oraz wydawania danych statusowych. Nowe generacje urządzeń (zgodnych z IEEE488.2 i SCPI) obligatoryjnie dysponują ujednoliconym systemem raportowania swojego stanu. Została zdefiniowana grupa stanów i zdarzeń raportowana przez urządzenia. Istnieje też możliwość programowania systemu raportowania stanu tak, aby SRQ było zgłaszane tylko w określonych sytuacjach.

Do obsługi zdarzeń związanych z SRQ typowo wykorzystuje się węzły pokazane na rys.20. Węzeł VISA Enable Event uruchamia mechanizm wykrywania zdarzeń związanych z danym zasobem pomiarowym i określonych przez wejście Event Type. VISA Disable Event wyłącza wykrywanie zdarzeń. Obszar programu, w którym oczekuje się na pewne zdarzenia przyrządowe rozpoczyna się węzłem VISA Enable Event i kończy węzłem VISA Disable Event.

Węzeł Wait for SRQ jest firmowym subVI, który realizuje oczekiwanie na SRQ wybranego zasobu przyrządowego przez okres czasu określony wejściem Timeout. Po wykryciu SRQ odczytuje bajt statusowy urządzenia i udostępnia go na wyjściu Status Byte.

Rys.20. Podstawowe węzły stosowane do obsługi SRQ.

Aplikacja z rys.21 realizuje cykliczne wykonanie serii 50 pomiarów napięcia AC po każdej inicjalizacji (INIT). Czas wykonania każdej serii pomiarów jest stosunkowo długi a jednocześnie trudny do oszacowania. Do potwierdzenia gotowości wyników wykorzystano bit OPC standardowego rejestru zdarzeń multimetru. System raportowania stanu multimetru zaprogramowano tak, aby zgłosił SRQ tylko gdy zostanie ustawiony bit OPC (*ese 1;*sre 32). Oczekiwanie na SRQ realizuję węzeł Wait for RQS z zadeklarowanym czasem oczekiwania 500sek.

Rys.21. Przykład synchronizacji z zastosowaniem oczekiwania na SRQ.

Po pomyślnym jego wykonaniu (urządzenie zakończyło serię pomiarów) i wysłaniu polecenia FETC? następuje odczyt komunikatu z wynikami (50 danych liczbowych w zapisie tekstowym oddzielonych znakami przecinka; łącznie 50*(16+1)=850 znaków). Transfer długich bloków danych może wymagać modyfikacji domyślnie ustalonego czasu przeterminowania (Property Node).

Węzeł synchronizacji (Wait for RQS) musi dysponować poprawnie określonym czasem maksymalnego oczekiwania. Projektant aplikacji musi go oszacować i ewentualnie zapewnić automatyczne dopasowanie w zależności od rodzaju mierzonej wielkości i sposobu wykonywania pomiarów. Jego zalety to:

- Oczekiwanie na SRQ bez wykonywania jakichkolwiek operacji na magistrali GPIB. Dopiero w wyniku wystąpienia SRQ jest realizowana procedura odczytu bajtu statusowego urządzenia.
- Operacja nie jest transakcją monopolizującą działanie systemu. W czasie jej realizacji mogą być wykonywane równoległe diagramy aplikacji jak również inne procesy uruchomione w systemie. Wynika to z odpowiedniej realizacji subVI realizującego ten węzeł. Oczekiwanie na SRQ można zrealizować węzłem VISA Wait on Event. Jest on jednak transakcją, która zmonopolizuje działanie systemu w czasie oczekiwania na zdarzenie. Węzeł Wait for RQS jest pętlą z działaniem ograniczonym czasem oczekiwania lub wystąpieniem SRQ. Diagram pętli wykorzystuje węzeł VISA Wait on Event, ale z zerowym czasem oczekiwania i kontrolą błędu timeout. Jeśli nie wystąpi to oznacza, że urządzenie zgłosiło SRQ.

Uwaga: W warunkach korzystania z biblioteki VISA firmy Agilent oraz innych produktów tej firmy (np. serwera pomiarowego Sicland z zastosowaniem protokołu VXI-11) nie można stosować węzła synchronizacji Wait for RQS podczas współdzielenia zasobów pomiarowych. Zakłada on, że w czasie jego realizacji linia SRQ jest ustawiana tylko przez urządzenie określone nazwą zasobu. Jeśli tak nie jest kończy swoje działanie w momencie wystawienia SRQ przez inne urządzenie lub błędem przeterminowania . Można natomiast stosować ten węzeł korzystając z biblioteki VISA firmy NI oraz serwera tej firmy NI-VISA Server.

Wykorzystując serwer Sicland, zamiast opisanej metody można wykorzystać pętlę cyklicznego odpytywania urządzenia, aż do uzyskania bajtu statusowego z określonym stanem. Wadą tej metody jest wykonywanie wielu operacji magistralowych i duże obciążenie serwera pomiarowego w zasadzie jałowymi operacjami.

Rys.22. SubVI Wait on STB.

Rys.22 pokazuje rozwiązanie oczekiwania na określony wejściem Mask Any Set stan bajtu statusowego urządzenia. Działanie pętli SubVI jest ograniczone dodatkowo podanym czasem oczekiwania (wejście Timeout) oraz błędem operacji VISA STB. Dodatkowe wyjście Set OK. określa stan wykonania operacji oczekiwania. Wyjście status dostarcza wartość bajtu statusowego uzyskanego w momencie zakończenia operacji oczekiwania lub zero w wypadku niepowodzenia. Pauza 10 msek ogranicza częstość powtarzania operacji VISA STB.

Podane rozwiązanie można z powodzeniem zastosować w aplikacji z rys.21, choć przy długich sekundowych czasach pomiarów każda operacja synchronizacji będzie wykonywała wiele operacji odczytu bajtu statusowego niepotrzebnie obciążając procesor i magistralę GPIB.

Żądanie obsługi oraz bajt statusowy urządzenia można wykorzystać nie tylko do synchronizacji ale również innych celów, jeśli pozwala na to jego zawartość. Tak jest w wypadku multimetru V553. Jego bajt zawiera oprócz informacji o gotowości wyniku, również informację o tym czy wynik jest wykonany na optymalnym podzakresie (niedomiar lub przekroczenie podzakresu). Przykład z rys.23 pokazuje rozwiązanie programowego ustawienia optymalnego podzakresu odpowiednio do aktualnie mierzonego napięcia DC. Każdy pomiar startuje z pozycji podzakresu numer 5 (10V). W zależności od wartości bajtu statusowego sygnalizującego gotowość wyniku (maska=0x40) podzakres jest zmniejszany (0x41) lub zwiększany (0x48). Wartość 0x40 oznacza poprawnie dobrany podzakres i wtedy pętla kończy swoje działanie. Zmodyfikowane numery podzakresów są przekazywane do kolejnej iteracji za pomocą rejestru przesuwnego pętli (Shift Register).

Rys.23. Zastosowanie węzła Wait on STB.vi do optymalnego doboru podzakresu multimetru V553.

8. Argumenty i dane binarne komunikatów urządzeniowych.

Jednym z typów argumentów poleceń nastawczych oraz danych urządzeniowych jest arbitralny blok binarny o zadeklarowanej długości. Jego budowę przedstawia rys.24. Pozwala on przesyłać do urządzeń lub odbierać od nich dane w postaci binarnej (int8/16/32, float-SGL, double-DBL) zamiast w formie tekstowej zapisu dziesiątkowego. Transfer danych w postaci binarnej pozwala szybciej realizować operacje zapisu i odczytu, ponieważ wymaga przesłania mniejszej liczby bajtów a dodatkowo odpadają operacje konwersji z postaci binarnej do tekstowej po stronie nadawcy i odwrotna konwersja po stronie odbiorcy. W wypadku przesłania danej typu rzeczywistego SGL transfer dotyczy czterech bajtów stanowiących reprezentację tego typu danej w pamięci systemu mikrokomputerowego urządzenia. Wysłanie tej samej danej ale w postaci tekstowej wymaga konwersji do zapisu tekstowego oraz najczęściej transferu 16 znaków, ponieważ zwykle stosuje się tak długi zapis, aby zapewnić dokładne odwzorowanie przekazywanych wartości.

Rys.24. Budowa arbitralnego bloku danych binarnych o zadeklarowanej długości.

Urządzenia wykorzystują arbitralne bloki danych binarnych do przekazywania dużych bloków danych, np. tablic wartości. W stosunku do pojedynczych wartości nie ma powodu ich transferu w postaci binarnej, ponieważ korzyści są niewielkie. Wynika to z narzutów czasowych operacji przygotowania transferu. Ich udział procentowy w całej operacji zapisu lub odczytu maleje wraz z długością transferowanego bloku i wówczas czas samego transferu wpływa znacząco na szybkość realizacji aplikacji.

Podsystem Format zasobów funkcjonalnych urządzenia, jeśli jest zaimplementowany, pozwala określić sposób wydawania danych liczbowych. Tak jest w multimetrze modułowym VXI HP E1411. Polecenie "form ASCII" wybiera wydawanie danych liczbowych w zapisie tekstowym a "form REAL,32" lub "form REAL,64" w postaci binarnej (odpowiednio SGL i DBL). Sposób wymuszenia formatu, odbioru odpowiedzi i jej konwersji do danych typu DBL przedstawia rys.25.

Rys.25. Konwersja danej tekstowej i danej z arbitralnym blokiem danych binarnych do typu DBL.

Komunikat odpowiedzi uzyskany z węzła VISA Read jest stringiem. Dla danej o wartości 0.0345 jest ciągiem 11 znaków "#18\3F\A1\AA\00\00\00\00\00\n" , w którym znaki "#18" stanowią nagłówek a kolejne 8 bajtów jest reprezentacją binarną danej typu DBL. Konwersja do danej typu DBL wymaga odrzucenia nagłówka (węzeł String Subset) i traktowania tak wyłonionego obszaru pamięci jako obszaru z daną typu DBL a nie stringu binarnego (węzeł Type Cast). Operacja Type Cast jest operacją zmiany typu, która rzutuje wskaźnik z wskazania na typ unsigned char na wskazanie do typu DBL. Wyjście węzła Type Cast dostarcza danej typu DBL, którą można użyć do realizacji operacji obliczeniowych.

Rys.26. Konwersja danej z arbitralnym blokiem danych binarnych do tablicy typu SGL.

Przykład z rys.26 pokazuje konwersję danych binarnych do tablicy typu SGL (float) w sytuacji, gdy multimetr po każdej inicjalizacji wykonuje serię 100 pomiarów i wysyła je w postaci binarnej Real32. Deklarację typu rzutowania dla węzła Type Cast realizuje dołączenie do jego wejścia stałej odpowiedniego typu, tutaj stałej typu tablica SGL.

Dane binarne mogą być także argumentem polecenia wysyłanego do urządzenia. Przykładem takiej operacji jest definiowanie kształtu sygnału dla generatora HP 33120. Można to wykonać przesyłając blok danych tekstowo :

DATA VOLATILE, <value>,<value>, .... gdzie <value> jest wartością rzeczywistą z zakresu (-1.0,+1.0);

lub binarnie :

DATA:DAC VOLATILE, <nagłówek bloku binarnego> <bajt> <bajt> .... gdzie każda para bajtów reprezentuje daną całkowitą (Int16) z zakresu (-2047,+2047).

Definiując kształt za pomocą 1000 wartości (max.16 000) blok danych prezentowanych tekstowo ma długość 10 000 znaków (9 znaków dla każdej wartości plus znak separatora) natomiast blok binarny składa się z 4 000 bajtów (2 bajty dla każdej wartości). Czas transferu danych binarnych będzie ponad dwukrotnie krótszy.

Sposób utworzenia komunikatu programującego z arbitralnym blokiem danych binarnych o zdefiniowanej długości pokazuje rys.27. Pokazano sposób utworzenia bloku binarnego z tablicy typu Int16, nagłówka bloku binarnego oraz złożenia całego komunikatu. Tak utworzony komunikat należy przekazać do węzła VISA Write.

Rys.27. Sposób tworzenia komunikatu z arbitralnym blokiem danych binarnych.

Format binarny wszystkich typów danych liczbowych został ujednolicony począwszy od standardu IEEE488.2 i odpowiada on formatom stosowanym w systemach komputerowych. Urządzenia zakładają otrzymywanie bajtów takich danych w kolejności od najstarszego do najmłodszego. Tymczasem niektóre systemy przechowują je w pamięci w odwrotnej kolejności. W tej sytuacji urządzenie otrzyma bajty każdej wartości w odwrotnej kolejności w stosunku do ustaleń. Problem ten rozwiązuje się po stronie urządzenia powiadamiając je wcześniej o potrzebie przestawienia kolejności otrzymywanych bajtów. Jest to polecenie FORMat:BORDer z argumentem NORMal lub SWAPped (odpowiednio normalna kolejność lub odwrotna).

9. Literatura.

1. VISA Implementation Specification for Textual Languages; VXIplug&play Systems Alliance; December 4, 1998, Revision 2.0.1 (http://www.vxipnp.org/
2. VISA Implementation Specification for the G Language; VXIplug&play Systems Alliance; December 4, 1998, Revision 2.0.1 (http://www.vxipnp.org/
3. Polecenia nakładkowe i technika synchronizacji. (Technika synchronizacji w IEEE-488.2.)
4. System raportowania stanu urządzeń GPIB. (IEEE-488.2 - System raportowania stanu urządzenia.)

15 listopad 2003 r. | opr. dr inż. Bogdan Kasprzak
Interfejsy systemów pomiarowych | Początek