Conrad 10215 Operation Manual [pl]

Page 1
ZANIM ROZPOCZNIEMY
Przy pierwszym podłączeniu karty IoT-WiFi (zwanej dalej także NanoESP) może się zdarzyć, że komputer nie odnajdzie automatycznie sterownika niezbędnego do konwertera portu USB na port szeregowy. W takim przypadku należy pobrać sterownik ze strony www.iot.fkainka.de/driver i
zainstalować ręcznie. W oprogramowaniu Arduino można wtedy wybrać port jako karetę Arduino Nano (procesor: Atmega328). Następnie kontroler powinien być w pełni gotowy do pracy.
Aby móc pracować z szeregowym monitorem, także trzeba dokonać ustawień. Stosuje się tutaj prędkość transmisji sygnału na poziomie 19200 bodów. Aby móc wysyłać polecenia należy ponadto wybrać opcję CR i NL obok menu prędkości transmisji sygnału.
Poprawne ustawienia w otoczeniu Arduino
Pracowałem z wersjami Arduino-IDE 1.6.5 i 1.6.6. Starsze wersje mogą sprawiać problemy. Aktualna wersja Arduino-IDE znajduje się na stronie internetowej
www.arduino.cc.
W przypadku jakichkolwiek problemów z kartą lub pakietem do nauki można zawsze znaleźć pomoc na stronie www.iot.fkainka.de. Ponadto znajduje się
Page 2
tam forum, nowe projekty użytkowników a także opisane tutaj programy w ich najnowszych wersjach.
W pakiecie do nauki znajduje się także karta z gniazdem, do której można podłączyć NanoESP - jak pokazano na ilustracji. Dzięki temu uzyskuje się dużo miejsca na eksperymenty a moduł WLAN wystaje z tyłu spoza karty. Kabel z wtykiem micro-USB można wtedy podłączyć tak, jak widać na ilustracji w kolejnym rozdziale - wtedy kabel prawie wcale nie przeszkadza. Szczegółowe ilustracje połączeń znajdują się w poszczególnych rozdziałach.
Karta IoT-WiFi (NanoESP)
Głównym elementem niniejszego zestawu jest karta IoT-WiFi (NanoESP). Jak widać na płytce, karta składa się z dwóch komponentów. Z lewej strony znajduje się system mikrokontrolera kompatybilny z Arduino, porównywalny z Arduino Nano. Prawą stronę zajmuje moduł WLAN o oznaczeniu ESP8266.
Oba komponenty komunikują się ze sobą poprzez generowany programowo port szeregowy.
NanoESP na karcie z gniazdem
Układ pinów na karcie
Na karcie znajduje się wiele różnych elementów, jak np. piny, z których niektóre mają szczególną funkcję, a także diody LED, których funkcja nie zawsze jest widoczna na pierwszy rzut oka. W celu zachowania orientacji na poniższej ilustracji podano najważniejsze funkcje i nazwy poszczególnych elementów.
Najważniejsze piny i oznaczenia na karcie
Moduł WLAN jest sterowany tzw. poleceniami AT. W tym celu część Arduino karty jest połączona pinami 11 i 12 z modułem WLAN. Niewielki układ przetwarza
Page 3
poziom 5 V na kompatybilny poziom 3,3 V. We własnych projektach nie należy więc używać pinów 11 i 12.
Dalsze istotne właściwości sprzętowe karty zostały zestawione w poniższej tabeli.
Dane techniczne
Mikrokontroler: ATmega328 Pamięć flash: 32 kB (z tego 0,5 kB na bootloader) SRAM: 2 kB EEPROM: 1 kB Częstotliwość taktowania: 16 MHz Piny I/O: 20 (z tego 2 do komunikacji z modułem WLAN)
U
w tym PWM: 6
U
w tym wejścia analogowe: 6
Chip USB-to-Serial: CH340G Napięcie robocze: 5 V Zalecane napięcie wejściowe: 7 – 12 V Maksymalny prąd na pin I/O: 40 mA Obciążalność wyjścia 3,3 V: 50 mA
Moduł WLAN: ESP8266 SPI-Flash 4 Mbit Napięcie robocze: 3,3 V Standardy WLAN: 802.11 b/g/n Tryby WLAN: Wi-Fi Direct (P2P), Soft-AP Firmware: AT-Firmware wersja 0.22 Inne: Zintegrowany stos TCP/IP +19,5 dBm mocy wyjściowej w trybie 802.11b Zintegrowany Low-Power-32-bit-CPU Komunikacja przez UART
ELEMENTY ZESTAWU DO NAUKI
Poniżej znajduje się zestawienie elementów zestawu do nauki.
Page 4
1 Karta IoT-WiFi (NanoESP) 1 płytka ze złączami wtykowymi 1 m drut sterujący 2 przyciski 1 klips 9-V 1 dioda LED (czerwona) 1 dioda LED RGB (4 piny podłączeniowe) 1 opornik 10 kiloomów (brązowy-czarny-pomarańczowy) 1 opornik 1 kiloom (brązowy-czarny-czerwony) 1 fototranzystor (2 piny podłączeniowe) 1 NTC 10 kiloomów 1 głośnik piezoelektryczny 1 potencjometr 10 kiloomów z czerwonym pokrętłem
POZNAWANIE MODUŁU
Pierwszy rozdział opisuje podstawowe funkcje modułu WLAN. Moduł jest sterowany tzw. poleceniami AT. Wszystkie zastosowane tutaj przykładowe programy a także pomoc i dalsze informacje znajdziesz także na stronie
www.iot.fkainka.de
Najprościej jest pobrać cały folder skompresowany zip i skopiować cały wyodrębniony folder do własnego folderu szkicu. Wtedy z poziomu interfejsu Arduino można wygodnie po kolei otwierać wszystkie programy.
1.1
|
Podstawowe polecenia AT
Aby uzyskać pierwsze wrażenie o stosowaniu poleceń AT, najlepiej je po prostu wypróbować. W związku z tym w niniejszym rozdziale opisano kilka z podstawowych poleceń modułu.
Otwórz program P01_SoftwareSerial w IDE Arduino. Jest to bardzo prosty program, którego jedynym zadaniem jest przekazywanie do kontrolera ESP
wszystkich danych odebranych przez sprzętowy interfejs mikrokontrolera. Działa to także w przeciwnym kierunku. Jak widać w tekście źródłowym, dwa podłączenia interfejsu programowego to piny 11 i 12. Nie należy ich wykorzystywać we własnych projektach jako pinów GPIO. Ponadto potrzebna jest SoftwareSerial-
Library, która jest w większości wersji Arduion jest już preinstalowana – jeśli nie,
należy pobrać bibliotekę przez managera. Po załadowaniu programu można uruchomić szeregowy monitor interfejsu
Page 5
Arduino. Przedtem jednak należy dokonać dwóch ważnych ustawień na szeregowym monitorze: w dolnym prawym rogu należy ustawić prędkość transmisji sygnału na 19200 a w kratce obok ustawić CR i NL.
Teraz pojawia się już pierwszy komunikat, jest to AT a kilka wierszy niżej OK. Polecenie AT zostało wysłane przez mikrokontroler do modułu ESP a moduł wysłał odpowiedź OK. Oznacza to, że moduł WLAN działa i jest gotowy do pracy.
Ustawienia terminala: CR i NL oraz prędkość transmisji sygnału 19200
1.1.1 | Podstawowe polecenia
Kilka podstawowych poleceń modułu można przetestować wpisując polecenie i przesyłając je do modułu naciśnięciem
[Enter]
. Wielkie i małe litery wpisywanego
polecenia mają znaczenie. Pierwsze własne polecenie można przekazać wpisując
AT
w szeregowym monitorze i naciskając
[Enter]
. Załadowany program przekazuje
polecenie do modułu ESP, który ponownie odpowiada wysyłając AT a następnie
OK . Kolejne polecenie, które można przetestować, brzmi:
AT+GMR
Tym poleceniem wyświetla się aktualne firmware i numer wersji. Poleceniem
AT+RST
można zresetować moduł. Wtedy najpierw na terminalu pojawi się najpierw kilka nieczytelnych znaków a na końcu komunikat ready jako znak, że moduł jest już gotowy. Kolejne polecenie brzmi:
Page 6
ATE0
Tym poleceniem można dezaktywować tzw. echo modułu. Oznacza to, że wysłane polecenie nie zostanie odesłane z powrotem, lecz zostanie wysłana sama odpowiedź. Jeśli zostanie wysłane np. AT, w odpowiedni nie przyjdzie najpierw AT a później OK, lecz tylko samo OK . Jednakże do pierwszych prób zaleca się użycie polecenia
ATE1
do ponownej aktywacji echa.
Pierwsze próby z poleceniami AT
1.1.2 | Polecenia WLAN
Poniższymi poleceniami WLAN można zmieniać właściwości WLAN modułu. Przy niektórych poleceniach można nie tylko ustawić stan, ale także sprawdzić stan aktualny. Dzieje się tak, jeśli bezpośrednio po poleceniu wpisany zostanie znak zapytania, np.
AT+CWMODE?
Page 7
Jako wartość zwrotna przychodzi zazwyczaj
+CWMODE=2
a za nim OK. Po wpisaniu
AT+CWMODE=?
moduł odpowiada podając możliwe parametry polecenia, w tym przypadku 1-3. CWMODE to polecenie, którym można ustalić tryb WLAN.
Są trzy tryby pracy, które są objaśnione poniżej.
1
AT+CWMODE=2 – moduł jako Access Point (tryb AP)
Fabrycznie moduł pracuje jako Access Point (punkt dostępu). Oznacza to, że za pomocą urządzenia obsługującego WLAN, jak np. smartfon lub komputer można nawiązać bezpośrednie połączenie z modułem. W tym celu należy po prostu wyszukać otwartą sieć WLAN o nazwie NanoESP i połączyć się z nią. W ustawieniu fabrycznym nie jest ustawione żadne hasło i nawiązanie połączenia powinno się odbyć bez problemów. Po połączeniu się z modułem nie uzyskuje się połączenia z internetem, jeśli moduł nie pracuje jako router z własnym połączeniem z siecią telefoniczną. Ten moduł WLAN jest jednakże bardzo przydatny, gdy potrzebna jest bezpieczna, zamknięta sieć. Jeśli chodzi o bezpieczeństwo: Jest możliwość chronienia sieci hasłem. Służy do tego polecenie:
AT+CWSAP
Należy tu jeszcze podać parametry w następującej kolejności i oddzielone przecinkami:
U
nazwa sieci w cudzysłowie,
U
hasło w cudzysłowie,
U
Channel ID (dowolna wartość między 1 a 13),
U
tryb kodowania (wartość 0-4).
Jedno z możliwych ustawień to:
AT+CWSAP="MyNanoESP","MyPassword",5,3
Po krótkim czasie pojawia się OK jako potwierdzenie. Jeśli pojawi się ERROR , należy jeszcze raz sprawdzić wpisane wartości, przede wszystkim cudzysłowy. Jeśli nadal pojawia się ERROR , należy sprawdzić, czy CWMODE to rzeczywiście
2. Jeśli wszystko zadziała poprawnie, można połączyć się z urządzenia
obsługującego WLAN z kartą. Wszystkie urządzenia połączone z modułem można wyświetlić wraz z ich adresami IP i MAC poleceniem
AT+CWLIF
Page 8
.
Moduł w trybie stacji. Adres IP połączonego komputera jest zaznaczony.
2
AT+CWMODE=1 – moduł w trybie stacji
Poleceniem
AT+CWMODE=1
ustawia się moduł w trybie stacji. Ten tryb umożliwia nawiązanie połączenia z routerem WLAN. Dzięki temu moduł jest połączony także z internetem i zyskuje wiele więcej możliwości.
Wcześniej jednak można poleceniem
AT+CWLAP
wyświetlić wszystkie sieci znajdujące się w zasięgu sprawdzając w ten sposób, czy Twoja sieć jest w zasięgu modułu. Do nawiązania połączenia z routerem potrzebne jest polecenie
AT+CWJAP
Polecenie to, podobnie jak CWSAP, zawiera ważne parametry, mianowicie nazwę
Page 9
sieci WLAN (zwaną także SSID) oraz hasło, obie wartości ponownie w cudzysłowie i oddzielone przecinkami. Nawiązywanie połączenia z drugim modułem, na którym ustawione są dane opisane w poprzednim rozdziale dane, wyglądałoby więc następująco:
AT+CWJAP="MyNanoESP","MyPassword"
Nawiązywanie połączenia może trwać kilka sekund i powinno być potwierdzone przez zwrotne OK. Można także wywołać nadany przez router adres IP modułu. Służy do tego polecenie
AT+CIFSR
. Będzie to istotne później przy nawiązywaniu połączenia z serwerem TCP modułu. Poleceniem
AT+CWQAP
można ponownie przerwać połączenie z routerem.
Karta nawiązuje połączenie z drugim NanoESP.
Page 10
3
AT+CWMODE=3 – tryb dual
Trzeci dostępny tryb ustawień WLAN to tryb podwójny. Jak już sama nazwa wskazuje, tryb ten umożliwia pracę modułu zarówno w trybie stacji jak i w trybie AP. Oznacza to, że urządzenia mogą zarówno nawiązywać bezpośrednie połączenie WLAN z modułem oraz przez router jako stację pośrednią. Jest to tryb
bardzo praktyczny, gdy np. planowane jest utworzenie wewnętrznej sieci z wieloma modułami i jeden z modułów ma pełnić rolę serwera dostarczającego dane do sieci. Więcej na ten temat w dalszej części.
1.2 | Konfiguracja automatyczna
Podstawowe polecenia zostały już przetestowane ręcznie. Ten rozdział jest poświęcony kwestii, w jaki sposób polecenia te mogą być obsługiwane bezpośrednio przez kontroler. Ponadto poznamy tu kolejne polecenie, którym można przetestować, czy dostępny jest określony komputer w sieci lub serwer w internecie. W tym przykładzie ping wysyłany jest do serwera Google. W przykładowym programie P02_GooglePing czynności, które w pierwszym przykładzie były wpisywane ręcznie, są teraz w znacznym stopniu zautomatyzowane. Kontroler wysyła kolejno po sobie polecenia do modułu ESP i w ten sposób m.in. nawiązuje połączenie z WLAN. Czasy timeout o róznej długości dają modułowi wystarczająco czasu na odpowiedź.
Ale zanim program będzie mógł prawidłowo działać, trzeba wpisać dane WLAN za #define SSID i #define PASSWORD zaraz na początku kodu źródłowego programu. Moduł potrzebuje bowiem dostępu do internetu, aby mógł wykonać swoje ostatnie polecenie. Poleceniem
AT+PING
można wysłać ping do innych urządzeń w sieci. Wysyłanie sygnału ping oznacza zapytanie, czy dany komputer zasadniczo jest osiągalny. Tutaj za pomocą AT+PING="www.google.de" ping jest wysyłany do serwera Google. Gdy nadejdzie odpowiedź, na monitorze szeregowym pojawia się komunikat o powodzeniu w zapala się dioda LEd oznaczona jako D3, która jest podłączona do pina D13 karty. Pierwsza komunikacja z internetem zakończyła się powodzeniem.
Program
W kolejnych częściach zostaną krok po kroku przeanalizowane funkcje programu. Najpierw omówiona zostanie komunikacja z modułem.
1
Komunikacja szeregowa
Wszystko działa za pośrednictwem szeregowego portu wirtualnego udostępnianego przez SoftwareSerial-Library . Podczas inicjalizacji muszą ponadto zostać podane używane piny, w tym przypadku 11 i 12.
Page 11
001
#include <SoftwareSerial.h>
002
SoftwareSerial esp8266(11, 12);
Tak samo, jak przy zwykłym porcie szeregowym, można poleceniami esp8266.print lub esp8266.println przesyłać bajty lub całe wiersze. Szczególnie praktyczne są także polecenia esp8266.find i esp8266.findUntil, którymi przychodzący strumień można sprawdzić pod kątem określonych łańcuchów znaków. W ten sposób bardzo proste jest wyłapanie pasującej odpowiedzi modułu. Jeśli jednak oczekiwany ciąg znaków się nie pojawia, oczekiwanie na dalszy bieg programu można nieco potrwać. Czas oczekiwania (timeout) jest definiowany przez esp8266.setTimeout . Przez findUntil() można jednakże zdefiniować drugi ciąg znaków, który pojawia się w funkcji wyszukiwania i daje false jako wartość zwrotną. To można wykorzystać w funkcji sendCom() :
001
//-------Controll ESP--------
002
003
boolean sendCom(String command, char respond[])
004
{
005
esp8266.println(command);
006
if (esp8266.findUntil(respond, "ERROR"))
007
{
008
return true;
009
}
010
else
011
{
012
debug("ESP SEND ERROR: " + command);
013
return false;
014
}
015
}
Po wywołaniu tej funkcji należy więc przekazać jej polecenie oraz oczekiwaną wartość zwrotną, np. AT oraz oczekiwana wartość zwrotnaOK. Funkcja println() przekazuje polecenie i czeka na odebranie oczekiwanej wartości zwrotnej lub komunikatu ERROR . Gdy oczekiwanie zostanie spełnione, funkcja odsyła wartośćtrue . Jeśli nie, moduł przez funkcję debug()-odsyła ESP SEND ERROR i
Page 12
wysłane polecenie, dzięki czemu można w łatwy sposób sprawdzić, które polecenie stwarza problemy.
Nie wszystkie polecenia AT mają jednoznaczne lub jednowierszowe wartości zwrotne. Gdy pojawia się np. zapytanie o adres IP, z reguły nie ma wcześniej znanej wartości. Dlatego jest druga funkcja sendCom(), która potrzebuje jedynie parametru command i odsyła cały odebrany strumień. Strumień nie może być jednak zbyt długi, ponieważ może dojść do przepełnienia buforu SoftwareSerial .
001
String sendCom(String command)
002
{
003
esp8266.println(command);
004
return esp8266.readString();
005
}
2
Poszukiwanie błędów
Podczas tworzenia programów dochodzi często do błędów i komplikacji. Aby mieć jakąkolwiek szansę powodzenia, są dwie funkcje debug, które są aktywowane i dezaktywowane jednym parametrem na samym początku programu.
#define DEBUG true
Pierwsza funkcja powoduje jedynie uproszczone wydawanie tekstu przez port szeregowy zdefiniowany jako standardowy. Jeśli stała DEBUG jest prawdziwa, wysyłana jest zawartość ciągu znaków Msg.
001
void debug(String Msg)
002
{
003
if (DEBUG)
004
{
005
Serial.println(Msg);
006
}
007
}
Drugą funkcję można także szybko wyjaśnić. Gdy wywołana zostanie funkcja serialDebug, program zapętla się i od tej chwili zachowuje się jak pierwszy testowany program SoftwareSerial. Oznacza to, że wszystkie dane wysłane przez szeregowy monitor do kontrolera, są dalej przekazywane do modułu i odwrotnie. Można więc w przypadku błędu wywołać tę funkcję i wysyłać ręczne polecenia,
Page 13
aby sprawdzić, gdie występuje błąd.
001
//---Debug Functions---
002
void serialDebug() {
003
while (true)
004
{
005
if (esp8266.available())
006
Serial.write(esp8266.read());
007
if (Serial.available())
008
esp8266.write(Serial.read());
009
}
010
}
3
Konfiguracja
Aby programy były ogólnie zbudowane bardziej przejrzyście, większość ustawień została przeniesiona do własnych funkcji, przede wszystkim do funkcji espConfig, w której ustawia się najważniejsze parametry dla danego programu.
001
//---Config ESP8266---
002
boolean espConfig()
003
{
004
boolean success = true;
005
esp8266.setTimeout(5000);
006
success &= sendCom("AT+RST", "ready");
007
esp8266.setTimeout(1000);
008
009
if (configStation(SSID, PASSWORD)) {
010
success &= true;
011
debug("WLAN Connected");
012
debug("My IP is:");
013
debug(sendCom("AT+CIFSR"));
014
}
Page 14
015
else
016
{
017
success &= false;
018
}
019
020
success &= sendCom("AT+CIPMODE=0", "OK");
021
success &= sendCom("AT+CIPMUX=0", "OK");
022
023
return success;
024
}
Na początku funkcji najpierw ustawiana jest zmienna success na true , ponieważ ta zmienna jest łączona z różnymi funkcjami ORAZ. Oznacza to, że nawet gdy tylko jedna z funkcji zwróci wartość false, wartość success natychmiast zmienia się na false i występuje niepowodzenie całej konfiguracji. Pierwsze polecenie AT, które w ten sposób jest sprawdzane pod kątem powodzenia, to polecenie Reset, który prawie zawsze jest wykonywany na początku programu w celu zapewnienia, że poprzednie próby nie zajmują już modułu. Może jednakże trwać do pięciu sekund, aż moduł odeśle komunikat ready. Dlatego na krótko przed funkcją sendCom() timeout jest wydłużany doesp8266.findUtil . Po resecie timeout jest ponownie ustawiany na standardową wartość jednej sekundy.
Następnie wywoływana jest samodzielnie zdefiniowana funkcja o nazwie configStation(), która jest omówiona w kolejnym rozdziale. Służy ona do połączenia modułu z siecią domową. W tym celu przekazywane są parametry SSID i PASSWORD , które zostały wpisane na początku programu. Jeśli próba nawiązania połączenia zakończyła się powodzeniem, najpierw komunikaty o powodzeniu a następnie aktualny adres IP modułu są przesyłane do monitora szeregowego. Na koniec tej funkcji ustawiane są jeszcze parametry, o których mowa będzie jeszcze później. Na koniec zwracana jest zmienna success, która ­miejmy nadzieję - zachowała wartość true.
001
boolean configStation(String vSSID, String vPASSWORT)
002
{
003
boolean success = true;
004
success &= (sendCom("AT+CWMODE=1", "OK"));
005
esp8266.setTimeout(20000);
Page 15
006
success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
007
esp8266.setTimeout(1000);
008
return success;
009
}
Funkcja configStation() została wywołana w funkcjiespConfig(). Tutaj dokonuje się ustawienia modułu WLAN w trybie stacji poleceniem CWMODE a następnie połączenia z siecią poleceniem CWJAP. Nawiązywanie połączenia może trwać bardzo długo, w związku z czym timeout jest tutaj na krótko wydłużany do 20 sekund. Jeśli jednak preferowany jest podwójny tryb WLAN, można tutaj dla CWMODE wpisać wartość 3.
001
boolean configAP()
002
{
003
boolean success = true;
004
005
success &= (sendCom("AT+CWMODE=2", "OK"));
006
success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK"));
007
008
return success;
009
}
Funkcja configAP() w tym przykładzie nie jest wywoływana, ale musi byc krótko omówiona. Można powiedzieć, że jest ona przeciwnością funkcjiconfigStation(), ponieważ tutaj moduł jest ustawiany jako Access Point. Długi timeout nie jest tutaj potrzebny, ponieważ moduł może przetworzyć polecenie CWSAPznacznie szybciej. W źniejszych próbach w funkcji espConfig()-zamiast configStation() będzie wywoływana funkcja configAP().
001
void setup()
002
{
003
// Open serial communications and wait for port to open:
Page 16
004
Serial.begin(19200);
005
// set the data rate for the SoftwareSerial port
006
esp8266.begin(19200);
007
008
if (!espConfig()) serialDebug();
009
else debug("Config OK");
010
011
if (sendCom("AT+PING=\"www.google.de\"", "OK"))
012
{
013
Serial.println("Ping OK");
014
digitalWrite(13, HIGH);
015
}
016
else
017
{
018
Serial.println("Ping Error");
019
}
020
}
021
022
void loop() // run over and over
023
{
024
//Start serial Debug Mode - Type Commandos over serial Monitor
025
serialDebug();
026
}
Omówione zostały najważniejsze funkcje, które znajdują się w prawie każdym programie. W znanych funkcjach Arduino setup() i loop() funkcje te są teraz stosowane. Najpierw jednak oba porty szeregowe zostają uruchomione z prędkością transmisji sygnału 19200 bodów. Dopiero wtedy otwierana jest funkcja espConfig(). W przypadku błędu uruchamiana jest natychmiast funkcja serialDebug(). Jeśli wszystko przebiegło bez problemu, wysyłany jest komunikat powodzenia. W późniejszych programach po udanej konfiguracji dodatkowo
Page 17
zapala się dioda LED na pinie 13, która na karcie oznaczona jest symbolem D3 . Dzięki temu pojawia się potwierdzenie także wtedy, gdy moduł nie jest podłączony do komputera z monitorem szeregowym. W tej próbie jednak dioda LED potrzebna jest do informacji zwrotnej o statusie sygnału ping. Zapytanie odbywa się także bezpośrednio w kolejnym wierszu po konfiguracji. Wysyłane jest polecenie AT+PING z adresem Google jako parametr. Zamiast tego adresu można wysłać zapytanie także na adres IP w sieci lokalnej. W przypadku powodzenia pojawia się komunikat i włącza się wspomniana dioda LED D3. W ostatnim kroku program przechodzi do funkcji loop, która z kolei wywołuje funkcję serialDebug(). Można więc po programie przetestować dalsze polecenia i przykładowo wysyłać sygnały ping na inne adresy.
1.3 | Rozpoznawanie sieci
W tym rozdziale będzie m.in. mowa po raz pierwszy o drobnych pracach przy sprzęcie. Celem projektu jest stworzenie swego rodzaju instalacji alarmowej, która będzie reagować, gdy w zasięgu znajdzie się określona sieć lub gdy zostanie włączona.
Potrzebne są tylko dwa podzespoły i kawałek drutu. Szczegóły budowy przedstawione są na odpowiednich ilustracjach.
Podłączenie głośnika piezoelektrycznego
Page 18
Tekst źródłowy tego projektu różni się od poprzedniej próby przede wszystkim w następujących funkcjach:
001
void findSSID()
002
{
003
esp8266.println("AT+CWLAP");
004
if (esp8266.findUntil(ToFindSSID,"OK")) alarm();
005
else debug("SSID not found!");
006
}
007
008
void alarm()
009
{
010
debug("alarm!");
011
012
digitalWrite(LED_ALARM, HIGH);
013
014
for (int i; i <=30; i++)
015
{
016
tone(PIEZO, 400, 500);
017
delay(500);
018
tone(PIEZO, 800, 500);
019
delay(500);
020
}
021
022
digitalWrite(LED_ALARM, LOW);
023
}
Funkcja findSSID() jest wywoływana co ok. 30 sekund w trybie loop i poszukuje wszelkich sieci w otoczeniu. Gdy odnaleziona zostanie szukana sieć, uruchamiana jest funkcja alarm(), włącza się dioda LED D3 a element piezoelektryczny wydaje sygnał. W tym przykładzie poszukiwana jest sieć o SSID NanoESP , czyli w
Page 19
zasadzie inne sieci NanoESP w zasięgu. Ale na początku programu w #define ToFindSSID można wpisać inne SSID. Można w ten sposób np. sprawdzić, jak daleko sięga dana sieć WLAN.
UDP I IP
Ten rozdział dotyczy podstawowej wymiany danych między dwoma systemami poprzez sieć WLAN. Zajmiemy się tutaj takimi tematami jak porty IP oraz protokół UDP. W pierwszym rzędzie należy więc wyjaśnić te podstawowe pojęcia.
Co to jest adres IP?
Adres IP działa tak, jak adres pocztowy. Na jego podstawie można jednoznacznie zidentyfikować i zaadresować komputer w sieci. Przykładowy adres IP utworzony na podstawie stosowanego jeszcze standardu IPv4 wygląda następująco:
192.168.4.1
są to cztery liczby, a mówiąc dokładniej cztery bajty. Oznacza to, że wartość jednej liczby może wynieść maksymalnie 255. Generalnie wyróżnia się lokalne adresy IP, czyli w skrócie IP, które są np. nadawane komputerom i urządzeniom w sieci domowej oraz globalne IP.
Lokalne IP są z reguły przydzielane przez router. Zazwyczaj rozpoczynają się od
192.168. Następująca potem liczba jest różna w różnych routerach. Gdy NanoESP działa jako Access Point i do jego sieci zgłaszają się komputery, każdy z nich otrzymuje adres rozpoczynający się od 192.168.4. W ten sposób tworzy się podsieć. Routery Fritz!Box przydzielają z reguły lokalne adresy IP wg schematu
192.168.178.X. Własny IP można sprawdzić w Windows wpisując w wierszu polecenia (Start -> programy -> akcesoria -> wiersz polecenia) polecenie
ipconfig. Pojawia się dłuższa lista zawierająca także punkt adres IPv4 z Twoim
lokalnym adresem IP w sieci. Globalne IP są z reguły nadawane przez dostawcę internetu. Jest to np. adres,
pod którym Twój router dostępny jest w sieci globalnej. Router tworzy sieć lokalną i przesyła dane do klientów. Jedną z możliwości sprawdzenia swojego globalnego adresu IP jest wejście na stronę http://www.meine-aktuelle-ip.de/. Na tej
stronie podawane są dodatkowo inne dane, do których ma wgląd serwer sieci web. Wbrew temu, co wielu sądzi, nie jesteśmy w internecie anonimowi.
Co to jest port?
Kontynuując porównanie do adresu pocztowego port można określić jako drzwi do mieszkania w domu wielorodzinnym. Komputer posiadający jednoznaczny IP może udostępniaćżne usługi przez różne porty. Poprzez IP można dotrzeć do serwera, ale poprzez port trzeba wybrać jeszcze odpowiednią usługę. Może to być np. port 20 do transmisji danych FTP lub port 23 do połączenia Telnet. Z reguły
Page 20
można dowolnie wybierać port, jednakże występują porty standardowe ułatwiające pracę z aplikacjami sieciowymi. Lista portów standardowych znajduje się na stronie
https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports
Co to jest UDP?
UDP to skrót od User Datagram Protocol. Jest to minimalny bezpołączeniowy protokół internetowy. Oznacza to, że jest on w zasadzie bardziej minimalistyczny i prostszy niż inne protokoły internetowe, jak np. TCP, którym zajmiemy sięźniej. Porównanie nie jest teraz zbyt proste, ale można już teraz zapamiętać sobie kilka właściwości protokołu:
U
UDP obsługuję funkcję broadcast.
U
Nie odbywa się sprawdzanie danych pod kątem poprawności oraz
korekta błędów.
U
Nie ma więc żadnej gwarancji, że dane zostały przekazane
pomyślnie.
U
Ponadto nie ma gwarancji, że dane nie zostały po drodze
zafałszowane lub przechwycone przez osoby trzecie.
U
Nie ma konieczności nawiązywania połączenia, lecz możliwa jest
szybka wymiana danych.
U
Prawie nie występują wahania opóźnienia transmisji.
U
Format ten nadaje się np. do VoIP (Voice over IP – czyli
telefonowanie przez internet).
Są to najważniejsze podstawy dotyczące pojęć używanych w poniższych projektach. Można głębiej zająć się tym tematem i w odpowiednim miejscu zostaną przedstawione jeszcze dalsze informacje. Teraz jednak przejdziemy do części praktycznej.
2.1 | Wymiana danych między kartą a PC przez UDP
W pierwszym projekcie dotyczącym UDP będą wymieniane dane między kartą i PC za pośrednictwem WLAN. Warunkiem jest posiadanie przez komputer adaptera WLAN. Program na komputerze dba o prawidłowe odbieranie wiadomości. W tej próbie nie jest konieczne dodatkowe rozbudowywanie sprzętu.
Program
Po załadowaniu programu P04_UDPBasics.ino na kontroler będzie on skonfigurowany jako Access Point i będzie możliwe odnalezienie otwartej sieci o nazwie NanoESP. Jednakże przed połą czeniem się z siecią należy wcześniej z internetu pobrać odpowiedni program na PC. Przy moich próbach użyłem programu Packet Sender od Dan Nagle, który można pobrać pod następującym linkiem:
https://packetsender.com/
Page 21
Po pobraniu i zainstalowaniu programu można połączyć komputer z otwartą siecią NanoESP. Należy zwrócić uwagę, aby firewall rozpoznał tę sieć jako sieć domową i nie blokował żadnych danych. Komputer powinien otrzymać IP 192.168.4.2. Można to sprawdzić wysyłając polecenie
AT+CWLIF
przez szeregowy monitor do modułu. To polecenie powoduje pokazanie wszystkich komputerów połączonych z Access Point wraz z adresami IP i MAC.
Teraz należy uruchomić Packet Sender, Settings -> Network den UDP Server Port ustawić na 90 i zaznaczyć pole wyboru Enable UDP Server . Z reguły na dole po lewej stronie powinno się wtedy pojawić UDP:90 . Jeśli nie, należy ponownie uruchomić program.
Prawidłowe ustawienia w programie Packet Sender
Program na komputerze służy teraz jako serwer UDP a kontroler jest ustawiony jako klient UDP. W protokole UDP rozróżnienie klient/serwer nie jest jednoznaczne, ale w tym przypadku oznacza to, że za pomocą kontrolera można wysyłać dane do komputera.
Page 22
Wiadomość została przekazana pomyślnie.
Aby wysłać dane, należy użyć polecenia:
AT+CIPSEND=7
Cyfra 7 oznacza tutaj ilość wysyłanych znaków. Pojawia się znak > jako odpowiedź. Oznacza to, że teraz można przesłać wiadomość. Należy wpisać Hello i ponownie potwierdzić przez
[Enter]
. Jako odpowiedź moduł wysyła SEND OK mimo, że zostało wpisanych tylko pięć znaków. Wynika to z tego, że po wpisaniu wiadomości wysłane razem z nią zostały jeszcze Carriage Return i New Line czyli dwa znaki więcej, które trzeba uwzględnić przy długości wiadomości.
Po powrocie do Packet Sender można w Traffic Log zobaczyć nadejście wiadomości. W widoku ASCII widać nawet oba wysłane razem z wiadomością znaki, przedstawione jako \r i \n.
Page 23
Wiadomość została odebrana przez Packet Sender.
001
boolean configUDP()
002
{
003
boolean success = true;
004
005
success &= (sendCom("AT+CIPMODE=0", "OK"));
006
success &= (sendCom("AT+CIPMUX=0", "OK"));
007
success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.2\",90", "OK"); //UDP-Server
008
return success;
009
}
W programie Arduino dla drogi komunikacji decydująca jest przede wszystkim
Page 24
funkcja configUDP() . Tam wykonuje się ustawienia istotne dla transmisji. Najpierw w CIPMODE ustawia się tryb transparencji danych na0. Następnie przez CIPMUX=0 ustawia się, że dopuszczone jest tylko jedno jedyne połączenie. Decydującym poleceniem jest CIPSTART. Służy ono do nawiązania polecenia z IP 192.168.4.2, czyli Twoim komputerem, oraz PORTEM 90, który nasłuchuje program Packet Sender przez serwer UDP. Są to na razie wszystkie czynności niezbędne do nawiązania pierwszej komunikacji.
2.2 | Wysyłanie i odbieranie danych przez UDP
W poprzednim projekcie przetestowana została komunikacja UDP w jednym kierunku czyli od karty do komputera. W tym programie moduł zostanie tak ustawiony, że możliwa będzie komunikacja także w drugim kierunku, prawie tak, jak na czacie.
Program
W zasadzie program zawiera tylko niewielką zmianę, która jednak w dużym stopniu wpływa na komunikację z zastosowaniem protokołu UDP. Po załadowaniu programu ponownie zostaje utworzony Access Point, za pośrednictwem którego można połączyć się z komputerem. Także tutaj potrzebny jest program Packet Sender lub podobny. Należy uruchomić program i wykonać takie same ustawienia, jak poprzednio (File -> Settings -> Network: Enable UDP Server, Port 90). Następnie w oknie głównym w polu IP Address trzeba wpisać adres modułu (192.168.4.1), ustawić Port na 91 i w znajdującym się dalej po prawej rozwijanym menu wybrać punkt UDP. Po dokonaniu tych ustawień i otwarciu szeregowego monitora można wysłać pierwszą wiadomość do modułu wpisując np. Hi w polu oznaczonym ASCII .
Po kliknięciu na Send na monitorze szeregowym pojawia się:
001
+IPD,2:Hi
002
OK
Page 25
Packet Sender pomyślnie przekazał wiadomość »Hi«.
Wiadomość została zatem odebrana. Można wysłać odpowiedź korzystając ponownie z polecenia CIPSEND, czyli np:
001
AT+CIPSEND=7
002
>Hello
żnica w porównaniu z poprzednim programem znajduje się w jednym wierszu:
success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.2 \",90,91", "OK");
Jak widać, podany został drugi port. Ten port, w tym przypadku port o numerze 91, to port, który moduł odsłuchuje czekając na nadchodzące dane. Po załączeniu tego prostego wiersza możliwe jest także wysyłanie danych do modułu. Ponadto można odsłuchiwać ten sam port, z którego wysyłane są wiadomości. Można więc dla obu portów wpisać liczbę 90. Teoretycznie zmiana ta daje możliwość
Page 26
odbierania przez moduł jego własnych danych.
2.3 | Sterowanie diodą LED przez UDP
W programie P06_UDPLED.ino chodzi w końcu w to, aby sterować sprzętem przez protokół UDP. Ten program daje możliwość włączania i wyłączania diody LED prostymi poleceniami. Ponadto dokonuje się dalszego ustawienia komunikacji UDP, która pozwala na jednoczesne kontrolowanie sprzętu z wielu komputerów. Do tego potrzebny jest układ ukazany na poniższej ilustracji. Dioda LED wygląda bardzo podobnie jak inna część - fototranzystor. Można rozróżnić oba elementy
oglądając główki tych części od góry. We wnętrzu diody LED znajduje się duża biała powierzchnia.
Packet Sender pomyślnie przekazał wiadomość »Hi«.
Program
Podczas gdy poprzednie przykładowe programy wymagały wielu ingerencji użytkownika poprzez monitor szeregowy, ten program powinien pracować autonomicznie. Mimo to przez monitor szeregowy nadal podawane są informacje do celów debugowania.
Kontroler czeka na dane odebrane przez moduł WLAN, które są awizowane przez komunikat +IPD. Dopuszczalne polecenia, które można wysłać przez Packet Sender brzmią led1 i led0. Kontroler interpretuje je i odpowiednio włącza lub wyłącza diodę LED. Przekazywana jest także informacja zwrotna do serwera. Jeśli wysłane zostanie inne polecenie, na szeregowym monitorze pojawia się komunikat »Wrong UDP Command«. Ta same wiadomość jest także przekazywana przez sieć do nadawcy. W tekście źródłowym zajmijmy się najpierw ponownie wierszem w funkcji configUDP():
Page 27
success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.4.255 \",90,91", "OK");
Tym razem bowiem zmienił się IP. Ten IP może wydawać się dziwny, ponieważ nie chodzi to o IP Twojego komputera. Jak więc dane w ogóle docierają? To, że ten IP działa, wynika z tego, że jest to szczególny adres IP a mianowicie tzw. Broadcast-IP. Broadcast można przetłumaczyć mniej więcej jako emisja, np. audycji radiowych. Tak jak przy audycjach radiowych, dane broadcast mogą być odbierane przez wielu użytkowników, w tym przypadku przez wszystkich użytkowników znajdujących się w tej samej podsieci. Adres 255 na końcu IP oznacza zawsze adres broadcast. Można teraz np. na innym komputerze uruchomić program Packet Sender i obejrzeć wszystkie wysłane wiadomości oraz wysłać polecenia. Czyli komunikacja odbywa się nie tylko między dwoma uczestnikami.
001
void loop() {
002
if (esp8266.available())
003
{
004
if (esp8266.find("+IPD,"))
005
{
006
if (esp8266.find("led")) {
007
int setLed = esp8266.parseInt();
008
digitalWrite(LED, setLed);
009
010
debug("LED=" + String(setLed));
011
if (sendCom("AT+CIPSEND=7", ">"))
012
{
013
sendCom("LED=" + String(setLed), "OK");
014
}
015
}
016
017
else {
018
debug("Wrong UDP Command");
019
if (sendCom("AT+CIPSEND=19", ">"))
020
{
Page 28
021
sendCom("Wrong UDP Command", "OK");
022
}
023
024
}
025
}
026
}
027
}
Analiza nadchodzących poleceń odbywa się w procedurze loop, która jest realizowana ciągle. Jeśli nadejdą dane z modułu (esp8266.available()), są one analizowane pod kątem obecności znaków »+IPD,«. Jeśli do tego znalezione zostanie polecenie led, poleceniem parseInt() automatycznie zapisywana jest następna liczba w zmiennejsetLed. Dzięki naszej definicji poleceń powinno to być albo 1 albo 0 i tym samym powinno włączać lub wyłączać diodę LED. W kolejnym kroku przez funkcję debug i polecenie CIPSEND przekazywane jest do komputera potwierdzenie. W przypadku, gdy polecenie led nie znajdowało się w danych odebranych przez moduł, komunikat o błędzie informuje o błędnym poleceniu. Pierwsze zasterowanie przez sieć jest tym samym kompletne.
2.4 | Włączniki sieciowe
W poprzednim programie analizowane były pierwsze polecenia z kontrolera i była odpowiednio załączana dioda LED.
Kolejny program zachowuje te funkcje , ale dodatkowo może sam wysłać polecenie do sieci. Połączyć przycisk z kontrolerem tak, jak pokazano na ilustracji.
Page 29
Włącznik umieszczony na D8 w sposób oszczędzający miejsce
Program
Program nadal analizuje nadchodzące polecenia. Dodatkowo jednak cały czas jest sprawdzany przycisk. Jeśli zostanie on naciśnięty przez użytkownika, kontroler wysyła tekst
Button=1
do sieci. Wszystkie połączone z modułem urządzenia z serwerem UDP na porcie 90 mogą odebrać to polecenie. Można to ponownie sprawdzić używając Packet Sender. Jeśli są do dyspozycji dwa kontrolery, można zbudować na drugim kontrolerze taki sam układ i załadować program na oba kontrolery dokonując nieznacznej zmiany. Jeśli bowiem zamiast polecenia Button=1 zostanie wpisane polecenie led=1 , można sterować diodą LED drugiego kontrolera przez naciśnięcie przycisku. Może się jednak zdarzyć, że sterowana będzie także dioda własnego kontrolera.
Page 30
Przebieg w Packet Sender
Zmiany programu można znaleźć przede wszystkim w procedurze loop. Zwykłe zapytanie if sprawdza, czy włącznik jest wciśnięty. Jeśli tak, kontroler przekazuje komunikat Button=1 do sieci. Ponadto pojawia się komunikat debug. Pojawiająca się następnie pętla while powoduje, że nie zostanie od razu wysłany cały potok poleceń, jeśli przycisk pozostaje wciśnięty. Trzeba więc zwolnić przycisk, aby program mógł dalej działać.
001
if (!digitalRead(SWITCH))
002
{
003
debug("Button=1");
004
sendUDP("Button=1");
005
while (!digitalRead(SWITCH)) {}
006
}
W projekcie automatyzacji domu teraz serwer odebrałby komunikat o stanie np. czujnika ruchu i przekazał innemu kontrolerowi polecenie włączenia światła. W ten sposób można zbudować całą sieć czujników i elementów wykonawczych.
Page 31
2.5 | Czujnik analogowy
W poprzednim projekcie zajmowaliśmy się przyciskiem jako najprostszą formą czujnika. Teraz jako czujnik analogowy zostanie zastosowany potencjometr w celu
permanentnego wysyłania do sieci wyników pomiarów. Użyty zostanie znajdujący się w zestawie potencjometr 10 kΩ. Budowa jest ukazana na poniższej ilustracji.
Widok z potencjometrem na A6
Program
Obok czujnika analogowego są jeszcze inne zmiany w programie. Tym razem kontroler nie ma pracować w trybie Access Point, lecz ma połączyć się z naszą siecią domową. Dane stacji można także w tym przypadku w prosty sposób wpisać u góry w programie.
Nawiązywanie połączenia z siecią po załadowaniu może chwilę potrwać. Jeśli zakończy się powodzeniem, dioda LED D3, zamontowana na stałe na karcie, zaświeci się. Jest to znak, że kontroler jest gotowy. Gdy stosowany jest szeregowy monitor, będzie wprawdzie widoczny także odpowiedni komunikat, ale gdy w późniejszych próbach karta będzie stosowana w sposób bardziej autarkiczny, ta odpowiedź może być bardzo przydatna. Przez monitor szeregowy podawana jest także informacja, jaki IP router przypisał karcie. Ten IP jest ważny, ponieważ karta musi byćźniej zaadresowana.
Komunikacja z kartą działa podobnie jak w poprzednich próbach. Zmienią sie jedynie IP modułu i komputera, ponieważ oba urządzenia otrzymały IP przydzielony przez router. Po starcie Packet Sender nie otrzymuje na początku jeszcze żadnych wyników pomiarów. Najpierw trzeba wysłać do modułu wiadomość, np. polecenie led=1. Ponadto w Packet Sender należy podać nowy IP modułu, który można odczytać na szeregowym monitorze. Po tym poleceniu nowe
Page 32
wyniki pomiarów będą napływać mniej więcej raz na sekundę.
Wyniki zostały odebrane przez Packet Sender.
W tym programie mamy jeszcze jedną zmianę w poleceniu CIPSTART. Po pierwsze został rozszerzony adres broadcast, ponieważ nie da się przewidzieć, jaką podsieć utworzy dany router. Druga zmiana polega na dodaniu parametru, tutaj drugiego. Nowy parametr umożliwia zmianę adresu docelowego polecenia CIPSEND. Moduł nasłuchuje więc najpierw na całym obszarze rozpoczynającym się od 192.168. i gdy odbierze polecenie, ustawia się na nowy IP.
success &= sendCom("AT+CIPSTART=\"UDP\",\"
192.168.255.255\",90,91,2", "OK");
Dla tego parametru są następujące możliwości:
1
Tryb 0: Oznacza to, że IP i port nie zmieniają się. Jest to zarazem ustawienie
domyślne, co wyraźnie widać, gdy przyjrzeć się drugiemu trybowi.
2
Tryb 1: Ustawienia zmieniają się raz. Oznacza to: Jeśli moduł startuje ze stosowanym właśnie adresem broadcast i następnie odbierze jakiś komunikat z PC, moduł ustawia się na nowy adres PC. Innymi słowy wpisany wcześniej docelowy IP staje się nieistotny i zamiast tego komunikaty wysyłane są na nowy adres. Ten adres pozostaje także wtedy, gdy moduł otrzyma dane z innego PC.
3
Tryb 2: Ustawienia zmieniają się przy każdym odbiorze z nowego urządzenia.
Page 33
Oznacza to, żer IP, nawet jeśli został już raz zmieniony, może ustawić się na nowy PC.
Jest to też powód, dlaczego najpierw trzeba wysłać polecenie do modułu, zanim będzie można odbierać dane. Wtedy powinno być także możliwe odbieranie danych od tego komputera. Chyba że z innego komputera zostanie ponownie wysłana wiadomość do modułu.
001
boolean sendUDP(String Msg)
002
{
003
boolean success = true;
004
005
success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2),
006
if (success)
007
{
008
success &= sendCom(Msg, "OK");
009
}
010
return success;
011
}
Wysyłanie wartości analogowej odbywa się w procedurze loop. Do tego używana jest nowa funkcja sendUDP() , która umożliwia łatwiejszy dostęp do znanych funkcji. Między wysyłaniem poleceń nie musi być ustawione opóźnienie, ponieważ na transmisję potrzeba nieco czasu. Jednakże częstotliwość, z jaką przekazywane są nowe dane, jest tak wysoka, że komputer jest prawie że bombardowany wiadomościami.
KLIENT TCP
W poprzednim rozdziale zajmowaliśmy się protokołem UDP, za pomocą którego można w prosty sposób wysyłać i odbierać dane. Z tym protokołem można zrealizować wiele zastosowań. W tym rozdziale zajmiemy się protokołem TCP­Protokoll (Transmission Control Protocol). Moduł będzie pracował w tym rozdziale
Page 34
jako klient TCP. Jest to rola, jaką odgrywa domowy komputer wobec serwera sieci web. Różnicę między TCP a UDP można ogólnie zebrać w kilku hasłach:
U
Połączenie jest zawiązane tylko między dokładnie dwoma
urządzeniami.
U
Wysłane pakiety są kontrolowane pod kątem błędów w transmisji i
ew. korygowane.
U
TCP jest stosowany przede wszystkim w internecie.
U
Ten protokół jest nieco wolniejszy niż UDP, ale bezpieczniejszy.
Tak więc protokół ten jest stosowany przez domowy komputer i serwer sieci web, z którego chcemy pobrać stronę www, w celu nawiązania połączenia między oboma użytkownikami. Właściwa zawartość strony www jest później przekazywana w formacie HTTP (HyperText Transfer Protocol). Kolejny rozdział opisuje, jak to dokładnie funkcjonuje.
3.1 | Przeglądarka
Do tej próby ponownie wykorzystana zostanie wykonana już konstrukcja. Chodzi o poznanie podstawowych struktur komunikacji TCP za pomocą szeregowego monitora.
Program
Program sposobem działania przypomina program SoftwareSerial z pierwszej próby, ale m.in. sam nawiązuje połączenie WLAN przy pierwszym
uruchomieniu. Dzięki temu odpada sporo pracy związanej z pisaniem i można szybciej rozpocząć pracę. Należy pamiętać o wpisaniu do programu danych sieci domowej. Następnie w szeregowym monitorze należy wpisać następujący wiersz polecenia:
AT+CIPSTART="TCP","www.example.com",80
Tym poleceniem nawiązuje się połączenie TCP ze stroną internetową
www.example.com. Port 80 jest standardowym portem do zapytań HTTP. Po
potwierdzeniu połączenia przez OK można wpisać kolejne, znane już, polecenie:
AT+CIPSEND=40
Chcemy bowiem teraz wysłać wiadomość przez nawiązane właśnie połączenie. Jeśli pojawi się znak > wzywający do wpisania tekstu, należy wpisać
GET / HTTP/1.1
i następnie nacisnąć
[Enter]
.
[Enter]
nie pojawia się na szeregowym monitorze,
ale moduł odebrał ten komunikat. Teraz następuje wiadomość
Page 35
Host:www.example.com
i dwukrotne naciśnię cie
[Enter]
. Wpisy należy jednak wysłać bardzo szybko po sobie. Najlepiej przygotować sobie dokument tekstowy, z którego będzie można szybko skopiować poszczególne wiersze. Jako odpowiedź nadchodzi długi tekst. Pierwsza część to odpowiedź serwera i zawiera ona kilka informacji dla przeglądarki. Tekst po <!doctype html> to strona internetowa, która jest widoczna także po bezpośrednim otwarciu www.example.com, ale tutaj tylko w formie tekstu. Przeglądarka zinterpretowałby ten tekst i przedstawiła w jednej z używanych przez nas form.
Wyciąg z odpowiedzi serwera sieci web
W tym przykładzie widoczne są podstawy formatu HTTP. Klient nawiązuje połączenie z serwerem sieci web. Tzw. DNS (Domain Name System) sprawia, że nie jest konieczne wpisywanie IP i można zastosować nazwę domeny w formie tekstu. Wysyła on zapytanie do trudnego do zapamiętania IP. Po połączeniu się z klientem przeglądarka wysyła zapytanie Get-Request. W tym zapytaniu należy podać co najmniej żądaną stronę lub zasób (w tym przypadku strona główna), zastosowany protokół (http 1.1) oraz hosta, do którego kierowane jest zapytanie (www.example.com). Podanie hosta jest ważne, ponieważ na jednym serwerze i tym samym pod jednym adresem IP może znajdować się wiele adresów internetowych. Jeśli ma być wywołana inna strona niż strona główna, należy wpisać zamiast tego / z. B. /example.html. Obok żądanej podstrony przeglądarka wysyła także wiele więcej informacji niż tylko żądany zasób. Wysyłane są także takie dane, jak np. używana przeglądarka, system operacyjny, rozdzielczość monitora i wiele innych. Dzięki temu serwer może dostosować zawartość. Następnie pojawia się odpowiedź serwera, która wygląda podobnie skomplikowanie. Header odpowiedzi zawiera wiele dodatkowych informacji dla przeglądarki. Dopiero na końcu pojawia się właściwa zawartość strony internetowej.
Page 36
3.2 | Zegar internetowy
Ten projekt wykorzystuje wiedzę zdobytą w poprzednich rozdziałach, aby spowodować, że NanoESP będzie samodzielnie pobierał informacje ze strony internetowej. Konkretnie program pobiera aktualną godzinę ze specjalnie utworzonej w tym celu strony i przedstawia realizowany przez bibliotekę wewnętrzny zegar pozwalający na podawanie dokładnego czasu. Czas podawany jest na szeregowym monitorze. Do budowy potrzebna jest tylko karta.
Program
Podczas gdy poprzedni program musiał być w większości obsługiwany ręcznie, ten pracuje w znacznym stopniu autonomicznie. Całkowicie samodzielnie kontroler łączy się ze stroną internetową:
http://chronic.herokuapp.com/ Poprzez URL można ustawićżne systemy i strefy czasowe. Aktualny,
obowiązujący zimą w Niemczaech czas jest sprawdzany przez URL http://chronic.herokuapp.com/utc/in-one-hour . Dlatego w wywołaniu wyjaśnionej źniej funkcji
getTime() jako drugi parametr pojawia się utc/in-one-hour. Wychodząc od UTC (uniwersalny czas koordynowany), latem należałyby zmienić wywołanie na utc/in­two-hours. Korzystając z tego samego systemu można poruszać się także po wszystkich pozostałych strefach czasowych.
Ustalony czas przekazywany jest do Time-Library Michaela Margolisa (źródło: http://www.pjrc.com/teensy/td_libs_Time.html). Ze względów praktycznych kopia używanej przeze mnie wersji Time-Library znajduje się w folderze szkicu. Musi ona zostać skopiowana do folderu libraries Twojego szkicownika. W tle cały czas obliczany jest nowy czas i podawany co sekundę w terminalu. Można w prosty sposób zaprogramować budzik lub inną sterowaną czasem aplikację. Aby sprawdzanie czasu mogło funkcjonować, wykorzystywana jest nowa funkcja:
001
boolean getTime(String Host, String Subpage)
002
{
003
boolean success = true;
004
int xyear, xmonth, xday, xhour, xminute, xsecond; //lokal variables
005
006
success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
007
String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n";
008
success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
Page 37
009
010
esp8266.println(getRequest);
011
012
if (esp8266.find("+IPD"))
013
{
014
if (esp8266.find("\r\n\r\n"))
015
{
016
xyear = esp8266.parseInt();
017
xmonth = esp8266.parseInt();
018
xday = esp8266.parseInt();
019
xhour = esp8266.parseInt();
020
xminute = esp8266.parseInt();
021
xsecond = esp8266.parseInt();
022
023
if (xday < 0) xday *= -1; //Because of date seperator ­parseInt detects negativ integer
024
if (xmonth < 0) xmonth *= -1; //Because of date seperator ­parseInt detects negativ integer
025
026
027
setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
028
sendCom("AT+CIPCLOSE", "OK");
029
return true;
030
}
031
else return false;
032
}
033
else return false;
034
}
Page 38
Do tej funkcji przekazywane są parametry adresu hosta oraz podadresu. Z tego w końcu tworzone jest zapytanie Get-Request a po nawiązaniu połączenia przekazywane do do serwera TCP strony internetowej. Odpowiedź serwera musi teraz zostać przeanalizowana. W tym celu program pomija całą część Request­Header szukając \r\n\r\n, co znaczy tyle, że program będzie kontynuował działanie po podwójnym Carriage Return i New Line. Kolejne liczby odpowiadają szukanej dacie i godzinie, które są zapisywane w tymczasowych zmiennych przez szereg wywołań funkcji parseInt(). Cecha szczególna pojawia się w dacie, ponieważ tutaj poszczególne wartości są oddzielone myślnikiem, co funkcja parseInt() interpretuje jako liczbę ujemną. Dlatego wartości te są mnożone przez -1. Na końcu godzina jest ustawiana przez funkcję setTime()- i podawana raz na sekundę przez procedurę loop. Zegar jest w pełni gotowy do pracy.
3.3 | Podawanie temperatury
W tym projekcie chodzi o podawanie aktualnej temperatury i aktualnej pogody. Także w tym przypadku wartości są podawane na szeregowym monitorze.
Dodatkowo pojawia się intuicyjna informacja za pośrednictwem diody LED RGB. Można więc jednym spojrzeniem ocenić, czy należy ubrać ciepłą kurtkę.
Podczas montażu ważne jest poprawne podłączenie diody LED RGB. RGB oznacza Red, Green, Blue, ponieważ dioda składa się właściwie z kilku diod ze wspólnym podłączeniem katody. Łącząc różne kolory o różnej jasności można uzyskać prawie każdą barwę. Tak, jak pokazano na ilustracji, diodę należy podłączyć z przez oporniki wstępne do wyjść PWM D3, D5 i D6 kontrolera.
Page 39
Podłączenie diody LED RGB do pinów D3, D5 i D6
Program
W szkicu ponownie chodzi o sprawdzenie strony internetowej, ale tym razem jest to strona zaprogramowana specjalnie do tego projektu, która pobiera dane ze strony z prognozą pogody
http://www.openweathermap.com/ . Na tej stronie dzięki wariacjom URL można uzyskać informacje o pogodzie w
swoim mieście. Miasto, dla którego ma być sprawdzona pogoda, można wpisać w tekście źródłowym po City. Jako przykładu użyjemy mojego miasta rodzinnego Essen: www.temp.fkainka.de/?city=Essen
Program odczytuje z tej strony temperaturę i prezentuje wynik odpowiednim kolorem diody LED RGB. Wartość podawana jest jednocześnie na monitorze szeregowym. Zakres temperatur stosowany w przykładowym programie do prezentacji na diodzie LED wynosi –20 °C do +40 °C.
W zasadzie program działa prawie tak samo, jak poprzedni. Ma on jedynie kilka drobnych cech specjalnych. Funkcja getTemp() odpowiada tym razem za pozyskiwanie danych i odsyła aktualną temperaturę, podobnie jak funkcja godziny w poprzednim programie.
001
void rgbTemp(int val)
002
{
003
int green, blue, red ;
004
Page 40
005
if (val <= 10 & val >= -20)
006
blue = map(val, -20, 10, 255, 0);
007
else blue = 0;
008
009
if (val >= 10 & val <= 40)
010
green = map(val, 10, 40, 255, 0);
011
else if (val >= -20 & val < 10) green = map(val, -20, 10, 0, 255);
012
else green = 0;
013
014
if (val > 10 & val <= 40) red = map(val, 10, 40, 0, 255);
015
else red = 0;
016
017
analogWrite(RED, red);
018
analogWrite(GREEN, green);
019
analogWrite(BLUE, blue);
020
}
Dostosowanie jasności LED jest wykonywane w funkcji rgbTemp() . Za pomocą polecenia map wartości są przekształcane w pasujące wartości bajtów (0-255) i podawane na diodzie LED. Kolor niebieski oznacza bardzo niskie temperatury i ma wpływ na sygnalizację temperatur w zakresie od –20 °C do +10 °C. Kolor zielony jest używany w całym zakresie temperatur, ale swoje maksimum ma przy wartości 10 °C. Kolor czerwony wkracza dopiero od wartości +10 °C i ma swoje maksimum przy +40 °C. Dzięki temu tworzy się intuicyjny kod kolorowy, na podstawie którego można oszacować aktualną temperaturę obok dokładnego wskazania na monitorze szeregowym.
SERWER TCP
W poprzednim rozdziale dowiedzieliśmy się nieco o zastosowaniu modułu jako klienta TCP. Teraz zajmiemy się modułem w roli serwera TCP. Także tutaj mamy
Page 41
jedno praktyczne i proste polecenie AT, którym można uruchomić to skompilowane zastosowanie serwera. Moduł zachowuje się wtedy jak serwer TCP z internetu, tylko że trzeba samemu zaprogramować wysyłanie strony internetowej.
4.1 | Serwer sieci web TCP
Pierwsze kroki w zakresie serwera sieci web TCP nie wymagają dodatkowego sprzętu. Najpierw przetestujemy najważniejsze polecenia z użyciem monitora szeregowego.
Program
Należy tak, jak poprzednio wpisać dane WLAN i załadować program na kartę. Następnie należy uruchomić monitor. Może potrwać kilka sekund, zanim pojawi się komunikat, że jest połączenie z kartą. Gdy pojawi się komunikat powodzenia oraz wyświetlony zostanie adres IP modułu, można rozpocząć na monitorze szeregowym od pierwszego polecenia:
AT+CIPMUX=1
Polecenie to dopuszcza wiele połączeń z modułem. W ten sposób wiele komputerów ma dostęp do serwera sieci web. Następne polecenie uruchamia serwer sieci web:
AT+CIPSERVER=1,80
Parametr 1 oznacza, że serwer zostaje uruchomiony. Parametr 0 kończy pracę serwera. Liczba 80 oznacza port, na którym serwer jest osiągalny. Wysyłane przez przeglądarkę zapytania HTTP są zasadniczo wysyłane przez port 80.
Można otworzyć jedną przeglądarkę wg własnego wyboru i na pasku adresowym wpisać IP modułu z następnie potwierdzić przez
[Enter]
. W przeglądarce pojawia się najpierw komunikat ładowania, ale na szeregowym monitorze można zaobserwować zmianę. Widoczne jest zapytanie Request podobne do ego, które już było ręcznie wysyłane.
Zapytanie przeglądarki
Przeglądarka czeka na odpowiedź i pokazuje znak ładowania do czasu, aż
Page 42
połączenie zostanie przerwane ze względu na upływ timeout. Można wysłać wiadomość do przeglądarki korzystając z wariantu znanego polecenia:
AT+CIPSEND=0,7
Parametr 0 oznacza tutaj klienta, do którego ma zostać wysłana wiadomość. Jest to konieczne, ponieważ dozwolonych jest wiele połączeń i w związku z tym
połączenia mogą być nawiązane także z wieloma klientami. Drugi parametr, tutaj
7, oznacza ponownie ilość wysyłanych znaków. Pojawia się > i można teraz
wpisać
Hallo
i wysłać naciskając
[Enter]
. W przeglądarce za razie nic się nie zmieni, ponieważ
najpierw trzeba zakończyć połączenie. Należy wykonać to następującym poleceniem:
AT+CIPCLOSE=0
Teraz w przeglądarce pojawi się Hallo. Tym samym zrealizowane zostało zastosowanie jako serwer sieci web.
Ta pierwsza część zawiera wiele informacji o dokładnych procedurach komunikacji w internecie. Wyświetlenie »Hallo« w przeglądarce jest przy tym bardzo proste, ponieważ został wysłany prosty tekst zamiast złożonej strony HTML. Do strony HTML konieczne byłoby ręczne pisanie całego headera zarówno dla zapytania Get-Request jak i tekstu HTML. W pierwszym teście oszczędzę Wam jednak tego wysiłku.
4.2 | Autonomiczny serwer sieci web
Teraz musimy wykorzystać wyniki poprzedniej próby w autonomicznym programie. Nowy program nie wysyła jednak tylko prostych stron internetowych do przeglądarki, lecz umożliwia oprócz tego obsługę diody LED. Na ilustracji widać poza tym, w jaki sposób można podłączyć do karty zewnętrzne zasilanie prądem.
Alternatywnym rozwiązaniem do tego typu zasilania jest power-bank (zewnętrzny akumulator, przeznaczony zazwyczaj do smartfonów), który może zasilać kartę w prosty sposób przez gniazdo micro-USB.
Page 43
W ten sposób należy podłączyć baterię do konstrukcji.
Program
Program wysyła bardziej złożoną stronę niż w poprzedniej próbie. Ponadto można sterować diodą LED na pinie D9, jeśli po IP modułu wpisze się /LED . Wtedy zmienia się aktualny stan diody LED, stan przełącza się za każdym razem (zmiana stanu na przeciwny).
Należy wpisać dane swojej sieci WLAN i załadować program. IP karty ukazuje się na monitorze szeregowym. Wtedy można otworzyć przeglądarkę i wywołać IP karty. Na stronie internetowej znajduje się teraz nagłówek i trochę więcej tekstu. Tekst informuje także, w jaki sposób można sterować diodą LED. Macie w ten sposób pierwszy w pełni autonomiczny serwer serwer sieci web.
001
void loop() {
002
if (esp8266.available()) // check if the esp is sending a message
003
{
004
if (esp8266.find("+IPD,"))
005
{
006
debug("Incomming Request");
007
int connectionId = esp8266.parseInt();
008
009
if (esp8266.findUntil("LED","\n")) digitalWrite(LED, !digitalRead(LED));
010
Page 44
011
String webpage = "<h1>Hello World!</h1>Open [IP]/LED to Toggle LED on D9";
012
013
if (sendCom("AT+CIPSEND=" + String(connectionId) + "," + String(webpage.length()), ">"))
014
{
015
sendCom(webpage,"SEND OK");
016
sendCom("AT+CIPCLOSE=" + String(connectionId),"OK");
017
debug("Send and Close");
018
}
019
}
020
}
021
}
Do uruchomienia serwera sieci web ponownie służy prosta funkcja o nazwie configTCPServer(). Jest to dokładnie to, co wcześniej było wpisywane ręcznie. Procedura loop oczekuje na przychodzące dane. Gdy te dane zawierają »LED«, dioda LED zaczyna zmieniać ciągle stan. Procedura nie sprawdza, gdzie dokładnie znajduje się »LED«, dlatego polecenie jest ważne w przekazanym URL. Sama strona www w tej próbie znajduje się w zmiennej webpage i zawiera następujący tekst:
001
<h1>Hello World!</h1>
002
Open [IP]/LED to Toggle LED on D9
Tutaj <h1> to polecenie dla przeglądarki, aby tekst do </h1> był przedstawiony jako nagłówek typu 1. Nie jest to jeszcze prawidłowy kod HTML, lecz raczej prosta forma prezentacji tekstu. Długość strony www jest przekazywana przez webpage.length() (funkcja klasy ciągu) do polecenia CIPSEND i w końcu do strony.
4.3 | Strona www z przyciskami
W tej próbie wygląd strony internetowej jest jeszcze bardziej wygładzony. Poza tym mamy teraz także elementy sterowania, za pomocą których można znacznie wygodniej sterować diodą LED. Budowa w tej próbie nie różni się od konstrukcji z poprzedniej próby: dioda LED na pinie D9, którą można sterować z modułu. Do tego w tekście źródłowym jest kilka nowych rzeczy.
Page 45
Program
Po załadowaniu programu można ponownie otworzyć w przeglądarce stronę internetową kontrolera. W tym celu należy wpisać IP modułu, który został podany przy starcie na szeregowym monitorze. Sama strona internetowa będzie w tej próbie zapisywana nieco inaczej niż w poprzedniej.
Strona internetowa serwera sieci web
W poprzedniej próbie prosta strona internetowa była zawarta w tekście źródłowym. Tym razem strona zostanie zapisana w tzw. zmiennych Progmem (Program Memory). Zastoowanie tego rodzaju zapisywania odciąża pamięć SRAM karty, która w przeciwnym razie byłaby odpowiedzialna za zapisywanie zmiennych. Pamięć SRAM mieści tylko 2 kB i przez stosowanie ciągów jest już bardzo obciążona. Dzięki funkcji Progmem zawartość strony www jest umieszczana w pamięci programu, która mając 32 kB jest znacznie większa. Jednakże dostęp do danych jest tutaj nieco bardziej skomplikowany.
001
const char site[] PROGMEM = {
002
"<HTML><HEAD>\n<meta name=\"viewport\" content=\"width=device-width, initial­scale=2.0,
003
(…)
004
};
W tym fragmencie widać, w jaki sposób strona www jest zapisywana w zmiennej Progmem. Jest to dłuższy dokument HTML w formacie kompatybilnym z C. Format charakteryzuje się m.in. tym, że cudzysłów jest stosowany w formie \" a nowy wiersz jest oznaczany przez \n. Jest to przypuszczalnie znane już z innych projektów, gdzie występowały ciągi. Podgląd strony www w formacie HTML można znaleźć także w folderze programów.
Page 46
001
String createWebsite()
002
{
003
String xBuffer;
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
return xBuffer;
012
}
W funkcji createWebsite() ładowana jest zawartość zmiennej Progmem i zwracana w formie ciągu. Widać wyraźnie, w jaki sposób zmienna Progmem jest ponownie ładowana z pamięci programu.
001
boolean sendWebsite(int connectionId, String webpage)
002
{
003
boolean success = true;
004
005
if (sendCom("AT+CIPSEND=" + String(connectionId) + "," + String(webpage.length()), ">"))
006
{
007
esp8266.print(webpage);
008
esp8266.find("SEND OK");
009
success &= sendCom("AT+CIPCLOSE=" + String(connectionId), "OK");
010
}
011
else
012
{
013
success = false;
Page 47
014
}
015
return success;
016
}
Procedura loop oczekuje żądanie Request. Gdy ono nadejdzie, wywołana zostanie funkcja sendWebsite() , której jako parametr zostanie przekazany wynik funkcji createWebsite(). Na tej podstawie będzie można ustalić długość tekstu za pomocą funkcji length(). Po przekazaniu strony www połączenie zostaje zakończone poleceniem AT+CIPCLOSE. Sterowanie diodą LED jest także częścią procedury loop i nieznacznie różni się od poprzedniego schematu. Poniższy szybki kurs HTML wyjaśni, jak dokładnie to się odbywa.
4.4 | Dygresja: szybki kurs HTML
W tym rozdziale przeprowadzimy mały szybki kurs na temat HTML. Szczególna uwagę poświęcimy tworzeniu stron www do sterowania NanoESP. Kurs obejmuje podstawowe struktury dokumentu HTML, tworzenie elementów wprowadzających i wydających oraz włączanie własnych stron www do programu Arduino.
Plik HTML zawsze posiada oznaczenie<HTML> na początku dokumentu. Koniec dokumentu jest oznaczony przez </HTML> . Z reguły początek i koniec fragmentu lub elementu są prezentowane w porównywalnej formie, co widać już na przykładzie headera. Hearde zawiera ważne informacje i formy, jak np. w tym przypadku tytuł strony internetowej, który jest wyświetlany u góry na pasku przeglądarki. W tym przypadku header zawiera dodatkową informację, która nie należy do podstaw HTML, ale poprawia widok na urządzeniach mobilnych (<meta name ="viewport" …). Możne te wiersze w każdym czasie wprowadzić na swoja stronę internetową HTML.
001
<HTML><HEAD>
002
<meta name="viewport" content="width=device-width, initial-scale=2.0, user­scalable=yes">
003
<title>
004
Switch LED
005
</title>
006
</HEAD>
Po HEAD następuje BODY. Tutaj znajduje się zawartość strony www. W obszarze startu BODY ustalane są dodatkowo takie parametry jak kolor tła i czcionki. Można je zawsze dostosować do własnych upodobań. Następnie w elemencie FONT ustala się rodzaj i rozmiar czcionki. Dotyczą one jednak tutaj tylko tekstu Switch LED, który jest przez to szczególnie duży, ponieważ następnie element FONT jest
Page 48
zamykany przez </FONT> .
001
<BODY bgcolor="#FFFF99" text="#000000">
002
<FONT size="6" FACE="Verdana">
003
Switch LED
004
</FONT>
Kolejna część jest bardzo podobna i ma tylko dwa nowe elementy, mianowicie <HR> tworzący poziomą linię na stronie www oraz <BR> pozwalający na przejście do kolejnego wiersza.
001
<HR>
002
<BR>
003
<FONT size="3" FACE="Verdana">
004
Switch the LED <BR>
005
on D9 ON and OFF
006
<BR>
007
<BR>
Wszystkie przedstawione dotychczas elementy dotyczy wyłącznie formy i służyły do tworzenia strony internetowej. Teraz kolej na ważny element form, za pomocą którego będzie realizowane sterowanie diodą LED.
001
<form method="GET">
002
<button type="submit" name="led" value="1">LED ON</button>
003
<button type="submit" name="led" value="0">LED OFF</button>
004
</form>
Element form - jak już wskazuje jego nazwa - jest przeznaczony do tworzenia formularzy w internecie. Mogą to być zarówno formularze zgłoszeniowe strony www lub ankiety itp. Przekazywanie danych wpisywanych przez użytkownika może odbywać się na różne sposoby. W tym elemencie stosowana jest metoda GET, w której wpisane dane są przekazywane do serwera sieci web w prosty sposób za pomocą URL. W tym formularzu zastosowanie znajdą dwa przyciski. Oba są typu submit, co oznacza, że formularz jest przekazywany bezpośrednio przy naciśnięciu jednego z tym dwóch przycisków. Oba przyciski mają nazwę led, ale różne wartości (values). Przy naciśnięciu pierwszego przycisku opisanego jako LED ON aktualny URL zostaje ponownie wywołany, ale z małym dodatkiem. Za
Page 49
URL, w tym przypadku za IP modułu, znajduje się jeszcze /?led=1. Dokładnie ten tekst jest potem w programie Arduino analizowany w ten sposób, że jest on szukany a następująca po nim liczba jest wczytywana z parseInt() i przekazywana do LED. Ta pierwsza, prosta wersja formularza umożliwia bezproblemowe i wygodne sterowanie diodą LED.
Tak wygląda URL po naciśnięciu przycisku LED ON.
001
<BR>
002
<HR>
003
004
</font>
005
</HTML>
Ostatnie wiersze tekstu źródłowego HTML nie zawierają nic nowego. Przejście do następnego wiersza i pozioma linia dopełniają obraz przed zamknięciem dokumentu przez </HTML>. Teraz można zmieniać stronę www w szkicowniku wg własnych upodobań. Można np. zmienić kolor tła lub wpisać więcej tekstu na stronie. Nie należy jednak przeładowywać strony, ponieważ można łatwo przeciążyć pamięć SRAM. Po dokonaniu zmian należy je przenieść do programu Arduino. W tym celu należy skopiować cały tekst do schowka i przejść na stronę www korzystając z Swiss Converter Tool: http://www.percederberg.net/tools/text_converter.html
Page 50
Strona Swiss-Converter-Tool po konwersji zakończonej powodzeniem
Tam należy wkleić tekst ze schowka w punkcie 2. Select Output: ustawićC/C++/PHP – StringText i UTF-8 – Unix (LF). Teraz w dolnym oknie pojawia się tekst zrozumiały dla Arduino, który można skopiować do zmiennej Progmem-Variable site . Po załadowaniu zmienionego programu z nową zmienną przy wywołaniu IP karty w przeglądarce ukaże się nowa strona www.
4.5 | Sterowanie diodą LED RGB przez TCP
W aktualnym projekcie chodzi o sterowanie diodą LED RGB ze strony www umieszczonej na serwerze sieci web. Dzięki przejrzystemu interfejsowi można
zmieniać kolor diody LED. Strona www została dostosowana i powinna być dobrze wyświetlana także na smartfonach. Budowa jest ukazana na poniższej ilustracji.
Page 51
Podłączenie diody LED RGB do pinów D3, D5 i D6
Program
Nową stronę www można ponownie znaleźć w zmiennej Progmem site. Także w tym przypadku podgląd strony HTML jest dostępny w szkicowniku. Po ustawieniu danych WLAN i załadowaniu programu do strony internetowej serwera sieci web można dotrzeć przez IP modułu. Kolor tła i nagłówek są podobne do poprzednich. Na stronie znajduje się jednak jeden nowy element: jest to element HTML5 Color Picker. Umożliwia on wyszukanie koloru dla diody LED. Natychmiast po potwierdzeniu koloru pojawi się on na diodzie LED. Widok elementu Color Picker może znacznie różnić się w różnych przeglądarkach.
Strona internetowa w przeglądarce
Page 52
Wybór koloru w przeglądarce Chrome
Nawet jeśli wygląd strony internetowej nie różni się znacznie od poprzedniej, to jest tu kilka elementów, które chcę bliżej opisać. Po pierwsze mamy zmianę w headerze dokumentu HTML, która dotyczy następującego wiersza:
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
Zadaniem tego wiersza jest zapobieganie temu, żeby przeglądarka po załadowaniu strony internetowej załadowała tzw. favicon. Z reguły strona internetowa posiada bowiem jeszcze specjalny symbol różniący się od innych stron internetowych i identyfikujący jednoznacznie stronę internetową na pasku przeglądarki za pomocą wielu klawiszy. Aby przeglądarka mogła załadować ten znak, po wywołaniu strony wysyła żądanie Request i pyta o favicon. Być może w pierwszych próbach z serwerem TCP zwróciliście uwagę na to dodatkowe zapytanie Request. Aby zatrzymać drugie zapytanie i nie obciążać niepotrzebnie karty, powyższy wiersz z kodem informuje przeglądarkę, że nie ma wysyłać drugiego żądania. Zalecam wpisanie tego wiersza do swoich stron HTML.
Druga rzecz szczególna w tym dokumencie to wspomniany już element Color­Picker. Można powiedzieć, że zastępuje on przyciski z poprzedniego przykładu. Jest to względnie nowy element HTML5.
Na poprzedniej stronie internetowej wybraliśmy po prostu przyciski typu submit i po ich naciśnięciu wartości formularza były przekazywane bezpośrednio. W elemencie typu color jest to niestety niemożliwe. Możliwym rozwiązaniem problemu byłoby utworzenie przycisku typu submit, który następnie po ustawieniu farby musiałby zostać dodatkowo naciśnięty. To zostanie zaprezentowane w późniejszej próbie. Tutaj został wklejony mały kod JavaScript (chodzi o częśćonchange="this.form.submit()"), który dba o to, żeby formularz był
Page 53
natychmiast przekazywany w przypadku dokonania zmiany.
Element Color-Picker w przeglądarce Android-5.0
Dzięki temu niepotrzebny jest kolejny przycisk.
001
<form method="GET">
002
<input type="color" name="rgb" onchange="this.form.submit()"><BR>
003
</form>
Wybrany kolor jest przekazywany w formie /?rgb=%23 + sześć dalszych znaków. Wyrażenie %23 mówi, że jest to liczba szesnastkowa. Dla koloru białego URL wygląda więc następująco:
[IP]/?rgb=%23ffffff
Z tej liczby HEX kontroler musi teraz odczytać poszczególne kolory diody LED. Odbywa się to w kolejnej części funkcji loop:
001
if (esp8266.findUntil("?rgb=", "\n"))
002
{
003
String hexstring = esp8266.readStringUntil(‚ ‚);
004
long number = (long) strtol( &hexstring[3], NULL, 16);
005
006
int r = number >> 16;
007
int g = number >> 8 & 0xFF;
Page 54
008
int b = number & 0xFF;
009
010
analogWrite(RED, r);
011
analogWrite(GREEN, g);
012
analogWrite(BLUE, b);
013
}
W funkcji strtol() tekst odebrany po %23 jest najpierw przekształcany w liczbę long a ta poprzez manipulację bitów w trzy wartości wyrażone w bajtach. One za pomocą funkcji analogWrite()- są przekazywane do diody LED RGB.
4.6 | Czujnik światła
W tym projekcie strona internetowa serwera sieci web nie jest wykorzystywana jako interfejs obsługi, lecz jako element komunikowania. Jasność zmierzona przez czujnik jasności jest jako wartość względna przejrzyście prezentowana przez nowy element HTML.
Do zbudowania tej próby potrzebny będzie fototranzystor pełniący rolę czujnika światła. Fototranzystor można łatwo pomylić z diodą LED. Aby odróżnić fototranzystor, należy spojrzeć z góry na główkę części. Fototranzystor ma wewnątrz dużą, czarną powierzchnię. Konstrukcję tej próby przedstawia ilustracja.
Kolektor fototranzystora to krótsze podłączenie na +5 V. Połączony szeregowo z fototranzystorem opornik ma 10 kiloomów.
Podłączenie fototranzystora do pinu A6 z opornikiem 10 kiloomów
Page 55
Program
Do tej pory strony internetowe serwera sieci web składały się zawsze z niezmiennej strony wysyłającej dane do kontrolera. Teraz strona internetowa ma zostać zmieniona przed przeniesieniem do przeglądarki, aby ukazać zmierzoną jasność fototranzystora. Będzie to działać, ponieważ w kodzie źródłowym strony internetowej ukryty jest znak wieloznaczny. Podczas ładowania danych ze zmiennej Progmem program zastępuje znak wieloznaczny *bright* aktualną wartością jasności. Tym samym zmienia się tekst komunikatu i pozycja regulatora suwakowego. Zadaniem kolejnego wiersza w pliku HTML jest zapewnienie, żeby strona ładowała się automatycznie co kilka sekund. Aktualna jasność jest już przejrzyście prezentowana w przeglądarce.
Strona internetowa czujnika jasności
Aby system mógł działać, w plikach HTML zostało wykonanych kilka drobnych zmian. Pierwsza zmiana ponownie znajduję się w obrębie headera:
<meta http-equiv="refresh" content="3">
Ten wiersz sprawia, że przeglądarka ładuje stronę internetową automatycznie co trzy sekundy. Dzięki temu nie trzeba ciągle naciskać
[F5]
, aby móc zobaczyć
nowe wartości. Druga zmiana znajduje się w miejscach, gdzie normalnie znajduje się element
form:
001
<label for="hell">Current Brightness: *bright*</label> <BR>
002
<input type="range" max = "1024" name="hell" value=*bright*><BR>
Tutaj nie jest teraz potrzebny żaden formularz, ponieważ strona internetowa jest wykorzystywana wyłącznie do podawania informacji. Obydwa elementy label i range pełnią rolę elementów podających informacje. W etykiecie, która zazwyczaj wykorzystywana jest do opisów, w tekście można znaleźć miejsce *bright* .
Page 56
Element suwaka range jako value otrzymuje wartość *bright* , która właściwie nie jest wartością poprawną, ale poźniej jest przez taką zastępowana. Maksymalna wartość range wynosi 1024 i została tym samym dopasowana do 10-bitowego zakresu ADC kontrolera.
Przed przekazaniem strony internetowej należy teraz tylko zadbać, że w tekście źródłowym znak wieloznaczny *bright* została zastąpiony poprawną wartością.
001
String createWebsite()
002
{
003
String xBuffer;
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
xBuffer.replace("*bright*", String(analogRead(SENSOR)));
012
013
return xBuffer;
014
}
Zastąpienie znaku wieloznacznego odbywa się w funkcjicreateWebsite(). Najpierw w zwykły sposób ładowana jest zmienna Progmem z pamięci i zapisywana w ciągu. Ale zanim funkcja zwróci ten ciąg, wszystkie ciągi znaków *bright* zostaną zastąpione aktualną wartością zmierzoną przez czujnik. Funkcja string replace() wykonuje tę pracę w pełni automatycznie. Na końcu zmieniony ciąg jest zwracany i przy wykorzystaniu znanych mechanizmów przekazywany do przeglądarki.
4.7 | GPIO-Control
Ten nowy projekt umożliwia proste sterowanie pninami cyfrowymi D2-D7 ze strony internetowej. Status poszczególnych pinów jest także pokazywany w przeglądarce, dzięki czemu zawsze mamy podgląd całości.
Aby można było pewnie kontrolować stan pinów, zaleca się wykonanie konstrukcji ukazanej na ilustracji. Zastosowanie znajdują zarówno dioda LED RGB jak i zwykła dioda LED. W tym przypadku katody diod nie są jednak podłączone do
Page 57
długich przewodów masowych na zewnątrz karty, lecz do wyjścia cyfrowego. Tylko, gdy te piny są w ustawieniu low, diody mogą świecić.
Podłączenie diod LED do D2-D7
Uwaga! Diody LED nie mogą być podłączane bez oporników wstępnych. W tym przypadku jest to dopuszczalne ze względu na opory On wewnętrznych FET portów o wartości ok. 30 omów. Ponieważ diody są umieszczone między dwoma portami, pracują one w rzeczywistości z oporem wstępnym o wartości 60 omów. W zależności od typu i koloru diody LED powstaje prąd LEd między15 mA a maksymalnie 30 mA, co jest jeszcze wartością dopuszczalną.
Program
Strona internetowa tego programu używa tzw. pól wyboru jako elementów HTML. Po załadowaniu programu i otwarciu strony karty pojawia się szereg pól, na które można kliknąć. Zaznaczenie pola oznacza, że pin jest w ustawieniu high. Brak zaznaczenia oznacza low. Teraz należy sprawdzić, które piny muszą być high a które low, żeby wszystkie diody świeciły.
Page 58
Strona internetowa GPIO-Control
W tym kodzie HTML strona internetowa pełni rolę zarówno formularza do wypełnienia oraz elementu podającego informacje. Gdy spojrzymy na element formuły, widać że wykorzystywany jest tam szereg elementów wpisu typu checkbox. Zostają im przypisane indywidualne nazwy wynikające z nazw pinów. Funkcję znaku wieloznacznego w tekście pełni tekst *checkedX*. Gdy pin jest low, znak wieloznaczny zostaje usunięty. Gdy pin jest high, program w miejsce*checkedX* wstawia CHECKED , wskutek czego pole wyboru podczas ładowania jest wyświetlane jako zaznaczone. Tym razem mamy także przycisk, który należy kliknąć po zaznaczeniu odpowiednich pól, aby formularz został przekazany.
001
<form method="GET">
002
<input type="checkbox" *checked2* name="ld2">D2
003
<input type="checkbox" *checked3* name="ld3">D3
004
<input type="checkbox" *checked4* name="ld4">D4
005
<br><br>
006
<input type="checkbox" *checked5* name="ld5">D5
007
<input type="checkbox" *checked6* name="ld6">D6
008
<input type="checkbox" *checked7* name="ld7">D7
009
<br><br>
010
<input type="submit" value="Send">
011
</form></HTML>
Analiza w programie odbywa się w następujący sposób: Załóżmy, że w formularzu
Page 59
zaznaczono pola wyboru 3, 5 i 7. Wtedy URL zmienia się na:
[IP]/?ld3=on&ld5=on&ld7=on
Oznacza to, że przekazane zostają tylko zaznaczone pola wyboru i można je zidentyfikować na podstawie indeksu. W procedurze loop odbywa się to w taki sam sposób. Najpierw cały port D, do którego podłączone są wyjścia cyfrowe, jest ustawiany na low. Następnie pętla while wyszukuje wszystkie »ld« w linku do zasobów. Na podstawie znalezionych ld, w ld3 byłoby to np. 3, można przez przesunięcie 1 w bajcie o wspomniany indeks 3 utworzyć bajt 0b0001000. On jest następnie łączony z aktualną wartością bajtu funkcją LUB. To dzieje się ze wszystkimi przekazanymi indeksami, aż rejestr D będzie miał właściwą wartość. Ta forma podawania informacji zamiast digitalWrite() jest przypuszczalnie dla użytkowników Arduino nieco obca, ale w tym przypadku znacznie praktyczniejsza.
001
if (esp8266.find("+IPD,"))
002
{
003
debug("Incomming Request");
004
int connectionId = esp8266.parseInt();
005
if (esp8266.find("/?")) PORTD = B00000000;
006
while (esp8266.findUntil("ld", "\n"))
007
{
008
int ld = esp8266.parseInt();
009
PORTD |= (1 << ld);
010
}
011
}
W odwrotną stronę podawanie pól wyboru działa w następujący sposób: W funkcji createWebsite() wymieniane są znaki wieloznaczne z dokumentu HTML. Pętla for przeszukuje po kolei wszystkie używane porty. Gdy pin jest high (sprawdzony także tutaj przez porównanie z bajtem, który został utworzony przez przesunięcie bitu high o miejsca indeksu), znak wieloznaczny z indeksem jest zastępowany przez tekstchecked. Gdy pin jest low, znak wieloznaczny zostaje po protu usunięty. Dzięki temu zapewniona jest poprawna prezentacja aktywnych portów.
001
String createWebsite()
002
{
003
String xBuffer;
Page 60
004
005
for (int i = 0; i <= sizeof(site); i++)
006
{
007
char myChar = pgm_read_byte_near(site + i);
008
xBuffer += myChar;
009
}
010
011
for (int x = 2; x <= 7; x++)
012
{
013
if (PORTD & (1 << x))
014
{
015
xBuffer.replace("*checked" + String(x) + "*", "checked");
016
}
017
else
018
{
019
xBuffer.replace("*checked" + String(x) + "*", "");
020
}
021
}
022
return xBuffer;
023
}
Podczas tworzenia tego programu napotkałem kilka problemów, których przyczyna nie była początkowo jasna. Podczas ładowania strony internetowej pojawiały się dziwne błędy i często zaznaczone były niewłaściwe pola wyboru. Za pomocą Arduino-MemoryFree-Master-Library (http://playground.arduino.cc/Code/AvailableMemory) udało się znaleźć rozwiązanie: Pamięć SRAM została zapełniona i to powodowało pojawianie się dziwnych, nieprzewidywalnych błędów. Musiałem znacznie odchudzić pierwotną wersję programu oraz kod HTML, aby program mógł działać w tej wersji. Wspominam o tym, ponieważ przy tworzeniu własnych projektów możecie natrafić na te same problemy. Przyczyną dużego obciążenia pamięci SRAM jest przede wszystkim szerokie stosowanie praktycznej wprawdzie, ale bardzo wyczerpującej zasoby funkcji string oraz generalnie stosowanie ciągów string zamiast łańcuchów char. Funkcja string.replace() jest bardzo praktyczna, ale zużywa bardzo dużo pamięci. Jeśli więc natraficie na nie dające się wyjaśnić błędy, zalecam z jednej
Page 61
strony zmniejszenie kodu źródłowego pliku HTML oraz ewentualnie optymalizację operacji string. Wspomniana wyżej biblioteka może pomóc przy poszukiwaniu błędów.
4.8 | Dygresja: Dostęp do karty z internetu
Wiele z przedstawionych tutaj prób to praktyczne rozwiązania do sterowania kartą w ramach własnej sieci domowej. Jednakże bardzo przydatna może być możliwość dostępu do karty z większej odległości. Można by np. podczas urlopy włączać światła w domu, żeby odstraszyć włamywaczy. Można także poprzez czujnik światła sprawdzić, czy światło jest rzeczywiście wyłączone. Można również wysłać osobom w domu krótką informację, że wrócimy później. Ale żeby zrealizować te pomysły, trzeba dokonać kilku ustawień na routerze.
Zazwyczaj w różnych typach routerów stosuje się także różne oprogramowanie. Omówię tutaj podstawowe czynności na przykładzie routera Fritz!Box. Ustawienia w Waszych routerach powinny być podobne.
Większość nowoczesnych routerów ma prosty interfejs sieciowy, podobny do tego, jaki stworzyliśmy na module. Potrzebna jest nazwa użytkownika i hasło, aby można się było zalogować na interfejsie. W routerach typu Fritz!Box IP to najczęściej 192.168.178.1. Można także wpisać http://fritz.box. Przy zastosowaniu innego routera należy odszukać odpowiedni IP. W reguły router w podsieci używa IP z adresem 1. Jeśli IP Waszego komputera to np. 192.168.4.2, IP routera to najprawdopodobniej 192.168.4.1. Hasło i nazwa użytkownika są zazwyczaj podane z tyłu routera lub w dołączonym podręczniku.
Po zalogowaniu się na interfejsie należy odszukać punkt Portfreigabe lub Portweiterleitung. W moim Fritz!Box punkt ten znajdeuje się pod Internet -> Freigabe. Należy utworzyć nową regułę portu. Ustawienia należy dobrać w taki sposób, aby zewnętrzne zapytania na porcie 80 były przekazywane do IP karty i portu 80. W menu Fritz!Box to ustawienie jest ułatwione i musiałem jedynie wybrać punkt HTTP-Server, późnej w rozwijanym menu mogłem wybrać spośród podanych IP. Wynik powinien wyglądać podobnie na wszystkich komputerach.
Page 62
Poprawne ustawienia w Fritz!Box
Ustawienia w routerze zostały wyjaśnione i można przejść do pierwszej próby. Do tego potrzebny jest IP< ale nie IP karty w lokalnej sieci, lecz Wasz globalny IP. Można to sprawdzić na stronie
http://www.meine-aktuelle-ip.de/ . Po wpisaniu w przeglądarce podanego na tej stronie IP powinna pojawić się
strona internetowa modułu. Tym razem jednak wybraliśmy długą drogę przez internet. Jeśli nie jesteście przekonani, że karta jest rzeczywiście dostę pna przez internet, możecie użyć smartfona z dostępem do internetu i otworzyć na nim stronę. Jeśli w tym czasie smartfon nie jest połączony z żadną siecią WLAN, strona zostanie otwarte przez internet.
Utworzony w ten sposób system doskonale nadaje się do testów, ale w praktycznym zastosowaniu pojawiają się dwa problemy. Po pierwsze nie jest łatwe zapamiętanie IP a po drugie IP zmienia się dość często. Większość routerów wykonuje co najmniej raz dziennie procedurę Reconnect, w związku z czym zmienia się także globalny IP routera. Jest rozwiązanie tego problemu i nazywa się ono Domain Name System (w skrócie DNS). Ten system dba o to, aby można było otworzyć np. www.google.de bez konieczności wpisywania IP, ponieważ koduje on skomplikowane IP prostymi do zapamiętania nazwami. Każda zwykła strona internetowa używa DNS i Wy także macie bezpłatną możliwość korzystania z tego systemu.
Jest wiele różnych stron internetowych oferujących bezpłatne DDNS. DDNS oznacza Dynamic Domain Name System i jest usługą zapewniającą przypisanie IP do właściwej domeny. Przedstawiam tutaj usługę strony http://www.anydns.info/ , ale można wybrać każdą inną usługę web oferującą tę funkcję.
Page 63
Strona internetowa AnyDns.info
Najpierw trzeba zalogować się na stronie internetowej i już wpisać nazwę domeny. Wybrałem nazwę nanoesp oraz hosta dynpc.net. Po zalogowaniu pojawia się domena:
http://nanoesp.dynpc.net/ Teraz usługa musi otrzymać jeszcze Wasze IP. Wpisać usługę do routera, aby
nowy IP został przekazany dalej bezpośrednio do usługi DDNS. W Fritz!Box musiałem kliknąć najpierw na dole na Ansicht: Erweitert , aby wyświetlone zostały wszystkie opcje. Wtedy pod Freigaben można było wpisać usługę DDNS.
Page 64
Ustawienia w Fritz!Box umożliwiające korzystanie z Dynamic DNS
Kilka słów tytułem ostrzeżenia:
Usługa dynamicznego DNS jest wprawdzie bardzo praktyczna, ale należy zachować ostrożność przy podawaniu nazwy domeny. Narażacie się na atak, ponieważ teraz do zaatakowania routera hakerowi wystarczy tylko nazwa domeny i nie musi znać aktualnego IP. Dlatego opisaną wyżej stronę pozostawię w sieci tylko do celów testowych.
THINGSPEAK
Ostatni rozdział dotyczy całkiem nowego tematu a mianowicie platformy ThingSpeak. Ta strona została stworzona specjalnie dla tematu Internet of Things i zawiera wiele różnych praktycznych funkcji. M.in. za pomocą tej strony można w prosty sposób protokołować długookresowe monitorowanie czujników pomiarowych i przestawiać je w przejrzystej formie. Mając połączenie z internetem zbędne staje się zapisywanie wartości na zewnętrznych nośnikach pamięci. Ponadto za pośrednictwem strony internetowej można realizować różne zadania związane ze sterowaniem. Dalsza część rozdziału zawiera wyjaśnienia, jak wyglądają poszczególne funkcje.
5.1 | ThingSpeak
Zanim tak jak do tej pory zajmiemy się konstrukcją i programem, musimy założyć
Page 65
konto na stronie
www.ThingSpeak.com
. Należy zalogować się podając swoje dane użytkownika w punkcie Sign In . Pojawia się strona przedstawiająca Wasze Channels (kanały). Ponieważ nie
macie jeszcze kanałów, jest ona dość pusta. Należy kliknąć na New Channel i wybrać nazwę, np. Light, ponieważ w tym projekcie będziemy mierzyli jasność. W punkcie Field 1 można dodatkowo ustawić nazwę pola, np. Brightness. Pozostałe pola zostawiamy na razie puste.
Tworzenie kanału na stronie ThingSpeak
Page 66
Kliknąć na Save Channel, aby zapisać ustawienia. Teraz następuje przejście na stronę Waszych kanałów, na której na razie znajduje się pusty diagram. W górnej
zakładce należy kliknąć na API Keys. Ciąg liczb i liter podany w punkcie Write
API Key będzie wkrótce potrzebny.
Konstrukcja do tej próby obejmuje czujnik na wejściu analogowym A6. Dzielnik napięcia z opornikiem 10 kΩ i fototranzystor umożliwiają pomiar aktualnej jasności. Można także zastosować czujnik temperatury. Połączenia pozostają
prawie takie same z tążnicą, że tranzystor świetlny zastępuje się czarnym NTC. Biegunowość przy NTC jest bez znaczenia.
Konstrukcja z fototranzystorem na A6
Program
Program mierzy teraz jasność. Jednakże w odróżnieniu od poprzedniej próby dane nie są podawane na stronie internetowej, lecz są wysyłane bezpośrednio na stronę ThingSpeek. Ta strona nie tylko zapisuje dane, lecz prezentuje je przejrzyście w formie wykresu - bardzo praktyczna funkcja przy pomiarze przez dłuższy okres czasu.
Aby program mógł przesyłać dane na stronę internetową, oprócz własnych danych WLAN należy w punkcie ThingSpeakKEY w programie wpisać także wspomniany wcześniej klucz API. Po załadowaniu na szeregowym monitorze widoczne są aktualne wyniki pomiaru. Dane są zbierane przez 15 sekund i następnie wyciągana jest z nich średnia. Ta wartość jest następnie przekazywana na stronę ThingSpeak. 15-sekundowy okres jest ważny, ponieważ nie można obciążać strony ThingSpeak co sekundę nowymi wartościami. Wynik pomiaru jest widoczny na stronie kanałów na przedstawionym poniżej wykresie.
Page 67
Wyniki pomiarów w formie wykresu
Wydaje się, że tekst źródłowy znacznie różni się od wszystkich poprzednich programów. Jednakże chodzi tutaj głównie o zestawienie znanych już elementów. Zmienna Progmem zwiera żądanie HTTP, które musi być wysłane do strony ThingSpeak oraz kilka znaków wieloznacznych, które muszą zostać zamienione w zależności od potrzeb.
001
POST *URL* HTTP/1.1
002
Host: api.thingspeak.com
003
Connection: close
004
Content-Type: application/x-www-form-urlencoded
005
Content-Length: *LEN*
006
007
*APPEND*
Jak widać, wywołanie odpowiada prawiem całkowicie znanemu wywołaniu Get. Także tutaj należy ponownie podać *URL* . Ponadto należy zastąpić *LEN* informacją o długości wiadomości, którą następnie podaje się w miejsce *APPEND* .
Jest uniwersalny obowiązujący dla strony internetowej format, za pomocą którego dane na podstawie zapytania POST są wysyłane na stronę. Jeśli teraz chemy, tak jak pokazuje przykład, wpisać dane pomiarów do kanału na swoim koncie, musimy skorzystać z następującej struktury: *URL* to /update. Jest to podstrona, na którą trzeba wysłać dane. Wiadomość składa się
Page 68
teraz z Waszego klucza AP, pola do wypełnienia oraz wartości. Długość wiadomości można w prosty sposób ustalić na podstawie długości ciągu znaków. W całości przykładowy POST wygląda następująco:
001
POST /update HTTP/1.1
002
Host: api.thingspeak.com
003
Connection: close
004
Content-Type: application/x-www-form-urlencoded
005
Content-Length: 35
006
007
api_key=GXE93O4WF03Q3X8I&field1=954
Na podstawie klucza API strona internetowa może jednoznacznie zidentyfikować użytkownika i kanał i wpisuje wartości. Cała funkcjonalność zestawienia żądań jest ukryta w wielu funkcjach. Do wysłania nowej wartości trzeba wywołać jedynie funkcję sendThingPost() , która jako parametry potrzebuje KEY oraz danych czujnika. Wszystko inne odbywa się automatycznie w tle.
5.2 | Wskaźnik Twitch
Strona internetowa ThingSpeak oferuje coś więcej niż tylko monitorowanie czujników przez dłuższy czas. Poniższy projekt jest podobny do projektów klienta TCP. Pobierane są mianowicie informacje ze strony internetowej z sieci. W tym przypadku chodzi o to, czy określony strumień jest aktualnie online czy nie.
Wariant ThingSpeak ma dwie znaczące zalety w porównaniu do pierwszych prób. Po pierwsze za pośrednictwem ThingSpeak można docierać także do stron internetowych poprzez HTTPS (HyperText Transfer Protocol Secure), podczas gdy moduł obsługuje wyłącznie protokół HTTP, który jest znacznie mniej bezpieczny. Po drugie strona internetowa może wstępnie przefiltrować ważne informacje i tym samym znacznie zredukować ilość danych do przetworzenia przez kontroler.
W tym projekcie zrealizujemy wskaźnik strumienia Twitch jako przykład różnych możliwości. Twitch (www.twitch.tv) to strona internetowa,a na której są przesyłane strumieniowo gry na żywo lub inne treści związane z grami komputerowymi. Jednym z bardziej znanych kanałów jest RocketBeansTV dawnego twórcy GameOne. Ten kanał nadaje 24 godziny na dobę i dzięki temu bardzo dobrze
nadaje się do pierwszego testu. Później można oczywiście skorzystać z kanału wg własnego wyboru.
Page 69
Konstrukcja próby z diodą LED na pinie D9
Program
Obok przygotowania sprzętu konieczne jest także wykonanie kilku czynności na stronie ThingSpeak. Po kliknięciu na stronie internetowej w najwyższym menu na Apps wyświetla się szereg różnych aplikacji. W tym przypadku zajmiemy się aplikacją ThingHTTP. Po kliknięciu na odpowiedni przycisk najpierw pojawia się raczej pusty interfejs. Kliknąć na New ThingHTTP. W wyświetlonym formularzu należy wpisać:
Name: Twitch URL: https://api.twitch.tv/kraken/streams?channel=
rocketbeanstv Method: GET HTTP Version: 1.1 Parse String: _total Jeśli preferowany jest inny kanał przesyłania strumieniowego, można w URL po
channel wpisać inny kanał. Kliknąć na Save ThingHTTP i następnie skopiować do schowka klucz API wyświetlony w nagłówku. Teraz należy skopiować klucz do programu w miejsce za #define ThingHTTP. Należy pamiętać o danych WLAN i już można załadować program. Raz na minutę program sprawdza, czy jest dostępny strumień. Jeśli tak, zapala się dioda LED.
Realizacja tego projektu jest możliwa, ponieważ strona Twitch udostępnia informacje także w znanym juz formacie JSON. Na stronie:
https://api.twitch.tv/kraken/streams?channel=rocketbeanstv można obejrzeć informacje podawane w formacie JSON. Jest to bardzo duża ilość
tekstu, ale nas interesuje atrybut _total, który informuje o ilości aktywnych strumieni. Gdy ta liczba jest większa od zera, oznacza to, że co najmniej jeden strumień jest aktywny. Z tego atrybutu strona ThingSpeak automatycznie wydziela istotne dane (można powiedzieć: analizuje go) i podaje w formie przejrzystej
Page 70
wartości. Tę wartość można później w prosty sposób w programie wywołać i przeanalizować funkcją getThingSpeakHttp().
5.3 | Instalacja alarmowa Twitter
Ten projekt dotyczy instalacji alarmowej, za pomocą której można np. sprawdzić, czy ktoś nieuprawniony nie otworzył szuflady. Instalacja na bieżąco sprawdza, czy na podłączony czujnik światła nie pada światło o ustalonej jasności. Jeśli tak, rozlega się dźwięk alarmu i jednocześnie zostaje wysłana informacja przez Twittera. Konstrukcję ukazuje poniższa ilustracja. Alternatywnie można tutaj także
zastosować czujnik temperatury i monitorować przekroczenie określonej temperatury.
Czujnik światła do A0, element piezoelektryczny do D8
Program
Tematem jest tutaj m.in aplikacja Twitter stronyThingSpeak. Należy więc kliknąć na Apps a następnie naThingTweet. Po kliknięciu na Link TwitterAccount i wpisaniu danych dostępu nawiązuje się połączenie między tymi dwoma usługami. Jeśli nie masz jeszcze konta na Twitterze, zaleca się założenie konta do celów testowych na czas pracy z pakietem. Po pomyślnym połączeniu Twitter z ThingSpeak, można znajdujący się pod Apps/ThingTweet klucz API wpisać do programu za punktem #define TwitterKEY .
Teraz program sprawdza ciągle, czy zmierzona jasność wzrośnie ponad wartość
Page 71
500. Jeśli tak, zostanie wysłana wiadomość przez Twittera i rozlegnie się alarm. Będzie on trwał tak długo, aż jasność ponownie spadnie poniżej 500. Aktualnie zmierzone wartości jasności można śledzić na szeregowym monitorze. Do pierwszych testów zalecam zakrycie czujnika światła, aby alarm nie uruchomił się za szybko.
Nowa funkcja w tym projekcie nazywa się sendTwitterPost(). Jako parametr należy jedynie wpisać TwitterKEY i podać wiadomość. Funkcja zbiera wszystkie niezbędne elementy, aby stworzyć z tego post ThingSpeak. Można więc naciśnięciem guzika wysyłać wiadomości lub publikować wyniki pomiarów. Wszystko dzięki prostej aplikacji ThingSpeak.
5.4 | TalkBack
Ten projekt dotyczy kolejnej aplikacji strony ThingSpeak a mianowicie aplikacji TalkBack. Funkcja ta umożliwia utworzenie polecenia, które zostanie odczytanie i wykonane przez kontroler. To, co wydaje się pozbawione sensu przy jednym kontrolerze, wygląda zupełnie inaczej, gdy zastosuje się dwa kontrolery lub całą sieć. Niektóre karty mogą wtedy działać jak czujniki, np. z czujnikami ruchu, i wysyłać polecenie TalkBack w przypadku wykrycia ruchu. Kolejny moduł odczytuje polecenie ze strony ThingSpeak i otwiera wtedy drzwi lub uruchamia alarm.
Do zbudowania układu potrzebny jest drugi przycisk. Dioda LED z opornikiem wstępnym wskazuje aktualny stan.
Konstrukcja z dwoma włącznikami na D5 i D10 oraz diodą LED na D9
Program
Najpierw w Apps/TalkBack trzeba utworzyć nowy kanał TalkBack. Jako nazwy można uzyć np. Doors. Polecenia moż na także wpisać w kanale. Może to być
Page 72
utworzony już kanał Light z pierwszej próby ThingSpeak lub inny własny kanał. Wtedy wszystkie polecenia są protokołowane. Istotny jest jednak przede wszystkim klucz API, który jest wpisywany w #define TalkBackKEY . Tym razem dodatkowo oprócz klucza API potrzebny jest także ID, który można znaleźć w podglądzie pod TalkBack ID po kliknięciu na Save TalkBack. Ten ID należy wpisać po #define TalkBackID do programu.
Po załadowaniu programu i otwarciu szeregowego monitora pojawi się najpierw komunikat No Command. Teraz należy nacisnąć jeden z dwóch przycisków. Po krótkim czasie pojawia się komunikat OpenDoor lub CloseDoor, w zależności od tego, który przycisk został naciśnięty. Ponadto przy poleceniu OpenDoor zapala się dioda LED.
Podglą TalkBack przy wpisywaniu polecenia
Istnieje także możliwość wpisywania poleceń bezpośrednio przez internet. Po kliknięciu na stronie TalkBack na swój kanał Doors na dole pojawia się opcja Add a new command. Korzystając z tej opcji można ręcznie wpisać polecenie
Page 73
OpenDoor lub CloseDoor i w ten sposób sterować modelem. Kartą można sterować także z różnych innych źródeł poprzez polecenia TalkBack. W tekście źródłowym funkcja getTalkBackCom() przejmuje zadania sprawdzania nowych poleceń. Gdy coś zostanie znalezione. polecenie jest zwracane. Trzeba podać jedynie parametry key i id .
5.5 | Cheerlights
Ta próba opiera się na projekcie Hansa Scharlera o nazwie Cheerlights. Idea: Światła na całym świecie zebrane w sieć, którymi można symultanicznie sterować
za pomocą poleceń Twitter. Dobry przykład na to, że świat jest coraz bardzie zrośnięty z internetem.
Dioda LED RGB na karcie na pinach D3, D5 i D6
Program
Do aktualnego programu wyjątkowo nie trzeba dokonywać własnych zmian ThingSpeak, ponieważ projekt ma już publiczny kanał, który znajduje się na
https://thingspeak.com/channels/1417 . Na tej stronie można poza tym znaleźć zawsze aktualny kolor oraz dalsze
informacje na temat projektu.
Page 74
Strona Cheerlights z aktualnym kolorem liliowym
Do programu niezbędna jest poza tym Crossfade-Library Radka Wierzbickiego (źródło: https://github.com/radekw/Arduino/tree/5f24ce7c8db9dfbb5252b59824c3217d851 b3a3c). Ze względów praktycznych kopia używanej wersji Library znajduje się w folderze szkicu. Musi ona zostać skopiowana do folderu libraries Twojego szkicownika. Library umożliwia szybkie i proste definiowanie kolorów i poza tym powoduje, że diody LED powoli przechodzą z jednego koloru do drugiego (tzw. fade).
Po załadowaniu programu po kilku sekundach pojawia się aktualny kolor diody LED. Teraz można napisać wiadomość Twitter i w ten sposób zmienić kolor nie tylko swojej diody LED, lecz kolor diod wszystkich innych użytkowników Cheerlights. Wiadomość musi po pierwsze zawierać #Cheerlights, @Cheerlights lub po prostu tylko hasło Cheerlights i po drugie po haśle musi być podany jeden ze zdefiniowanych wstępnie kolorów. Zdefiniowane wstępnie kolory to:
red, green, blue, cyan, white, warmwhite, purple, magenta, yellow, orange, pink
Page 75
Możliwy tweet może wyglądać np. tak:
Testing my #cheerlights project on my #NanoESP with the color blue #ThingSpeak #IoT
I w ten sposób nadaje się całemu światu nowy kolor. Sprawdzanie aktualnego koloru odbywa się przy użyciu funkcji
getCheerlightColor() . Jako parametry podaje się hosta, czyli api.thingssspeak.com, oraz URL, tutaj /channels/1417/field/1/last.txt. Jest to więc proste sprawdzenie klienta TCP znanego rodzaju. Także w tym przypadku odpowiedź serwera jest skracana do istotnego tekstu i odsyłana. Porównanie z hasłami daje poszukiwany kolor, który następnie jest wyświetlany za pomocą Crossfade-Library. Stosunkowo łatwa próba dająca duży efekt.
5.6 | Czujnik pożaru Twitter z funkcją TalkBack
Ten projekt czujnika pożaru łączy dwa elementy, które poznaliście w trakcie pracy z niniejszym pakietem. Karta jest stosowana m.in. do długookresowego monitorowania temperatury. Jednocześnie karta może wydać sygnał alarmowy, gdy temperatura przekroczy określoną wartość, np. gdy pojawi się pożar. Tutaj kontrolowanie przekroczenia wartości progowej nie jest zadaniem karty, lecz aplikacji ThingSpeak React.
Do funkcji czujnika pożaru jako czujnik używany jest NTC (Negative Temperature Coefficient) prezentowany do tej pory tylko jako alternatywa dla czujnika światła. Zmiania on swoją oporność w zależności od temperatury. Można go podłączyć do
opornika 10 kiloom, ale w tym przypadku użyto potencjometru, ponieważ w ten sposób można jeszcze wyregulować pomiar.
Page 76
Układ projektu czujnika pożaru
Program
Program musi połączyć ze sobą wiele różnych elementów. Duże znaczenie ma tutaj ponownie strona ThingSpeak. M .in. także tutaj aplikacja ThingSpeak będzie zajmować się monitorowaniem wartości progowej NTC. Z tego miejsca będą także realizowane alarmy a mianowicie będzie wysyłana wiadomość na Twottera oraz będzie wprowadzane polecenie TalkBack, które będzie wyzwalać alarm na kontrolerze.
W pierwszym rzędzie należy na stronie ThingSpeak utworzyć nowy kanał. Można go nazwać przykładowo FireAlarm. Pole field 1 otrzymuje wtedy nazwę Temp. W API Key znajduje się pierwszy klucz, który należy pod ThingSpeakKEY. Tym samym transmisja aktualnej wartości temperatury jest już zapewniona.
W drugim kroku należy utworzyć nowy element TalkBack. Jako nazwę można użyć przykładowo Alarms. Ponadto można zalogować polecenia w kanale FireAlarm. Klucz API należy wpisać po TalkBackKEY a ID po TalkBackID. Teraz można już wysyłać polecenia do karty. Można także ręcznie wpisywać polecenia. W tym celu w podglądzie TalkBack kanału alarmu należy kilknąć naAdd a new Command i tam wpisać polecenie pod Command String Alarm . Podanie pozycji nie jest konieczne, ponieważ polecenie jest zapisywane automatycznie na pierwszym miejscu. Można teraz już załadować program i przetestować, czy transmisja aktualnej wartości temperatury funkcjonuje i czy karta wykonuje polecenia. W tym miejscu zaleca się także skalibrować NTC na potencjometrze przy użyciu zwykłego termometru.
Właściwie byłby to już w pełni wartościowy projekt, ale brakuje jeszcze funkcji
Page 77
dodatkowych. Te jednak nie są wykonywane w programie, lecz na stronie ThingSpeak. W tym celu należy przejść do Apps i następnie wybrać React . Poprzez React można zareagować na określone zdarzenia. Klikająć na New React należy zatem stworzyć nową funkcję React i wpisać następujące wartości:
Name: FireDetect1 Condition Type: Numeric Test Frequency: On Data Insertion Condition: If Channel FireAlarm field 1 (Temp) is greater than 40 Action: ThingTweet then tweet:
Fire Alarm on the #NanoESP! Temp: %%trigger%%C
#ThingSpeak #IoT Using Twitter Account [Twitter Account] Opcje: Run action only the first time the condition is met Zapisać ustawienia przez Save React. Pierwszy krok monitorowania został
wykonany. Gdy wartość zostanie przekroczona, ThingSpeak wysyła przez Twoje konto wiadomość na Twittera. Do wykonania drugiego kroku czyli wprowadzenia poleceń alarmu należy sięgnąć nieco głębiej do worka z trikami, ponieważ ta funkcja nie jest obsługiwana automatycznie. Obsługiwany jest jednak ThingHTTP. Czyli należy kliknąć na Apps a następnie na ThingHTTP. Tam należy utworzyć nowy element i dokonać następujących ustawień:
Name: Alarm
URL: https://api.thingspeak.com/talkbacks/[YOUR
TALKBACK ID]/commands Method: POST HTTP Version: 1.1 Host: api.thingspeak.com Headers:
Body: api_key=[YOUR TALKBACK ID]Key
command_string=Alarm&position=1 Należy zwrócić uwagę, aby [YOUR TALKBACK ID] i [YOUR TALKBACK KEY] w
URL oraz w Body-Part zastąpić własnym TalkBack ID i własnym KEY . Teraz można utworzyć kolejny element React, który zawiera takie same parametry, jak pierwszy z tą zmianą, że w Action należy wybrać ThingHTTP a tam punkt Alarm. Tym samym mamy pewność, że rozlegnie się alarm, gdy przekroczona zostanie wartość krytyczna.
Page 78
Można także ustawić czasowe sterowanie alarmem. W tym celu w Apps należy kliknąć na TimeControl i utworzyć nowy element, np. o nazwie AlarmClock. Tam należy dokonać następujących ustawień:
Name: Presents Frequency: One Time Time Zone: Berlin Run At: 2015-24-12 7:00 am Fuzzy Time: ± 0 minutes TalkBack: Alarms, add command: Alarm
Poprawne ustawienia TalkBack dla alarmu pożarowego
Do pierwszego testu zaleca się wybranie czasu za kilka minut. Jeśli zadziała, można ustawić poprawny czas. Nie jest to na pewno najpiękniejszy dźwięk budzika, ale za to szczególnie efektywny.
Page 79
ZAŁĄCZNIK
Polecenia AT
Polecenie
Pisownia
Podstawowe informacje
Polecenie testowe
AT
Reset
AT+RST
Informacje o firmware
AT+GMR
Echo wł./wył.
ATE<1/0>
Polecenia WLAN
Tryb WLAN (1 = Client, 2 = AP, 3 = podwójny)
AT+CWMODE=<mode>
Poszukiwanie sieci WLAN
AT+CWLAP
Połączenie WLAN
AT+CWJAP=«<ssid>«,«<pass >«
Rozłączenie WLAN
AT+CWQAP
Ustawienia punktu dostępu WLAN
AT+CWSAP=«<ssid>«,«<pas s>«[,<chan>,<enc>]
Podanie adresu IP
AT+CIFSR
Aktywacja/dezaktywacja DHCP
AT+CWDHCP=<1/0>
Automatycznie połączenie WLAN
AT+CWAUTOCONN=<1/0>
Page 80
Zmiana adresu MAC stacji
AT+CIPSTAMAC=<MAC>
Ustawianie adresu IP (stacja)
AT+CIPSTA=<IP>
Ustawianie adresu IP (punkt dostępu)
AT+CIPAP=<IP>
Uruchomienie SmartConfig
AT+CWSTARTSMART=<typ>
Zatrzymanie SmartConfig
AT+CWSTOPSMART
Komunikacja
Funkcja ping
AT+PING=<HOST>
Zezwolenie na wiele połączeń
AT+CIPMUX=<mode>
Tryb danych (0=transparentny, 1=tryb danych)
AT+CIPMODE=<mode>
Struktura odebranych danych
+IPD,<id>,<len>:<data>
Nawiązanie połączenia
AT+CIPSTART=«<type>«,«<a ddress>«,<port>
Wysłanie danych
AT+CIPSEND=<id>,<len>
Rozłączenie połączenia
AT+CIPCLOSE=<id>
Polecenia serwera
Uruchomienie serwera
AT+CIPSERVER=1,<port>
Zakończenie serwera
AT+CIPSERVER=0
Status serwera & połączeni klienci
AT+CIPSTATUS
Ustawienie timeout serwera
AT+CIPSTO=<timeout>
Wyświetlanie połączonych klientów
AT+CWLIF
Page 81
Pinout
Loading...