ESP8266, IoT – praktyczny przykład cz. 1

ESP8266 - IoT ESP8266 pojawił się najpierw jako prosty interfejs WiFi dla Arduino. Społeczność szybko odkryła, że jego  możliwości są znacznie większe, gdyż w jego wnętrzu znajduje się wydajny mikrokontroler. Pokażę Wam jak można szybko zrobić coś użytecznego z ESP8266, co będzie waszym pierwszym krokiem w świat IoT – czyli Internet of Things

Rodzaje modułów ESP8266

Są aktualnie trzy rodzaje modułów ESP w naszej ofercie. Ich oznaczenia to ESP8266-01, ESP8266-07 lub ESP8266-12. Różnią się ilością wyprowadzeń.
Moim ulubionym jest „-07”. Wyposażony jest w 9 pinów GPIO, wbudowaną antenę oraz złącze zewnętrznej anteny. Docenisz to gdy będziesz chciał umieścić ESP w metalowej obudowie :).
ESP8266-12 ma tylko wbudowaną antenę.
ESP8266-01 jest wyposażony w wygodne złącze 2×4 o rozstawie pinów 2.54 mm. Posiada tylko 2 styki GPIO mogące pracować jako rozmaite interfejsy szeregowe.

Dlatego do projektów wymagających więcej niż dwa wyjścia GPIO  ESP -07 lub -12 jest najlepszym wyborem.

Co zbudujemy?

ESP8266 świetnie się sprawdza jako mały serwer w sieci, dzięki któremu możemy albo odczytywać jakieś dane albo czymś sterować. Jako przykład użycia zbudujemy serwer kontrolujący przez moduł przekaźników dwa urządzenia elektryczne. Prosta strona WWW, która pozwoli nam zdalnie je włączyć bądź wyłączyć. Świetny start do własnego systemu automatyki domowej.

Lutowanie modułu ESP8266 do adaptera

Moduły -07 i -12 nie mają goldpinów –  przeznaczone są do wlutowania w płytkę drukowaną, dlatego do prototypów niezbędny będzie adapter.

ESP8266-07 z adapterem
ESP8266-07 z adapterem

Lutowanie ESP na adapterze nie jest trudne. Miejsca lutownicze modułu pokryte są cyną i przygotowane do lutowania w piecu. Nie nadają się do lutowania lutownicą. Dlatego, najlepiej usunąć tą cynę za pomocą plecionki. Potem położyć ESP, przylutować dwa pady na przeciwległych krańcach (po przekątnej). Potem po kolei, resztę padów.

Podłączenie modułu ESP8266

Adapter jest tak szeroki, że sięga ostatnich wtyków płytki stykowej. Można podłączyć ESP do płytki stykowej przez przewody męsko-żeńskie. Można też użyć zworek typu JW-140, by przenieść wszystkie połączenia kilka rzędów niżej:

Dzięki zworkom - ESP mieście się na jednej płytce stykowej
Dzięki zworkom – ESP mieście się na jednej płytce stykowej
Dzięki zworkom - ESP mieście się na jednej płytce stykowej
Dzięki zworkom – ESP mieście się na jednej płytce stykowej

Przedstawione wyżej rozwiązania są niewygodne, gdyż zaciemniają czytelność układu. Trudno potem znaleźć wadliwe połączenie.

Jak najwygodniej podłączyć ESP do płytki stykowej?

Polecam inną metodę – „na bogato”  ponieważ wymaga dwóch płytek stykowych. Zapewnia duże pole robocze i możliwość wpinania przewodów tuż przy podpisanych wyprowadzeniach adaptera.

Doceniłem to zwłaszcza od czasu gdy zajmuję się więcej niż jednym projektem na raz. Aby nie być gołosłownym: krótki przegląd tego co dziś mam na półce:

Przegląd bieżących projektów
Przegląd bieżących projektów

Mając wszystko na płytce stykowej, bez wiszących elementów na przewodach można przekładać projekty z miejsca a miejsce nie ryzykując, że coś się rozłączy. Wiadomo – płytka stykowa zawsze jest podatna na rozłączenie przy szarpnięciu, ale można minimalizować takie ryzyko.

OK, no to jak się podłączyć? Okazuje się, że choć płytki stykowe mają możliwość połączenia ich razem zatrzaskami, nie dla nas to rozwiązanie. Nieszczęsny adapter do ESP ma taki rozstaw pinów, że po trwałym połączeniu płytek, piny nie będą pasować do otworów… Pozostaje płytki zetknąć a wtedy adapter ESP pasuje jak ulał.

Jak połączyć płytki z adapterem ESP
Jak połączyć płytki z adapterem ESP

Nie jest to rozwiązanie idealne. Płytki ruszają się lekko, bo połączone są tylko płytką adaptera ESP. Trzeba pamiętać o tym przenosząc projekt. Ale jeżeli zwrócisz na to uwagę, to taka platforma świetnie się sprawdza. Uwaga – zdaje się, że odczepienie jednej szyny zasilającej od płytki stykowej pozwoli połączyć całość zatrzaskami na sztywno i adapter wtedy będzie pasował. Ale nie sprawdzałem tego, YMMV…

Po wsadzeniu adaptera zostaje przygotować sobie płytkę. Połączmy szyny zasilania i masy w centralnej części płytki (bo są to duże, 830 polowe płytki i one mają szyny zasilania podzielne w połowie. Symbolizuje to przerwa w czerwonej i niebieskiej kresce wzdłuż szyny. Dlatego – zworki się przydadzą (również do połączenia obu szyn).

Zworki rozprowadzające zasilanie
Zworki rozprowadzające zasilanie

Skąd brać zasilanie? ESP potrzebuje koniecznie zasilania 3.3V (maksymalnie 3.6V), nie ma mowy, aby podłączyć zasilanie 5V. Do komunikacji z komputerem używany jest port szeregowy UART, tak więc niezbędny będzie konwerter USB/Serial.

Niektóre z takich konwerterów, choć w nazwie mają 3.3V linie zasilającą mają 5V, więc uważaj by nie popełnić błędu i nie podłączyć zasilania z takiego konwertera do ESP. Niektóre z nich mają możliwość wybrania czy Vcc będzie 5V czy 3.3V (np FTDI Friend lub MMUSB). Jednak nawet taki konwerter może nie być wystarczający. W zależności od trybu pracy ESP pobiera nawet 150 mA prądu – konwertery zwykle nie są w stanie zapewnić tak dużego poboru prądu.

Ja w takich sytuacjach używam tego co zwykle mam pod ręką w dużych ilościach, a jest szansa że masz też to na swoim warsztacie  – Arduino UNO! Ważne by to było UNO, nie Leonardo – ma dedykowany układ służący jako konwerter USB/Serial oraz stabilizator 3.3V pozwalający zasilić ESP. Co prawda, Arduino podaje na swoich stronach, że maksymalny prąd pinu 3.3V to 50 mA, ale jeśli spojrzeć na schemat UNO (przynajmniej na wersję od Arduino.org, którą obecnie sprzedajmy), to użyty regulator 3.3 V to LP2985-33DBVR. Po krótkim googlaniu wychodzi na to, że ma wydajność 150 mA, więc może to tłumaczy, czemu ESP jednak po prostu dobrze działa zasilany z UNO… Jednak, gdy wyjdziesz poza prototyp, warto użyć porządnego stabilizatora na 3.3V który bez problemu te 200-300 mA dostarczy…

Podłączmy zasilanie do naszych przygotowanych szyn na płytce stykowej.

Podłącz pin 3.3V do płytki
Podłącz pin 3.3V do płytki

Teraz – konwerter USB/Serial. Możesz wyjąć fizycznie ATmegę328 z podstawki (tak długo jak masz wersję nie-SMD) ale to jest ryzyko wygięcia nóżek i zupełnie niepotrzebna operacja. Wystarczy wziąć przewód i spiąć na stałe wejście RESET i GND. Spowoduje to blokadę układu ATmega328 i nie będzie on w żaden sposób kolidować z transmisją komputer <-> ESP. Jest tylko jedna rzecz, na którą trzeba zwrócić uwagę. Oznaczenia na płytce Arduino portów TX i RX dotyczą wyjść z ATmegi.

Gdybyś chciał podłączyć ESP, tak by komunikowało się z UNO, to wówczas robimy przeplot – TX z UNO podłączamy z RX z ESP a RX z UNO z TX z ESP. Sęk w tym, że tym razem zablokowaliśmy ATmegę a ESP ma zastąpić ATmegę. Dlatego połączymy TX na płytce z TX na ESP i RX na Arduino z RX na ESP.  Dzięki temu komputer będzie mógł komunikować się z ESP.

Test połączenia

Do wgrywania programu na ESP przyda się ESPlorer. Oprócz wsparcia dla LUA (język programowania który będziemy używali) potrafi też się dogadać z ESP korzystając z komend AT. Ponieważ i tak użyjemy go później to:  ściągnąć, zainstalować, uruchomić (wymaga Javy do pracy).

Wybierzmy port szeregowy do którego podpięte jest UNO, prędkość 115200 i klikamy Open. Z lewej strony powinna być wybrana zakładka AT v0.20. Po poprawnym nawiązaniu połączenia, w białym oknie po prawej stronie powinny pojawić się komunikaty takie jak na zdjęciu:

ESPlorer w akcji
ESPlorer w akcji

Najważniejsze to:

Communication with MCU... 
Got answer! AutoDetect firmware... 
 
AT-based firmware detected.

Dzięki temu wiemy, że nasze podłączenie do ESP jest poprawne i działa komunikacja.

Przygotowanie oprogramowania

Nowe ESP ma wgrane oprogramowanie SDK od producenta. Można się z nim komunikować przez port UART tak jakby był modemem. Jedak my chcemy używać ESP jak normalny mikrokontroler, także chcemy wgrywać własny kod a nie tylko sterować komendami AT.

Społeczność opracowała już rozszerzenie do Arduino IDE pozwalające pisać programy  tak jak na Arduino. My jednak w tym przykładzie zastosujemy inne podejście. Wgramy na ESP oprogramowanie nodeMCU. Jaka jest różnica? Nie wchodząc w techniczne detale, zależy nam by łatwo operować na łańcuchach znakowych, a w nodeMCU (język LUA) jest to na pewno prostsze i mniej okazji do popełnienia błędów (w porównaniu do C/C++). W przyszłości pokażę też jak programować ESP z użyciem Arduino IDE, ale tym razem – nodeMCU – nadchodzimy!

Pierwszy krok – oprogramowanie nodeMCU. Składa się z różnych modułów, można je przygotować samodzielnie, ale nie jest to trywialne zadanie dla początkującego. Dlatego istnieje coś takiego jak http://nodemcu-build.com/ czyli strona, która zbuduje dla nas wybrane firmware. Dla naszego przykładu sterowania modułami przekaźników standardowy zestaw nam wystarczy. Jeżeli jednak planujesz korzystać z nodeMCU w innym projekcie może będziesz musiał zaznaczyć dodatkowe opcje – np obsługę OneWire czy I2C. Podajesz adres email i zazwyczaj w ciągu kilku, kilkunastu minut otrzymujesz dwa pliki z firmware. Jeden z integer w nazwie, drugi z float. Pierwszy obsługuje tylko operacje na liczbach całkowitych ale za to oferuje mniejszą zajętość pamięci.

Teraz pozostaje wgrać ten plik na nasze ESP. Użytkownicy Windowsa mają do dyspozycji nodemcu-flasher a użytkownicy Linux esptool napisany w pythonie. Nim  wgrasz nowy firmware, nie zapomnij zamknąć portu szeregowego w programie ESPlorer, bo nie jest możliwa komunikacja z portem szeregowym dwóch programów jednocześnie.

Wgrywanie firmware odbywa się w specjalnym trybie pracy ESP. By go włączyć w takim trybie, podepnij GND do pinu GPIO0 i odłącz na chwilę zasilanie Vcc od ESP i włącz ponownie. Teraz ESP jest gotowy do wgrania nowego firmware:

./esptool.py --port /dev/ttyACM0 write_flash 0x000000 bins/nodemcu-master-7-modules-2016-03-07-23-47-41-integer.bin

Część wytłuszczona to ścieżka do firmware otrzymanego z nodemcu-builder.

Pierwszy program w LUA

Po udanym wgraniu firmware pozostaje przetestowanie czy wszystko jest jak należy. W tym celu podłączymy się do lokalnej sieci WiFI (wszędzie jest, nie?).  Uruchamiamy ponownie ESPlorer, port szeregowy zostaje ten sam jednak prędkość spada do 9600 (takie jest ustawienie nodeMCU, fabryczny firmware działał na 115200). Przełącz się tym razem na zakładkę NodeMCU + MicroPthon. W obszar edycji po lewej wklej kod ściągnięty z: Przykładowy program w LUA. Popraw oczywiście SSID i PWD na właściwą nazwę sieci i hasło.

Nagraj skrypt lokalnie pod nazwą init.lua i wgraj go na ESP przez przycisk Save to ESP (w lewym dolnym rogu). Efekt powinien być mniej więcej taki, na końcu skrypt powinien wypisać adres IP nadany przez router.

ESP podłącza się do WiFi
ESP podłącza się do WiFi

Kilka słów o programie w LUA

Przyjrzyjmy się naszemu programowi. LUA jest językiem niezbyt trudnym. Jak znasz jakiś inny język programowania, to nie będziesz miał problemu ze zrozumieniem co się dzieje w programie.

Pierwsza informacja: linie zaczynające się od dwóch myślników to komentarze, ignorowane podczas wykonywania programu. Komenda print wysyła komunikaty na UART, (myśl o Serial.print dla Arduino).

wifi.setmode(wifi.STATION) ustawia tryb pracy WiFi jako klient (bo ESP może pracować jako access point). wifi.sta.config ustawia nazwę sieci i hasło, a wifi.sta.connect rozpoczyna proces podłączenia.

Jak dotąd różnica w stosunku do Arduino to brak średników i inaczej oznaczane komentarze. Teraz pojawia się coś, czego nie znasz jeśli jedyne Twoje doświadczenie z programowaniem to Arduino, natomiast doskonale znane np korzystającym z JavaScript. Ustawienie tzw timera, który jako jeden z argumentów bierze definicję funkcji. Czyli ustawiamy zegar:

tmr.alarm(1, 2000, tmr.ALARM_AUTO, KOD) Pierwszy argument (1) to numer zegara, 2000 to czas co jaki zostanie wywołany (w milisekundach czyli 2 sekundy). tmr.ALARM_AUTO to tryb pracy – co każde dwie sekundy alarm zostanie uruchomiony. Tak długo dopóki alarm nie zostanie wyłączony. KOD to właśnie funkcja, która będzie co dwie sekundy uruchamiana. Ale nie jej nazwa, tylko od razu definicja:

function() 
    if wifi.sta.getip()== nil then 
        print("IP unavaiable, Waiting...") 
    else 
        tmr.stop(1)
        print("Config done, IP is "..wifi.sta.getip())
    end 
end

Dlatego, że jest używana tylko w tym miejscu funkcja nie ma swojej nazwy, tylko słowo kluczowe funcion() i treść. A co w treści? Pamiętajmy – jest ona wywoływana co 2 sekundy. Sprawdza czy jest już adres IP, jeśli nie, to pisze o tym. Jeśli już został nadany, to komenda tmr.stop(1) zatrzymuje działanie zegara o nr 1 (ten sam numer który został użyty w tmr.alarm), wypisuje numer IP nadany przez router i kończy pracę.

Ponieważ alarm zostaje zatrzymany dopiero po tym jak zostanie nadany adres IP program będzie wypisywał co 2 sekundy komunikat o braku adresu IP, aż do momentu jego uzyskania.

Co jeśli nie działa?

Pamiętaj – pierwszy program musi się nazywać init.lua by wykonał się po restarcie. Jeśli wszystko poszło źle i nic nie działa zawsze możesz skorzystać z przycisku Format po prawej – usunie on wszystkie programy z ESP (tylko te w LUA, sam firmware nodeMCU zostanie). Jeśli nie uda się wyczyszczenie (błąd na konsoli mówi o timeout),  to spróbuj kilka razy nacisnąć Format  – czasem, gdy ESP jest zajęte zdarzy się timeout i file.format() się nie wykonuje.

Programowania w LUA jest dość łatwe, choć całe środowisko ma swoje zwyczaje, które komuś nowemu wydawać się mogą czasem wydać się irytujące. Np jeśli popełnisz jakiś poważny błąd w programie, to całe ESP się restartuje.Gdy ten błąd jest w krótkim czasie od startu, ze względu na ciągła pętlę restartów, może chwilę zająć nim utrafisz we właściwy moment z Format by wyczyścić flash. Wynika to z tego, że program w LUA jest interpretowany na ESP. Wgranie programu nie kompiluje kodu LUA na assembler ESP, tylko jest program na ESP „na żywo” interpretujący (wykonujący komendę LUA po komendzie) program w LUA.

Czego się dowiedzieliśmy o ESP?

Po tym artykule powinieneś umieć podłączyć się do ESP, wgrać nodeMCU i nawiązać komunikację z siecią WiFi. W następnej części napiszę jak sterować przez internet wybranymi pinami do których podłączymy moduły przekaźników.

Co dalej?

Część nr 2 dotycząca ESP8266 w kontekście IoT jest już opublikowana.