Conrad Components 10215 Profi Lernpaket Internet of Things Course material 14 years and over Instrukcja obsługi

Conrad Components 10215 Profi Lernpaket Internet of Things Course material 14 years and over Instrukcja obsługi
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ę
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
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:
Pamięć flash:
SRAM:
EEPROM:
Częstotliwość taktowania:
Piny I/O:
ATmega328
32 kB (z tego 0,5 kB na bootloader)
2 kB
1 kB
16 MHz
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:
5V
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:
SPI-Flash
Napięcie robocze:
Standardy WLAN:
Tryby WLAN:
Firmware:
Inne:
ESP8266
4 Mbit
3,3 V
802.11 b/g/n
Wi-Fi Direct (P2P), Soft-AP
AT-Firmware wersja 0.22
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.
1
1
1m
2
1
1
1
1
1
1
1
1
1
Karta IoT-WiFi (NanoESP)
płytka ze złączami wtykowymi
drut sterujący
przyciski
klips 9-V
dioda LED (czerwona)
dioda LED RGB (4 piny podłączeniowe)
opornik 10 kiloomów (brązowy-czarny-pomarańczowy)
opornik 1 kiloom (brązowy-czarny-czerwony)
fototranzystor (2 piny podłączeniowe)
NTC 10 kiloomów
głośnik piezoelektryczny
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 SoftwareSerialLibrary, 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
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:
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?
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
.
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ę
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.
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
eń w załączniku i na stronie
utworzenie wewnętrznej sieci z wieloma modułami
i jeden z modułów ma pełnić rolę serwera
olecenia znajdują się także w
dostarczającego dane do sieci. Więcej na ten
wspomnianej już wcześniej stronie
temat w dalszej części.
t.fkainka.de. Niektóre polecenia, jak
ci transmisji sygnału, zostały
e, ponieważ można nimi uczynić
ym.
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.
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
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
006
Serial.println(Msg);
}
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,
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
009
esp8266.write(Serial.read());
}
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
}
015
else
016
{
017
018
success &= false;
}
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);
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
006
success &= (sendCom("AT+CWMODE=2", "OK"));
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
póź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:
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
019
Serial.println("Ping Error");
}
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
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.
mi wtykowymi, 1 x NanoESP, 1 x
yczny, drut sterujący
Podłączenie głośnika piezoelektrycznego
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
004
005
esp8266.println("AT+CWLAP");
if (esp8266.findUntil(ToFindSSID,"OK")) alarm();
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
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ć róż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
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ę póź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
pomyślnie.
żadnej
gwarancji,
że
dane
zostały
U Ponadto nie ma gwarancji, że dane nie zostały
zafałszowane lub przechwycone przez osoby trzecie.
przekazane
po
drodze
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.
telefonowanie przez internet).
do
VoIP
(Voice
over
IP
–
czyli
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/
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.
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.
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
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
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
Róż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ść
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.
mi wtykowymi, 1 x NanoESP, 1 x
a), 1 x opornik 1 kiloom (brązowyrut sterujący
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():
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
{
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.
mi wtykowymi, 1 x NanoESP, 1 x
Połączyć przycisk z kontrolerem tak, jak pokazano
a), 1 x przycisk, 1 x opornik 1 kiloom
na ilustracji.
erwony), drut sterujący
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.
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.
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
mi wtykowymi, 1 x NanoESP, 1 x
zestawie potencjometr 10 kΩ. Budowa jest
ornik 1 kiloom (brązowy-czarnyukazana na poniższej ilustracji.
ncjometr, drut sterujący
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ć póź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
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.
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 TCPProtokoll (Transmission Control Protocol). Moduł będzie pracował w tym rozdziale
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ść
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.
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ć róż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
póź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/intwo-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
004
boolean success = true;
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), ">");
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;
parseInt detects negativ integer
024
if (xmonth < 0) xmonth *= -1;
parseInt detects negativ integer
//Because of date seperator //Because of date seperator -
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 }
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ęść RequestHeader 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
mi wtykowymi, 1 x NanoESP, 1 x
jednym spojrzeniem ocenić, czy należy ubrać
x opornik 1 kiloom (brązowy-czarnyciepłą kurtkę.
ujący
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.
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
004
int green, blue, red ;
005
006
007
if (val <= 10 & val >= -20)
blue = map(val, -20, 10, 255, 0);
else blue = 0;
008
009
010
if (val >= 10 & val <= 40)
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
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ż
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
mi wtykowymi, 1 x NanoESP, 1 x
smartfonów),
który
może
zasilać
kartę
w
prosty
a), 1 x opornik 1 kiloom (brązowysposób przez gniazdo micro-USB.
rut sterujący, 1 x bateria 9 V (brak w
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
010
if (esp8266.findUntil("LED","\n")) digitalWrite(LED, !digitalRead(LED));
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.
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, initialscale=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.
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
006
if (sendCom("AT+CIPSEND=" + String(connectionId) + "," +
String(webpage.length()), ">"))
{
007
esp8266.print(webpage);
008
esp8266.find("SEND OK");
009
success &= sendCom("AT+CIPCLOSE=" + String(connectionId),
"OK");
010
}
011
else
012
{
013
success = false;
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, userscalable=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
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
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
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
mi wtykowymi, 1 x NanoESP, 1 x
także na smartfonach. Budowa jest ukazana na
x opornik 1 kiloom (brązowy-czarnyponiższej ilustracji.
ujący
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
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 ColorPicker. 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ł
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;
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
mi wtykowymi, 1 x NanoESP, 1 x
opornik ma 10 kiloomów.
opornik 10 kiloom (brązowy-czarnyut sterujący
Podłączenie fototranzystora do pinu A6 z opornikiem 10 kiloomów
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* .
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
mi wtykowymi, 1 x NanoESP, 1 x
x dioda LED, drut sterujący
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.
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
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;
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
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.
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ę.
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.
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ć
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
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ą różnicą, że tranzystor
świetlny
zastępuje
się
czarnym
NTC.
mi wtykowymi, 1 x NanoESP, 1 x
Biegunowość przy NTC jest bez znaczenia.
opornik 10 kiloom (brązowy-czarnyut sterujący
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.
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ę
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
mi wtykowymi, 1 x NanoESP, 1 x
wyboru.
a), 1 x opornik 1 kiloom (brązowyrut sterujący
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
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.
mi wtykowymi, 1 x NanoESP, 1 x
opornik 10 kiloom (brązowy-czarnyelement piezoelektryczny, drut
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ść
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
mi wtykowymi, 1 x NanoESP, 1 x
wskazuje aktualny stan.
a), 1 x opornik 1 kiloom (brązowyrut sterujący
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ć
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
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.
mi wtykowymi, 1 x NanoESP, 1 x
x opornik 1 kiloom (brązowy-czarnyujący
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.
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
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
mi wtykowymi, 1 x NanoESP, 1 x
jeszcze wyregulować pomiar.
ement piezoelektryczny, 1 x NTC, 1 x
ut sterujący
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
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.
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.
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>
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
Pinout
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement