Czym jest Xbee?

XBee to modem radiowy z interfejsem szeregowym i dodatkowymi pinami, które możesz wykorzystać we własnym zakresie. Modem taki pozwala przesyłać dane bez pomocy kabla z prędkościami od 1200 do 230400 bitów na sekundę w paśmie 2.4 Ghz (czyli tym samym co WiFi). Modem zasilany jest napięciem 3.3 V. Dostarczany jest w postaci małej płytki drukowanej.
Sygnały potrzebne do działania dostarczane są do niej za pomocą goldpinów rozmieszczonych na 2 bokach. Niestety goldpiny z racji wielkości modułu mają gęściej rozmieszczone wyprowadzenia niż standardowe 2.54 mm (0.1″). Na szczęście można dokupić różne adaptery dopasowujące XBee do płytki stykowej, jednocześnie dostosowujące napięcie działania do 5 V.

Co jeszcze będzie potrzebne?

Nakładka na Arduino "Arduino XBee Shield"

Jest to nakładka, która wchodzi w gniazda Arduino "Analog In 0 - 5", "Digital 0 - 7" oraz ICSP. Nakładka jest przelotowa, co oznacza, że od górnej strony płytki wystają takie same gniazda, z których można normalnie korzystać.


XBee Shield wykorzystuje cyfrowe piny 0 i 1 (do komunikacji szeregowej) oraz sygnały +5 V, GND i RESET ze złącza programatora ICSP.

Nakładka posiada także dodatkowe pola lutownicze, w które można wlutować goldpiny, gniazda lub przewody. Dodatkowe pola dotyczą pinów cyfrowych i analogowych Arduino, zasilania, oraz wyprowadzeń modułu XBee.

Płytka wyposażona jest też w przycisk RESET, odpowiadający temu z płytki Arduino, oraz diodę LED oznaczoną jako ASSOCIATE informującą o działaniu XBee (świecenie) i zalogowaniu się do sieci (mruganie).

Sygnał RESET podłączony jest również przez tranzystor do sygnału CTS modułu. Powoduje to automatyczne resetowanie Arduino po wysłaniu zbyt dużej ilości danych, których nie ma kto odebrać.

Xbee explorer lub dongle

Posłuży nam do podłączenia jednego z modemów Xbee do komputera

Adapter XBee USB dongle Adapter XBee Explorer ze złączem USB

Sieć ZigBee

Sieci Zigbee składają się z trzech głównych elementów:

Każdy modem XBee można skonfigurować do pracy jako jeden z wymienionych elementów sieci Zigbee. W przypadku XB24-B do wyboru są 3 role:

Oczywiście każdy element sieci pełni normalne funkcje modemu i jest zdolny transmitować dane.

Podstawowe parametry sieci Zigbee

ID - Numer sieci. Ponieważ na tym samym obszarze może istnieć wiele sieci Zigbee (wiele Koordynatorów), dlatego każda powinna mieć inny niezależny numer. Każde urządzenie chcące przynależeć do tej samej sieci musi mieć skonfigurowany jej numer.

CH - Kanał. Modem może pracować z różnymi częstotliwościami, które wybiera się właśnie za pomocą kanału. Zwykle wyboru dokonuje koordynator, przeszukując pasmo w celu znalezienia najmniej zatłoczonego kanału i rozgłasza go podległym urządzeniom.

SH/SL - Jest to numer seryjny urządzenia w sieci Zigbee. Numer ten służy do adresowania urządzeń w sieci. Numer ten podzielony jest na dwie 32-bitowe połowy.

DH/DL - W tym parametrze ustalony jest odbiorca danych naszego modemu. Przypisujemy im numery SH/SL urządzenia do którego chcemy wysyłać dane.

BD - Parametr ustalający prędkość interfejsu szeregowego. Domyślne prędkości to 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 i 230400.

Konfiguracja modemu

Do konfiguracji modemów służy program "X-CTU", który można pobrać ze strony digi.com.
Program napisany jest dla Windows, ale część jego elementów działa również pod innymi systemami na których działa Wine.

Po podłączeniu modemu do komputera, uruchamiamy program i naszym oczom ukazuje się las... ;-)

W tej zakładce należy wybrać odpowiedni port do którego podłączony jest modem.
Prawidłowość połączenia możemy zbadać klikając przycisk "Test / Query", w wyniku czego otrzymamy okno potwierdzające prawidłowość połączenia, typ modemu i wersje firmware w nim zakodowanego.

Ostatnia zakładka "Modem Configuration" służy do przeglądania, edytowania i zapisywania konfiguracji modemu oraz wybranego firmware (oprogramowania dla procesora w modemie).

Po kliknięciu przycisku "Read" informacje o XBee zostaną automatycznie wczytane i wyświetlone.

Następną czynnością jest wybór roli modemu w menu "Function Set".

W przypadku dwóch modemów jakie testowałem jednemu przydzieliłem funkcję "ZIGBEE COORDINATOR AT", a drugiemu "ZIGBEE ROUTER/END DEVICE AT".

Kolejnymi czynnościami będzie skonfigurowanie parametrów sieci obydwu modemów. Najpierw wybieramy numer identyfikacyjny sieci ID.

Możesz wybrać dowolną liczbę szesnastkową z zakresu 0 - 3FFF. Jeśli wybierzesz liczbę FFFF, koordynator sam wybierze losowy numer sieci.

U siebie ustawiłem na 3333.

Teraz trzeba ustawić odbiorcę danych w parametrach DL/DH. Oczywiście przepisujemy je z SL/SH drugiego modemu. Również DL/DH drugiego modemu ustawiamy na SL/SH pierwszego modemu.

Na koniec ustalamy wybraną prędkość transmisji w parametrze BD.

Po kliknięciu przycisku "Write", firmware i parametry powinny zapisać się w modemie.

Jeśli dobrze wszystko zaprogramowałeś obydwa modemy po włączeniu powinny się zachować jak kabel "nullmodem". Czyli to co wyślemy do pierwszego, automatycznie odbierze drugi i na odwrót.

Należy się jeszcze mała uwaga. Odkryłem błąd w modemie. Jeśli zaczniesz wysyłać dane wcześniej niż 5 s po uruchomieniu, modem przestanie wysyłać dane aż do chwili zresetowania go lub ponownego włączenia zasilania.

Konfiguracja X-CTU dla Wine

Na początku należy stworzyć link symboliczny dowiązujący port szeregowy "/dev/ttyUSBn" do katalogu urządzeń Wine.

ln -s /dev/ttyUSB0 ~/.wine/dosdevices/com10

Następnie po uruchomieniu programu przechodzimy do zakładki "User Com Ports". Teraz w pole "Com Port Number" należy wpisać nazwę dowiązania "COM10" i kliknąć przycisk "Add". Port powinien pojawić się na liście interfejsów, które można użyć do komunikacji.

Na Ubuntu 10.10 z Wine 1.3.5 program działał dość topornie i nie potrafił zaktualizować swojej bazy firmware-u modemów. Po swoim działaniu rozwalał też system obsługi portów szeregowych tak, że wymagane było ponowne uruchomienie systemu.
W Ubuntu 11.04 z Linux 2.6.37 praca programu wydaje się bardziej stabilna.

Komendy AT

Oczywiście konfiguracji modemu nie trzeba przeprowadzać tylko i wyłącznie z poziomu X-CTU. Można np. posiadając wielu odbiorców pakietów rozsyłać je do różnych modemów w sieci. Jak to zrobić? W odpowiedzi przychodzą nam komendy AT, znane ze starych modemów telefonicznych albo z niektórych dzisiejszych telefonów GSM.

Ponieważ normalnie modemy przesyłają dane, nie można wysyłać im komend, bo dane podobne do rozkazów mieszałyby ustawienia modemu. Modem XBee posiada zatem dwa tryby pracy - wysyłania danych i wykonywania rozkazów. Przejście z trybu danych do rozkazów następuje po wysłaniu do modemu ciągu "+++" i odczekaniu sekundy (gdy nie odczekasz sekundy i zaczniesz wysyłać dalsze bajty modem uzna "+++" jako część danych i je wyśle).

Po sekundzie modem powinien odpowiedzieć ciągiem "OKr". Domyślnie modem używa znaku 'r' (CR) o numerze 13 - jako znaku zakończenia linii i tak należy się z nim komunikować. Rozkazy można ćwiczyć ręcznie w zakładce "Terminal" programu X-CTU.

Każdy rozkaz zaczyna się od liter "AT". AT to też jeden z podstawowych rozkazów informujący, że mamy doczynienia z tym standardem. Wydając rozkaz "AT" (oczywiście w trybie rozkazów) powinniśmy otrzymać w odpowiedzi znane już "OK". Jeśli jest inaczej powinieneś sprawdzić czy modem ma ustawiony odpowiedni "Function Set". Prawidłowe to te zakończone na "AT".

Bardziej złożone komendy AT

Wcześniej pisałem o parametrach modemu jako dwuliterowych symbolach (np. "ID" lub "CH"). Symbole te występowały również w menu programu do konfiguracji. Ma to takie znaczenie, że te symbole są częścią rozkazów. Jeśli np. chcemy odczytać numer sieci (parametr ID), używamy komendy "ATID". Modem powinien w jej odpowiedzi odesłać numer sieci.

Przypominam na wszelki wypadek, o przejściu w tryb komend za pomocą "+++" i kończeniu każdej linii rozkazu za pomocą znaku "r".
Z trybu rozkazów można wyjść do trybu wysyłania danych na 2 sposoby. Gdy upłynie ustalony czas od ostatniego rozkazu (domyślnie 10 s), modem sam przejdzie w tryb transmisji danych. Drugim sposobem jest wydanie polecenia "ATCN".

Jest jeszcze jedna forma rozkazów - rozkazy z parametrem. Są one potrzebne wtedy, kiedy chcemy zmienić jakiś parametr modemu. Są one podobne do rozkazów odczytu z tym, że zamiast kończyć się na symbolu parametru mają za nim liczbę w postaci szesnastkowej (hex).
Np. gdybyś chciał ustawić numer sieci na 0x3333 należy wydać rozkaz "ATID3333".

Poniżej przedstawiam opis najważniejszych rozkazów modemu. Po więcej odsyłam do dokumentacji lub programu konfiguracyjnego, który po kliknięciu w parametr przedstawia jego dość dokładny opis.

ATID - numer sieci - wszystkie modemy należące do sieci muszą mieć ten sam numer w jej obrębie

ATCH - numer kanału - domyślnie przydziela go koordynator, jednak może się przydać sprawdzenie w razie problemów

ATSL i ATSH - zawierają 32 bitowe połówki adresu modemu

ATDL i ATDH - zawierają 32 bitowe połówki adresata danych

ATBD - steruje prędkością transmisji interfejsu szeregowego jego parametr to cyfra od 0 do 8 oznaczająca:

ATAI - podaje stan sieci, jeśli zwraca wartość 0 to wszystko OK, jeśli inną to błąd sieci lub nie znaleziono koordynatora.

ATWR - zapisuje zmienione parametry w pamięci modemu, tak by po ponownym uruchomieniu nie trzeba było ich znowu ustawiać

ATRE - przywraca fabryczne parametry modemu

ATCN - wychodzi z trybu rozkazów do trybu danych

ATVR - podaje wersję oprogramowania modemu

ATHV - podaje wersję sprzętu

ATPL - ustawia moc nadawania od 0 - najsłabsza do 4 - najsilniejsza

ATPM - ustawia dodatkowe wzmocnienie nadawania 0 - wyłączone, 1 - włączone

ATDB - odczytuje siłę odebranego sygnału

AT%V - odczytuje napięcie zasilania modemu - wynik należy podzielić przez 1023 i pomnożyć przez 1200 (np. jeśli wynikiem jest B0C czyli 0xb0c/1024.0*1200 = 3314.0625 mV = 3.314 V)

Te podstawowe parametry pozwolą ustawić transmisję danych. Przykład z użyciem sieci o numerze 1234, prędkością transmisji 19200 i dwoma modemami jeden o adresie 13A230403AB2ED, a drugi 13A230433AB2FD.

[modem 1]
+++
OK
ATID1234
OK
ATBD4
OK
ATDH13A230
OK
ATDL403AB2ED
OK
ATWR
OK
ATSL
433AB2FD
ATSH
13A230

[modem 2]
+++
OK
ATID1234
OK
ATBD4
OK
ATDH13A230
OK
ATDL433AB2FD
OK
ATWR
OK
ATSH
13A230
ATSL
403AB2ED

Dynamiczne adresowanie

Jeśli w sieci istnieje kilka urządzeń z modemami XBee, czasem istnieje potrzeba odwoływania się do kilku z nich. Pierwsze prawidło takich sieci mówi, że koordynator oprócz swojego własnego sprzętowego adresu ma też adres 0, 0 [H, L].
Kolejnym prawidłem jest to, że wysyłając dane na adres 0, FFFF - wyślemy je do wszystkich urządzeń w sieci na raz. Pewnym ograniczeniem/zabezpieczeniem takiego nadawania jest to, że co 8 bajtów następuje ograniczona losowym czasem przerwa w transmisji. Przerwa ma zapobiec zbyt dużemu blokowaniu całej sieci.

Każdemu modemowi można nadać nazwę, składającą się z 20 (widzialnych [czyli np. nie spacja, nie tab itp.]) znaków ASCII. Odpowiada za to parametr "NI", czyli polecenie "ATNI".

ATNIrobot1

Od chwili wydania tego polecenia modem będzie widziany w sieci również jako urządzenie o nazwie "robot1".
Aby inny modem mógł się z nim połączyć za pośrednictwem nazwy, należy ustawić parametr "DN" za pomocą polecenia "ATDN".

ATDNrobot1

Polecenie to zwróci "OK" w przypadku znalezienia nazwy lub "ERROR" w przypadku jej nieznalezienia. Jeśli znaleziono nazwę to automatycznie zostaną ustawione parametry "DL" i "DH" na adres właściciela nazwy.

Istnieje również możliwość wygenerowania listy wszystkich modemów w dostępnych w sieci (wraz z ich parametrami) za pomocą polecenia "ATND". Każdy modem to kilka linii tekstu na końcu którego jest pusta linia z samym znakiem 'r'. Ostatni element listy zakończony jest dwiema pustymi liniami. Pojedynczy element listy wygląda tak:

861F
13A230433AB2FD - adres modemu
ROBOT1 - nazwa modemu
FFFE
01
00
C105
101E
 - pusta linia 1
 - pusta linia 2 (koniec listy)

Programowe wydawanie poleceń AT w Arduino

Żeby było wam wygodnie, napisałem kilka prostych funkcji do wykorzystania w komunikacji z XBee.

once_at

Podstawową i najprostszą funkcją jest "once_at". Posiada ona 2 argumenty. Pierwszym jest nazwa komendy AT, a drugim jej parametr.
Funkcja ta przechodzi do trybu komend wysyła komendę, wraca do trybu danych i zwraca nam wynik działania komendy.
np.

once_at("ATID", "3333");

zmienia adres sieci na 3333.

get_message_type

Argumentem tej funkcji jest typ String zawierający dane zwrócone w wyniku działania komendy AT. Funkcja ta sprawdza rodzaj zwróconych danych i zwraca jedną ze stałych:

MESSAGE_ERROR - Funkcja nie wykonała się prawidłowo

MESSAGE_OK - Funkcja wykonała się prawidłowo

MESSAGE_VALUE - Funkcja zwróciła jakąś wartość

MESSAGE_STRUCT_ERROR - Funkcja zwróciła nieprawidłowe dane
np.

String msg = once_at("ATID", "3333");
if (get_message_type(msg) == MESSAGE_OK)
{
    // Funkcja wykonała się prawidłowo
}

command_mode

Funkcja nie posiada argumentów i pozwala przejść w tryb wydawania komend AT. Funkcja zwraca stałą tak jak "get_message_type".
np.

if (command_mode() == MESSAGE_OK)
{
    // Tu wpisz co ma się dziać po przejściu w tryb komend AT
}

data_mode

Funkcja nie posiada argumentów i pozwala przejść w tryb wysyłania danych. Funkcja zwraca stałą tak jak "get_message_type".
np.

if (data_mode() == MESSAGE_OK)
{
    // Tu wpisz co ma się dziać po przejściu w tryb wysyłania danych
}

AT

Funkcja posiada 2 argumenty. Pierwszym jest nazwa komendy AT, drugim jej parametr.
Funkcja wysyła komendę AT do modemu i zwraca wynik jej działania jako String.
np.

String id = "";
if (command_mode() == MESSAGE_OK) // Przejście w tryb komend
{
    id = AT("ATID"); // Pobranie adresu sieci
    if (data_mode() == MESSAGE_OK) // Przejście w tryb danych
    {
        Serial.print(id); // Wysłanie adresu sieci do odbiornika
    }
}

W tym przykładzie zostanie pobrany adres sieci z modemu i wysłany do odbiornika.

read_message

Funkcja ta nie posiada argumentów. Funkcja zwraca jedną linię danych z modemu zakończoną znakiem "r" (czyli wynik działania komendy AT). Funkcja może być przydatna przy czytaniu wieloliniowych odpowiedzi na komendy AT.

Programowe wydawanie poleceń AT w Pythonie

Napisałem też moduł do języka Python. Moduł składa się z 2 klas. Najważniejszą z nich jest klasa "ATXBee". Służy ona do wysyłania poleceń do modemu i odbierania odpowiedzi. Konstruktor klasy wymaga argumentu, którym jest obiekt komunikacji z modemem typu "Serial".

import atxbee
import serial

xbee = serial.Serial('/dev/ttyUSB0', 9600) # obiekt komunikacji z modemem
at = atxbee.ATXBee(xbee) # obiekt do wydawania polecen AT do modemu

Metody klasy "ATXBee" niewiele się różnią od funkcji w bibliotece z poprzedniego rozdziału. Główną metodą jest "once_at", która automatycznie przechodzi w tryb poleceń modemu, wykonuje polecenie i wraca do trybu danych, jednocześnie zwracając odpowiedź na polecenie.
Odpowiedzią na polecenia klasy "ATXBee" jest obiekt drugiej klasy o nazwie "Response". Obiekt ten informuje jakiego typu jest zwrot, oraz zawiera pole przechowujące string zwrotu.
Do badania typu zwrotu służą metody "is_ok" (odpowiedź typu OK), "is_error"(odpowiedź typu ERROR), "is_value" (odpowiedź zwraca wartość), "is_struct_error" (błędna odpowiedź). Każda metoda zwraca wartość "True" jeśli modem zwrócił odpowiedź odpowiadającą wybranej metodzie. Jeśli odpowiedź jest typu "VALUE", to jej treść znajduje się w polu "message".

Poniżej przykład na zmianę adresu sieci:

response = at.once_at("ATID", "3333")
if response.is_ok():
    # Tu umieszczamy program, który się wykona jeśli polecenie zakończy się sukcesem

Kolejnymi metodami oferowanymi przez klasę "ATXBee" są "command_mode" (przechodzi do trybu poleceń), "data_mode" (przechodzenie do trybu danych) i "AT" (wydanie pojedynczego polecenia AT).
Za przykład posłuży nam program do odczytu adresu sieci modemu:

if at.command_mode().is_ok(): # przejście do trybu poleceń
    response = at.AT("ATID") # wydanie polecenia ATID
    if response.is_value(): # sprawdzenie czy zwrócona wartość jest odpowiedniego typu
        if at.data_mode().is_ok(): # przejście do trybu wysyłania danych
            print response.message # wyświetlenie adresu sieci

Komunikacja z XBee za pomocą API

Przeglądając menu funkcji modemu zapewne dostrzegłeś, że oprócz firmware-ów dla koordynatora i rutera/end point z końcówką "AT", są jeszcze takie z końcówką API. API to inny format wydawania rozkazów dla modemów XBee, opierający się na wysyłaniu binarnych struktur danych.
Ponieważ temat przekracza objętość tego artykułu, a do komunikacji przez API istnieje mnóstwo bibliotek, polecam skorzystanie z nich i zaznajomienie się z ich dokumentacją.