TinyOS w sieciach czujnikowych

| Technika

Ponad 10 lat temu Kristofer Pister, profesor Uniwersytetu Berkeley, podjął się utworzenia sieci niewielkich czujników, które mogłyby wykrywać zmiany oświetlenia, drgań i ruchu powietrza. Każdy taki czujnik zwany motem, miał komunikować się drogą radiową na odległość do 100m, korzystać z zasilania energią słoneczną i mieć objętość nie większą niż 1cm3. Pomimo, że nie wszystkie te cele udało się osiągnąć, efekty prac są i tak bardzo interesujące.

TinyOS w sieciach czujnikowych

Ponieważ każdy mot musi działać bez pomocy użytkownika przez wiele miesięcy lub lat, jego najważniejszymi cechami są odporność na uszkodzenie i niskie zużycie energii.

Zwykle ma bardzo ograniczone zasoby sprzętowe: mikrokontroler o częstotliwości pracy rzędu 4MHz, pamięć RAM o pojemności w granicach od 4 do 10kB, pamięć Flash dla programu o pojemności 60 – 128kB i radiowy interfejs nadawczo-odbiorczy zapewniający szybkość transmisji danych na poziomie do 20kB/s. Niektóre urządzenia mają wbudowaną pamięć flash EEPROM 512kB, która służy do przechowywania danych oraz informacji o ich konfiguracji. Pobór prądu waha się w granicach od 10?A do 25mA – zależnie od tego, które podzespoły są aktywne. Często o wielkości urządzenia decydują rozmiary baterii zapewniającej mu zasilanie.

Wykorzystanie zasobów sprzętowych jest zazwyczaj niewielkie. W przykładowej aplikacji moty wychodzą ze stanu uśpienia co pięć lub dwadzieścia minut, aby dokonać pomiaru trwającego około sekundy, a następnie przesłać pakiet danych z odczytami. W czasie uruchamiania czujnika procesor w zasadzie jest bezczynny. Zwykle moty działają aktywnie przez 0,1% swojego czasu życia, zaś w trybie czuwania wykorzystują 2% szerokości pasma sieci i możliwości CPU. Czasem występuje gwałtowny wzrost aktywności, kiedy węzły odbierają i nadają komunikaty lub przetwarzają dane pobrane od sąsiednich motów.

Czym jest TinyOS?

Jest to system operacyjny, który przechowywany może być w pamięci mikrokontrolera mota. Zapewnia on reakcję na zdarzenia i współbieżne wykonywanie wielu operacji realizowanych w sieci czujników. Mot może korzystać m.in. z oprogramowania planującego, bazy danych, programu obsługi łączności bezprzewodowej, programu obsługi sieci, zarządzania zużyciem energii, a nawet technologii kodowania, zapewniającej poufność transmisji danych. Ponieważ jest to zazwyczaj oprogramowanie typu open source, istnieje również wiele dodatków dostosowujących je do różnych implementacji.

Wersje platform motów zawierające TinyOS noszą nazwy telos, tmote, micaz, mica, mica2, mica2DOT. Różnią się m.in. częstotliwością transmisji radiowej: mica2 wykorzystuje 433MHz, zaś Mica2DOT - 916MHz. Moty kontaktują się z komputerem oraz z innymi węzłami przy pomocy łączy radiowych lub portów – równoległego lub szeregowego.

Oprogramowanie

Mica2
TinyOS oraz jego biblioteki i aplikacje są napisane w języku nesC, który składnią przypomina C, ale obsługuje model współbieżności TinyOS oraz mechanizmy tworzenia, oznaczania i łączenia komponentów programowych w systemy sieciowe. Aplikacje w nesC tworzone są z komponentów, czyli modułów programowych, które kontaktują się między sobą przy pomocy tzw. interfejsów. W ten sposób projektant aplikacji może tworzyć oprogramowanie z komponentów nawet nie wiedząc jak są one wewnątrz zbudowane. Istotne są bowiem realizowane przez nie funkcje dzięki którym program może pracować na danej platformie, realizować wymagany protokół transmisji, wykonywać określone czynności, czy dostarczać odpowiednie dane.

Interfejs jest jedynym punktem dostępu do komponentu. Może zawierać rozkazy, takie jak deklaracje procedur, które zostaną wykonane na żądanie np. innego komponentu, a także deklaracje procedur wykonywanych w wyniku spełnienia określonych warunków, czyli zaistnienia zdarzeń. Przykładem rozkazu jest send(), który powoduje wysłanie pakietu danych, zaś przykładem zdarzenia jest receive(), czyli odebranie transmisji przez docelowe urządzenie.

Komponent interfejsu deklaruje zestaw rozkazów oraz dostarcza procedury implementujące poszczególne rozkazy, natomiast komponent użytkownika interfejsu deklaruje zestaw zdarzeń wraz z odpowiednimi procedurami. Innymi słowy komponent, który wywołuje rozkaz zadeklarowany w interfejsie, musi mieć zaimplementowaną obsługę zdarzeń związanych z wykonywaniem danego rozkazu. W powyższym przykładzie, jeśli komponent żąda wysłania do niego danych, musi mieć procedurę, która ustali sekwencję jego działań, kiedy dane zostaną odebrane.

Podczas edycji aplikacji, każdy komponent jest zapisywany w oddzielnym pliku o rozszerzeniu .nc. Język nesC rozróżnia dwa typy komponentów: moduły i konfiguracje. Moduł zawiera interfejsy i kod aplikacji. Nazwę pliku modułu zwykle kończy się literą M (np. RobotM.nc) dla odróżnienia od nazwy pliku konfiguracji (np. Robot.nc). Z kolei konfiguracja służy do łączenia komponentów i uzgadniania interfejsów używanych przez jedne komponenty, a dostarczane przez inne. Możliwe jest również deklarowanie interfejsów. Konfigurację ze związanymi z nią modułami można traktować więc jako duży moduł wyższego rzędu. W ten sposób tworzone są drzewiaste struktury hierarchiczne, w których poszczególne elementy wykonawcze, czyli moduły elementarne można wymieniać tak, aby całość działała w sposób optymalny. Każda aplikacja nesC zawiera główną konfigurację (top-level configuration), która wywołuje moduły niższego rzędu. Odróżnienie modułów od konfiguracji umożliwia składanie aplikacji z modułów dostarczanych przez firmy lub wydziały, które specjalizują się w ich projektowaniu.

Przykład pliku konfiguracyjnego

Niech będzie dany następujący kod programu:

Zapytania bazodanowe

Telos podczas programowania
Do pobierania informacji z sieci motów służy system przetwarzania zapytań TinyDB. Ma on prosty interfejs typu SQL, który pozwala zdefiniować dane do pobrania wraz z dodatkowymi parametrami, takimi jak np. częstość odświeżania danych. Na tej podstawie TinyDB zbiera dane z motów, filtruje je, tworzy agregaty i kieruje do PC, stosując wydajne algorytmy przetwarzania w sieci. Sygnały z danego czujnika mogą być łączone z sygnałami z sąsiednich czujników i do stacji bazowej przesyłana jest już przetworzona informacja.

Znacznie upraszcza to tworzenie aplikacji, uwalnia programistę od pisania kodów niskiego poziomu dla urządzeń czujnikowych oraz interfejsów sieci czujników. Z drugiej strony, dane są przetwarzane niemal u źródła, co znacznie zmniejsza natężenie ruchu w sieci. Lokalne operacje są wykonywane lokalnie. Ułatwia to zatem rozbudowę sieci.

Podobnym językiem jest TinySQL. Przykładowo zapytanie w postaci:
SELECT AVG(temperature) INTERVAL 50s spowoduje, że co 50s węzły sieci będą przesyłały do stacji bazowej informacje o uśrednionych temperaturach, mierzonych z częstością np. 100 pomiarów na sekundę.

Tworzenie aplikacji

Środowisko programowe TinyOS zawiera sterowniki do obsługi m.in. takich programatorów jak:

  • MIB500 firmy Crossbow lub podobny, wykorzystujący do komunikacji port równoległy PC,
  • MIB510 firmy Crossbow, wykorzystujący port szeregowy,
  • AVRISP firmy Atmel,
  • EPRB (Ethernet PRogramming Board)

Więcej informacji na temat TinyOS

TinyOS został opracowany na Uniwersytecie w Berkeley i więcej informacji na jego temat można uzyskać na stronie http://webs.cs.berkeley.edu/tos. Na stronie znajdują się również przykłady programów do obsługi motów. Dane na temat TinyOS oraz sam system znaleźć można również na stronie http://www.tinyos.net/. Kurs programowania systemu (w języku angielskim) dostępny jest pod w pliku PDF pod adresem http://csl.stanford.edu/~pal/pubs/tinyos-programming-1-0.pdf. Obszernym źródłem informacji o podzespołach jest wreszcie strona http://www.btnode.ethz.ch/Projects/SensorNetworkMuseum

W TinyOS wykorzystywane jest najczęściej programowanie w systemie, czyli uisp (? In-System Programmer). Jest to program dostarczany z omawianym systemem – podczas jego instalacji należy podać typ programatora i sposób komunikowania się z nim. Do kompilacji kodu wykorzystuje się programy avrgcc, perl, flex, cygwin w przypadku Windows oraz JDK.

Pracę nad aplikacją ułatwia utworzenie pliku Makelocal, w którym zdefiniowane są bieżące parametry środowiska. Parametry te określają ścieżkę do kodu, oznaczenie programowanej grupy urządzeń, częstotliwość roboczą mota (np. 916,7MHz) oraz domyślny programator. TinyOS może współpracować z różnymi platformami sprzętowymi. Jedną z nich jest Mica. Poniżej przedstawiony zostanie przykład operacji koniecznych do kompilacji aplikacji Blink, której główna konfiguracja to blink.nc. Plikiem wykonawczym ma być main.exe dla mota zawierającego platformę Mica. W tym celu należy wywołać kompilator ncc poleceniem: ncc –o main.exe –target=mica Blink.nc

Edytor TinyDT  plug-in do platformy Eclipse wspierający programowanie w nesC (program można pobrać ze strony http://www.tinydt.net/)
Kompilator ncc lokalizuje i kompiluje wszystkie komponenty aplikacji, łączy je w jeden kod i sprawdza zgodność interfejsów. Jednym z zadań procesu kompilacji jest również wykrywanie ewentualnych wyścigów danych w programie. Następnie należy stworzyć main.srec – binarną wersję pliku main.exe w formacie tekstowym, którą można będzie przesłać do mota: avr –objcopy –output-target=srec main.exe main.srec

Kolejnym narzędziem do wywołania może być uisp, który pozwoli na przesłanie kodu do motów. Można w tym celu przyłączyć płytkę mota do programatora lub przesłać kod siecią bezprzewodową, wskazując adres węzła, w którym znajduje się dany mot.

W pewnych aplikacjach zamiast programować każdy mot w nieco inny sposób, można wysłać do wszystkich urządzeń ten sam program, natomiast każde urządzenie będzie wykonywało tylko przeznaczony dla niego zestaw instrukcji. Aktualizacja oprogramowania całej sieci zostanie uzyskana w ten sposób w jednej tylko operacji rozgłoszeniowej, która trwa nieporównanie krócej niż aktualizacja oprogramowania np. kolejno w kilkuset węzłach.

Komunikacja

Na komunikację składają następujące funkcje:

  1. Ustalenie zawartości wysyłanego komunikatu.
  2. Ustalenie węzłów, do których komunikat jest adresowany.
  3. Ustalenie kiedy zostanie zwolniona pamięć związana z wysyłanym komunikatem.
  4. Buforowanie odbieranego komunikatu.
  5. Przetwarzanie odebranego komunikatu.

źródło: EPFL
Przesyłane dane mogą mieć maksymalnie 29 bajtów w pakiecie obejmującym w sumie 39 bajtów. Kiedy aplikacja warstwy odpowiedzialnej za transmisję komunikatów otrzyma polecenie send(), blokuje bufor nadawania i komponenty nie mogą go modyfikować aż do zakończenia transferu, co jest sygnalizowane zdarzeniem Send Done().

Łączność bezprzewodową można realizować przy pomocy m.in. protokołów ZigBee lub IEEE 802.15.4. Od strony sprzętowej wykorzystywany jest do tego celu np. radiowy układ nadawczo-odbiorczy CC2420 lub CC1000 firmy Chipcon.

Komunikacja radiowa w TinyOS jest zgodna z modelem AM (Active Message), w którym każdy pakiet w sieci zawiera identyfikację procedury obsługi zdarzenia (handler ID), która jest wywoływana w węzłach odbiorczych. Po odebraniu komunikatu, sygnalizowane jest zdarzenie odbioru, związane z danym ID. Każde urządzenie odbiorcze może mieć inną procedurę obsługi zdarzenia odbioru. Jednym z istotnych zadań procedury jest zwolnienie buforu odbioru tak, żeby sieć mogła przesłać następny komunikat.

Nagłówek komunikatu zawiera 8-bitowe oznaczenie grupy urządzeń, do których wysyłany jest komunikat oraz 16-bitowy adres węzła sieci, który jest unikalny w ramach danej grupy. Istnieje również adres rozgłaszania, o wartości 0xFFF. Komunikaty z takim adresem są odbierane przez wszystkie urządzenia, niezależnie od adresów węzłów, w których się znajdują.

Taki sposób komunikowania się z węzłami sieci umożliwia np. zmianę oprogramowania urządzeń bez konieczności wymontowywania ich z sieci.
Przykładowo polecenie make mica install.38 spowoduje zainstalowanie oprogramowania w urządzeniu znajdującym się węźle o adresie 38.

Odebrany komunikat może zostać przesłany dalej, co ułatwia tworzenie sieci drzewiastych, w których nie wszystkie urządzenia mają bezpośrednie połączenie z komputerem nadrzędnym. Jest to tak zwana transmisja wieloskokowa. Węzły mogą być zablokowane, poza zasięgiem lub wyłączone podczas przesyłania danych. Stosowane jest więc czasem cykliczne ponawianie transmisji aż do skutku.

Każdy węzeł może gromadzić statystyki jakości łącza i szacunki kosztów transmisji przy zastosowaniu różnych rodzajów komunikacji. Wykorzystuje te informacje przy wyborze optymalnej trasy do przesyłania danych. Ma to szczególnie znaczenie przy przesyle danych między węzłami sieci, kiedy zarówno konfiguracja sieci, jak i programy aplikacyjne poddawane są stosunkowo częstym modyfikacjom.

Inne systemy operacyjne dla czujników

Btnode v. 3.20
TinyOS to nie jedyny istniejący system operacyjny sieci czujnikowych. Przykładowo program SensorWare wykorzystuje skrypty Tcl do programowania węzłów przy pomocy interpretera. Jest on jednak przeznaczony do urządzeń zawierających pamięć o większej pojemności. W każdym węźle można wówczas umieścić interpreter, co w przypadku motów jest niemożliwe.

Z kolei SOS jest systemem operacyjnym sieci czujników, który umożliwia dynamiczną aktualizację kodu przy pomocy systemu modułowego. Moduły mogą wywoływać rdzeń oraz komunikować się między sobą. Dzięki temu transmisja danych w tej sieci jest wydajniejsza niż w TinyOS.

Podobnie jak SOS również system Impala middleware umożliwia dynamiczne instalowanie modułów naturalnego kodu. Moduły mają tylko interfejsy rdzeniowe. Impala nie zawiera ogólnych mechanizmów pozwalających na zmianę zdarzeń wyzwalających, gdyż jest opracowany do konkretnej aplikacji – sieci ZebraNet.

Systemy takie jak exokernel i SPIN umożliwiają użytkownikom pisanie interfejsów i poprawianie sprawności działania sieci przez zwiększenie kontroli. Jednak w sieciach czujników sprawność – czy to rozumiana jako szerokość pasma, czy jako liczba operacji na sekundę – jest rzadko istotna. Transmisje dotyczą zazwyczaj niewielkich paczek danych wysyłanych w dużych odstępach czasu. Zatem odporność na uszkodzenia i sprawność energetyczna są ważniejszymi parametrami.

Innymi przykładami systemów są ANTS, PLAN i Smart Packets, które współpracują z Internetem. Wszystkie umożliwiają dynamiczne programowanie sieci czujników. ANTS wykorzystuje Javę, zaś pozostałe dwa są językami opracowanymi przez ich autorów. Ponieważ oparte są na modelu komunikacji i zasobów Internetu, wiele ich decyzji nie pasuje do sieci motów. W przeciwieństwie do Internetu, gdzie generowanie danych jest najczęściej funkcją peryferyjną, w sieciach czujników każdy węzeł zarówno odbiera i nadaje komunikaty, jak i generuje dane.

Podsumowanie

Przedstawiony przegląd wybranych aspektów systemu operacyjnego TinyOS wskazuje na jego niezwykłą elastyczność i uniwersalność. Programy zajmują bardzo niewiele pamięci, a mimo to realizują tak skomplikowane funkcje jak przetwarzanie danych z grupy czujników przed wysłaniem zbiorczego komunikatu do węzła bazowego, kodowanie transmisji, aktualizowanie programów urządzeń w zasadzie bez przerywania ich pracy. Struktura programu, która złożona jest z odpowiednio połączonych komponentów, pozwala w prosty sposób tworzyć aplikacje. Projektant nie musi znać szczegółów protokołów transmisyjnych, czy obsługi danego urządzenia – wystarczy, że ma do dyspozycji odpowiednie komponenty. Oparta na zdarzeniach praca aplikacji ogranicza zużycie energii w czasie między zdarzeniami i przyczynia się do ograniczenia wielkości programu.

Tabele

  • TABELA 1. Wybrane układy oferowane komercyjnie, które mogą współpracować z TinyOS
  • TABELA 2. Porównanie wybranych interfejsów radiowych

Janusz Proniewicz, Zbigniew Piątek