Arduino WiFi - Kurs Arduino cz. 4
Nakładka Ethernet błyskawicznie podłączy Twoją płytę Arduino do sieci, ale w niektórych sytuacjach przydaje się łączność bezprzewodowa. Na przykład gdy musisz odbierać na bieżąco dane z samobieżnego robota własnej konstrukcji albo gdy Twój
układ musi być podłączony do sieci, a w pobliżu nie ma łącza ani routera przewodowego. Sięgnij wtedy po nakładkę WiFi, eleganckie rozwiązanie umożliwiające podłączenie Arduino do sieci bezprzewodowej i przesyłanie danych.
UWAGA: Jeżeli posiadasz nakładkę SparkFun WiFly (popularny odpowiednik oficjalnej nakładki Arduino WiFi) albo z jakiegoś powodu musisz ją wykorzystać w projekcie, na stronie internetowej oryginalnego wydania książki znajdziesz odpowiednio zmienioną wersję tego podrozdziału (w języku angielskim). Odnośnik do niego zamieściliśmy w dodatku E.
Nakładka Arduino WiFi
Nakładka Arduino WiFi umożliwia podłączenie płyty do dowolnej sieci bezprzewodowej typu 802.11b/g. Wykorzystuje moduł bezprzewodowy H&D Wireless HDG104, oferujący uzyskanie zoptymalizowanego, energooszczędnego połączenia radiowego.
Nakładka umożliwia komunikację za pomocą protokołów TCP i UDP, a jej użycie jest bardzo proste i polega na zamontowaniu na płycie Arduino i wpisaniu w szkicu kilku wierszy kodu wykorzystującego bibliotekę WiFi. Łączówki nakładki posiadają w górnej części gniazda, umożliwiające łatwe wykorzystanie pinów Arduino albo założenie dodatkowych nakładek.
Oprócz obsługi sieci bezprzewodowych w standardzie 802.11b/g nakładka WiFi oferuje szyfrowanie WEP oraz WPA2. Po załadowaniu szkicu i skonfigurowaniu płyty Arduino można ją odłączyć od komputera, zasilić z zewnętrznego źródła i zestawić
dwukierunkową komunikację z dowolnego miejsca w zasięgu routera bezprzewodowego.
Ale to nie wszystko. Nakładka WiFi zawiera również slot na kartę microSD, który może być wykorzystany zarówno przez płytę Arduino Uno, jak i Mega, dzięki prostej w użyciu bibliotece SD. Jest to bardzo przydatna funkcjonalność, jeżeli zamierzasz
zapisać dane, a następnie przesłać je przez sieć. W podrozdziale 8.7 dowiesz się dokładnie, jak korzystać z biblioteki SD.
Arduino piny wejścia/wyjścia
Ważna informacja na temat pinów wejścia/wyjścia
Nakładka Arduino WiFi oraz czytnik kart SD komunikują się z Arduino za pomocą szyny SPI (opisanej niżej w podrozdziale 8.6), którą cechuje kilka istotnych szczegółów związanych z wykorzystaniem pinów wejścia/wyjścia.
W płycie Arduino Uno komunikacja jest realizowana na pinach nr 11, 12 i 13, natomiast w płycie Mega na pinach nr 50, 51 i 52. W obu płytach pin nr 10 jest używany do wybrania do komunikacji układu HDG104, natomiast pin nr 4 do wybrania czytnika karty
SD. Sprzętowy pin SS w płycie Mega (pin cyfrowy nr 53) nie jest używany ani przez czytnik kart, ani przez układ HDG104, ale musi być skonfigurowany jako wyjście, aby interfejs SPI działał prawidłowo. Pin cyfrowy nr 7 jest używany do przesyłania danych
pomiędzy nakładką WiFi a Arduino. Bardzo ważne jest więc, aby żaden z wymienionych wyżej pinów nie był wykorzystywany do innych operacji wejścia/ wyjścia.
I wreszcie ponieważ zarówno układ HDG104 w nakładce WiFi, jak również czytnik kart SD korzystają z tej samej szyny SPI, tylko jeden z komponentów może być aktywny w danej chwili. Jeżeli wykorzystywane są oba, biblioteki SD oraz WiFi realizują ich obsługę
automatycznie. Ale jeżeli jest wykorzystywany tylko jeden z nich, należy jawnie odseparować drugi (jeżeli nie jest używany czytnik kard SD, należy go ręcznie odseparować), jak pokazuje przykładowy kod.
Konstrukcja nakładki WiFi jest starannie przemyślana i oprócz nawiązywania połączeń bezprzewodowych oferuje szereg przydatnych funkcjonalności. Jej budowa jest całkowicie otwarta. Nakładka jest wyposażona w port Micro-USB na potrzeby przyszłych aktualizacji wbudowanego oprogramowania. Zawiera również serię diod LED dostarczających przydatnych informacji, takich jak status połączenia (zielona dioda LINK), błędy transmisji (czerwona dioda ERROR) i wysyłanie lub odbieranie danych (niebieska dioda DATA).
JAK UŻYWAĆ NAKŁADKI WIFI ZE STARSZYMI PŁYTAMI ARDUINO?
Nakładka WiFi wykorzystuje pin IOREF, dostępny w nowszych wersjach płyty Arduino, do wykrywania napięcia odniesienia dla pinów wejścia/wyjścia, do których jest podłączona. Oznacza to, że w przypadku zastosowania płyty Arduino Uno lub Mega2560
w wersji wcześniejszej niż REV3 trzeba koniecznie zewrzeć piny nakładki IOREF oraz 3.3V (pokazane na rysunku 8.4).
Rysunek 8.4. Układ pinów nakładki WiFi
Biblioteka WiFi i jej funkcje - Kurs Arduino
Biblioteka WiFi realizuje niskopoziomową komunikację bezprzewodową i obsługuje wiele poleceń i funkcjonalności oferowanych przez nakładkę. W tym miejscu warto zapoznać się z tabelą 8.5, zawierającą przegląd najważniejszych funkcji z biblioteki WiFi.
Po przejrzeniu tabeli 8.5 możesz przejść do opisu przykładowego projektu, w którym przez sieć bezprzewodową będą przesyłane dane z czujnika gestów.
Funkcja | Opis |
WiFi.begin() | Inicjuje bibliotekę WiFi i rozpoczyna komunikację z urządzeniem. |
WiFi.begin(char[] ssid) WiFi.begin(char[] ssid, char[] haslo) WiFi.begin(char[] ssid, int iindeksKlucza, char[] klucz) |
Umożliwia podłączenie do dowolnej otwartej sieci, jak również do sieci zabezpieczonej z szyfrowaniem WPA po podaniu identyfikatora SSID i hasła oraz sieci z szyfrowaniem WEP po podaniu indeksu i klucza (w szyfrowaniu WEP mogą być zastosowane cztery klucze, dlatego trzeba podać jego indeks). Funkcja zwraca status połączenia z siecią WiFi. |
WiFi.disconnect() | Odłącza się od bieżącej sieci. |
WiFi.SSID() | Odczytuje identyfikator SSID bieżącej sieci i zwraca go jako ciąg znaków typu String. |
WiFi.BSSID(bssid) | Odczytuje adres MAC routera, z którym jest nawiązane połączenie, i umieszcza go w 6-bajtowej tabeli przekazanej jako argument (na przykład byte bssid[6]). |
WiFi.RSSI() | Zwraca siłę sygnału połączenia jako liczbę typu Long. |
WiFi.encryptionType() WiFi.encryptionType (wifiAccessPoint) |
Zwraca rodzaj szyfrowania bieżącego (lub wskazanego) punktu dostępowego. Zwracana wartość jest typu byte. W przypadku szyfrowania TKIP (WPA) = 2, WEP = 5, CCMP (WPA) = 4, NONE = 7, AUTO = 8. |
WiFi.scanNetworks() | Zwraca wartość typu byte zawierającą liczbę wykrytych sieci bezprzewodowych. |
WiFi.getSocket() | Zwraca pierwsze dostępne gniazdo połączenia. |
WiFi.macAddress() | Zwraca 6-bajtową tabelę zawierającą adres MAC nakładki WiFi. |
WiFi.localIP() | Zwraca adres IP nakładki (jako obiekt typu IPAddress). |
WiFi.subnetMask() | Zwraca maskę podsieci nakładki (jako obiekt typu IPAddress). |
WiFi.gatewayIP() | Zwraca adres IP bramy (jako obiekt typu IPAddress). |
WiFiServer(int port) | Tworzy serwer nasłuchujący na zadanym porcie. |
WiFiServer.begin() | Uruchamia serwer oczekujący na komunikaty. |
WiFiServer.available() | Zwraca obiekt klienta, jeżeli są już odebrane od niego dane. |
WiFiServer.write(data) | Wysyła dane (typu byte lub char) do wszystkich dołączonych klientów. |
WiFiServer.print() | Wysyła dane do wszystkich klientów. Liczby są wysyłane jako ciągi znaków ASCII, na przykład liczba 123 jest wysyłana jako ciąg trzech znaków: ‘1’, ‘2’ i ‘3’. |
WiFiServer.println() | Działa podobnie jak WiFiServer.print(), ale dodatkowo wysyła znak nowego wiersza na końcu każdego komunikatu. |
WiFiClient() | Tworzy obiekt klienta, który może łączyć się z określonym adresem IP i portem określonym w funkcji connect(). |
WiFiClient.connected() | Zwraca informację, czy klient jest połączony z serwerem. Jeżeli połączenie jest zamknięte, a jakieś dane wciąż nie są odczytane, funkcja zwróci wartość true. |
WiFiClient.connect(ip, port) WiFiClient.connect(URL, port) |
Nawiązuje połączenie z określonym adresem IP i portem. Adres URL jest zamieniany na adres IP. |
WiFiClient.write(data) | Wysyła dane (typu byte lub char) do serwera. |
WiFiClient.print() | Wysyła dane do klienta. Liczby są wysyłane jako ciągi znaków ASCII, na przykład liczba 123 jest wysyłana jako ciąg trzech znaków: ‘1’, ‘2’ i ‘3’. |
WiFiClient.println() | Działa podobnie jak WiFiClient.print(), ale dodatkowo wysyła znak nowego wiersza na końcu każdego komunikatu. |
WiFiClient.available() | Zwraca liczbę bajtów gotowych do odczytania (liczbę bajtów wysłanych przez serwer). |
WiFiClient.read() | Odczytuje następny bajt odebrany z serwera. |
WiFiClient.flush() | Usuwa wszystkie bajty wysłane do klienta, ale jeszcze przez niego nieodczytane. |
WiFiClient.stop() | Zamyka połączenie z serwerem. |
Ruchy ciała i bezprzewodowe przyspieszeniomierze - Arduino
W tym przykładzie zastosujesz Arduino z funkcją WiFi do bezprzewodowego przesyłania danych z przyspieszeniomierza. Przyspieszeniomierze to czujniki znakomicie nadające się do realizacji wszelkiego rodzaju interakcji za pomocą ruchów ciała. Można
dzięki nim testować nowe scenariusze gier (jak w popularnych konsolach Nintendo Wii) lub po umieszczeniu ich na ciele tancerza wykorzystywać jego ruchy do sterowania efektami wizualnymi i dźwiękowymi. Przyspieszeniomierzy można również używać do wspomagania osób niepełnosprawnych fizycznie. Jak widzisz, jest mnóstwo praktycznych zastosowań przyspieszeniomierzy i na pewno przychodzą Ci do głowy kolejne.
W tym przykładzie będą Ci potrzebne:
- płyta Arduino,
- nakładka Arduino WiFi,
- przynajmniej jeden przyspieszeniomierz.
W przykładzie użyjesz języka Processing do utworzenia serwera, za pomocą którego będziesz przesyłać i analizować dane z bezprzewodowych przyspieszeniomierzy.
Łączenie komponentów - Kurs Arduino
Podłączenie nakładki WiFi jest bardzo proste i polega na założeniu jej bezpośrednio na płytę Arduino od jej wierzchniej strony. Sposób podłączenia przyspieszeniomierza jest różny i zależy od zastosowanego modelu.
Jeżeli korzystasz z trójosiowego przyspieszeniomierza ADXL335 posiadającego niezależne wyjścia analogowe dla każdej osi (x, y, z), połącz go zgodnie z rysunkiem 8.5. Jeżeli posiadasz inny model, połączenia mogą być podobne albo zamiast wejściowych
pinów analogowych mogą być zastosowane piny PWM. W przypadku zastosowania innego rodzaju przyspieszeniomierza zajrzyj do jego danych technicznych lub dokumentacji, jak go poprawnie podłączyć. Po podłączeniu nakładki WiFi i przyspieszeniomierza możesz zacząć tańczyć rockand- rolla.
Rysunek 8.5. Schemat podłączenia przyspieszeniomierza analogowego do Arduino
Szkic do komunikacji Bluetooth - Arduino
Do bezprzewodowego przesyłania z Arduino danych z przyspieszeniomierza do serwera działającego na Twoim komputerze użyjesz biblioteki WiFi. Zaraz, serwer na Twoim komputerze? Jak to zrobić?
Zastosujesz środowisko programistyczne o nazwie Processing. Jeżeli nie masz go zainstalowanego na swoim komputerze, otwórz stronę www.processing.org i pobierz najnowszą wersję oprogramowania. Jeżeli nie korzystałeś wcześniej z tego środowiska,
nie przejmuj się. Kod z listingu 8.4 wygląda znajomo i jest podobny do tego, który pisałeś już wcześniej.
Ale najpierw zajmijmy się stroną Arduino i poniższym kodem (listing 8.3).
Listing 8.3. Kod klienta dla Arduino obsługującego przyspieszeniomierz
char ssid[] = "nazwa_sieci"; // Ustawienie nazwy sieci
char pass[] = "klucz_sieci"; // Ustawienie klucza sieci
IPAddress server_address(192,168,0,1); // Ustawienie adresu serwera
int server_port = 10000; // Ustawienie portu serwera
int status = WL_IDLE_STATUS;
WiFiClient client; // Obiekt klienta WiFi
void setup() {
Serial.begin(9600); // Zestawienie połączenia szeregowego
connectToNetwork(); // Próba połączenia z siecią
}
void connectToNetwork(){
while ( status != WL_CONNECTED) {
Serial.print("Proba polaczenia z SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Połączenie z siecią
delay(10000); // Oczekiwanie na połączenie z siecią
}
printWifiStatus();
}
void loop() {
if(status == WL_CONNECTED){ // Sprawdzenie, czy jest połączenie z siecią
if(!client.connected())
{
client.connect(server_address, server_port); // Połączenie z serwerem
delay(1000);
}
else
{
Serial.print("Polaczony, przesylanie danych do "); // Odczyt i wysłanie bieżących danych z przyspieszeniomierza
Serial.println(server_address);
client.print("x: ");
client.print(analogRead(0));
client.print(" y: ");
client.print(analogRead(1));
client.print(" z: ");
client.println(analogRead(2));
}
delay(20); // Zwłoka 20 ms przed następną próbą połączenia
}
else{
Serial.println("Siec WiFi niedostepna");
connectToNetwork();
}
}
void printWifiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("Adres IP: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("Sila sygnalu (RSSI): ");
Serial.print(rssi);
Serial.println(" dBm");
}
Po zaimportowaniu potrzebnych bibliotek i określeniu kilku szczegółów dotyczących konfiguracji sieci i serwera tworzony jest obiekt WiFiClient . Następnie w funkcji setup inicjowana jest biblioteka obsługująca transmisję szeregową na potrzeby diagnostyki
, po czym podejmowana jest próba nawiązania połączenia sieciowego za pomocą utworzonej funkcji connectToNetwork . Później kod próbuje wybrać sieci WiFi za pomocą funkcji WiFi.begin i przez 10 sekund oczekuje na połączenie . Potem następuje wejście do głównej pętli. Jeżeli udało się połączyć z siecią , ale nie ma jeszcze połączenia z serwerem , podejmowana jest próba połączenia się z nim. Jeżeli połączenie z serwerem już jest nawiązane, z przyspieszeniomierza odczytywane są bieżące dane i wysyłane do serwera .
W listingu 8.4 przejdziemy do środowiska Processing i utworzymy serwer, który będzie przyjmował połączenia przychodzące od klientów (Arduino) i wyświetlał na ekranie odbierane komunikaty.
Listing 8.4. Szkic Processing odbierający od klienta Arduino dane z przyspieszeniomierza
int direction = 1; // Ustawienie kierunku tekstu
boolean serverRunning = false; // Utworzenie ciągu dla danych z przyspieszeniomierza
String currentData = "";
Server myServer; // Utworzenie obiektu serwera
void setup()
{
size(400, 400); // Ustawienie wielkości okna
textFont(createFont("SansSerif", 16));
myServer = new Server(this, 10000); // Inicjalizacja serwera
serverRunning = true;
printData();
}
void printData() {
background(0);
text("Dane z bezprzewodowego przyspieszeniomierza: ", 15, 25);
text(currentData, 15, 60);
}
void draw()
{
Client thisClient = myServer.available(); // Sprawdzenie komunikatów od klienta
if (thisClient != null) {
if (thisClient.available() > 0) {
currentData = "komunikat od: " + thisClient.ip() + " : " + // Rozpakowanie i wyświetlenie danych
thisClient.readString();
printData();
}
}
}
Po skonfigurowaniu w funkcji setup okna i czcionki do wyświetlania danych tworzona jest instancja serwera oczekującego na połączenia przychodzące od klientów . Funkcja draw, podobna do funkcji loop Arduino, bez przerwy sprawdza, czy nadeszły połączenia od klientów . Jeżeli tak, wyodrębnia komunikat (funkcja thisClient.readString()), dołącza do niego dodatkowe informacje, na przykład adres IP klienta, i wyświetla w oknie .
Załadowanie i test szkicu
To wszystko, co trzeba zrobić w tym projekcie. Kliknij przycisk Run w środowisku Processing. Na ekranie pojawi się okno i uruchomi serwer. Załaduj szkic do Arduino. Jeżeli Twoja sieć jest skonfigurowana prawidłowo (Arduino i komputer znajdują się
w tej samej sieci WiFi i w szkicu podałeś jako adres serwera adres IP swojego komputera), w oknie programu Processing powinny zacząć pojawiać się wartości odbierane z przyspieszeniomierza.
Jeżeli masz ochotę na więcej, dobrym początkiem może być wyodrębnienie z odebranego ciągu znaków poszczególnych danych z przyspieszeniomierza i przedstawienie ich w trójwymiarowym (x, y, z) widoku na ekranie.
Arduino w akcji Autorzy: Martin Evans, Joshua Noble, Jordan Hochenbaum Wydawnictwo: Helion