Robert Piskorz, VII semestr, ISP, zaoczne
Ćwiczenie 1: Obsługa aparatury pomiarowej z wykorzystaniem standardu SCPI oraz zintegrowanego środowiska programistycznego VEE PRO
Pytanie 1: Cechy środowiska VEE Pro.
1. CHARAKTERYSTYKA OGÓLNA HP VEE.
HP VEE jest profesjonalnym środowiskiem projektowania oprogramowania systemów pomiarowych. Umożliwia zrealizowanie :
Sterowania przyrządów (ustawiania ich zasobów funkcjonalnych);
Pomiarów (inicjalizacji, nadzoru, wykrycia ich wykonania);
Akwizycji (zebranie danych pomiarowych, także zapamiętanie na stałych nośnikach);
Przetwarzania zebranych danych (od prostych operacji matematycznych do cyfrowego przetwarzania sygnałów);
Prezentacji wyników w postaci tekstowej i graficznej (wyświetlacze tekstowe i wykresy);
Generacji raportów z wyników badań;
Graficznego interfejsu użytkownika.
Cechą charakterystyczną tego środowiska jest odejście od tradycyjnego programowania tekstowego (środowiska Borlanda i MS do projektowania w języku C lub C++) na rzecz projektowania graficznego. Składnikiem podstawowym zapisu programu nie jest instrukcja lecz ikona obiektu wykonującego określone operacje na swoich danych wejściowych. Z kolei sekwencja wykonywania instrukcji jest zastąpiona przepływem danych pomiędzy obiektami programu projektowanym za pomocą linii łączących wyjścia i wejścia obiektów.
Graficzną formę zapisu programu tworzy się podobnie do schematu blokowego urządzenia, przedstawiając jego elementy funkcjonalne oraz drogi przepływu danych oraz informacji sterujących. Po wybraniu właściwej koncepcji rozwiązania projektowanego urządzenia skonstruowanie jego schematu blokowego nie stanowi większego problemu. Podobnie jest w przypadku graficznego zapisu programu tym bardziej, gdy dysponuje się zestawem obiektów o dużych możliwościach funkcjonalnych i odpowiedniej uniwersalności. To z kolei można łatwo osiągnąć w dedykowanych środowiskach projektowych. W rezultacie końcowym, graficzne środowisko projektowania aplikacji pomiarowej zapewnia duże ułatwienia w projektowaniu profesjonalnych aplikacji oraz znakomicie przyspiesza uzyskanie końcowego produktu przy zminimalizowaniu trudności projektowych.
HP VEE pozwala wyposażyć projektowaną aplikację w graficzny interfejs użytkownika zawierający elementy interakcyjnej współpracy operatora z aplikacją. Do tego celu środowisko oferuje bogaty zestaw różnego rodzaju nastawników, wskaźników i wyświetlaczy. Istnieje też możliwość wykorzystania technologii ActiveX i w ten sposób integrowania projektowanej aplikacji z innymi komercyjnymi produktami, takimi jak np. Microsoft Excel, Word itp. Wbudowane mechanizmy wykorzystania zewnętrznych bibliotek dynamicznych pozwalają budować hybrydowe aplikacje, których część jest kreowana za pomocą tradycyjnych środowisk projektowych, np. w C, C++ lub Pascal.
Zaprojektowana aplikacja może być wykonywana poza środowiskiem projektowo-uruchomieniowym przy zastosowaniu tzw. ”runtime'u” wchodzącego w skład pakietu HP VEE (program veerun.exe; polecenie wykonania: ”veerun [option] aplikacja.vee”).
HP VEE jest dostępne dla większości popularnych systemów operacyjnych, między innymi dla wszystkich wersji systemu Windows, systemu Windows NT, Linux, Unix oraz Sun.
2. PODSTAWOWY SKŁADNIK PROGRAMU HP VEE - OBIEKT VEE.
Podstawowymi składnikami programu są obiekty VEE prezentowane w postaci prostokątów z odpowiednim opisem charakteryzującym dany obiekt. Utworzony obiekt przyjmuje nazwę domyślną, ale można ją zmienić wprowadzając dowolny opis charakteryzujący precyzyjniej rolę obiektu. Zadaniem obiektu jest wykonanie określonych operacji na danych wejściowych obiektu oraz ich dostarczenie na wyjście danych. Obraz graficzny obiektu posiada dwa przyciski : lewy-górny rozwija menu obiektu; prawy-górny minimalizuje obraz obiektu. Menu obiektu zawiera szereg operacji ułatwiających edycję programu (Clone-powielenie obiektu, Cut-usunięcie) oraz konfigurowanie obiektu (dodawanie i usuwanie końcówek oraz określanie dodatkowych cech obiektu - Properties). W zakresie cech ogólnych programista może określić opis obiektu, uaktywnić opcję prezentacji pełnego opisu końcówek, określić zachowanie obiektu odnośnie momentu jego inicjalizacji oraz sposobu działania, np. uaktywnienie opcji Wait for Input dla obiektu nastawczego powoduje, że dane wyjściowe pojawią się dopiero po akcji ponownego ustawienia nastawnika (rys.1). Zakres edytowanych własności zależy od rodzaju obiektu.
rys.1. Plansza konfigurowania ogólnych własności obiektu.
Konfigurowanie obiektu obejmuje także wprowadzanie dodatkowych wejść i wyjść (rys.2). Obiekty dysponują czterema rodzajami końcówek :
Wejścia i wyjścia danych (najczęściej po jednej);
Wejście i wyjście sekwencyjne (zawsze po jednym; niektóre obiekty nie mają wyjścia);
Wejścia sterujące;
Wyjście błędu.
rys.2. Menu obiektu - konfigurowanie dodatkowych wejść i wyjść.
Domyślnie obiekt posiada wejścia i wyjścia sekwencyjne oraz najczęściej jedno wejście i wyjście danych (rys.3). Obiekty generacyjne nie mają wejść danych. Pozostałe końcówki nie są uaktywnione i dopiero poprzez menu obiektu użytkownik może je dodać. Podobnie można dodać dodatkowe wejścia dla danych a także w odniesieniu do szeregu obiektów dodatkowe wyjścia danych.
rys.3. Standardowe wejścia i wyjścia obiektu.
Końcówki danych służą do obsługi zasadniczych danych przetwarzanych przez program. Z kolei końcówki sekwencyjne można wykorzystać do ustalenia kolejności działania obiektów. Wejście sekwencyjne wyznacza dodatkowo moment aktywizacji obiektu, natomiast wyjście moment zakończenia jego działania. Wejścia danych oraz wejście sekwencyjne obiektu synchronizują działanie obiektów, tzn. obiekt wykona swoje specyficzne operacje na danych wówczas, gdy otrzyma wszystkie dane wejściowe oraz pobudzenie na wejście sekwencyjne. Dodatkowo obiekt może dysponować wejściami asynchronicznymi, sterującymi. Dana na takim wejściu powoduje pewną akcję obiektu, ale bez inicjowania jego działań zasadniczych. Obiekt wykonuje poleconą operację natychmiast po otrzymaniu danej sterującej. Lista możliwych wejść sterujących zależy od rodzaju obiektu i najczęściej jest to Clear (zerowanie np. wyświetlacza lub wykresu), Autoscale (autoskalowanie wykresu), Default Value (ustalenie domyślnej wartości nastawy obiektu, np. w przypadku obiektów nastawczych) itd.
rys.4. Przykłady obiektów z dodanymi wejściami sterującymi (kolor szary).
Każdy obiekt dysponuje też wyjściem błędu, które w przypadku wystąpienia błędu działania obiektu dostarcza danych opisujących go. Wyjścia danych i wyjście błędu działają wykluczająco, tzn. jeśli nie ma błędu dane wyjściowe są obecne na wyjściach a wyjście błędu jest puste i odwrotnie, gdy błąd wystąpi. Domyślnie wyjście błędu nie jest włączone i w takim przypadku wystąpienie błędu spowoduje przerwanie działania programu z wyświetleniem planszy informującej o powodach błędu. Uaktywnienie wyjścia błędu wyłącza automatyczne przerywanie działania programu , ale zakłada się wtedy, że aplikacja ma wbudowaną własną obsługę błędów.
rys.5. Obiekty z unikalnym wejściem XEQ oraz dodanym wyjściem błędu.
Dwa obiekty Collector oraz Sample&Hold wykorzystują dodatkowy rodzaj wejścia asynchronicznego XEQ, za pomocą którego można wymusić natychmiastowe działanie obiektu nawet, gdy wejścia danych są puste. Wejście to musi być podłączone, podobnie jak wejścia danych.
3. TYPY ZMIENNYCH PROGRAMU HP VEE.
HP VEE używa 14 typów danych przy czym 3 z nich są używane wyłącznie w przyrządowych transakcjach I/O. Jedenaście z nich może znaleźć zastosowanie w ogólnych operacjach VEE, tzn. każdy kontener danych przesyłany między obiektami VEE może zawierać dane jednego z tych typów :
Całkowite 32-bitowe (Int32);
Rzeczywiste 64-bitowe (Real64, około 16 cyfr znaczących w zapisie dziesiętnym);
Zespolone w reprezentacji moduł-kąt (Pcomplex) w postaci (mag, @phase). Kąt jest podawany w ustawionych dla środowiska jednostkach: stopniach lub radianach. Oba składniki są typu rzeczywistego.
Zespolone w reprezentacji kartezjańskiej (Complex) w postaci (real, imag). Oba składniki są typu rzeczywistego.
Kształt sygnału (Waveform). Zespół danych, który zawiera kolejne, równomiernie rozłożone w określonym przedziale czasowym wartości rzeczywiste reprezentujące kształt sygnału w domenie czasowej. Dane muszą tworzyć tablicę jednowymiarową (Array 1D).
Widmo sygnału (Spectrum). Zespół danych, który zawiera wartości zespolone Pcomplex prążków częstotliwościowych oraz wartości zakresu częstotliwościowego zespołu danych. Rozłożenie prążków może być liniowe lub logarytmiczne. Dane muszą tworzyć tablicę jednowymiarową.
Współrzędne (Coord). Zespół danych określających współrzędne punktu w przestrzeni wielowymiarowej ( dwu-, trójwymiarowej itd.) w postaci (x, y, ...). Każdy składnik jest typu rzeczywistego. Dana musi być skalarem lub tablicą jednowymiarową.
Enumeryczne (Enum). Dana jest tekstem stringowym z przypisaną porządkową wartością całkowitą. Dana enumeryczna musi być skalarem.
Tekstowe (Text). Dana tekstowa jest stringiem złożonym ze znaków alfanumerycznych.
Rekord (Record) jest typem złożonym z pól. Każde pole ma swoją nazwę oraz kontener, który może być dowolnego typu (także rekordem) i być skalarem lub tablicą.
Obiekt (Object) jest zmienną obiektową używaną dla kontrolek i obiektów ActiveX. Dane typu obiektowego mogą być przekazywane do lub z UserObject oraz UserFunction.
HP VEE traktuje zawsze dane całkowite jako dane 32-bitowe oraz dane rzeczywiste jako 64-bitowe. Urządzenia pomiarowe często wykorzystują 8-bitowe lub 16-bitowe dane całkowite oraz 32-bitowe dane rzeczywiste. Z tego powodu HP VEE wspiera także te trzy typy danych, ale wyłącznie w odniesieniu do przyrządowych transakcji I/O :
Byte - 8-bitowa dana całkowita;
Int16 - 16-bitowa dana całkowita;
Real32 - 32-bitowa dana rzeczywista.
Typ bajtowy (Byte) jest używany w transakcjach READ BINARY, WRITE BINARY oraz WRITE BYTE. Ostatnia transakcja jest często wykorzystywana do przesyłania do urządzeń specyficznych znaków ASCII, np. z grupy znaków sterujących NL, CR, TAB itp.
4. KONTENERY VEE, POLIMORFIZM OBIEKTÓW ORAZ KONWERSJE TYPÓW NA WEJŚCIACH DANYCH OBIEKTÓW VEE.
Kontener VEE jest wewnętrznym formatem danych i charakteryzuje się typem danych (text, real itp.) oraz wymiarem danych (pojedyncza dana - skalar lub wieloelementowa dana - tablica jedno- lub wielowymiarowa). Pojedyncza dana (skalar) może być typem złożonym, np. Complex, Record itp.
Kontener może zawierać pojedynczą daną lub tablicę z wieloma różnymi danymi tego samego typu. Niezależnie od tego tylko jeden kontener danych jest wysyłany z wyjścia danych, gdy obiekt zakończy działanie. Wejścia danych mogą przyjmować dowolne kontenery lub określonego typu. Decyduje o tym skonfigurowanie wejścia obiektu, które można wykonać na etapie projektowania aplikacji. Domyślnie wejścia obiektu są ustawione w opcji przyjmowania kontenera o dowolnym typie i wymiarze (Any).
Większość obiektów cechuje się polimorfizmem (wielopostaciowością). Ich wejścia mogą przyjmować dane różnego typu i o różnym wymiarze dostosowując jednocześnie swoje działanie do rodzaju otrzymanych aktualnie danych. Tak więc obiekt może akceptować nie tylko numeryczne wartości skalarne lecz także tablice danych numerycznych jedno lub wielowymiarowe. W tych warunkach funkcja otrzymując wartość skalarną dostarczy również wartość skalarną, ale ta sama funkcja może działać na wejściowych danych tablicowych dostarczając na wyjściu przetworzoną tablicę danych (rys.6).
rys.6. Polimorfizm funkcji matematycznej.
Polimorfizm dotyczy też szeregu operatorów. Przykładowo operacja sumowania realizowana przez obiekt formuły A+B (rys.7) dostarczy następujących rodzajów danych wyjściowych dla danych wejściowych typu liczbowego (real, int) :
gdy A i B są skalarami - wynik jest też skalarem typu real;
gdy A jest skalarem a B tablicą jednowymiarową - wynik jest tablicą jednowymiarowa typu real, której elementy zostały zwiększone o A;
gdy A i B są tablicami o takich samych rozmiarach - wynik jest tablica jednowymiarowa, której elementy są sumą odpowiadających elementów tablic wejściowych.
rys.7. Polimorfizm funkcji sumowania.
W wypadku operacji dwuargumentowych występuje szereg ograniczeń. Np. dane skalarne typu Record muszą mieć taką samą budowę a tablice muszą mieć identyczne wymiary i rozmiary dla każdego wymiaru.
Polimorfizm obiektów VEE ułatwia projektowanie aplikacji, ale wymaga od projektanta zachowania ostrożności w pewnych sytuacjach, aby nie doprowadzić do nieoczekiwanych rezultatów. Np. w przykładzie z sumowaniem, jeśli na wejście A wprowadzi się tekst lub tablicę tekstową wówczas wynik będzie odpowiednio skalarem tekstowym lub tablicą tekstową, ponieważ wartość numeryczna z wejścia B zostanie automatycznie przetworzona do postaci tekstowej i rezultat będzie tekstem wynikającym z połączenia obu tekstów.
Jeśli tekst lub tablica tekstowa zawiera tekstowo prezentowane wartości numeryczne (np. wyniki pomiarów odczytane z przyrządu) a operacja miałaby dostarczyć wartości numerycznych (np. wyeliminować offset) to wynik byłby całkowicie nie do przyjęcia choć operacja zakończy się powodzeniem. Inna sytuacja wystąpi, jeśli na danych tekstowych uzyskanych z przyrządu trzeba wykonać obliczenia za pomocą pewnej funkcji matematycznej, np. przeliczyć je na decybele. Tym razem obiekt funkcji log10(x) zgłosi błąd, ponieważ może pracować tylko na danych numerycznych. W obu przytoczonych przykładach należałoby dokonać jawnej konwersji danych tekstowych do danych numerycznych i na nich wykonać żądane obliczenia.
rys.8. Niejawna i jawna konwersja danych Text do Real.
Można też zrezygnować z jawnej konwersji realizowanej za pomocą odpowiedniej funkcji (From String lub asReal(x)) na rzecz specyficznego skonfigurowania wejścia obiektu - tutaj należy zadeklarować przyjmowanie danych typu Real (rys.9). Taka deklaracja nie oznacza ograniczenia typu przyjmowanych danych lecz wymusza ich konwersję do zadeklarowanego typu.
rys.9. Plansza konfigurowania własności wejścia obiektu.
Opcja ta jest bardzo wygodna, ponieważ obiekt dokona automatycznie konwersji typów danych wejściowych i wykona na nich żądane operacje. Wymiar danych nie podlega zmianie; tablica zostaje tablicą ale typ danych może podlegać konwersji. Programista nie musi używać do tego celu osobnych funkcji (upraszcza się zapis programu), ale musi mieć świadomość rodzaju dostępnych konwersji, ponieważ nie wszystkie są możliwe do zrealizowania (tablica 1). Jeśli konwersja nie jest możliwa do wykonania obiekt zgłosi błąd wykonania.
Tablica 1. Dopuszczalne konwersje promocyjne i obniżające na wejściach danych.
Z \ Na |
Int32 |
Real64 |
Complex |
Pcomplex |
Waveform |
Spectrum |
Coord |
Enum |
Text |
Int32 |
x |
tak |
Tak[1] |
Tak[1] |
nie |
nie |
Tak[2] |
nie |
tak |
Real64 |
(tak)[3] |
x |
Tak[1] |
Tak[1] |
nie |
nie |
Tak[2] |
nie |
tak |
Complex |
(nie) |
(nie)[4] |
x |
tak |
nie |
nie |
nie |
nie |
tak |
Pcomplex |
(nie) |
(nie)[4] |
(tak) |
x |
nie |
nie |
nie |
nie |
tak |
Waveform |
(tak)[3] |
(tak)[8] |
(nie) |
(nie) |
x |
Tak[5] |
tak |
nie |
tak |
Spectrum |
(nie) |
(nie) |
(tak)[8] |
(tak)[8] |
(tak)[5] |
x |
tak |
nie |
tak |
Coord |
(nie) |
(nie) |
(nie) |
(nie) |
(nie) |
(nie) |
x |
nie |
tak |
Enum |
(nie)[6] |
(nie) |
(nie) |
(nie) |
(nie) |
(nie) |
(nie) |
x |
tak |
Text |
(tak)[7] |
(tak)[7] |
(tak)[7] |
(tak)[7] |
(nie) |
(nie) |
(tak)[7] |
(nie) |
x |
Uwagi:
x |
- |
nie dotyczy; |
tak, nie |
- |
konwersja promocyjna odpowiednio możliwa i niemożliwa; |
(tak), (nie) |
- |
konwersja obniżająca odpowiednio możliwa i niemożliwa; |
|
|
|
[1] |
- |
Wartość Int32 lub Real64 promowana do typu Complex (value, 0) lub Pcomplex (value, @0); |
[2] |
- |
Pierwsze n-1 pól n polowej danej coord są indeksami tablicy, pole n przyjmuje wartość elementu tablicy wejściowej. Kontener wejściowy musi być tablicą. |
[3] |
- |
Konwersja obniżająca powoduje błąd, gdy wartość przekracza zakres typu docelowego; |
[4] |
- |
Konwersja obniżająca nie jest realizowana automatycznie, można ją wykonać programowo przy użyciu funkcji matematycznych re(x), im(x), mag(x) oraz phase(x); |
[5] |
- |
Automatycznie jest realizowana operacja FFT lub inwersja FFT; |
[6] |
- |
Konwersja obniżająca nie jest realizowana automatycznie, można ją wykonać funkcją ordinal(x); |
[7] |
- |
Konwersja obniżająca powoduje błąd, gdy tekst nie jest zapisem liczby. Tekst konwertowany do :
|
[8] |
|
Konwersja obniżająca zachowuje mapowanie typów waveform i spectrum. |
Większość obiektów akceptuje każdy typ danych na swoich wejściach, ale istnieje kilka obiektów wymagających szczególnych typów lub wymiarów danych. W ich przypadku również następuje próba automatycznej konwersji do żądanego typu. Jeśli nie można jej zrealizować obiekt zgłosi błąd. Przykład takiej konwersji ma miejsce, gdy na wejście wykresu spektralnego (Magnitude Spectrum) zostanie wprowadzony kontener wyjściowy generatora funkcji (Function Generator). Dane wejściowe są typu waveform a wymagane są dane typu spectrum. W celu uzyskania zgodności automatycznie realizuje się operacja FFT przejścia z prezentacji czasowej na prezentację częstotliwościową.
5. PRZEPŁYW DANYCH POMIĘDZY OBIEKTAMI VEE.
Przepływ danych pomiędzy obiektami VEE ilustrują w programie linie połączeniowe wprowadzone przez programistę. W trakcie działania programu przepływają nimi kontenery z danymi określonego typu. Wykorzystanie tych danych zależy od rodzaju wejść, i tak :
Wejścia danych muszą otrzymywać wypełnione danymi kontenery. Mogą akceptować kontenery z dowolnym typem danych lub można to uściślić do określonego typu. Złożone typy danych (Waveform, Spectrum, Record, Coord, and Object) wymagają wieloelementowych danych, zwykle tablic. Dlatego do obiektu z wejściem wymagającym takich danych nie można przekazać kontenera z wartością skalarną.
Wyjście danych generuje kontener z typem danych uzależnionym od rodzaju danych wejściowych oraz rodzaju realizowanych operacji. W wielu przypadkach typ danych wyjściowych jest jednoznacznie określony. Kontener z danymi wyjściowymi pojawi się tylko wówczas, gdy wszystkie zainicjalizowane operacje synchroniczne obiektu zakończą się bez błędu.
Wejście sekwencyjne jest aktywowane pojawieniem się dowolnego kontenera. Jego zawartość jest nieistotna i jest ignorowana. Może to być pusty kontener (nil). Wobec tego do inicjalizowania akcji obiektu można wykorzystać dowolne dane, zarówno z wyjść danych jak i wyjść sekwencyjnych innych obiektów.
Wyjście sekwencyjne generuje pusty kontener (nil) na zakończenie działania obiektu.
Wejścia sterujące wymagają różnego rodzaju danych w zależności od wejścia. Jeśli wejście dotyczy akcji jednoznacznie określonej, np. Clear, Autoscale, Disable Editing, Enable Editing, to zaakceptuje ono dowolny kontener (jego treść jest nieistotna). Wejścia ustawiające pewne dane obiektu, np. wartość domyślą obiektu, potrzebują określonego typu danych.
Wejście EXQ jest aktywowane pojawieniem się dowolnego kontenera. Jego zawartość jest nieistotna i jest ignorowana.
Wyjście błędu, jeśli jest uaktywnione, propaguje kontener z numerem błędu ale tylko gdy ten wystąpi. W warunkach wystąpienia błędu obiekt propaguje wyłącznie kontener z informacją o błędzie oraz pusty kontener z wyjścia sekwencyjnego.
Przepływ danych pomiędzy obiektami tworzącymi program VEE decyduje o kolejności aktywizacji obiektów i wykonania przez nie operacji obliczeniowych czy sterujących przyrządami. Siatkę połączeniową należy odpowiednio zaprojektować i zrealizować. Obowiązuje następująca zasada :
Do wejścia można dołączyć tylko jedno wyjście. Wejście może mieć jedno źródło danych. W szczególnych sytuacjach, gdy dane wejściowe mają spływać z różnych źródeł należy wprowadzić je poprzez obiekt JCT.
Wyjście może łączyć się z wieloma wejściami, czyli może być źródłem danych dla wielu wejść.
Kolor i kształt linii połączeniowej obrazuje rodzaj połączenia oraz typ przenoszonych danych. Środowisko projektowe automatycznie ustala charakterystykę linii połączeniowej podczas jej kreowania. Domyślnie obowiązują następujące przyporządkowania :
Kolor niebieski dla danych numerycznych;
Kolor pomarańczowy dla danych tekstowych;
Kolor czarny dla rekordów i innych typów danych;
Kolor szary dla połączeń końcówek sekwencyjnych;
Podwójne linie dla danych tablicowych (niebieskie, pomarańczowe lub czarne);
Linie przerywane dla wejść sterujących.
6. POSTAĆ PROGRAMU VEE
Obiekty VEE połączone liniami przepływu danych oraz sekwencyjnymi (linie ciągłe) tworzą tzw. wątek (thread). Linie przepływu danych sterujących (przerywane) nie wiążą obiektów w wątek. Prosty program zawiera zwykle tylko jeden wątek natomiast bardziej złożone składają się z wielu wątków i subwątków (subthread). Program z rysunku 10 składa się z dwóch równoległych, niezależnych wątków. Niezależnych, ponieważ nie są one połączone ani liniami danych ani liniami sekwencyjnymi.
rys.10. Program złożony z dwóch niezależnych wątków.
Rozgałęzienia wątku tworzą subwątki. Dwa subwątki rozpoczynające się od tego samego wyjścia obiektu i nie mające wzajemnych powiązań liniami danych lub sekwencyjnymi stanowią subwątki równoległe (rys.11).
rys.11. Rozgałęzienie wątku na równoległe subwątki.
Program z wieloma wątkami równoległymi może wykonywać je jednocześnie (pseudojednocześnie, ponieważ środowisko wykonawcze VEE cyklicznie wykonuje fragmenty każdego z nich). Kolejność wykonywania fragmentów poszczególnych wątków i subwątków jest ustalana przez środowisko przypadkowo. Zwykle wykonuje się jeden lub kilka obiektów jednego wątku, następnie jeden lub kilka obiektów z kolejnego wątku itd. Istnieją tylko dwa wyjątki od tej zasady :
Jeśli wątek zawiera obiekt Interface Event lub Device Event, wtedy uzyskuje on wyłączność działania podczas śledzenia określonego zdarzenia. Np. podczas detekcji SRQ na magistrali GPIB wątek zawierający Interfaces Event będzie monopolizował działanie programu aż do wykrycia SRQ. Pozostałe wątki pozostają wstrzymane do momentu zakończenia obsługi zdarzenia.
Jeśli jeden z wątków ma obiekt przycisku Start i uruchomienie aplikacji nastąpiło przez jego przyciśnięcie, wtedy cały ten wątek musi być wykonany zanim zaczną działać pozostałe.
Program VEE ma więc cechy programów wielowątkowych (multithread). W rzeczywistości nie jest nim w pełni, ponieważ własność ta nie jest zaimplementowana na poziomie systemu operacyjnego i zdarzenia systemowe mogą wstrzymywać działanie wątków programu VEE.
7. ZASADY WYKONANIA WĄTKU PROGRAMU (PROPAGACJA DZIAŁAŃ).
Kolejność wykonania operacji przez obiekty wątku programu jest określona przepływem danych pomiędzy obiektami oraz dodatkowo danymi sekwencyjnymi. Stąd mówi się, że program VEE jest sterowany przepływem danych. Wątek rozpoczyna działanie od obiektu znajdującego się na skrajnej, lewej pozycji połączeń danych. Pozostałe obiekty wątku aktywizują się w miarę dopływu do nich danych z poprzedzających obiektów trasy przepływu danych. Każdy z obiektów aktywizuje swoje działanie tylko raz chyba, że wątek lub jego subwątek jest objęty pętlą powtarzania działań. Podstawowe zasady propagacji działań w wątkach programu są następujące :
Obiekty nie mające wejść danych oraz nie wykorzystujące wejścia sekwencyjnego wykonują się w pierwszej kolejności (kolejność jest przypadkowa).
Inne obiekty wykonują swoje operacje w kolejności określonej przepływem danych, czyli obiekt z wejściami danych zadziała dopiero wówczas, gdy otrzyma wszystkie dane wejściowe.
Kolejność propagacji może ulec modyfikacji przez wykorzystanie wejść sekwencyjnych obiektów.
Kolejność wykonywania równoległych subwątków nie jest określona (przypadkowa).
Idea konstrukcji wątku oraz dalsze szczegóły propagacji działań wynikają bezpośrednio z zasad funkcjonowania wszystkich obiektów VEE :
Dane przepływają od lewej do prawej strony obiektu.
Sygnał sekwencyjny przepływa z góry do dołu obiektu.
Wszystkie wejścia danych oraz wejście EXQ, jeśli występuje, muszą być dołączone (do źródeł danych).
Końcówka wejścia (danych, sekwencyjna, sterująca) akceptuje tylko jedno połączenie (jedno źródło danych).
Końcówka wyjścia danych oraz wyjścia sekwencyjnego może być dołączona do wielu obiektów.
Końcówka wyjścia danych oraz końcówka wejścia i wyjścia sekwencyjnego nie muszą być wykorzystane (dołączone do innych obiektów).
Obiekt rozpocznie działanie dopiero, gdy wszystkie jego wejścia danych zaakceptują dane. Jeśli obiekt wykorzystuje wejście sekwencyjne (jest połączone z innym obiektem), wówczas dodatkowo rozpoczęcie jego działania jest uwarunkowane akceptacją sygnału sekwencyjnego dowolnego typu. Wyjątek stanowi obiekt JCT, który aktywizuje się po akceptacji danej na jednym z wejść danych. Dzięki tej własności można go wykorzystać do dostarczania danych z różnych źródeł na wejście jakiegoś obiektu.
Obiekt wykonuje swoje operacje tylko raz chyba, że jest objęty pętlą lub zmuszony do działania przez wejście EXQ.
Akceptacja danych na wejściu sterującym wymusza natychmiastowe wykonanie określonych działań przez obiekt, ale nie dotyczy to nigdy podjęcia przez niego zasadniczych zadań oraz propagacji jakichkolwiek danych wyjściowych lub sekwencyjnych.
Kolejność wykonywania operacji przez obiekt jest następująca:
Jeśli obiekt wykorzystuje wejście sekwencyjne, wówczas oczekuje zarówno na komplet danych wejściowych jak również daną sekwencyjną. Wejścia odbierają dane do momentu aktywizacji obiektu (rozpoczęcia działania);
Obiekt akceptuje dane na swoich wejściach danych. Czeka aż uzyska dane na wszystkich wejściach danych;
Obiekt wykonuje swoje specyficzne funkcje;
Obiekt wysyła dane ze swoich wyjść danych;
Obiekt oczekuje na sygnał potwierdzenia, który uzyska, gdy każdy obiekt korzystający z jego danych wyjściowych wykona swoje działania. Oznacza to wykonanie operacji przez całą część wątku od rozpatrywanego obiektu w dół (rys.12).
rys.12. Warunek wygenerowania danej sekwencyjnej przez obiekt Formuła 1.
Często występują sytuacje, gdy ta część wątku nie może wykonać w pełni swoich zadań, ponieważ np. nie wszystkie wejścia w tej części wątku uzyskały dane (rys.13). We wszystkich takich przypadkach, sygnał potwierdzenia pojawi się, gdy wątek zrobi wszystko co jest możliwe w danej sytuacji.
Po uzyskaniu sygnału potwierdzenia obiekt wysyła kontener sekwencyjny (nil) ze swojego wyjścia sekwencyjnego;
Obiekt dezaktywuje się (kończy działanie).
rys.13. Warunek wygenerowania danej sekwencyjnej przez obiekt Formuła 1 oraz Int 20.
8. WARUNKOWE ROZGAŁĘZIENIA WĄTKÓW ORAZ CYKLICZNE POWTARZANIE WYKONANIA
WĄTKÓW.
Wątek programu VEE można rozgałęzić na wiele subwątków realizowanych alternatywnie. Służą do tego obiekty If/Then/Else (rys.14) oraz jego uściślenia z grupy Conditional. Domyślnie obiekt If/Then/Else posiada jedno wejście danych oraz wyjścia Then i Else umożliwiające dołączenie do nich alternatywnie wykonywanych subwątków. Pole edycyjne obiektu pozwala wpisać wyrażenie logiczne, którego wartość logiczna jest określana podczas działania obiektu. Jeśli wyrażenie logiczne jest prawdziwe aktywizuje się wyjście Then a wyjście Else jest puste (brak danej) i odwrotnie, gdy wartość wyrażenia jest fałszywa. Wyjścia dostarczają wartości typu całkowitego; Then zawsze 1, Else zawsze 0. W zasadzie wartości są mniej istotne, ważny jest fakt wysłania kontenera danych, który zainicjalizuje wybrany subwątek. Obiekt If/Then/Else można rozbudować dodając mu kolejne stopnie wyboru. Utworzony w ten sposób obiekt posiada wiele alternatywnych wyjść a jego działanie odpowiada wielostopniowej instrukcji wyboru z języka C.
rys.14. Wątek pozwalający wykonać pętle z iteracjami liniowymi lub logarytmicznymi.
W programach VEE wątki i subwątki mogą być objęte różnego typu pętlami. Pętle buduje się za pomocą specjalnych obiektów powtarzania cykli subwątku dołączonego do wyjścia takiego obiektu. Do dyspozycji są następujące typy obiektów powtarzania :
Obiekt For Count - powtarza wykonanie swojego subwątku zadeklarowaną w nim ilość razy. Dana wyjściowa obiektu przyjmuje w kolejnych obiegach wartości całkowite od 0 do N-1, gdzie N jest zadeklarowaną liczbą obiegów pętli.
Obiekt For Range - liczba powtórzeń wykonania subwątku wynika z zadeklarowanej w obiekcie wartości startowej, końcowej i kroku inkrementacji. Dana wyjściowa obiektu przyjmuje w kolejnych obiegach wartości rzeczywiste od wartości startowej. Kolejne wartości są zwiększane o zadeklarowany krok. Pętla działa dopóki wartość iterowana jest mniejsza lub równa podanej wartości końcowej. Wartości iterowane są rozłożone liniowo.
Obiekt For Log Range - pętla podobna do poprzedniej z tym, że iterowane wartości są rozłożone logarytmicznie. Zamiast kroku podaje się liczbę iteracji w dekadzie. Kolejna n-ta wartość wyjściowa jest obliczana według zależności Start*exp10(n/dec), gdzie dec jest zadeklarowaną liczbą iteracji w dekadzie.
Obiekt Until Break - pętla działająca do momentu przerwania. W kolejnych iteracjach jego wyjście dostarcza zerową wartością rzeczywistą. Dana wyjściowa służy do inicjalizowania dołączonego subwątku. Dane wyjściowe poprzednich obiektów powtarzania mogły być wykorzystane również do innych celów. Przerwanie działania pętli Until Break wymaga wykorzystania w dołączonym subwątku obiektu Break;
Obiekt On Cycle - pętla nieskończona podobnie jak Until Break. Iteracje pętli są powtarzane periodycznie w zadeklarowanych odstępach czasu (sekundach). Dana wyjściowa obiektu jest typu real ale określa aktualną datę i czas, które mogą być wyświetlone w sposób jawny przez każdy obiekt stosujący format liczbowy Time Stamp. Obiekt stosuje się często do inicjalizowania pomiarów w określonych odstępach czasu.
Program VEE może wykorzystywać pętle równoległe (jako równoległe wątki) oraz zagnieżdżone (rys.15).
rys.15. Wątek zawierający zagnieżdżone pętle For Count.
Obiekty Break i Next są związane z pętlami i służą odpowiednio do przerwania działania pętli i wymuszenia kolejnej iteracji (identycznie jak instrukcje break i continue języka C). Obiekty te dotyczą zawsze najbliższego obiektu powtarzania, czyli tego w którego subwątku taki obiekt się znajduje (rys.16).
rys.16. Wykorzystanie obiektu Break do przerywania zagnieżdżonej pętli On Cycle.
W odniesieniu do wszystkich rodzajów pętli obowiązują następujące zasady:
Wyjściowa dana sekwencyjna pojawia się w obiektach powtarzania zawsze po zakończeniu działania pętli, czyli po wykonaniu wszystkich iteracji lub na skutek zadziałania obiektu przerywającego (Break).
W momencie rozpoczynania kolejnej iteracji wszystkie kontenery danych wysłane w poprzedniej iteracji tracą ważność. To zapobiega ponownemu użyciu starych danych w aktualnej iteracji. Warto o tym pamiętać konstruując programy, w których wątek objęty pętlą posiada rozgałęzienia warunkowe i w takiej sytuacji pewne jego obiekty nie wykonują operacji w każdej iteracji. Kontenery danych wysłane przez te obiekty mogą utracić ważność zanim inne obiekty je wykorzystają. W celu zapewnienia właściwej propagacji danych w takim przypadku należy wykorzystać obiekt Sample&Hold zapamiętujący dane. W przykładzie z rys.17 obiekt Sample&Hold zapamiętuje ostatnią daną z obiektu Counter2 i dzięki temu zostaje ona zachowana mimo, że pętla For Count wykonuje jeszcze kilka iteracji, w której obiekt Counter2 nie bierze udziału.
rys.17. Przykład zastosowania obiektu Sample&Hold zapobiegający stracie danych.
Pętle równoległe nie mogą się krzyżować (posiadać połączenia danych lub sekwencyjne) oraz nie mogą się łączyć, np. przy użyciu obiektu JCT lub matematycznego.
rys.18. Przykłady błędnych konstrukcji z zastosowaniem pętli.
9. ZMIENNE PROGRAMU VEE.
Program VEE może używać zmiennych globalnych, lokalnych kontekstowo i lokalnych w bibliotekach :
Globalne są dostępne w każdym miejscu programu niezależnie od miejsca gdzie znajduje się obiekt deklarujący zmienną.
Lokalne kontekstowo są zmiennymi, których użycie jest limitowane do obiektu użytkownika (UserObject) lub funkcji użytkownika (UserFunction), w których występuje ich deklaracja.
Lokalne w bibliotece są zmiennymi zadeklarowanymi w bibliotece funkcji użytkownika (lokalnej lub importowanej) i ich użycie jest ograniczone do funkcji danej biblioteki.
Zmienne nie muszą być deklarowane, ale warto to robić, ponieważ program z zadeklarowanymi zmiennymi funkcjonuje szybciej. Obsługę zmiennych zapewniają cztery specjalne obiekty :
Declare Variable - deklaruje zmienną. Programista określa w polach edycyjnych obiektu unikalną nazwę, rodzaj, typ i liczbę wymiarów. Typ zmiennej może być jednym z 11 dostępnych w VEE typów danych. Maksymalną, dopuszczalną liczbą wymiarów jest 10, czyli tablica dziesięciowymiarowa. Wartość zero oznacza zmienną skalarną.
Delete Variable - usuwa wszystkie zmienne lub jedną o podanej nazwie.
Set Variable - ustawia wartość zmiennej o określonej nazwie zgodnie z daną wejściową.
Get Variable - dostarcza poprzez wyjście aktualną wartość zmiennej o podanej nazwie.
Każdy obiekt Set i Get Variable jest związany z określoną zmienną, poprzez podanie w oknie edycyjnym tych obiektów nazwy zmiennej. Zadeklarowane zmienne muszą zostać zainicjalizowane przy użyciu obiektu Set Variable zanim rozpocznie się jakiekolwiek inne działania z ich wykorzystaniem.
W programie korzystanie z danej zmiennej odbywa się przy użyciu obiektów Set i Get Variable. Alternatywnie w obiektach, dla których określa się wyrażenia obliczeniowe (np. formuły matematyczne) nazwa zmiennej może być elementem wyrażenia i nie trzeba wprowadzać jej przez wejście obiektu (rys.19). Podobnie zamiast używać obiektu Set Variable do ustalenia nowej wartości zmiennej, można użyć obiektu formuły z wpisanym wyrażeniem przypisania, np. Stop=1, gdzie Stop jest nazwą zmiennej.
rys.19. Wykorzystanie zmiennej globalnej do przekazywania danych pomiędzy równoległymi wątkami.
Zmienne wykorzystuje się do przekazywania różnego rodzaju danych pomiędzy wątkami programu. Zastosowanie równoległych wątków często owocuje sprawniejszym działaniem programu, czytelniejszym jego zapisem graficznym lub jest konieczne z powodu zastosowania konstrukcji pętlowych. Jeśli wątki nie mogą być w pełni niezależne i nie mogą być scalone w jeden, wtedy powiązania pomiędzy nimi można uzyskać przy pomocy zmiennych globalnych lub lokalnych. Przykład z rys.19 pokazuje takie powiązanie. Program składa się z trzech wątków :
Wątek 1 - Podstawowy wątek programu. Jest pętlą nieskończoną (Until Break) realizującą po akcji użytkownika (przycisk MIERZ) pętlę periodyczną On Cycle z iteracjami co 1 sekundę. Każda iteracja może dotyczyć przykładowo operacji pomiarowych. Pętla periodyczna jest pętlą nieskończoną. Ograniczenie jej działania uzyskuje się za pomocą rozgałęzienia warunkowego na podstawie wartości zmiennej Stop.
Wątek 2 - Pomocniczy wątek służący do przerwania pętli On Cycle wątku 1. Po użyciu przycisku STOP zmienna Stop przyjmuje wartość 1.
Wątek 3 - Jednokrotna inicjalizacja początkowa zmiennej Stop.
Zaletą przytoczonego przykładu jest przede wszystkim czytelność zapisu programu oraz prostota wprowadzenia połączeń sterujących, które uaktywniają przycisk STOP tylko w czasie działanie pętli periodycznej oraz przywracania stanu przycisków do stanu spoczynkowego.
10. OBIEKT FORMUŁY MATEMATYCZNEJ.
Obiekt formuły matematycznej jest obiektem wykonującym zdefiniowane przez użytkownika operacje matematyczne. Żądane wyrażenie wpisuje się w oknie edycji formuły. Wyrażenie kreuje się przy użyciu operatorów matematycznych, nawiasów grupujących, nazw predefiniowanych stałych, nazw wejść i wyjść obiektu, nazw zmiennych globalnych i lokalnych oraz nazw funkcji wbudowanych środowiska lub zdefiniowanych przez użytkownika. Istnieje duże podobieństwo do zapisu wyrażeń w języku C z tym, że środowisko VEE nie rozróżnia wielkości liter w nazwach.
Użytkownik może dodać obiektowi formuły żądaną liczbę wejść i wyjść danych. Nazwy wejść i wyjść danych stanowią zmienne lokalne formuły i mogą być wykorzystane w zapisie wyrażenia. Predefiniowanym wyjściem jest wyjście o nazwie Result. Wyrażenie formuły może być rozbudowane do postaci wieloelementowego wyrażenia (rys.20), w którym elementarne wyrażenia rozdziela się znakiem średnika. Stosując takie złożone wyrażenie można przypisać konkretnym wyjściom obiektu wartości wynikające z wykonanych operacji. Lewym argumentem operatora przypisania jest wtedy nazwa wyjścia. Predefiniowane wyjście Result otrzymuje wynik ostatniego wyrażenia (jawne przypisanie jest zbyteczne).
rys.20. Przykład formuły z wieloelementowym wyrażeniem.
W przykładzie z rys.20 A, B, C, Result, X i Tmp są lokalnymi zmiennymi obiektu. Result otrzymuje wynik ostatniego wyrażenia (10*tmp). Tmp pełni tutaj rolę zmiennej pomocniczej do zapamiętania wyniku pośredniego. Musi jednak znaleźć się na liście wyjść, ponieważ w ten sposób zmienna jest deklarowana. Wejście A i wyjście A to ta sama zmienna z tym, że na wyjściu ma już inną zawartość. Pierwsza linia wyrażenia pokazuje użycie wbudowanej funkcji trygonometrycznej sinus oraz predefiniowanej stałej PI (3,14...). Trzeci wiersz stosuje operator trójargumentowy:
( condition ? expression1 : expression2 )
działający w ten sposób, że jego rezultatem jest wynik wyrażenia 1, jeśli warunek jest prawdziwy lub wynik wyrażenia 2, gdy warunek nie jest spełniony.
W wyrażeniach złożonych obowiązują następujące priorytety kolejności wykonywania operacji (wyliczone w malejącym porządku):
1 |
( ) |
Nawiasy grupujące. |
2 |
^ |
Operator potęgowania (a ^ b oznacza a do potęgi b). |
3 |
- |
Minus jednoargumentowy. |
4 |
*, /, MOD, DIV |
Kolejno: mnożenie, dzielenie, operacja modulo, dzielenie całkowite (bez części ułamkowej). |
5 |
+, - |
Dodawanie i odejmowanie. |
6 |
~=, ==, !=, <, >, <=, >= |
Operatory porównania; kolejno: równy w przybliżeniu, równy, różny, mniejszy, większy, mniejszy-równy, większy równy. |
7 |
NOT |
Zaprzeczenie logiczne. |
8 |
AND |
Iloczyn logiczny. |
9 |
OR, XOR |
Suma logiczna i suma XOR. |
Operacje dwuargumentowe wymagają zgodności typów obu argumentów. W sytuacji, gdy argumenty są różnego typu następuje promocja argumentu niższego typu do typu odpowiadającego drugiemu argumentowi i wynik jest też tego typu (tabela 1). W procesie promocji typów obowiązuje następujące uporządkowanie (od poziomu najwyższego):
Object
Record
Text ( Enum jest traktowany jak typ Text)
Spectrum
Pcomplex
Complex
Coord (bez możliwości konwersji na inny typ numeryczny)
Waveform
Real
Int32
Przykładowo obiekt formuły A+B dostarczy następujących rodzajów danych wyjściowych:
A i B są skalarami typu text - wynik jest też skalarem typu text (połączone teksty z A i B);
A jest skalarem typu real a B skalarem typu text - wynik jest skalarem typu text, który jest połączeniem tekstowego zapisu liczby z wejścia A (domyślna konwersja zapisu liczby) z tekstem z wejścia B;
A jest skalarem typu real a B skalarem typu complex - wynik jest skalarem typu complex.
W przykładzie drugim argumenty są różnego typu. Musi nastąpić wyrównanie typu obu argumentów. Automatycznej konwersji promocyjnej podlega argument niższego typu, czyli argument typu real. Nastąpi jego promocja do postaci tekstowej z zastosowaniem formatowania domyślnego. Operacja dostarczy daną typu text (rys.21).
rys.21. Automatyczne konwersje typów.
Podobna sytuacja dotyczy przykładu trzeciego. Tutaj argument typu real jest promowany do typu complex (A,0) i po wyrównaniu typów nastąpi sumowanie danych typu zespolonego. Wynik jest daną zespoloną typu complex , której elementy są sumą odpowiadających sobie składników argumentów operacji (rys.21).
Projektant aplikacji powinien w sposób przemyślany korzystać z automatycznych konwersji. Są one bardzo wygodne, ale ich lista jest ograniczona (tabela 1) a wynik może odbiegać od oczekiwanego. Potrzebna jest wiedza dotycząca możliwych operacji i ich wyników. Np. operację sumowania można używać do łączenia tekstów. Operacja mnożenia nie może mieć obu argumentów tekstowych, ale jest dostępna, jeśli jeden jest tekstowy a drugi numeryczny. Dostarcza wtedy powielony tekst, np. operacja ”Hello” * 2.01 zakończy się dostarczeniem tekstu ”HelloHello”.
W dwuargumentowych operacjach tablicowych (oba argumenty są tablicami) rozmiar, wymiar oraz mapowanie tablic musi być identyczne dla obu argumentów. W przypadku jakiejkolwiek niezgodności operacja kończy się błędem wykonania. W sytuacji, gdy jeden z argumentów jest skalarem następuje promocja jego typu, wymiaru i rozmiaru tak, aby uzyskać zgodność z drugim argumentem. Dlatego operacja sumowania rzeczywistej wartości skalarnej z jednowymiarową tablicą wartości rzeczywistych dostarczy zawsze tablicę, której elementy mają wartość elementów tablicy wejściowej zwiększoną o podaną wartość skalarną. Wynika to z promocji skalarnego argumentu do tablicy o wymiarze i rozmiarze drugiego argumentu. Powstanie zatem tymczasowa tablica jednowymiarowa, której wszystkie elementy mają wartość argumentu skalarnego i dopiero po tej promocji wykona się sumowanie odpowiadających sobie elementów obu tablic.
W wyrażeniach VEE stosuje dość specyficzne odwołania do elementów tablic. Obowiązuje następująca syntaktyka ( tablice są indeksowane od 0 ) :
Nawiasy kwadratowe [ ] użyte po nazwie tablicy obejmują parametry specyfikujące podtablice (fragment całej tablicy).
Przecinek separuje specyfikację poszczególnych wymiarów tablicy. Każdy wymiar musi mieć swoją specyfikację.
Dwukropek separuje wartości określające zakres elementów w obszarze danego wymiaru.
Gwiazdka * specyfikuje wszystkie elementy z danego wymiaru.
Specyfikacja indeksów może być określona przez stałą lub zmienną.
Przykłady wyrażeń udostępniających fragmenty jednowymiarowej tablicy A o wartościach:
Indeks |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Wartość |
0.1 |
0.2 |
0.3 |
0.4 |
0.5 |
0.6 |
0.7 |
0.8 |
0.9 |
1.0 |
A lub A[*] - zwraca całą tablicę;
A[1] - zwraca skalar, który jest drugim elementem tablicy (0.2);
A[1:1] - zwraca jednowymiarową tablicę, która zawiera tylko drugi element tablicy A;
A[0:5] - zwraca jednowymiarową tablicę, która zawiera pierwsze sześć elementów tablicy A;
A[2:*] - zwraca jednowymiarową tablicę, która zawiera elementy tablicy A od trzeciego do końca.
Przykłady wyrażeń udostępniających fragmenty dwuwymiarowej tablicy B o wartościach:
|
0: |
1: |
2: |
3: |
4: |
5: |
0: |
0.1 |
0.2 |
0.3 |
0.4 |
0.5 |
0.6 |
1: |
1.1 |
1.2 |
1.3 |
1.4 |
1.5 |
1.6 |
2: |
2.1 |
2.2 |
2.3 |
2.4 |
2.5 |
2.6 |
3: |
3.1 |
3.2 |
3.3 |
3.4 |
3.5 |
3.6 |
4: |
4.1 |
4.2 |
4.3 |
4.4 |
4.5 |
4.6 |
B lub B[*,*] - zwraca całą tablicę;
B[1,2] - zwraca skalar o wartości 1.3 (wiersz 1, kolumna 2);
B[1,*] - zwraca wiersz o indeksie 1 jako jednowymiarową tablicę;
B[3:4,4:5] - zwraca dwuwymiarową tablicę, której wiersz zerowy zawiera elementy 3.5 i 3.6 a wiersz pierwszy 4.5 i 4.6.
rys.22. Przykład wypełnienia tablicy wartościami przypadkowymi.
Przykład z rys.22 pokazuje wykorzystanie wyrażenia do określenia treści tablicy. Obiekt formuły A[B]=C ma wprowadzone dodatkowe wyjście A udostępniające tablicę po modyfikacji jej zawartości. Wyjście domyślne Result zostało usunięte, ponieważ zawiera w kolejnych iteracjach pętli wyniki operacji, czyli skalar odpowiadający zmodyfikowanej zawartości elementu tablicy (A[B]) a nie całą tablicę i jest tutaj zbyteczne. Bezpośrednio po starcie programu zainicjalizowana tablica jest wprowadzona na wejście A formuły. W kolejnych iteracjach pętli, to samo wejście dostaje za pośrednictwem obiektu JCT ponownie tablicę, ale już zmodyfikowaną.
rys.23. Przykład utworzenia tablicy z wartościami przypadkowymi.
W programach VEE należy unikać, jeśli jest to możliwe, stosowania pętli do operowania na tablicach, ponieważ wykonują się one stosunkowo wolno. Środowisko posiada doskonałe środki do obsługi operacji na tablicach traktowanych całościowo. Dlatego trzeba poszukiwać algorytmów i narzędzi, które pozwolą globalnie operować na tablicach. Program z rys.23 jest takim przykładem. Dostarcza podobnie jak poprzedni program tablicę z wartościami przypadkowymi, ale wykonuje się około 50 razy szybciej (dla 1000 elementowej tablicy).
Wyrażenia występują nie tylko w obiektach formuł matematycznych. Stosują je obiekty IF/Then/Else, Direct I/O (obsługi przyrządów), obiekty Set i Get Value z grupy Access Array oraz Set i Get Field z grupy Access Record. W większości dostępne są te same możliwości zapisu wyrażeń jak w formułach matematycznych. Można je też stosować w polach numerycznych obiektów Constant, ale wyrażenie takie musi dać się obliczyć na etapie kompilacji. Nie może zatem zawierać nazw zmiennych.
1