Aplikacja jako automat skończony Wykład 4
Automat skończony Automat skończony jest modelem zachowania systemu zdefiniowanym za pomocą stanów oraz przejść między nimi. Działa na skończonych zbiorach : sygnałów wejściowych, stanów wewnętrznych, sygnałów wyjściowych. Trzy podstawowe pojęcia związane z automatem: Stan – charakterystyczny stan systemu. W odniesieniu do systemów pomiarowych dotyczy zwykle zakresu realizowanych zadań , np. inicjalizacji, akwizycji danych, archiwizacji danych, oczekiwania na akcje użytkownika itd. Zdarzenie – zaistnienie faktu wpływającego na stan systemu, np. przekroczenie limitu kontrolowanego parametru, akcja użytkownika, błąd obliczeń itd. Ogólnie zdarzenie może być zdarzeniem zewnętrznym lub wewnętrznym generowanym przez automat. Akcja – odpowiedź systemu na zdarzenie, która zależy od aktualnego stanu systemu i zaistniałego zdarzenia.
LabView i automat skończony Automat skończony jest jednym z podstawowych modeli projektowania aplikacji w LabView. Architekturę automatu skończonego można zastosować do projektowania złożonych algorytmów opisanych przez diagramy stanów lub diagramy przepływowe. Projekt wykorzystujący architekturę automatu skończonego charakteryzuje się: Przejrzystością; Łatwością dokumentowania rozwiązania aplikacji; Łatwością modyfikowania i tym samym wykorzystania w nowych warunkach; Wybór rodzaju projektu: Wzorzec projektowy w postaci automatu skończonego
Przykład opisu automatu – diagram stanów Podczas działania automat znajduje się w jednym ze stanów. Z aktualnego stanu może przejść: Tylko do jednego; Jednego z kilku możliwych. Decyzja dotycząca przejścia bazuje zwykle na : Danych wejściowych od użytkownika; Algorytmach decyzyjnych realizowanych w bieżącym stanie. Przykład: maszyna_stanowa\Revised Coke Machine.vi
Zasada realizacji automatu w LabView Implementacja automatu wykorzystuje: Pętlę while – do zapewnienia zdolności ciągłego wykonywania kodu aż do wystąpienia warunku zakończenia; Strukturę CASE – do zdefiniowania stanów automatu i działań w nich realizowanych; Rejestr przesuwny – do zapamiętania informacji dotyczącej przejścia do następnego stanu w kolejnej iteracji pętli; Stałą enumeryczną – do zdefiniowania stanów automatu w kategoriach wartości.
Określenie stanu następnego a) Rozwiązanie przejścia z jednym możliwym stanem następnym. b) Rozwiązanie przejścia do jednego z dwóch możliwych stanów następnych.
Określenie stanu następnego (cd.) c) Rozwiązanie przejścia do jednego z kilku możliwych stanów następnych. Pozycja wartości TRUE w tablicy (0, 1, ...) lub –1 gdy brak TRUE
Zabiegi samodokumentowania Przykład automatu sekwencyjnego: Przechodzi przez stany w jednoznacznie określonej kolejności. Wybór stanu można dokonać na podstawie numeru iteracji pętli realizującej automat. Etykiety ramek konstrukcji CASE są określone numerami wybierającymi. Czyli tak jakby nadać stanom automatu nic nie mówiące nazwy 0, 1, 2, itd. Znacznie korzystniej jest utworzyć stałą enumeryczną ( utworzyć odpowiadający typ !!! ) z wartościami przypisanymi do stanów automatu. Aby wykorzystać licznik iteracji do sterowania wyborem stanu trzeba wykonać konwersję danej numerycznej na enumeryczną określonego typu:
Rozwiązanie samodokumentujące Dwa równoważne rozwiązania:
Rodzaje wykonania automatów skończonych: Najczęściej spotykane rozwiązania : Automat skończony w modelu sekwencyjnym; sekwencyjna realizacja listy stanów. Automat skończony w modelu decyzyjnym; W każdym stanie jest podejmowana decyzja dotycząca wyboru kolejnego stanu do wykonania. Automat skończony w modelu kolejkowym; Kolejność wykonania stanów wynika z aktualnej zawartości kolejki stanów.
Automat skończony w modelu kolejkowym: Przykład: automat_queue\ kolejka.vi (stosuje bibliotekę vi.lib\utility\queue.llb)
Aplikacja z interaktywnym interfejsem użytkownika Architektura automatu skończonego jest przydatna w konstrukcji aplikacji z interaktywnym interfejsem użytkownika. Działanie aplikacji daje się opisać grafem stanów i aplikację można zbudować w postaci automatu skończonego. Akcje użytkownika dotyczą wykonania pewnych specyficznych działań w aplikacji, które są związane z określonymi stanami aplikacji, np. inicjalizacją aplikacji, akwizycją danych, analizą danych, zapisem danych itp. Stosuje się różne wzorce projektowe, np. : Automat z cyklicznym pollingowaniem stanu interfejsu użytkownika (bardzo popularne); Automat wykorzystujący zgłoszenia zdarzeń (przeciwieństwo cyklicznego pollingowania interfejsu użytkownika).
Automat z pollingowaniem interfejsu użytkownika Trzy przyciski boolowskie: Acquire – wykonaj zebranie danych Analyze – wykonaj analizę danych Stop – zakończ program
Grupowanie nastawników w klaster Nastawnik w postaci klastra posiada terminal wejściowy dostarczający stany wszystkich jego nastawników ( integracja danych). Klaster w tym przykładzie jest złożony z pól tego samego typu. Można go prosto przekształcić w tablicę jednowymiarową, której kolejne pola podają stany przycisków Acquire, Analyze i Stop.
Wyszukanie aktywnego przycisku Węzeł przeszukiwania tablicy poszukuje pierwszego wystąpienia zadeklarowanej wartości (tutaj TRUE). Zwraca indeks pozycji lub –1, jeśli tablica nie zawiera szukanej wartości. Diagram dostarcza wartości : -1, 0, 1 lub 2.
Realizacja programowa aplikacji Pętla while zawiera konstrukcję case, której ramki stanowią realizację przyjętych stanów aplikacji (tutaj cztery ramki). Diagram każdej ramki oprócz operacji związanych z jej zasadniczym przeznaczeniem określa też stan do realizacji w następnej iteracji pętli. Przekazanie wartości nowego stanu do następnej iteracji pętli zapewnia rejestr przesuwny.
Realizacja programowa aplikacji (cd.)
Przykład w działaniu: Uwagi do rozwiązania aplikacji: Przykład: automat_polling \ main_model1.vi Uwagi do rozwiązania aplikacji: Aplikacja wykorzystuje dwa podprogramy. Jeden realizuje akwizycję danych a drugi ich analizę. Oba subVI są skonstruowane jako programy z własnymi pulpitami interfejsu użytkownika. Pulpit subVI jest widoczny i można posługiwać się jego kontrolkami tylko podczas realizacji podprogramu. Własność tę uzyskuje się poprzez odpowiednie skonfigurowanie własności subVI:
Podsumowanie Przedstawiony metoda realizacji interfejsu użytkownika posiada kilka istotnych wad: Jest nieefektywna, ponieważ wymaga ciągłego monitorowania stanu nastawników (niezależnie od ich stanu). Zbyt częste monitorowanie niepotrzebnie obciąża procesor; trzeba wprowadzić opóźnienie – np. poddiagram opóźnienia 200ms. Zbyt rzadka kontrola stanu nastawników prowadzi do nieefektywnej obsługi aplikacji. Obserwuje się wtedy opóźnioną reakcję na działania operatora a także inną od oczekiwanej kolejność wykonania zleceń na skutek nerwowych działań operatora, itp. Bardziej efektywne i łatwiejsze projektowanie interfejsu użytkownika uzyskuje się w środowiskach pozwalających wykorzystać zdarzenia pochodzące z pulpitu aplikacji. Obsługa zdarzeń jest dostępna w LabVIEW począwszy od wersji 6.1.
Zdarzenie Zdarzenie jest asynchronicznym powiadomieniem o zaistnieniu pewnej sytuacji szczególnej dotyczącej wykonywanej aplikacji. Źródłem zdarzenia może być: Interfejs użytkownika ( kliknięcie myszki, przesuwanie wskaźnika myszki, przyciśnięcie klawisza klawiatury itp. ); Zewnętrzne urządzenia I/O ( sygnał zegarowy lub wyzwolenia, który sygnalizuje rozpoczęcie lub zakończenie akwizycji danych ); Inne części programu ( zdarzenia generowane programowo w celu zapewnienia komunikacji pomiędzy różnymi częściami programu ).
Rodzaje zdarzeń – zdarzenie powiadamiające Zdarzenie powiadamiające wskazuje, że zdarzyła się specyficzna akcja, system wykonawczy wykonał operacje związane z tą akcją i tylko aplikacja, której przypisano to zdarzenie, ma odpowiednio zareagować , realizując specyficzne operacje wynikające z sygnalizowanego zdarzenia.
Rodzaje zdarzeń – zdarzenie filtrowane Zdarzenie filtrowane informuje, że użytkownik zakończył akcję, ale środowisko wykonawcze jeszcze nie. Np. użytkownik wcisnął klawisz znaku ‘a’, zdarzenie jest zgłoszone, ale znak nie jest jeszcze dostępny w kontrolce String; nowa jej zawartość nie jest jeszcze określona. Środowisko wykonawcze nie wykonało jeszcze operacji przetwarzających związanych z tą akcją i wykona je dopiero po zrealizowaniu ramki obsługującej to zdarzenie. Diagram wykonywanej ramki może zmienić znak (patrz rysunek). Dopiero po wykonaniu ramki środowisko wykonawcze przypisze kontrolce String nową wartość. Diagram ramki może zmodyfikować dane zdarzenia udostępnione przez węzeł danych.
Sposób oznaczania rodzaju zdarzenia Zdarzeniom filtrowanym nadano nazwy kończące się znakiem zapytania, np. Key Down?, co pozwala odróżnić je łatwo od zdarzeń powiadamiających. Większość zdarzeń filtrowanych posiada odpowiadające im zdarzenia powiadamiające, np. Key Down? -> Key Down.
Zdarzenia rejestrowane statycznie Aplikacja wymaga pewnego ograniczonego zestawu zdarzeń i rejestracja odpowiada za aktywizację wybranych zdarzeń. Rejestracja statyczna obowiązuje przez cały czas działania programu VI i nie można jej zmieniać podczas działania programu. Zdarzenia rejestrowane statycznie dotyczą wyłącznie źródeł zdarzeń związanych bezpośrednio z wykonywanym programem VI. Zdefiniowano trzy podstawowe źródła zdarzeń: aplikacji VI obiektów kontrolnych
Struktura obsługi zdarzeń Zawiera kilka ramek obsługujących wybrane zdarzenie lub grupy zdarzeń. Każda ramka zawiera poddiagram realizowany po zdarzeniu aktywizującym wykonanie danej ramki struktury. Struktura oczekuje na wystąpienie określonych zdarzeń przez zadeklarowany okres czasu; tutaj 500ms. Jeśli w zadeklarowanym czasie wystąpi zdarzenie, struktura wykonuje diagram ramki związany z tym zdarzeniem. W przeciwnym razie wykonywana jest ramka przeterminowania (Timeout). Diagram ramki może korzystać z danych opisujących zdarzenie. Programista może dodać nową ramkę oraz zdefiniować i konfigurować zdarzenia aktywizujące tę ramkę.
Elementy struktury obsługi zdarzeń Selektor wyboru ramki umożliwia przeglądanie ramek struktury a etykieta ramki zawiera określenie zdarzenia aktywizującego widoczną ramkę. Terminal czasu przeterminowania służy do określenia czasu oczekiwania struktury na zdarzenie. Domyślnie jest mu przypisana wartość –1 oznaczająca nieograniczone oczekiwanie na zdarzenie. Jeśli jest podany konkretny czas, a zdarzenie nie wystąpi , wtedy jest wykonywana ramka przeterminowania (Timeout).
Elementy struktury obsługi zdarzeń (cd.) Węzeł danych opisujących zdarzenie. Zakres dostępnych danych zależy od rodzaju zdarzenia. Zawsze dostępny jest czas wystąpienia zdarzenia oraz typ zdarzenia. Liczba widocznych pól danych w zakresie dostępnych dla danego zdarzenia może być regulowana przez modyfikowanie rozmiaru węzła. Węzeł wprowadzenia przefiltrowanych danych zdarzenia pozwala na modyfikację danych dotyczących zdarzenia. Filtracja jest dostępna tylko dla zdarzeń filtrowanych a zakres modyfikacji zależy od rodzaju zdarzenia. Terminale zarejestrowanych zdarzeń dynamicznych.
Węzeł danych zdarzenia Dostępne pola węzła danych zdarzenia Value Changed: Type – Typ zdarzenia. Time – Wartość czasu w chwili wystąpienia zdarzenia (w ms). CtrlRef – Referencja do obiektu kontrolnego będącego źródłem zdarzenia. OldVal – Wartość obiektu kontrolnego przed zmianą. NewVal – Wartość obiektu kontrolnego po zmianie.
Węzły danych zdarzenia filtrowanego (cd.) Char – dostarcza wartość kodu ASCII wciśniętego klucza klawiatury. Wyjście Char pozwala zmienić kod na inny. W ten sposób można np. zapewnić dostarczenie tekstu zapisanego zawsze wielkimi literami. Wyjście Discard? pozwala anulować zdarzenie. Wprowadzenie wartości True do tego wyjścia spowoduje wyeliminowanie efektu przytrzymania klawisza i wielokrotnego wprowadzenia tego samego znaku.
Program z obsługą zdarzeń Program obsługujący zdarzenia wykorzystuje: Pętlę while – do zapewnienia zdolności ciągłego wykonywania kodu aż do wystąpienia warunku zakończenia; Strukturę EVENT – do zdefiniowania operacji realizowanych przez zdarzenia (każda ramka struktury zdarzeniowej odpowiada za obsługę jednego lub grupy wybranych zdarzeń. Każda ramka określa też wartość boolowską dostarczaną do terminala kontynuacji pętli. Lista ramek Aplikacja wykorzystuje trzy obiekty nastawcze: Zmiana wartości każdego z nich ma powodować wykonanie pewnych operacji przez aplikację. Dodatkowo w okresach bezczynności w odstępach 2 sekundowych aplikacja ma wykonywać inne zadania.
Ramki przykładowej struktury obsługi zdarzeń
Konfigurowanie konstrukcji zdarzeniowej: Rozwinięte menu struktury EVENT. Wybór: Edycji zdarzeń obsługiwanych przez widoczną ramkę. Dodanie nowej ramki zdarzeniowej.
Przypisanie zdarzeń do ramki: Lista zdarzeń przypisanych do ramki numer 1. Przypadek grupy zdarzeń przypisanych do jednej ramki. Dane zdarzenie może być przypisane tylko do jednej ramki. Duplikat C[F] – Value Change nie może wystąpić. Ale dane źródło można wykorzystać wielokrotnie. Okno wyboru źródła zdarzenia. Okno wyboru rodzaju zdarzenia dla wybranego źródła. Domyślnie panel czołowy jest blokowany podczas wykonywania diagramów konstrukcji zdarzeniowej .
Program z zastosowaniem sterowania zdarzeniami
Program z zastosowaniem sterowania zdarzeniami (cd.) Przykład: automat_event \ main_model2.vi
Uwagi projektowe: Oddzielne asynchroniczne pętle pozwalają lepiej wykorzystać współbieżność wykonania kodu oferowaną przez LabView. Zalety współbieżności są dodatkowo wzmocnione przez możliwość skutecznego wykorzystania wielordzeniowych CPU. Oddzielne pętle odpowiedzialne za : Akwizycję danych Uaktualnienie wskaźników pulpitu Obsługę interfejsu użytkownika pozwalają uzyskać sprawniej działającą aplikację. Np. uaktualnianie wyświetlaczy nie spowalnia procesu akwizycji. Niezależna obsługa interfejsu użytkownika pozwala na równoległą, ciągłą akwizycję danych. Każda z tych pętli realizuje osobny automat skończony. Obsługa interfejsu użytkownika stosuje konstrukcję zdarzeniową natomiast pozostałe wykorzystują typowy automat w modelu decyzyjnym.