poniedziałek, 24 czerwca, 2024

ESP 8266

Projekt składa się z dwóch części:
1. Termometru cyfrowego, który wysyła dane na serwer, a tam one są przetwarzane i wyświetlane;
2. Węża z diodami RGB.
Realizacja projektu jest oparta o moduł WiFi NODE MCU v2 ESP8266-12E.

Ma on wbudowany konwerter USB-UART, dzięki czemu możemy go programować z komputera poprzez USB oraz stabilizator napięcia 3,3V DC (takim napięciem są zasilane układy ESP8266).
Moduł ten jest wyposażony w 22 pinowy układ ESP8266-12E z wbudowanym 32-bitowym układem RISC. Jest on taktowany zegarem 80MHz.
Ma on do dyspozycji 10 portów GPIO, 2 porty UART. Posiada też 10-bitowe wejście ADC.
Schemat blokowy NODE MCU v2 ESP8266-12E


Każdy z portów GPIO moża wykorzystać jako SPI, PWM, I2c lub do termometru cyfrowego 1-Wire,


który to właśnie wykorzystałem w części pierwszej projektu.

Do ESP dodałem trzyprzewodowy wąż diod RGB składający się z 30 sztuk.


Każdą z nich możemy zaprogramować na dowolny kolor.
Ten pasek diod, który wykorzystałem zasilany jest napięciem 5V DC i potrzebuje trochę mocy.
Dlatego do zasilania ich oraz ESP trzeba użyć zasilacza stabilizowanego 5V DC o wydajności prądowej co najmniej 4A (20W). Ja wykorzystałem 25W firmy Mean Well.
Zabawę z programowaniem zacząłem od wgrania firmwaeru.
Aby to zrobić wchodzimy na stronę nodemcu.
Następnie dwa razy wpisujemy swój adres e-mail i zaznaczamy opcje jak poniżej.

Kończymy naciskając Start your build.
Po kilku minutach powinny na naszej poczcie pojawić się dwie wiadomości.
Pierwsza informująca o tworzeniu plików, a kilka minut później druga – już z linkami do pobrania dwóch plików.
Jeden to nodemcu…float.bin, a drugi nodemcu…integer.bin.
Do ESP wgrywamy tylko jeden z tych dwóch plików.
Jeśli chcemy korzystać z obliczeń tylko na liczbach całkowitych wtedy wgrywany plik nodemcu…integer.bin.
Do wgrywania wybranego pliku (firmwaeru) używamy odpowiedniej wersji programu NodeMcu-PyFlasher.

Oczywiście prędzej trzeba podłączyć ESP do portu USB.
Uruchamiamy nasz NodeMcu-PyFlasher i odpowiednio ustawiamy. Trzeba jednak pamiętać o prawidłowym wyborze portu USB.
Po zakończeniu wgrywania firmwaeru potrzebujemy program ESPlorer do programowania ESP.
Po pobraniu, rozpakowujemy go do jakiegoś katalogu i uruchamiamy plik ESPlorer.jar.
Uwaga: trzeba mieć zainstalowaną Javę.

Teraz możemy zacząć przygodę z ESP.

Pierwszym krokiem jest wgranie pliku init.lua.
Plik ten jest jako pierwszy uruchamiany podczas startu ESP.
Zwykle ten plik jest zapisany w ESPlorerze, trzeba go tylko otworzyć i możemy go modyfikować.

U góru po lewej stronie mamy przycisk Open.
Piszemy skrypt, a następnie wgrywamy go do ESP naciskając Save to ESP znajdujący się na dole po lewej stronie.
Coś więcej o języku lua.

A teraz kilka plików z projektu.
Zaczniemy od pliku init.lua, który musi być i jest on wykonywany podczas uruchamiania ESP.

W pierwszej linii mamy node.compile(\”rgb.lua\”).
Jest to funkcja, która utworzy nam nowy plik o tej samej nazwie ale z rozszerzeniem lc. Plik ten będzie skompilowany dzięki czemu będzie miał mniejszą objętość. Plik ten lub każdy inny wywołujemy komendą dofile(\”plik.lc\”) lub dofile(\”plik.lua\”).
Gdy użyliśmy w/w przykładu, to po pierwszym uruchomieniu programu możemy usunąć plik z rozszerzeniem lua gdyż nie będzie on nam już potrzebny oraz usunąć linię node.compile(\”plik.lua\”) z pliku init.lua, po czym ponownie go wgrać.
Aby usunąć już nie potrzebny plik należy w panelu ESPlorer całkiem po prawej stronie nacisnąć Reload. Wtedy po chwili poniżej pojawi się lista wszystkich plików znajdujących się w pamięci ESP.
Na interesującym nas pliku naciskamy prawym przyciskiem myszy. Pojawi się lista, z której wybieramy Remowe plik.lua.
Poniżej w pliku init.lua mamy funkcję file.open(\”dane.lua\”,\”r\”).
Służy ona do otwierania pliku w tym przypadku tylko do odczytu.
W następnej linii widzimy zie = tonumber(file.readline(\”*n\”)).
Odczytujemy w niej jedną linię z otwartego pliku, a następnie zamieniamy ją na liczbę całkowitą.
Jest to o tyle istotne, że jeśli mamy liczbę np. 1 i zapiszemy ją do pliku, to po ponownym jej odczycie będziemy mieli wartość 1 ale jako string w kodzie ASCII czyli 49.
I jak to bywa, po przeczytaniu pliku musimy go zamknąć korzystając z funkcji: file.close().

Fuckcja konfig()

Funkcja służy do konfiguracji połączenia z wifi.

W wifi.setmode() mamy do wyboru Access Point oraz Station Mode.
Jeśli wybierzemy Access Point wtedy nasz moduł stanie się hostem i będziemy się z nim łączyć z innych urządzeń.
Mnie interesowało połączenie do już istniejącego hosta więc wybrałem Station Mode czyli wifi.setmode(Station Mode).
Następnie podałem nazwę sieci i hasło:
station_cfg.ssid=\”*****\”
station_cfg.pwd=\”*****\”.
Ponieważ korzystam z dwóch różnych hostów, więc najpierw wykonuję pięć prób połączenia się z jednym,
a gdy to się nie uda próbuję się połączyć z drugim.
Po połączeniu z jednym z nich wywołuję station_cfg.save=true – funkcja ta zapisuje dane do pamięci flash.
Następnie wywołuję wifi.sta.config(station_cfg) aby uruchomić połączenie z hostem wifi.

Teraz zajmiemy się cyklicznym wywoływaniem funkcji lub pliku.
Służy to tego tmr.alarm(1, 600000, 1, function() end))

Pierwszy parametr to numer Timera.
Możemy użyć do 7 Timerów (od 0 do 6).
Drugi parametr to czas w milisekundach i określa, co ile milisekund ma być wywoływana funkcja.
Następnie określamy jak Timer ma być wywoływany:
tmr.ALARM_SINGLE – alarm jednorazowy (bez potrzeby wywoływania tmr.unregister ())
tmr.ALARM_SEMI – ręczne powtarzanie alarmu (wywołanie tmr.start () w celu ponownego uruchomienia)
tmr.ALARM_AUTO – automatycznie powtarza alarm.
Skoro odczytujemy plik z pamięci, to musimy go też w niej utworzyć.
Robimy to za pomocą file.open(\”plik.lua\”,\”w+\”).
Pierwszy parametr to nazwa pliku, a drugi otwiera plik tekstowy do aktualizacji (odczytu i zapisu), najpierw obcinając plik do zerowej długości, jeśli istnieje lub tworzy plik, jeśli nie istnieje.
Skoro plik już jest otworzony, więc możemy w nim zapisać dane używając file.writeline(string.format(\”%d\\n%d\\n%d\\n%d\\n\”,zie,cze,nie,zapis)), a następnie file.close() zamykamy plik.
Jak widzimy String zapisany do pliku jest sformatowany jako Integer (%d).
W moim przypadku musiałem mieć pewność aby zmienna zapisana w pliku była sformatowana jako Integer, a nie String.
I tu z pomocą przyszła mi funkcja zapis = tonumber(zmienna)

Jak na początku artykułu wspomniałem projekt wysyła dane między innymi ze zmierzoną przez DS18B20 temperaturą na mój serwer, a tam one są obrabiane i przetwarzane.
Służy do tego plik http_temp.lc, który jest wywoływany co 10 minut w init.lua.

Funkcja http_temp.lc

Jak zwrócimy uwagę w jednej linii jest conn:send(\”GET /esp8266.php?temperatura=\”..cels..\” HTTP/1.1\r\n\”) gdzie cels jest to zmienna przechowująca odczytaną temperaturę.
Odczytujemy ją przez wywołanie pliku temperatura.lc w init.lua

Jak widzimy w pierwszej linii mamy pin=5.
Tutaj zdefiniowałem pin, na którym odbywa się komunikacja pomiędzy ESP8266 oraz DS18B20.
W trzeciej linii jest ds18b20.setting({\”28:64:6:4A:8:0:0:43\”},9).
W pierwszym parametrze podaję adres czujnika.
Jeśli mamy tylko jeden czujnik możemy wpisać Nil.
Drugi parametr odpowiada za rozdzielczość pomiaru w bitach od 9-12. Dokładność pomiaru jest okupiona szybkością.
W następnej linii odczytywane jest kilka parametrów.
Dla mnie ważnym był temp. Jest to wartość temperatury. Wartość ta jest następnie zapisana w cels. Po czym zostaje ona wysłana na serwer.
W ostatniej linii jest collectgarbage(\”stop\”).
Chodzi o to aby niepotrzebnie nie przechowywać w pamięci śmieci.