Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'ESP'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona


TempX

  1. Witam drodzy koledzy...mam zamiar zrobić bezprzewodowy dzwonek z tego tytułu że czasem ktoś się boi wejść na podwórko z powodu psa...w planach jest jeden TX i dwa RX...planuje użyć płytek lolin32 i esp-now, wolałbym żeby ten model płytki został bo mam odrazu na pokładzie ładowarkę li-ion i stabilizację 3.3v a ponadto mogę teraz kupić te płytki po ~10zl sztuka, więc grzech nie brać...wszystkie moduły planuje zasilać z baterii 1s (jedno lub dwa ogniwa li-ion równolegle) TX będzie cały czas w uśpieniu, po naciśnięciu guzika będzie nadawał powiedzmy 30s, natomiast tak wymyśliłem żeby dla oszczędności energii RX był uśpiony i co 15s budził się na czas potrzebny do odbioru (1-2s?) ewentualnych danych... Co do radzicie odnośnie płytki? Czy to się będzie nadawać w takiej konfiguracji jak podałem?
  2. Od dawna interesowały mnie pomiary warunków meteorologicznych w mojej miejscowości, pierwsza stacja meteorologiczna, którą zbudowałem około roku 2010, wykonana była na mikrokontrolerze Atmega32. Do komunikacji z światem wykorzystywała moduł LAN Wiznet 7010a. Stacja ta była oprogramowana w języku BASCOM. Projekt który chcę zaprezentować dzisiaj działa już od roku 2018 i został oprogramowany w środowisku Arduino. Stacja została podzielona na 2 moduły, pierwszy pomiarowy oparty jest na klonie Arduino Nano oraz drugi odbiorczy którego sercem jest ESP8266 NodeMCU v3, służy on również do wyświetlania aktualnych pomiarów na wyświetlaczu LED dot matrix o wymiarach 8x56 punktów. Na pracach stolarskich się nie będziemy skupiać napiszę tylko że klatka meteorologiczna została wykonana z drewna sosnowego i umieszczona na wysokości 2 m. Moduł Pomiarowy Czujniki jakie zastosowałem to dwie sztuki DS18B20 pierwszy zajmuje się pomiarem temperatury przy gruncie na wysokości 5cm, drugi pełni rolę zapasowego czujnika temperatury na wypadek uszkodzenia się głównego czujnika BME280. Do pomiaru prędkości wiatru wykorzystuję wiatromierz firmy Maplin na jeden obrót wiatromierza przypadają 2 impulsy z kontaktronu który jest w nim zamontowany, producent dostarcza również odpowiedni wzór według którego można obliczyć rpm oraz prędkość wiatru w km/h. Dane mierzone przez wiatromierz możemy podzielić na dwie wartości, pierwsza to chwilowa prędkość, druga prędkość w porywach, aby uśrednić wartości mierzone program zlicza impulsy z 5s a następnie dokonuje odpowiednich obliczeń. Zebrane dane przesyłane są do drugiego urządzenia poprzez moduły radiowe które działają na częstotliwości 433,92 MHz. W tym celu zastosowana została biblioteka RCSwitch. Każda mierzona wartość jest wysyłana jako osobna transmisja. aby rozróżnić pomiary z konkretnych czujników mierzona wartość mnożona jest przez 100 a następnie dodawana jest liczba 100 000 dla pierwszego czujnika, 200 000 dla drugiego itd. Przykład kodu który realizuje tę funkcję poniżej: // temperatura sensor BME codetosend = temp * 100 + (1 * 100000); mySwitch.send(codetosend, 24); // wilgotnosc sensor BME codetosend = hum * 100 + (2 * 100000); mySwitch.send(codetosend, 24); Moduł Wewnętrzny Obudowa, która idealnie nadawała się do implementacji wewnętrznego modułu pochodzi z tunera IPTV Motorola VIP1910-9. Przedni panel został wykonany z ciemnego półprzepuszczalnego plastiku który idealnie nadaje się do umieszczenia w nim wyświetlacza. Sercem urządzenia jest układ ESP8266. "Moduł wewnętrzny" został również wyposażony w czujnik temperatury oraz wilgotności DHT22, dodatkowo w celu prezentacji zmierzonych wartości dołączone zostało 7 szt. modułów wyświetlacza LED dot matrix z układem MAX7219. Do obsługi tej matrycy zastosowałem bibliotekę Max72xxPanel.h która współpracuje z biblioteką Adafruit_GFX.h w ten sposób nie byłem zmuszony implementować do rozwiązania własnych czcionek. Matryca ta oprócz modułowej konstrukcji umożliwia również sterowaniem jasnością podświetlania, w tym celu aby uprzyjemnić użytkowanie w porach nocnych odbiornik został wyposażony w fotorezystor dzięki któremu potrafi określić natężenie oświetlenia otoczenia i odpowiednie ustawienie podświetlenia. Na wyświetlaczu w pierwszej kolejności wyświetlam aktualną godzinę oraz temperaturę wewnątrz pomieszczenia oraz wilgotność, po około jednej minucie wyświetlane są informacje odczytane z stacji meteo czyli temperatura wilgotność i ciśnienie, postanowiłem nie wyświetlać tutaj informacji dotyczących prędkości wiatru oraz temperatury przy gruncie. Decyzję tą podjąłem na podstawie użytkowania innego podobnego rozwiązania, akurat jak chcemy odczytać godzinę to wyświetlane są inne informacje. Dodatkowo w godzinach nocnych, które zostały ustawione w sztywnych ramach czasowych między 21:00 a 7:00 informacje odczytane z stacji meteo zostały okrojone tylko do temperatury. W projekcie zostały zastosowane 2 rodzaje animacji pierwsza z nich, przesuwa tekst z prawej strony wyświetlacza na lewą, z możliwością zatrzymania w interesujących momentach. Drugi rodzaj to pionowa animacja. Mikrokontroler również poprzez protokół NTP i bibliotekę time.h pobiera aktualną godzinę i datę. Za odbiór danych z pierwszego układu odpowiedzialny jest moduł radiowy którego obsługą tak jak w poprzednim module zajmuje się biblioteka RCswitch. Poniżej fragment programu który demonstruje w jaki sposób odbierane i dekodowane są dane: rc = mySwitch.getReceivedValue(); // czujnik temperatury powietrza BME280 if (abs(rc)>=50000&& abs(rc)<150000) { rc=(rc-100000)/100; if (rc > -50 and rc < 60) { temp1 = rc; Serial.print("Czujnik BME280 - temperatura: \t"); Serial.println(rc); matrix.drawPixel(55,0,1); matrix.write(); } } // czujnik wilgotności BME280 if (abs(rc)>=150000 && abs(rc)<250000) { rc=(rc-200000)/100; if (rc > 5 and rc <= 100) { hum = rc; Serial.print("Czujnik BME280 - wilgotnowsc: \t"); Serial.println(rc); matrix.drawPixel(55,1,1); matrix.write(); } } Dzięki zastosowaniu zewnętrznej anteny oraz odbiornika opartego na superheterodynie, zasięg w otwartym terenie to około 250 m. Po odebraniu danych z pierwszego układu poprzez moduł radiowy następuje przekazanie ich do serwera z systemem Domoticz. Domoticz to bardzo lekki system automatyki domowej, który pozwala monitorować i konfigurować różne urządzenia, przełączniki, czujniki takie jak temperatura, opady deszczu, wiatr, promieniowanie ultrafioletowe (UV), zużycie energii elektrycznej, zużycie gazu, zużycie wody i wiele więcej. Wykresy dostępne są również na stronie www http://meteo.palowice.net Poniżej film z działania odbiornika, smużenie animacji które występuje na filmiku ludzie oko nie rejestruje. Gdyby kogoś interesował kod to również zamieszczam: meteo.zip
  3. ◼ Wstęp Razem z @PiCh przedstawiamy zapowiedź naszego nowego zawodnika w konkurencji Linefollower Standard którego debiut planujemy na zbliżającej się edycji XChallenge 😎 🦎Salamandra 2.0 to następca poprzedniej konstrukcji która startowała bez powodzenia w zeszłorocznej edycji XChallenge. Pierwsza wersja niestety puściła dym po tym jak przypadkowo podczas zawodów włożyliśmy mikrokontroler na odwrót (Arduino Nano). Lekko nas podłamało w tamtym czasie bo nie takiej nagrody za naszą pracę oczekiwaliśmy. Dzięki temu zyskaliśmy jednak sporo doświadczenia i wiedzy którą w nowszej konstrukcji zamierzamy wykorzystać. Salamandra 1.0 Salamandra 2.0 ◼ Koncepcja i Założenia 📋 Podczas gdy całokształt pracy nad pierwszą wersją miał charakter badawczy i większość decyzji była "na czuja" teraz mamy już pojęcie jak powinny wyglądać roboty które wygrywają, inspiracją dla nas podobnie jak dla wielu innych konstruktorów były roboty takie jak Cukiereczek, Fuzzy oraz RoChN'y. 🔽 Założenia wyglądają następująco: Konstrukcja zgrabna i przemyślana 🛠️ Ostatnio zlekceważyliśmy zupełnie temat wagi i kompaktowości. Nowszy model zaprojektowany jest tak aby w jak największym stopniu wyzbyć się zbędnych przestrzeni na płytce. Również zdecydowaliśmy się na cieńszy laminat- 0.8 mm. Stosujemy również mniejszy akumulator lipo 150 mah oraz oponki wide high grip od Kyosho z serii mini-z. Salamandra 1.0 wyposażona była w łącznik wzięty z lego i przytwierdzony de facto na stałe, następnik będzie posiadał lżejsze i trwalsze płaskowniki węglowe. Ostatnio na zawodach zepsuła nam się jedyna bateria dlatego teraz wyposażamy się w kilka akumulatorków i lipo guarda który zasygnalizuje gdy się rozładują. Wymienne platformy przednie ⚙️ Na to wpadliśmy akurat podczas tworzenia obrysu płytki i wychodząc z założenia że skoro nie będzie nas to nic kosztowało bo połączymy to i zamówimy jako jedną płytkę to czemu nie. Odkryliśmy że tak to nie działa podczas zamawiania gdy kazali za każdą osobną platformę dopłacać. Platformy między sobą nie różnią się znacznie bo wszystkie są bardzo małe i tak cienkie jak się tylko da ale planujemy skrupulatnie poddać je testom i wybrać tą najlepszą (dla zadanych warunków toru). Platformy mają po 10 transoptorów. Nie starczyłoby nam wyjść analogowych więc zmuszeni byliśmy zastosować komparatory które regulować można za pomocą potencjometrów. Kalibrację ułatwiają diody które sygnalizują kiedy czujnik wykrywa linię. Koniec z Arduino ❌ Nie tylko dlatego że ostatnio nam puściło dym na torze ale też dlatego że ta platforma nam się już zwyczajnie przejadła. Drogie, zawodne i mało wydajne to podsumowanie naszych dotychczasowych doświadczeń (trzymam w szufladzie 4 ardu które przestały działać od czapy). W tej konstrukcji nie zdecydowaliśmy się jeszcze na klasycznego tutaj STMa za to spodobał nam się podsunięty przez @ethanak pomysł na oparcie konstrukcji w całości na nietypowym tutaj ESP32 którym moja fascynacja trwała już od pewnego czasu. Konkretny model jednostki to największy i najnowszy jak na razie ESP32-WROOVER_E ze względu na dużą ilość wyjść IO jak na ESP (dalej za mało jak na standardy bardziej zaawansowanego LFa). Aplikacja mobilna i OTA 📱 Salamandry 1.0 nie testowaliśmy długo bo wszystko robiliśmy na chwilę przed zawodami ale momentalnie odczuliśmy trudności związane z ciągłym łapaniem robota, podpinaniem i zmienianiem programu. Po całym dniu takich testów odkryłem że od takiego czegoś nabawiłem się siniaków na kolanach. Teraz zamierzamy w całości wykorzystać dobrodziejstwa zastosowania ESP, do typowych testów i zmian będzie aplikacja a do zmiany samego kodu będzie OTA. Zero klękania i podpinania. Enkodery 🏎️ Początkowo marzyło nam się też imu do mapowania trasy ale to jeszcze nie teraz. Enkodery są jednak sprawdzonym sposobem na przyspieszenie robota więc będą one obecne na pokładzie Salamandry 2.0. Bramka pomiarowa i zautomatyzowane testy? ✨ Ostatni punkt to bardziej moja fantazja którą bardzo chciałbym zrealizować mimo że możliwe że nie przyniesie to faktycznych rezultatów na torze. Jestem w trakcie tworzenia laserowej bramki opartej na ESP która ma wysyłać wynik pomiaru razem z parametrami przejazdu z aplikacji(pid, prędkość i wszystko co będzie modyfikowalne) do bazy danych. W zamyśle do zrealizowania jest to żeby móc te wyniki podejrzeć, jak starczy czasu chęci i umiejętności to podejrzeć w aplikacji a jak czasu chęci i umiejętności znajdę jeszcze więcej to aplikacja będzie czytała wyniki z bazy danych po czym w trybie machine learningu będzie ładowała nowe ustawienia przejazdów aby uzupełniać bazę danych o nowe testy i ostatecznie dobrać ustawienia optymalne. Plan ambitny dlatego myślę że mimo iż robota przygotowujemy pod zbliżającą się edycję XChallenge to pracować będziemy mogli nad rozwijaniem tej konstrukcji na długo po zakończeniu tych zawodów. ◼ Aktualne postępy Obecnie czekamy na dostawę PCB które będziemy mogli zalutować. Bramka pomiarowa jest na razie w częściach i nie zaprogramowana. Pracę nad aplikacją opierają się na razie na robieniu przeze mnie kursu na Udemy z Fluttera. Większość części mamy oprócz silników i magnesów do enkoderów a całokształt ostatecznego wyglądu robota raczej mamy dopracowany. Jako że udało się już zamówić płytkę stwierdziliśmy że jest to odpowiedni moment aby upublicznić nasz projekt. 📣 Gdy uda nam się coś więcej osiągnąć wrzucimy update. Liczymy że ten worklog dodatkowo zmotywuje nas do regularnej pracy 🤠.
  4. Ten artykuł jest częścią serii "Tworzenie interfejsu sieciowego z wykorzystaniem ESP" #1 - część 1 (właśnie to czytasz) #2 - część 2 ESP32 czy też ESP8266 na dobre już zagościło w wielu warsztatach domowych majsterkowiczów. Większość obecnych projektów z wykorzystaniem ESP skupia się wokół dorzucenia do niego garści czujników, podłączenia do baterii i wybudzania go od czasu do czasu, aby wysłać dane o wykonanych pomiarach do naszego serwera. Czasem zdarza się, że nasze urządzenie pobiera pewne dane z zewnątrz i je wykorzystuje, np. budzik czas z serwera NTP, czy stacja pogodowa, informacje o pogodzie z wybranego serwisu. Co w sytuacji kiedy chcemy kontrolować nasze urządzenie lub obserwować jego stan z poziomu przeglądarki, a nie posiadamy Raspberry Pi, czy innej opcji, na której moglibyśmy mieć własny serwer? Co jeżeli zastosowanie dodatkowego serwera jest po prostu nieadekwatne do naszego celu? W tym artykule postaram się: omówić najpopularniejsze rozwiązania pokazać jak uruchomić serwer www ESP32 stworzyć prostą stronę www do naszych zadań wykonać interakcje strona-ESP w postaci: kontroli portu GPIO wyświetlanie wyniku pomiaru z ADC pobieranie pliku z pamięci ESP/karty SD Ten artykuł bierze udział w naszym konkursie! 🔥 Na zwycięzców czekają karty podarunkowe Allegro, m.in.: 2000 zł, 1000 zł i 500 zł. Potrafisz napisać podobny poradnik? Opublikuj go na forum i zgłoś się do konkursu! Czekamy na ciekawe teksty związane z elektroniką i programowaniem. Sprawdź szczegóły » Wszystkie powyższe rzeczy postaram się zobrazować w jak najprostszy i przejrzysty sposób. Poruszany temat jest niewątpliwie bardzo złożony i niestety nie jest możliwe aby wszystkie informacje zawrzeć w jednym artykule. Temat wymaga zarówno znajomość obsługi samego ESP, HTML, JavaScriptu czy też CSS, zaś znajomość protokołów sieciowych również byłaby mile widziana. Tutaj będą jedynie ukazane podstawy jak to wszystko ze sobą połączyć. Pokazane metody z pewnością nie będą należeć do najbardziej optymalnych rozwiązań, mają jedynie na celu ukazanie koncepcji i zachęcenia do dalszej analizy tego zagadnienia. Wszystkie kody będą skomentowane. W treści będę również odsyłał do dodatkowych materiałów, które dokładniej opisują poszczególne zagadnienia oraz tam gdzie można zdobyć więcej wartościowych informacji. Ale w jakim celu? Część z osób może zadać pytanie po co uruchamiać serwer na ESP, wiąże się to z dużym poborem energii, pomiary najlepiej z wielu czujników wysyłać w jedno miejsce, to dużo pracy itd. Inni zaś, od razu stwierdzą, że to jest to czego oni potrzebują. Jako że nie widzę większego sensu pisania długich wywodów na temat dlaczego warto, dlaczego nie, kiedy tak, kiedy nie. Przedstawię poniżej dwa praktyczne przykłady i możliwości takich realizacji które pozwolą samemu ocenić te aspekty. Pierwszym przykładem jest zdalny interfejs drukarki 3D. Dzięki niemu możemy zdalnie uruchomić drukarkę, wysyłać do niej pliki, uruchamiać druk, obserwować parametry druku, dostosowywać je, konfigurować drukarkę i wiele innych. Zostało to zrealizowane na ESP8266 i projekt jest dostępny pod tymi linkami Duet WiFi Server oraz Duet Web Control Drugi przykład jest to interfejs do sterowania lampką/oświetleniem LED. Z poziomu przeglądarki możemy ustawiać różne efekty świetlne, barwę, jasność, konfigurować urządzenie. Więcej o tym projekcie można dowiedzieć się tutaj Aircookie WLED Co będzie nam potrzebne? Podstawowa znajomość platformy ESP oraz programowania w Arduino w tym obsługa SPIFFS lub kart SD Płytka z ESP32 (wszystko powinno być kompatybilne z ESP8266) Zainstalowana biblioteka Async Web Server Dodatkowo: Znajomość języka angielskiego – dodatkowe odnośniki Płytka stykowa, potencjometr, fotorezystor czy cokolwiek sobie wymyślicie aby urozmaicić sobie temat 🙂 Zrozumienie tematu również ułatwi znajomość podstaw HTML oraz JavaScriptu. Jako że wymagane są już podstawowe umiejętności odnośnie obsługi ESP oraz Arduino, pominę kwestie instalacji biblioteki, omówienia zagadnień struktury programu czy też obsługi peryferiów. Z czym to się je? Podstawowa koncepcja naszego projektu opiera się na tym, iż na ESP uruchamiamy serwer, który na zapytanie klienta (klient czyli nas - naszej przeglądarki) zwraca odpowiednie pliki lub wykonuje pewne operacje. W ten sposób możemy poprosić ESP aby zwrócił nam plik HTML zawierający naszą stronę, przeglądarka ją odbierze, a my będziemy się mogli cieszyć widokiem naszej witryny. W ten sposób możemy wyróżnić pierwszy ze sposobów interakcji z naszym ESP, czyli z wykorzystaniem metod HTTP. W uproszczeniu, metody są to pewnego rodzaju „komunikaty” czego oczekujemy od naszego serwera. Przykładowo, wysyłamy zapytanie „GET” – oznacza że chcemy coś od serwera i ma on nam to dać, zapytanie „POST” – oznacza że chcemy coś dać od siebie. Każde nasze zapytanie będzie skutkować odpowiedzią (lub jej brakiem 🙂 ). Odpowiedzi posiadają swoje kody, które mają różne znaczenie – to daje nam dodatkowe możliwości interakcji. Wiedząc co oznacza dany kod możemy przykładowo stwierdzać czy dostaliśmy odpowiedź, czy wyświetlić jakiś błąd, lub stwierdzić że coś nie istnieje (każdemu znane 404). Najprostszym użyciem tych zapytań jest po prostu wykorzystanie odpowiednich struktur w HTML z stosownymi atrybutami. Metodę „POST” możemy wykorzystać przy tworzeniu formularza. Wadą tego rozwiązania jest fakt tego iż będzie to skutkować przeładowaniem strony przy każdej tego typu akcji. Inną opcją jest wykorzystanie pomocy Java Scriptu który będzie służył jako nasza „trzecia ręka” wykonująca te operacje w tle. Rozwiązanie to nazywa się AJAX (z angielskiego Asynchronus JavaScript and XML) i na nim się głównie skupimy w tym artykule. Drugą powszechną opcją jest skorzystanie z WebSocket. Jest to sposób ciągłej komunikacji między klientem a serwerem. Polega ona na nawiązaniu „kontaktu” z serwerem i zapytaniem go czy jest chętny na „pogawędkę”. Metoda ta idealnie się nadaje do wymiany ciągów informacji na żywo. Przykładowo potrzebujemy ciągłego odczytu z przetwornika ADC – można stwierdzić „wirtualny port szeregowy”. Oczywiście moglibyśmy zrealizować to samo zadanie z wykorzystaniem wcześniej wspomnianych metod, ale wykorzystanie metody HTTP wiąże się z całym procesem, wysłania zapytania, otrzymania odpowiedzi, co w skali procesora trwa wieki (np. jedno zapytanie kilkadziesiąt – set ms). Tutaj nie mamy tego problemu, gdyż nasze połączenie ciągle trwa i sobie rozmawiamy. W przypadku gdy nie zależy nam na ciągłym podglądzie (np. odświeżanie informacji raz na pół minuty) możemy spokojnie zadowolić się wykorzystaniem AJAX i metod HTTP. Ponadto warto nadmienić iż korzystanie z WebSocketów jest zarówno korzystne dla serwera jak i klienta ze względu na minimalną ilość przesyłanych danych (ograniczenie tego co jest nam w rzeczywistości zbędne). No to zaczynamy! Na wstępie warto nadmienić że pracujemy wewnątrz sieci lokalnej. Jeżeli połączymy się z naszym WiFi, inne urządzenia z tej samej sieci będą miały dostęp do naszego serwera. Bez stosownej konfiguracji sieci (jak i czasem ograniczeń narzuconych przez naszego dostawcę internetowego) nie będziemy mieć dostępu do naszego urządzenia z dowolnego miejsca na świecie. Na początek zacznijmy od tego czym jest nasza biblioteka i dlaczego ona. Otóż umożliwia ona komunikację asynchroniczną, co pozwala nam na posiadanie więcej niż jednego połączenia w danej chwili i działa poza pętlą loop(). Aby się nie rozpisywać na temat innych zalet i możliwości zainteresowanych dogłębną analizą odeślę tutaj. Uwaga dla użytkowników ESP8266! Biblioteka od obsługi WiFi definiuje się jako: #include <ESP8266WiFi.h> Zaś obsługa SPIFFS: #include <FS.h> Ponadto w poniższej pętli while() potrzebne jest opóźnienie, aby zapobiec uruchamianiu się watchdoga while (WiFi.status() != WL_CONNECTED){ delay(1000); } Powyższe uwagi będą zawarte w komentarzach kodów. Uruchamiamy serwer! #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" #define PASS "hasło sieci" AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/" typu GET, request->send_P(200, "text/plain", "Witaj! :)"); //odpowiedz mu kodem 200, danymi tekstowymi, o treści "Witaj! :)" }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } W powyższym kodzie widzimy następujące etapy, łączymy się z naszą siecią WiFi, ESP zwraca nam przez port szeregowy swój adres IP w naszej sieci. Będzie on nam potrzebny do wpisania w pasku przeglądarki w celu połączenia się z serwerem. Następnie tworzymy funkcję która obsługuje konkretne zapytania, w naszym przypadku po otrzymaniu zapytania GET pod adresem „/” – można to określić jako „folder główny” serwera, tak samo jak w komputerze mamy dysk np. „D:\” – odeśle klientowi odpowiedź o kodzie 200 (oznacza to „ok” – więcej o kodach tutaj) i zawartości typu tekstowej (są to typy MIME, mówią one przeglądarce co jej chcemy przekazać – więcej o typach MIME tutaj). Rezultatem, po wpisaniu w pasek przeglądarki adresu IP naszego ESP, jest strona. Tworzymy prostą stronę Jako że celem tutaj nie jest nauka HTML czy też CSS, ograniczyłem stronę do absolutnego minimum, potrzebnego do naszych zabaw. Tutaj też, odeślę do wartościowego źródła gdzie można znaleźć wiele wartościowych informacji odnośnie HTML, JavaScript, CSS oraz innych. Nasza strona będzie się składać z pola tekstowego gdzie wyświetlimy wartość odczytaną z ADC, dwóch przycisków do włączania i wyłączania diody oraz przycisku pobierania pliku z naszego ESP. <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8"/> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> </script> </body> </html> Kluczowe podczas tworzenia takiej strony jest nadawanie unikalnego ID każdemu elementowi, ułatwi to współpracę z JavaScriptem. Gdy już mamy przygotowaną stronę musimy ją wgrać do SPIFFS. Stąd będziemy wysyłać plik HTML jako odpowiedź dla klienta. Analogicznie można te pliki wgrać na kartę pamięci i z delikatną modyfikacją kodu serwować z niej pliki. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" #define PASS "hasło sieci" AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Teraz po wpisaniu adresu IP naszej strony w pasek przeglądarki ukaże się nam prosta strona. Pora na działanie! Na pierwszy ogień weźmiemy obsługę LED. W tym celu konieczne będzie dorzucenie trochę JavaScriptu do naszej strony document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "off" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; Kod ten sprawdza czy któryś z przycisków został naciśnięty, a jeżeli został wysyła stosowne zapytanie do naszego serwera. Finalnie kod strony przedstawia się jak poniżej. <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8"/> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "off" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; </script> </body> </html> Ponadto w sekcji setup() naszego kodu ESP musimy dodać obsługę nowo powstałych zapytań. serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); Co daje nam w rezultacie kod jak poniżej. Ważne aby wszystkie zapytania były przed funkcją serwer.begin() #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "haslo sieci" //hasło sieci #define LED 22 //numer pinu gdzie mamy podłączoną diodę AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Teraz możemy zaobserwować działanie naszego kodu. Odczyt ADC Teraz pora na odczyt wartości z przetwornika analogowo-cyfrowego. Tym razem nasz skrypt będzie automatycznie, z pewnym interwałem czasowym (500ms), wysyłał zapytanie do serwera. setInterval(function () { const zapytanie = new XMLHttpRequest(); zapytanie.open("GET", "/adc"); zapytanie.send(); zapytanie.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById("pomiar").innerHTML = "Pomiar:" + this.responseText; } }; }, 500); Powyższy fragment powinien znaleźć się w pliku .html w sekcji <script>, tak jak poprzednio. Serwer w odpowiedzi będzie zwracał wartość z ADC w postaci tekstu, zaś JavaScript, w tle będzie nam podmieniał wartości na stronie uzyskane w odpowiedzi od serwera, bez konieczności przeładowania. W kodzie ESP wystarczy że dodamy taki fragment kodu do sekcji setup() przed funkcją serwer.begin(). serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, String wartosc = String(analogRead(ADC)); //wykonaj pomiar ADC i zapisz do Stringa request->send(200, "text/plain", wartosc); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); Na powyższej animacji widać jak zmieniają się wartości. W konsoli przeglądarki (przycisk F12 powinien nam ją uruchomić w większości przeglądarek) można obserwować wszystkie zapytania wymieniane między klientem a serwerem. Jest to bardzo przydatne narzędzie do „debugowania” kiedy coś nie chce do końca z nami współpracować. Powyższe zadania możemy zrealizować również w inny sposób, poprzez wywołanie naszej funkcji z poziomu funkcji obsługi zapytań. Przykład obsługi ADC przedstawiałby się w następujący sposób. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "hasło sieci" //hasło sieci #define ADC 34 //numer pinu potencjometru AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 String odczyt_ADC() { return String(analogRead(ADC)); } void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(200, "text/plain", odczyt_ADC()); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Pobieranie pliku Na koniec zajmiemy się pobieraniem pliku z naszego serwera. W celu pokazania jak korzystać z typów MIME przedstawię jak pobrać obrazek z naszego prostego serwera. Do naszej ESP pamięci wgramy poniższy obrazek. W tym celu musimy dodać fragment skryptu do naszej strony. document.getElementById("download").onclick = function () { //po nacisinięciu elementu o ID "download" location.href = "/download"; //przekieruj pod /download }; Podobnie jak uprzednio dodajemy go do naszej sekcji <script></script>. Działa on podobnie jak poprzednie włączanie i wyłączanie diody, lecz w normalnej sytuacji, takie działanie spowodowałoby przekierowanie pod ten adres /download. Ponieważ w kodzie programu ustawimy atrybut pobierania. Będzie to skutkowało wyskoczeniem okna pobierania. serwer.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(SPIFFS, "/Lenna.png", "image/png", true); //odeślij odpowiedź w postaci pliku png o nazwie obrazek.png z SPIFFS i umożliwij pobranie (true) }); Jak widzimy musimy wskazać skąd nasz plik ma zostać pobrany (SPIFFS, może to być również karta SD), następnie wskazujemy dokładną lokalizację naszego pliku, jego rodzaj (MIME) oraz ustawiamy atrybut pobierania jako true. W efekcie uzyskujemy pobieranie naszego pliku. Zachęcam do sprawdzenia rezultatu po zmienieniu atrybutu pobierania na false. Poniżej zamieszam finalne wersje programu Arduino oraz kodu strony HTML. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "hasło sieci" //hasło sieci #define LED 22 //numer pinu gdzie mamy podłączoną diodę #define ADC 34 //numer pinu potencjometru AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, String wartosc = String(analogRead(ADC)); //wykonaj pomiar ADC i zapisz do Stringa request->send(200, "text/plain", wartosc); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); serwer.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(SPIFFS, "/Lenna.png", "image/png", false); //odeślij odpowiedź w postaci pliku png o nazwie obrazek.png z SPIFFS i umożliwij pobranie (true) }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8" /> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; setInterval(function () { const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie jak poprzednio zapytanie.open("GET", "/adc"); zapytanie.send(); zapytanie.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById("pomiar").innerHTML = "Wartość:" + this.responseText; } }; }, 500); document.getElementById("download").onclick = function () { //po nacisinięciu elementu o ID "download" location.href = "/download"; }; </script> </body> </html> Podsumowanie Bardzo się cieszę że dotrwałeś do tego momentu! Jak wspomniałem na początku, przedstawione rozwiązania są najprostszymi, niekoniecznie zgodnymi ze sztuką rozwiązaniami. Starałem się w kodach programów ograniczyć wszystkie zbędne fragmenty i uprościć do absolutnego minimum – czego często brakuje w poradnikach z internetu, co skutkuje utrudnioną analizą działania programu. Pokazane sposoby mają na celu jedynie wprowadzenie do koncepcji tematu, zachęcenia do pracy oraz poznawania możliwości rozwiązań sieciowych, o których można by było pisać całe książki. Zarówno komunikacja z wykorzystaniem Websocketów czy tworzenie samej strony którą widzi klient – czyli strony internetowej – mogłaby zająć czas na oddzielne artykuły. W drugiej części artykułu omówię w teoretyczny sposób (bez gotowych rozwiązań programowych) jak z wykorzystaniem ESP oraz dostępnych technologii i bibliotek rozwiać takie problemy jak: konfigurowanie urządzenia z poziomu przeglądarki przeglądanie i zarządzanie plikami w pamięci ESP provisioning i co to oraz po co to właściwie jest M. S.
  5. Hej, zwracam się do Was z prośbą i radą jaki protokół do komunikacji miedzy różnymi mikrokontrolerami najlepiej użyć do mojego wymyślonego projektu. To zaczynając od pomysłu. Chciałem stworzyć kontroler główny, który będzie miał komunikację 2 kierunkową z urządzeniami podłączonymi do niego: mniej więcej tak ja na tym schemacie: Z Założenia chcę, aby urządzenia łączyły się ze sobą kablowo najprawdopodobniej skrętką 8 żyłową(2 lub 4 przewody chciałbym poświęcić na zasilania, reszta na komunikację) a odległość maksymalna to będzie 20m, Dane przesyłane miedzy nimi nie będą duże( najprawdopodobniej string o długości max 30 znaków lub char do identyfikacji typu wiadomości i int16) a częstotliwość komunikacji raz na 1s z każdym urządzeniem wystarczy. Chciałbym także aby te podłączenia można było robić w trakcie używania urządzenia a ich wykrywanie było na zasadzie "do portu 3 zostało coś podłączone" i po przez różnego rodzaju wiadomości urządzanie będzie rozpoznawało z czym konkretnie się połączył. Dodatkowo chciałbym aby można było podłączyć różne mikrokontrolery, takie jak STM32, ESP oraz Arduino. Jest Modbus, SPI, I2C, CAN, UART itd... Ale co najlepiej do takiego zastosowania by się nadało? Wiem, że każdy wybór ma swoje plusy i minusy i zdaję sobie sprawę, że muszę pójść na jakieś kompromisy. Moim wstępnym pomysłem było wykorzystanie do tego RS-485. Tylko nie miałem z nim nigdy styczności i nie jestem przekonany, że się sprawdzi. Dlatego chcę waszej opinii i porady, co byście do takiego zastosowania użyli, a może już ktoś robił coś podobnego i ma w tym doświadczenie.
  6. Dodając krok po kroku trochę automatyki w mieszkaniu powstał projekt i realizacja sterownika rolet zewnętrznych. Główne cechy urządzenia: obsługa 7 rolet zdalny dostęp z dowolnego miejsca na świecie sterowanie przez Wifi sterowanie przez Bluetooth sterowanie przez sieć CAN automatyczny pomiar czasu pracy poszczególnych rolet harmonogram otwierania/zamykania rolet sterowanie grupowe tworzenie scen pobieranie aktualnego czasu z serwera NTP Sterownik został podzielony na dwie części, pierwsza to płytka z przekaźnikami i zasilaniem, druga płytka to układ sterowania wraz z modułami komunikacyjnymi. Główne elementy wykorzystane w sterowniku to: STM32F103C8T6 jako moduł Bluepill Moduł Wifi ESP-12 Bluetooth HC-05 Największym wyzwanie okazało się wykrywanie zakończenia pracy rolety. Było to niezbędne do automatycznego pomiaru czasu pracy, które jest wykorzystywane do określania pozycji pośrednich. Na początku testowałem wykrywanie prądu z wykorzystaniem modułu ACS711, ale niewielki prąd pobierany przez roletę podczas pracy powodował niestabilne pomiary z układu ACS711. Drugim pomysłem było wykorzystanie przekładników prądowych. Pomiary były stabilne, ale to rozwiązanie odpadło ze względu na fizyczne rozmiary takich przekładników, potrzebowałem użyć ich aż siedem sztuk. Ostatecznie zastosowałem rozwiązanie polegające na spadku napięcia na diodach, które aktywuje transoptor PC814. Rolety które posiadam mają wewnętrzne zabezpieczenie przed podaniem napięcia na oba uzwojenia silnika (góra, dół), jednak tak zaprojektowałem układ, aby sprzętowo nie było to możliwe. Pokazane jest to na poniższym rysunku. Program został napisany w C++ z wykorzystanie Arduino Core. ESP-12 pełni rolę konwertera komunikacyjnego, od strony wifi oferuje RestApi, konwertuje otrzymane wiadomości/zapytania na komunikację uart i wysyła do głównego procesora STM32. Na drugim porcie uart w STM32 jest podobna komunikacja z wykorzystaniem modułu bluetooth. Moduł BT aktualnie służy do przeglądania bieżących logów. Ponadto moduł posiada opcję komunikacji z wykorzystaniem sieci CAN, jestem bardziej fanem rozwiązań przewodowych tam gdzie jest to możliwe. Jak w mieszkaniu pojawi się więcej elementów automatyki to będę chciał całość przepiąć na sieć CAN zamiast Wifi. Sterowanie modułem odbywa się jak wspomniałem wyżej zapytaniami REST, na Banana Pro posiadam domowy serwer www, dołożyłem do niego prostą stronę w PHP, która pozwala w wygodny sposób wysyłać zapytania do sterownika. Do połączenia się ze sterownikiem poza domową siecią wykorzystuje OpenVPNa.
  7. Używam esp32-cam i chciałbym zapisywać dane z czujnika na kartę SD. Niestety, ale gdy wysyłam dane komendą file.println w pętli loop, to albo plik jest pusty, albo plik zawiera dane tylko tak jakby po jednym przejściu pętli.
  8. Cześć. Postanowiłem zamieścić tu przykład kodu w ramach podzielenia się swoja "twórczością". Jeśli zły dział, proszę przenieść. Post głównie w celach edukacyjnych dla osób, które jeszcze nie miały okazje zrezygnować z miliona zmiennych Pin_1, Pin_2 itd. Dużo przyjemniej i czytelniej jest mieć wszystko skompresowane do obiektów, nawet jeśli to bedzie przerost formy nad treścią. Po prostu sam chciałbym coś takiego przeczytać rok-dwa temu 🙂 Swego czasu, gdy trochę więcej poświęcałem czasu na embedded, natrafiłem na jednym z kursów M. Salamona fajną (według mnie) metodę implementacji obsługi przycisku. Postanowiłem sobie ją trochę przerobić, gdyż oryginał był pisany pod C i używał callbacków, które średnio mi dobrze pasowały, bo za każdym razem napotykałem rozmaite problemy, z którymi średnio sobie umiałem poradzić. Napisałem więc sobie to jako klasę, a kolejno dopisałem drugą klasę, która dziedziczy po niej, a jednocześnie implementuje to co dzieje się po wciśnięciu tego przycisku. Jest to taki chyba najprostszy przykład zastosowania programowania obiektowego dla arduino. Zamieszczam Link do GitHub z plikami .h i .cpp. gdyż wstawienie tu całego kodu byłoby trochę przesadą? Celem w ogóle użycia dziedziczenia było zrobienie swoistej "templatki" dla klasy, która implementuje obsługę przycisku, ale nie definiuje tego co dzieje się po wciśnięciu tego przycisku. Zapewne 80% przycisków w projektach po prostu wystawia jakiś stan na konkretny Pin, więc można było darować sobie to dziedziczenie, no ale.. zrobiłem sobie to głównie pod siebie na przyszłość. W temacie programowania obiektowego jestem początkujący więc wszelakie uwagi od bardziej doświadczonych kolegów mile widziane, bo niestety ale wszystko to moje własne próby sklejenia czegoś z informacji, które zdobyłem. Opisując skromnie co dzieje się w implementacji i jakie są założenia: 1. Brak możliwości stworzenia podstawowej klasy // virtual destructor virtual ~TypeButton() = 0; // virtual methods virtual void ButtonPressed() = 0; virtual void ButtonNotPressed() = 0; Chciałem stworzyć sobie klasę, która będzie miała zaimplementowaną swoista "blokade", żeby nie kusiło stworzenia obiektu, który nie posiada implementacji dla funkcji obsługującej przycisk. W tym celu zmieniłem destruktor na wirtualny i przypisałem mu 0. W ten sposób ustawiłem destruktor czysto wirtualny, czyli taki którego nie można wywołać. Co za tym idzie, nie można również stworzyć obiektu. 2. Funkcje Pressed i NotPressed są wykonywane raz Funkcje wykonywane są raz tylko przy zmianie stanów z Debbounce -> Pressed i z Pressed-> Idle. Zabezpieczało mnie to przed wchodzeniem ciągle, w funkcje, która ustawia stan na wysoki/niski. 3. Działanie głównie opiera się na sprawdzaniu w pętli metody ButtonTask() void TypeButton::ButtonTask() { switch (this->State) { case IDLE: ButtonIdle(); break; case DEBBOUNCE: ButtonDebbounce(); break; case PRESSED: ButtonIsPressed(); break; default: break; } } Metoda za każdym razem sprawdza aktualny stan obiektu, z którego została wywoływana (this->State) i wykonuje funkcje, zależnie od tego w jakim stanie znajduje się aktualnie przycisk. 4. Opierając się na Klasie-rodzic można dorabiać dalej własne implementacje klasy-dziecka, które bedą wykonywać inne zadania. Kwestia inwencji własnej. Ogólnie, jak wspomniałem wcześniej wygląda to jak przerost formy nad treścią, ale obecnie bardzo mi ułatwia pisanie prototypów bo nie musze znowu martwić czy dobrze napisałem kod do przycisku. No i było bardzo fajną lekcją w kontekście robienia klas/metod wirtualnych. Z napotkanych problemów: Mimo, że zaimplementowałem destruktor jako pure virtual to i tak musiałem dodać w pliku .cpp na początku: TypeButton::~TypeButton(){} Bez tego dostawałem ciągłe błedy o tym, że w klasie-dziecko jest nieznany typ destruktora własnie TypeButton::~TypeButton(). Trochę nie mogłem zrozumieć czemu musiałem to zrobić. Wygrzebałem to w jednym z tematów na Stack Overflow i było to tam opisane czymś w rodzaju "Czasem trzeba dodać tego typu deklaracje mimo pure virutal destruktora". Albo ja nie uważałem podczas uczenia się, ale rzadko kiedy widziałem by ktoś miał taki problem. Może ktoś dużo mądrzejszy mi to wytłumaczy? 🙂 To by było na tyle. Wszelakie uwagi mile widziane
  9. Hej, próbuje wysłać przez kolejkę na FreeRTOS strukturę wraz z rozróżnieniem dwóch tasków wysyłających i jednym odbierającym. Tak wygląda mój kod: #include "queue.h" typedef int taskProfiler; typedef enum { eSender1 = 0, eSender2, }DataSource_t; typedef struct { uint8_t ucValue; DataSource_t eDataSource; }Data_t; static Data_t xStructToSend[2] = { (100, eSender1), (50, eSender2) }; QueueHandle_t xQueue; taskProfiler senderTaskProfiler = 0; taskProfiler receiverTaskProfiler = 0; void setup() { // put your setup code here, to run once: Serial.begin(115200); delay(5000); Serial.println(xStructToSend[1].ucValue); xQueue = xQueueCreate(3, sizeof(Data_t)); xTaskCreate(vSenderTask, "Sender Task 1", 8192, &(xStructToSend[0]), 2, NULL); xTaskCreate(vSenderTask, "Sender Task 2", 8192, &(xStructToSend[1]), 2, NULL); xTaskCreate(vReceiverTask, "Receiver Task", 8192, NULL, 2, NULL); } void vSenderTask(void *pvParameters) { BaseType_t xStatus; const TickType_t xTicksToWait = pdMS_TO_TICKS(100); Data_t xReceivedStructure; memcpy(&xReceivedStructure, &pvParameters, sizeof(pvParameters)); while(1) { xStatus = xQueueSend(xQueue, pvParameters, xTicksToWait); if(xStatus != pdPASS) { Serial.println("Could not send to the Queue"); } Serial.println(xReceivedStructure.ucValue); } } void vReceiverTask(void *pvParameters) { Data_t xReceivedStructure; BaseType_t xStatus; while(1) { xStatus = xQueueReceive(xQueue, &xReceivedStructure, 0); if(xStatus == pdPASS) { if(xReceivedStructure.eDataSource == eSender1) { Serial.print("This is from Sender1: "); Serial.println(xReceivedStructure.ucValue); } else { Serial.print("This is from Sender2: "); Serial.println(xReceivedStructure.ucValue); } } else { Serial.println("Could not receive data from the queue"); } } } void loop() { // put your main code here, to run repeatedly: } W "setup()" linia "Serial.println(xStructToSend[1].ucValue);" zwraca mi wartość 0 chociaż teoretycznie powinna 50. Tak samo dzieje się w tasku wysyłającym w linii "Serial.println(xReceivedStructure.ucValue);". Wyglada jakby od samego początku była zła inicjalizacja wartości zmiennych w wysyłanej strukturze. Sam task Receiver zwraca wartość 152 lub 160. Jaki błąd został popełniony w tym kodzie i w jaki sposób prawidłowo mogę zainicjalizować zmienne w strukturze? Z góry dziękuje za pomoc. Pozdrawiam
  10. Po kursie Arduino chcesz nauczyć się czegoś jeszcze? Albo chcesz zrobić inteligenty dom? A może Arduino po prostu ci nie wystarcza - na to wszystko jest rozwiązanie! ESP8266 to wydajny i tani mikrokontroler. Znajdziemy go na wielu płytkach, od małego 01 na NodeMCU kończąc. Dzisiaj zobaczymy jakie są rodzaje płytek, co w sobie ukrywa kostka mikrokontrolera, oraz spróbujemy przygotować środowisko i wgrać Blinka. Niestety, tak nie robimy - tylko zewrzemy piny. Spis treści serii artykułów: 1. Omówienie, i przygotowanie środowiska 2. Zapoznanie z nowym środowiskiem, praca jako Arduino, prosty serwer WWW 3. Przyspieszony kurs na webmastera 4. Wykresy, zapis do SPIFFS, mini smart-dom 5. Odbiór danych z przeglądarki, stałe IP, łączenie modułów ESP Ten wpis brał udział konkursie na najlepszy artykuł o elektronice lub programowaniu. Sprawdź wyniki oraz listę wszystkich prac » Partnerem tej edycji konkursu (marzec 2020) był popularny producent obwodów drukowanych, firma PCBWay. Możliwości ESP8266 Uznałem, że najlepiej będzie zestawić NodeMCU v3 z Arduino UNO. Najważniejsze informacje podałem w tabeli. Pamiętamy, że ESP pracuje na napięciu 3.3v. Kiedy podłączałem do 5V (nie róbcie tego w domu) się tylko grzał, ale lepiej tego nie róbcie. ESP ma także pamięć FLASH w oddzielnej kostce - co pozwala na dużą jej pojemność (zależy to od wersji modułu). Co więcej, interfejsy możemy zdefiniować na (prawie) każdym pinie. ESP pracuje o wiele szybciej od Arduino - bo aż na 80MHz (z możliwością do 160!), i przede wszystkim ESP jest 32 bitowe. No, i ESP się lekko grzeje, ale to nic złego. Warianty ESP8266 Ten mały mikrokontroler możemy znaleźć na równie małych płytkach, lub znacznie większych i rozbudowanych modułach. Jednym z mniejszych, samodzielnych modułów jest ESP12. Posiada wiele wyprowadzeń, lecz nie jest (nawet z przejściówką) zbyt przyjazny dla płytki stykowej. Posiada natomiast aż 4MB pamięci FLASH (wersja ESP12F). Będzie to optymalny wybór dla rozwiązań wbudowanych (np. własnych płytek). ESP12 Jeżeli natomiast szukamy czegoś równie małego, ale bardziej przyjaznego dla nas, tutaj nadchodzi ESP01. Ten mały modulik ma niestety mniej pamięci (niebieska wersja 512kB, czarna 1MB), oraz tylko 8 wyprowadzonych pinów - lecz do konkretnego zastosowania, np. gniazdka z przekaźnikiem, wystarczy. ESP01 (niebieski) ESP03 i ESP07 to uboższe wersje ESP12, ale posiadają ceramiczną antenę - a ESP07 nawet złącze do zewnętrznej anteny. ESP07 Pozostałe moduły rzadko się spotyka, różnią się jedynie ilością wyprowadzeń, rozmiarem, i sposobem montażu. Przygotowanie ESP do programowania W zależności od tego, jaki moduł wybrałeś, będziesz musiał albo przylutować przewody do jego wyprowadzeń, lub podłączyć się przewodami do płytki stykowej. Dlatego na początek nauki, najlepiej zakupić NodeMCU (płytkę deweloperską z ESP12 na pokładzie), Wemos (troszkę mniejsze płytki z ESP12) - mają wszystko wbudowane. Jeżeli taką płytkę wybrałeś, możesz pominąć ten krok. Mając "surowe" ESP12 lub 01, musisz je odpowiednio podłączyć. Połączenie ESP01 z konwerterem USB ↔ UART. Rozpiska pinów dla ESP01. Do tego będziemy potrzebować dwóch przycisków tact switch, kondensatora elektrolitycznego (z zakresu 100-1000µF), dwóch rezystorów 10kΩ, przewodów, oraz oczywiście ESP i konwertera. Pokazałem to na przykładzie ESP01, ale każdy ESP też ma takie wyprowadzenia: pin CH_PD łączymy na stałe do napięcia zasilania przez rezystor 10kΩ pin RST podciągamy do VCC rezystorem 10kΩ, oraz podpinamy przycisk zwierający do masy pin GPIO0 podpinamy do przycisku zwierającego z masą między VCC a GND dajemy kondensator pin RX konwertera łączymy z pinem TX ESP, a pin TX konwertera z pinem RX ESP piny VCC i GND ESP łączymy z pinami VCC i GND konwertera napięcie na konwerterze ustawiamy na 3.3V! Na NodeMCU także znajdziemy dwa przyciski. Przycisk RST odpowiada ze reset mikrokontrolera - tak samo jak w Arduino. Ale co robi przycisk PRG? Otóż, jeżeli na pin GPIO0 podamy logiczne 0 podczas startu mikrokontrolera, wprowadzimy go w tryb programowania. Dzięki temu będziemy mogli wgrać do niego nasz kod. Jeżeli nie mamy zainstalowanych sterowników dla konwertera (np. CH340), powinniśmy je pobrać i zainstalować. Przygotowanie środowiska ESP możemy programować na dwa sposoby, w języku lua - oraz klasycznie, jak arduino, w c++. Opiszę wam sposób jak programować ESP jako Arduino - a do tego potrzebne będzie Arduino IDE. Jeżeli jeszcze takowego nie mamy, pobieramy najnowszą wersję stąd, po czym instalujemy. Dokładny proces instalacji został opisany na kursie Arduino - jeżeli mamy już zainstalowane środowisko, uruchamiamy je, a następnie przechodzimy do zakładki Plik → Preferencje. Powinno nam się otworzyć nowe okno. Szukamy okienka "Dodatkowe adresy URL do menedżera płytek", i wklejamy ten adres: https://arduino.esp8266.com/stable/package_esp8266com_index.json Całość powinna teraz wyglądać tak: Klikamy OK - następnie przechodzimy do zakładki Narzędzia → Płytka → Menedżer płytek Szukamy "esp8266", i klikamy Instaluj. Pobrane zostanie ok. 100MB danych. Od teraz możemy wybrać płytkę ESP jak zwykłą płytkę Arduino. ALE! Jeżeli już kiedyś programowałeś, w innym IDE, zapewne wiesz, że Arduino IDE jest troszkę przestarzałe. Brak autouzupełniania, podpowiedzi, rozbudowanego systemu plików, GIT, i innych funkcji. Jest na to sposób! Dlatego w tym poradniku także opiszę instalację i konfigurację Microsoft Visual Studio Code do pracy z Arduino. Dzięki temu będzie o wiele prościej i wygodniej pisać programy. Pobieramy zatem najnowsze VS Studio Code z tej strony. Jak widać jest ono dostępne na Windowsa, Linuxa, i MacOS. Po pobraniu i zainstalowaniu, powinniśmy zobaczyć taki widok: Jeżeli ciemny motyw nam nie odpowiada, możemy to zmienić naciskając koło zębate (lewy, dolny róg) i "Color Theme" - jasny motyw to Light+. Problemem dla niektórych może być język angielski - lecz w informatyce jest on niezbędny do funkcjonowania. Nie ma problemu aby wrócić do spolszczonego Arduino IDE. Jeżeli jednak chcesz zostać przy VS Code, musimy zainstalować rozszerzenie Platform.io. Dokładniej masz to opisane w tym forbotowym artykule. Po zainstalowaniu Platformio, klikamy magiczny przycisk F1 (musimy go zapamiętać!), i ukazuje nam się to okno: Znajdziemy tam wszystkie funkcje znane z Arduino IDE! Teraz możemy podpiąć nasz konwerter lub NodeMCU do komputera. Tworzymy nowy projekt, i szukamy po lewej pliku platformio.ini. Tam możemy wybrać inną płytkę niż ta, którą wybraliśmy podczas tworzenia projektu. Możemy także ustalić inne rzeczy - więcej w dokumentacji. Otwieramy podfolder src, i szukamy pliku main.cpp. Otworzyło nam się nowe okno - pierwsze co widzimy, to biblioteka Arduino. Dołączy ona wszystkie funkcje z starego IDE. Wklejamy poniższy kod. Największą różnicą ESP w stosunku do Arduino, jest tutaj zapalenie poprzez ustawienie LOW na pinie. #include <Arduino.h> void setup() { pinMode(LED_BUILTIN, OUTPUT); //pin drugi jako wyjście } void loop() { digitalWrite(LED_BUILTIN, LOW); //zapalamy diodę delay(1000); //czekamy sekundę digitalWrite(LED_BUILTIN, HIGH); //gasimy diodę delay(1000); //czekamy sekundę } Teraz przyszedł moment na wgranie szkicu. Klikamy przycisk PRG (gdzieniegdzie opisywany jako FLASH), trzymamy, a następnie RESET, i puszczamy. Dioda powinna raz mrugnąć - oznacza to, że ESP jest gotowe do zaprogramowania. Klikamy zatem znowu F1, a następnie "Platformio: Upload". Cierpliwie czekamy, aż program się wgra. Kiedy zobaczymy ten komunikat: Przyciskamy przycisk reset na naszej płytce - i dioda powinna zacząć mrugać. Na dole, po lewej, na niebieskim pasku są także małe ikonki pozwalające wgrać szkic. Gratulacje, udało Ci się zaprogramować ESP! Możesz je teraz wykorzystać jako moduł Wifi, samodzielne urządzenie, zastosowań jest tyle ile dla Arduino, a nawet i więcej. Udało Ci się także skonfigurować poprawnie VS Code do pracy z płytkami Arduino (i nie tylko!). W następnym odcinku zobaczymy co tak naprawdę oferuje przesiadka na VS Code, oraz spróbujemy połączyć się przez Wifi. Liźniemy nawet trochę HTMLa z CSSem, aby postawić stronę WWW! W przypadku jakichkolwiek problemów, nie bójcie się pisać komentarzy. Spis treści serii artykułów: 1. Omówienie, i przygotowanie środowiska 2. Zapoznanie z nowym środowiskiem, praca jako Arduino, prosty serwer WWW 3. Przyspieszony kurs na webmastera 4. Wykresy, zapis do SPIFFS, mini smart-dom 5. Odbiór danych z przeglądarki, stałe IP, łączenie modułów ESP
  11. Cześć, nie dawno wpadłem na pomysł małego tuningu swoich zasłon. Przy użyciu ESP8266, dwóch servomotorów MG996R 360, 4 czujnikow kontkatronowych i wydruku 3D. Projekt jest zasilany z 5v ładowarki od jbl W lecie oraz w słoneczne dni oglądanie telewizji w moim domu jest niemalże niemożliwe. Dostęp do rolety po lewej stronie jest nieco utrudniony , przez stojąca pod oknem klatkę królika. Urządzenia tego typu są stosunkowo drogie. Więc wraz ze szwagrem wpadliśmy na pomysł zbudowania automatu, który będzie odpowiadał za sterowanie zaslonami/ roletami okiennymi. Póki co sterowanie ogranicza się do http i rolety sterowane sa pojedynczo przez ograniczenie prądowe zasilacza impulsowego. Lecz finalnie chcemy go rozbudować o moduł czujnika natężenia światła oraz o optocoupler podłączony do usb telewizora. Które po włączeniu tv będzie miało stan wysoki, sygnał z modułu optocouplera będzie docierał do esp i na podstawie odczytu z czujnika światła; Płytka będzie decydowała czy zasłonić oba okna, czy jedno będzie wystarczające. Zaś po jego wyłączeniu będą się one automatycznie podnosić, tak aby w domu nie było ciemno przez cały czas. Myślę że projekt jest stosunkowo ciekawy i prosty do wykonania dla majsterkowiczów. Przez zastosowanie serwa udało się zmniejszyć rozmiary samego urządzenia. W przypadku zastosowania silnika krokowego i przekładni były sporo większy. Link do prezentacji YouTube: Poniżej załączam listę komponentów: -1x Esp 8266 -4x czujniki kontaktronowe (okienne) https://allegro.pl/oferta/kontaktron-boczny-czujnik-do-okien-drzwi-b-1p-10973809269?snapshot=MjAyMi0wMS0zMVQyMzoxNjo1NS44NThaO2J1eWVyOzA2ZWI1NmEyMTQ3ODljNmVkMWIzM2QyZWMzNDJiNjEwOGI3MzE4OGQ3MTkxNDMxMmU4ZmRkYzMxN2UzOWRkM2U%3D -2x servo MG996R https://allegro.pl/oferta/serwo-mg996r-metalowe-zebatki-15kg-360-11755893673?snapshot=MjAyMi0wMS0zMFQxNToxNjowMS43NzdaO2J1eWVyO2Q4NzBmNjY2OTRkMzc0ZDA1NzkzNjBhNjA2ZThhZGI5NWFiZTY3Nzk5YmQ4Mzg3N2NhODI5OWVkNzhhMGUzNGE%3D -4m przewodu wykorzystywanego w instalacjach alarmowych -2x wtyk usb https://electropark.pl/pl/p/Wtyk-USB-typ-A/475 - zasilacz impulsowy 5v 2,5A -2x moduł czujnika światła https://electropark.pl/pl/p/Modul-natezenia-swiatla-fotorezystor/9542 -12X klips do mocowania przewodu https://www.castorama.pl/klips-z-tasm-na-przew-5mm-4szt-id-1108710.html
  12. Witam chciałbym się pochwalić moim growboxem (gwowbox-częściowo lub całkowicie zamknięty system do uprawy roślin). Na samym początku małe wyjaśnienie, projekt powstał ponad rok temu, „plony” już dawno zebrane. Skrzynia stoi i się kurzy więc trzeba się jej pozbyć. Zaczynając projekt moim jedynym doświadczeniem z programowaniem mikrokontrolerów było ukończenia kursu z Arduino na Forbocie 🙂 . Bardzo ale to bardzo przepraszam za nieład w przewodach i jakość wykonania, zdjęcia były robione dziś a sam box podczas swojej pracy przechodził różne updaty i finalnie nie chciało mi się już tego jakoś sensownie układać. Sorki za długi wstęp. Do projektu wybrane zostało Arduino Mega a raczej jego klon (Połączenie dwóch układów Mega2560 z ESP8266). Ze względu na cene 49,99 🙂 Wyświetlacz to 7 calowy Nextion, ekran pojemnościowy bardzo czytelny. Bardzo łatwo się go programuje a na YT można znaleźć polskie tutoriale. Połącznie Andino i wyświetlacza odbywa się tak samo jak z ESP po UART, działa to może trochę topornie ale wbrew pozorom całkiem dobrze. Wyświetlacz wykorzystywany był w celu wyświetlania informacji, które arduino odczytało z czujników i przedstawienie ich w przejrzysty sposób oraz wprowadzania wartości zmiennych dla arduino. Jako, że płytka arduino wyposażona była w układ esp postanowiłem go w jakimś stopniu wykorzystać i tak najprostsza metodą (komendami AT) dodana została możliwość wyświetlania informacji z czujników po połączeniu się z ip serwera ESP. Wykonanie: Konstrukcja - wykonana została z twardego styropianu o grubości 30mm (Polistyrenu XPS- Produkt cechuje się wysoką odpornością na ściskanie, działanie wilgoci oraz jest bardzo lekki). Wymiary zewnętrzne 120/120/60cm, drzwiczki otwierane na 3 zawiasach uszczelnione, zamykane gumami montażowymi. Środek skrzynki obklejony folią "mylar" (odbija około 90% światła). Lampy – skrzynka posiada dwie lampy, każda z nich składa się z radiatora 290/246/25 mm do którego przyklejone zostały 3 diody COB 50W każda. Diody posiadają własne sterowniki i są zasilane napięciem sieciowym. Ze względu na wysokie temperatury do lampy dołożony został wentylator którego prędkość obrotowa zależy od wskazania czujnika LM35 doklejonego do radiatora. Wentylacja – skrzynka wyposażona została w wentylator który tłoczył powietrze do środka, trzy wentylatory mieszające powietrze w środku, oraz wentylator wyciągający powietrze. Działanie i funkcjonalności: Po włączeniu zasilania na wyświetlaczu ukazuję się ekran główny z poziomu, którego możemy sterować oświetleniem, wentylacja, wilgotnością, temperaturą, podlewaniem, ustawić profil automatyczny, podejrzeć obecną datę i godzinę, datę i godzinę ostatniego podlewania oraz przejść do ustawień. Strona oświetlenie daje nam możliwość zapalenia/gaszenia każdej z 6 diod COB, dodatkowo pokazuje moc każdej z lamp oraz jej temperaturę. Strona Wentylacja pozwala na ustawienie prędkości wentylatorów nawiewu, wyciągu oraz mieszaczy powietrza wewnątrz skrzynki. Strona Wilgotność i temperatura pozwala ustawić wartości wilgotności i temperatury poniżej których załączy się nawilżacz powietrza oraz grzałka. Ponadto na bieżąco wyświetla informacje o obecnie panującej temperaturze i wilgotności powietrza oraz wilgotności gleby doniczek. . Strona Podlewanie w zamyśle miała włączać i wyłączać pompkę podlewającą rośliny, jednakże zabrakło czasu i chęci do dokończenia. Strona Profile jest w zasadzie najważniejsza ze wszystkich, po jej dodaniu inne strony przestały być potrzebne. Podzielona jest na 4 części w których mamy do wypełnienia po 8 pól. Podział na 4 części daje możliwość rozbicia doby na rano, południe, wieczór i noc dzięki czemu możemy symulować roślinie normalny cykl dnia. Pod przyciskiem „i” pokaże nam się strona z informacjami jak ów pola uzupełnić. Strona Ustawienia daje możliwość ustawienia daty i godziny oraz jasności ekranu. Dodatkowo można stąd przejść do strony Serwer info gdzie wyświetlane jest czy połącznie z siecią Wifi się powiodło oraz pod jakim adresem IP możemy podejrzeć wartości panujące w skrzynce. Na koniec krótki filmik jak to działa 🙂
  13. Cześć! Tworzę mały projekcik, dzięki któremu będę mógł kontrolować warunki wokół moich roślin. Jednym z podstawowych założeń jest oszczędność baterii. Układ jest zasilany przez baterię 18650 a jego mózgiem jest ESP8266. Aby zaoszczędzić energię chcę włączać zasilanie dla czujników tylko na moment, poprzez podanie stanu wysokiego z GPIO14 i 13 na tranzystory typu MOSFET (IRLML6246 jako N MOSFET i IRLML6401 jako P MOSFET). Niestety mam małą wiedzę na temat budowy własnych układów elektronicznych i nie jestem pewien czy wybrane przeze mnie tranzystory spełnią swoją rolę. Wrzucam dwa schematy, które różnią się tylko sposobem przekazywania informacji o stanie naładowania baterii (jako element główny tego podukładu wykorzystuję TL431). Pierwszy układ ma za zadanie podawać stan niski na GPIO2, kiedy bateria ma poniżej 3,6v a drugi podaje stan wysoki na GPIO2, kiedy bateria ma poniżej 3,6v. W przypadku pierwszego układu, poprzez dzielnik napięcia ograniczyłem napięcie płynące do GPIO2 tak, aby przy maksymalnym naładowaniu baterii nie przekroczyć 1,3*Vdd mikrokontrolera. Proszę o sprawdzenie, czy dobrane tranzystory spełnią swoją rolę przy włączaniu układu monitorującego baterię i w przypadku włączania czujników oraz o ewentualne poprawki układu jeśli coś przeoczyłem. PS. Celowo nie wrzucam odcinania baterii jeśli jej stan spadnie poniżej 3,2V. Po prostu chce maksymalnie zaoszczędzić czas pracy na baterii.
  14. Cześć, mam problem z komunikacja pomiędzy esp i arduino. Wykorzystuje bibliotekę #include "SerialTransfer.h" do wysyłannia danych i komunikacja pomiędzy dwoma esp8266 działa bardzo dobrze ale jeżeli próbuje podłączyć esp i arduino i pokazują sie śmieci na terminalu. Konwerter TTL podłączony, napięcia prawidłowe 5V i 3.3V. O co może chodzić? 1 zdjecie ESP-ESP 2 zdjęcie ESP-Arduino, próbowałem na dwóch róznych TTL jak i pin TX z ESP do RX arduino bezpośrednio i tez nie działa.
  15. Przeglądając sieć w poszukiwaniu różnych DIY od czasu do czasu można trafić na różne układziki które mają za zadanie odczytać jakiś parametr a następnie przesłać do urządzenia nadrzędnego. Przeważnie te układy są zasilane z akumulatorów zawierają dodatkowe przetwornice i inne podobne rozwiązania. Byłem ciekaw czy faktycznie esp8266 zawsze musi mieć zasilanie akumulatorowe? Czy pobiera aż tyle prądu że nie da się użyć baterii? Po krótkim przejrzeniu możliwości tych układów okazało się te układy mogą “zejść” z poborem prądu aż do 15uA no nie jest to jakiś rekord wśród współczesnych układów ale jak najbardziej jest osiągalne. Jak to zrobić? Wpierw należy wybrać układ dzięki któremu osiągniemy cel najkrótszą drogą, płytki deweloperskie typu nodeMCU, oraz Vemos od razu odrzuciłem ze względu na wbudowane stabilizatory oraz układy konwerterów rs232. Esp01 od biedy mógłby być, jednak wymaga kombinacji polegającej na lutowaniu dodatkowego przewodu do pinu wake. Postanowiłem użyć modułu ESP-07 jednak aby wykorzystać pełnię możliwości tego układu należy usunąć diody informujące o stanie urządzenia, ten zabieg wymaga nieco wprawy w posługiwaniu się lutownicą ale gdy już się to uda kolejne µA zaoszczędzone. Następnie, ponieważ opis dotyczy współpracy z BME280 z płytki tego układu również trzeba usunąć stabilizator napięcia oraz zewrzeć dwa punkty. Przeróbki widać poniżej. W kwestii schematu urządzenie nie jest skomplikowane, płytka jest przygotowana do pracy z popularną przejściówką FTD232 programowanie odbywa się półautomatycznie z wykorzystaniem pinu DTR, chcąc wgrać nowy soft należy po uruchomieniu skryptu nacisnąć przycisk reset. Dodatkowego komentarza wymaga złącze H4 z rezystorem R5. Rezystor przy rezystancji 1ohm w obwodzie zasilania ułatwia pomiary prądu, zwłaszcza, podczas gdy moduł jest w trybie odczytu lub wysyłania danych. Przebieg napięcia na rezystorze odwzorowuje pobór prądu przez układ do zmierzenia oscyloskopem ponieważ klasycznym multimetrem mało co da się zmierzyć, złącze H1 oraz J1 są do dowolnego wykorzystania, złącze pinu ADC wyprowadziłem ale w tym projekcie ADC mierzy wewnętrzne napięcie zasilania. Na koniec opisu elektroniki ważna uwaga: Trzeba pamiętać o konwersji napięć przejściówki oraz samym zasilaniu gdyż ani ESP ani BMP nie zawierają żadnych układów ograniczających napięcie więc można pracować z napięciami do 3.3V nie ma znaczenia czy z przejściówki czy z baterii. Program Całość napisałem w Visual Studio Code z bibliotekami Arduino Co ważne dla czujnika BME280 znacznie lepiej sprawdziła się biblioteka od sparkfun dlatego że libs od Adafruit zawiera jak dla mnie zbyt dużo niepotrzebnych delay - ów już sama inicjalizacja czujnika to niepotrzebne 100mS a ponieważ nie chciało mi się w tym grzebać, dowiedziałem się że właśnie ta od sparkfun jest lepiej napisana. Na początku kodu widać kilka stałych dosłownych: #define SLEEP 600e6 // 10minut #define WIFI_CHANNEL 11 // kanal #define TIMEOUT 300 #define RTCMEMSTARTADRESS 65 // adrs RTC mme #define DEBUG 0 #Sleep pozwala określić co ile moduł ma być wybudzony. #wifi_channel wiąże się to z tym że część odbiorcza - o której później, nie powinna pracować na tym samym kanale co usługa esp now stąd na stałe przypisana taka wartość, czasem warto poeksperymentować z innymi można zmieniać od 1 do 14 klik #timeout ustala czas w jakim moduł powinien “wyrobić się” z wszystkimi zadaniami, gdyby coś poszło nie tak to funkcja sleep zostanie uruchomiona po tym czasie (w ms) #rtcmemstartaddress określa początek obszaru danych w pamięci RTC, pamięć ta nie jest kasowana po resecie urządzenia więc świetnie nadaje się do przechowywania ustawień bieżących modułu. #debug zmienienie tej wartości na 1 przede wszystkim uruchamia wbudowany uart i funkcje związane z obsługą Serial, przydaje się do testowania oprogramowania. #include <Arduino.h> #include <ESP8266WiFi.h> #include <Adafruit_Sensor.h> #include <SparkFunBME280.h> #include <ftoi.h> /* #include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> */ #include <Wire.h> #include <Ticker.h> #include <espnow.h> #define SLEEP 600e6 // 10minut #define WIFI_CHANNEL 11 // kanal #define TIMEOUT 300 #define RTCMEMSTARTADRESS 65 // adrs RTC mme #define DEBUG 0 uint8_t broadcastAddress[] = {0xE0, 0x98, 0x06, 0x25, 0x40, 0x80}; // mac modulu odbiorczego ADC_MODE(ADC_VCC); const char nazwa[] = "CZUJNIK ZEWNETRZNY"; typedef struct { uint32_t temp; // temperatura 4 uint32_t press; // cisnienie 4 int humm; // wilgotnosc 4 uint16_t vbat; // U zas czujnika 2 uint16_t okno; //okno 0 -> zamkniete, 1->otwarte } bme_t; bme_t g_czujnik; BME280 bme; bool readSens(bme_t *bmeSens); bool checkData(bme_t *dta); // porownuje aktualny pomiar z danymi zapisanymi w rtc_mem void continueProg(void); void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus); void sleep(void); bool porownaj(bme_t *s, bme_t *d); Ticker tmr, tbme; /************************************* START ******************************/ void setup() { tmr.once_ms(TIMEOUT, sleep); // w razie w #if DEBUG == 1 Serial.begin(115200); Serial.println("start"); #endif Wire.begin(); Wire.setClock(400000L); bme.setI2CAddress(0x76); bme.beginI2C(); bme.setMode(MODE_SLEEP); //Sleep for now if (readSens(&g_czujnik)) { // jesli wartosci rozne to wykonaj reszte kodu WiFi.setOutputPower(0); // nie zmienia czasu ale zmniejsza pobierana moc WiFi.mode(WIFI_STA); // nie zmienia czasu - lepiej zostawic wlaczone if (esp_now_init() != 0) { #if DEBUG == 1 Serial.println("Error initializing ESP-NOW"); return; ESP.deepSleep(SLEEP); #else sleep(); #endif } //memcpy(&SendBUf[sizeof(nazwa)],&Czujnik_Data[1],sizeof(czujnik_t)); // kopiowanie struktury static uint8_t SendBuf[64]; memcpy(SendBuf, &nazwa, sizeof(nazwa)); memcpy(&SendBuf[sizeof(nazwa)], &g_czujnik, sizeof(g_czujnik)); esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); // jako master esp_now_register_send_cb(OnDataSent); // callback esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0); // do kogo wyslac? esp_now_send(broadcastAddress, SendBuf, sizeof(SendBuf)); // wyslij sleep(); } else sleep(); // jesli dane takie same to nie trzeba wysylac } void loop() { } // odczyt bme bool readSens(bme_t *bmeSens) { static bme_t pomiar; // static dlatego aby zmienna byla automatycznie wyzerowana system_rtc_mem_read(RTCMEMSTARTADRESS, &pomiar, sizeof(bme_t)); #if DEBUG == 1 Serial.println("Start pomiar"); #endif int cc, cu; bool znak; bme.setMode(MODE_FORCED); //Wake up sensor and take reading while (bme.isMeasuring() == false); //Wait for sensor to start measurment while (bme.isMeasuring() == true) ; //Hang out while sensor completes the reading bmeSens->humm = (int)bme.readFloatHumidity(); floatToInt(bme.readFloatPressure() / 100.0F, 1, &znak, &cc, &cu); // konwersja wstaw((uint32_t *)&bmeSens->press, znak, cc, cu); floatToInt(bme.readTempC(), 1, &znak, &cc, &cu); wstaw((uint32_t *)&bmeSens->temp, znak, cc, cu); bmeSens->vbat = ESP.getVcc(); bmeSens->okno = 0x0; if (porownaj(&g_czujnik, &pomiar)) { // zwraca true kiedy wyniki rozne system_rtc_mem_write(RTCMEMSTARTADRESS, &g_czujnik, sizeof(bme_t)); // kopiowanie do mem return true; } else return false; // jesli nie bylo zmian #if DEBUG == 1 Serial.print("T="); Serial.println(bme.readTempC(), 2); Serial.print("P="); Serial.println(bme.readFloatPressure(), 0); Serial.print("H="); Serial.println(bme.readFloatHumidity(), 0); #endif } // callback void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) { #if DEBUG == 1 if (sendStatus == 0) { Serial.println("Dostarczono"); sleep(); } if (sendStatus) { Serial.println("Blad wysylki danych"); sleep(); } #else // sleep(); #endif } void sleep() { WiFi.mode(WIFI_OFF); // //ESP.deepSleepInstant(SLEEP,WAKE_NO_RFCAL); WiFi.forceSleepBegin(); ESP.deepSleep(SLEEP, WAKE_NO_RFCAL); } bool porownaj(bme_t *s, bme_t *d) { char *ps = (char *)s; char *pd = (char *)d; for (uint16_t i = 0; i < sizeof(bme_t); i++) { if (ps[i] != pd[i]) return true; // jesli nowy pomiar != pomiar poprzedni } return false; } Jak widać oprogramowanie to zaledwie kilka linijek kodu, funkcja nawet nie wchodzi w loop(); po resecie następuje odczyt czujnika BME, gdy się powiedzie zostaje wywołana funkcja która ustawia moduł w tryb wysyłania danych, warunkiem uruchomienia esp now jest również to że dane z poprzedniego pomiaru muszą być różne od bieżących. Przy tych samych nie ma sensu ponownie wysyłać pomiarów. Zaciekawienie może budzić funkcja floatToInt dodałem ją ponieważ nie potrzebne mi były pomiary z dwoma i więcej miejsc po przecinku( a takie wyniki odsyła funkcja odczytu bme) więc wyniki są konwertowane do dwóch intów i jednego bool określającego znak. Pomiary Pomiarów dokonywałem za pomocą rezystora szeregowego włączonego w obwodzie masy, pierwszy oscylogram pokazuje trudne początki z układem, jeszcze bez ograniczenia mocy esp, z biblioteką Adafruit i ogólnie nie prezentowały się zbyt zachęcająco, dopiero po kilku próbach oraz pomocy elektroda (dzięki @khoam) udało się uzyskać wyniki jak powyżej. Jak widać poza trybem czuwania gdzie układ faktycznie pobiera te kilkanaście µA. Urządzenie od wybudzenia do zakończenia wysyłki potrzebuje zaledwie 240mS gdzie największy pobór (ok 100mA) zajmuje niecałe 60mS. Niestety trochę czasu zajmuje inicjalizacja modułu, głównie czas przez który uruchamia się bootloader właściwie to już nie walczyłem z tym. Część odbiorcza Odbiornik jest zbudowany na esp12e(planowo esp 01) program działa tak, że nasłuchuje transmisji od części nadawczej, gdy pojawią się nowe dane odbiornik przełącza się w tryb wifi, łączy się do z serwerem remoteMe wysyła dane po czym znów przechodzi w tryb nasłuchiwania. Przyszłościowo chciałbym aby wszelkie konfiguracje mogły zostać wpisane z poziomu aplikacji a nie jak teraz ręcznie z poziomu kodu. Jak na razie oddaję w wasze ręce nie tylko kody źródłowe obu modułów, napisałem również prostą aplikację pod android która będzie odczytywała wartości z czujnika zdalnego, pomijam konfigurację usługi remoteMe. Aby jednak móc przetestować urządzenie trzeba zrobić kilka kroków: W programie nadajnika wpisać poprawny MAC adres odbiornika można to zrobić w prosty sposób wpisując króciutki program #include <ESP8266WiFi.h> void setup(){ Serial.begin(115200); delay(500); Serial.println(); Serial.print("MAC: "); Serial.println(WiFi.macAddress()); } Następnie ustawić wstępne warunki kompilacji i już można wgrywać kod. W module odbiornika jest więcej zabawy: Należy dokonać ustawień związanych z remoteme, hasła do swojego wifi i ja jeszcze mam ustawione stałe IP dla swojego modułu gdyż znacznie przyśpiesza połączenie z siecią. #define DEVICE_ID 17 // id #define DEVICE_NAME "" // twoja nazwa #define TOKEN "" // twój token #include <Arduino.h> #include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> #include <Ticker.h> #include <espnow.h> #include <ftoi.h> #include <RemoteMe.h> #include <RemoteMeSocketConnector.h> #define RTCSTARTADRESS 65 const char *ssid = ""; // wifissid const char *password = ""; // pass IPAddress staticIP(192, 168, 0, 10); // ponizej adresow przydzielanych dynamicznie IPAddress gateway(192, 168, 26, 1); IPAddress subnet(255, 255, 255, 0); RemoteMe &remoteMe = RemoteMe::getInstance(TOKEN, DEVICE_ID); Ticker tmr; uint32_t licznik; typedef void(*ptrParseFun_t)(void); typedef struct { uint32_t temp; // temperatura 4 uint32_t press; // cisnienie 4 int humm; // wilgotnosc 4 uint16_t vbat; // U zas czujnika 2 uint16_t okno; // okno 0 -> zamkniete, 1->otwrte 1 } readNow_t; // struktura zajmuje 19 bajtow const char czZew[] = "CZUJNIK ZEWNETRZNY"; const char okno1[] = "OKNO01"; const char * const ptrStr[] = {czZew,okno1}; // tab wskaznikow enum incomingDTA {no_data,bme_sens, okno_pok}; // 0 1 2 typedef struct { readNow_t data; uint32_t stat; ptrParseFun_t p; // wskaznik na f parsujaca } sysMem_t; sysMem_t g_structData; void RestartFunction(void); void parseOkno(); void parseData(); void timeout(void); void OnDataRecv(unsigned char *mac, unsigned char *incomingData, unsigned char len); void onBMEzewnetrznyChange(String s); void onStanOkienChange(String s); inline void setBMEzewnetrzny(String s) { remoteMe.getVariables()->setText("BMEzewnetrzny", s); } inline void setStanOkien(String s) {remoteMe.getVariables()->setText("StanOkien", s); } void setup() { // sysMem_t g_structData; Serial.begin(115200); system_rtc_mem_read(RTCSTARTADRESS, &g_structData, sizeof(sysMem_t)); Serial.println("Wifi start"); Serial.print("MAC: "); Serial.println(WiFi.macAddress()); WiFi.disconnect(); if (g_structData.stat == 1) { // tryb wysylania do remoteMe Serial.println("Tryb remote"); WiFi.config(staticIP, gateway, subnet); WiFi.begin(ssid, password); WiFi.mode(WIFI_STA); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Restart..."); ESP.restart(); // jesli nie powiodlo sie laczenie z siecia. (Todo: } // uruchomic kreatora WiFi?) remoteMe.getVariables()->observeText("BMEzewnetrzny", onBMEzewnetrznyChange); remoteMe.getVariables()->observeText("StanOkien", onStanOkienChange); remoteMe.setConnector(new RemoteMeSocketConnector); remoteMe.sendRegisterDeviceMessage(DEVICE_NAME); if (g_structData.p) g_structData.p(); // jesli wskaznik przypisany to wykonaj else RestartFunction(); // jesli wskaznik nie zostal przypisany } else { WiFi.mode(WIFI_STA); Serial.println("Tryb odbioru z czujnikow"); if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); esp_now_register_recv_cb(OnDataRecv); } pinMode(LED_BUILTIN, OUTPUT); pinMode(D3, INPUT_PULLUP); } void loop() { /* ArduinoOTA.handle(); */ if(g_structData.stat == 1){ // jesli jakies dane do wyslania remoteMe.loop(); } } void OnDataRecv( unsigned char *mac, unsigned char *incomingData, unsigned char len) { // dane z czujnikow kopiowanie do pamieci rtc i restart uint8_t l = 0; uint8_t bf[4]; for (uint8_t i = 0; i < sizeof(ptrStr) / sizeof(char *); i++) { if (0 == strcmp((char *)incomingData, ptrStr[i])) { l = i + 1; // sprawdzam z ktorego czujnika przylecialy dane break; } } sysMem_t x; if (l == bme_sens) { memcpy(&x.data, &incomingData[strlen(ptrStr[l - 1]) + 1], sizeof(readNow_t)); // x.stat = l; x.stat = 1; x.p = parseData; system_rtc_mem_write(RTCSTARTADRESS, &x, sizeof(sysMem_t)); } if (l == okno_pok) { memcpy(&bf, &incomingData[strlen(ptrStr[l - 1]) + 1], sizeof(bf)); // x.stat = l; x.stat = 1; x.data.okno = bf[0]; memcpy(&x.data.vbat, &bf[2], 2); x.p = parseOkno; system_rtc_mem_write(RTCSTARTADRESS, &x, sizeof(sysMem_t)); } Serial.print("Nowe dane - Restart ESP"); ESP.restart(); } void parseData(){ char buf[100]; char b2[5]; bool znak; int cc =0 ; int cu = 0; uint8_t * p; uint8_t * p2 = (uint8_t*)&cc; strcpy(buf,"EXT="); // naglowek -> nazwa czujnika EXT -> external, zewnetrzny //if(g_BMEstatus)strcat(bf,"OK");else strcat(bf,"FALSE"); // status BME strcat(buf,"OK"); strcat(buf,"&T="); // temperatura p = (uint8_t*)&g_structData.data.temp; znak = p[0]; cu = p[1]; p2[0] = p[2]; p2[1] = p[3]; //Serial.print("t= "); Serial.print(znak); Serial.print(cc); Serial.print(".");Serial.println(cu); //p2[1] = p[3]; if(znak)strcat(buf,"-"); strcat(buf,itoa(cc,b2,10)); strcat(buf,"."); strcat(buf,itoa(cu,b2,10)); strcat(buf,"&H="); strcat(buf,itoa(g_structData.data.humm,b2,10)); strcat(buf,"&P="); p = (uint8_t*)&g_structData.data.press; znak = 0; cu = p[1]; p2[0] = p[2]; p2[1] = p[3]; strcat(buf,itoa(cc,b2,10)); strcat(buf,"."); strcat(buf,itoa(cu,b2,10)); strcat(buf,"&U="); strcat(buf,itoa(g_structData.data.vbat/1000,b2,10)); uint16_t xx = (g_structData.data.vbat % 1000)/10; strcat(buf,"."); if(xx<10)strcat(buf,"0"); // zero wiodace strcat(buf, itoa(xx,b2,10)); strcat(buf,"&end"); g_structData.p = NULL; // po wyslaniu kasowanie wskaznika system_rtc_mem_write(RTCSTARTADRESS, &g_structData, sizeof(sysMem_t)); Serial.println("wysylka do Remoteme"); setBMEzewnetrzny(buf); tmr.once(5,timeout); // jesli brak odpowiedzi z remoteme } void parseOkno(){ char buf[50]; char b2[5]; strcpy(buf,"Okno="); if(g_structData.data.okno)strcat(buf,"Otwarte"); if(0 == g_structData.data.okno)strcat(buf,"Zamkniete"); strcat(buf,"&U="); strcat(buf,itoa(g_structData.data.vbat/100,b2,10)); uint16_t xx = (g_structData.data.vbat % 100); strcat(buf,"."); if(xx<10)strcat(buf,"0"); // zero wiodace strcat(buf, itoa(xx,b2,10)); //strcat(buf,"&R="); //strcat(buf,itoa(g_structData.data.timeToRestart,b2,10)); strcat(buf,"&end"); //g_structData.stat = 0; g_structData.p = NULL; // po wyslaniu kasowanie wskaznika system_rtc_mem_write(RTCSTARTADRESS, &g_structData, sizeof(sysMem_t)); Serial.println("wysylka do Remoteme"); setStanOkien(buf); tmr.once(5,timeout); // jesli brak odpowiedzi z remoteme } void timeout(){ Serial.println("RemoteMe Time OUT"); RestartFunction(); } void RestartFunction(){ // zapisuje do rtc mem i restart g_structData.stat = 0; system_rtc_mem_write(RTCSTARTADRESS, &g_structData, sizeof(sysMem_t)); ESP.restart(); } void onBMEzewnetrznyChange(String s) { Serial.println("RemoteMe potwierdzilo odbior"); RestartFunction(); } void onStanOkienChange(String s){ Serial.println("RemoteMe potwierdzilo odbior"); RestartFunction(); } Na koniec prosta Apka którą napisałem w javie z pomocą Basic for Android pozwala ona na szybki dostęp do czujników, aplikacja prosi o dostęp do aparatu gdyż kopiowanie linku do zmiennych remoteme następuje przez skanowanie kodu qr. Podobnie powstała bliźniacza aplikacja na PC (tu jednak tylko print screen) pozwala ona na więcej gdyż mogę również sterować urządzeniami w mieszkaniu. SCH_zewnetrzny_2021-08-12.zipESPnow.zip PCB_PCB_zewnetrzny_2021-08-12.zipESPnowNadajnik.zip Kod źródłowy aplikacji z widokami: sesnsor.zip Skompilowana aplikacja: APK.zip
  16. Pisząc drobne programiki na AVR w C nie był możliwy taki konstrukt: int w = 10; // przykład, w może oznaczać rozmiar ciągu danych np: z uart char str[w]; Tymczasem działając teraz z programem pod esp8266 tak z ciekawości napisałem: int packetSize = Udp.parsePacket(); char packetBuffer[packetSize]; Pytanie teraz do ekspertów: czy powyższy zapis jest prawidłowy? to się kompiluje i działa ale czy nie powinienem zastosować jakichś funkcji do dynamicznej alokacji danych?
  17. Witam. Mam nadzieję że ktoś mi pomoże/podpowie. Dopiero zaczynam swoją przygodę z ESP32. Podpiąłem kilka czujników, działają poprawnie, Do tej pory wyświetlałem na Serialu teraz chciałbym w apce Blynk. Z tego co ustaliłem to ESP łączy się z WiFi (w apce pojawią się informacja że płytka jest online). Problem jest w tym że nic się nie wyświetla. Próbowałem zrobić to za pomocą wirtualnego pinu. Najpewniej czegoś brakuje w kodzie lub też wkradł się jakiś błąd a może brak jakiejś biblioteki. Poniżej wklejam kod. Proszę o pomoc i dzięki za ewentualne podpowiedzi. P.S (token, ssid i hasło umyślnie zmieniłem) #include <EEPROM.h> #include "GravityTDS.h" #include "OneWire.h" #include "DallasTemperature.h" #include "SRF05.h" #define BLYNK_PRINT Serial #include <WiFi.h> #include <WiFiClient.h> #include <BlynkSimpleEsp32.h> #include <SimpleTimer.h> char auth[] = "xxx"; char ssid[] = "xxx"; char pass[] = "xxx"; SimpleTimer timer; #include <SimpleTimer.h> #define TdsSensorPin 35 GravityTDS gravityTds; OneWire oneWire(5); DallasTemperature sensors(&oneWire); // trigPin, echoPin, MaxDist, readInterval SRF05 Sensor(12, 13, 200, 500); void setup() { Serial.begin(115200); Blynk.begin(auth, ssid, pass); gravityTds.setPin(TdsSensorPin); gravityTds.setAref(3.3); //reference voltage on ADC, default 5.0V on Arduino UNO gravityTds.setAdcRange(4096); //1024 for 10bit ADC;4096 for 12bit ADC gravityTds.begin(); //initialization sensors.begin(); Serial.begin(115200); // If using SR04 enable the following line: Sensor.Unlock = true; } void loop() { Blynk.run(); timer.run(); } void MainFunction() { int tdsValue; sensors.requestTemperatures(); gravityTds.setTemperature(sensors.getTempCByIndex(0)); gravityTds.update(); //sample and calculate tdsValue = gravityTds.getTdsValue(); // then get the value Serial.print("Czystość wody w skali od 1 do 200 to:"); Serial.print(tdsValue,0); Serial.print("ppm------------------------------ "); if (tdsValue > 100) Serial.print ("Woda jest czysta"); if (tdsValue < 100) Serial.print ("Woda jest brudna"); Serial.print('\n'); Serial.print(" Temperatura wody w akwarium to: "); Serial.print(sensors.getTempCByIndex(0)); Serial.print('\n'); delay(1000); // Distance read if ( Sensor.Read() > -1 ) { // New distance reading! if ( Sensor.Distance == 0 ) { Serial.print("Out of range"); } else { // ------------- Serial.print("Odległość: "); Serial.print(Sensor.Distance); Serial.println(" cm"); Serial.print('\n'); Serial.print('\n'); Serial.print('\n'); Blynk.virtualWrite(V2, tdsValue); } } }
  18. _LM_

    Serwer stacji pogodowych

    Cześć poszukuję jakiegoś uniwersalnego serwisu do wyświetlania danych ze stacji pogodowej. Najlepiej aby też działał jako aplikacja webowa. Nie bardzo chce mi się od podstaw tworzyć całą stronę więc myślę nad jakimś gotowcem. Testowo dane wysyłane będą do remoteme jednak końcowo chciałbym coś w ładniejszej oprawie. Mierzone parametry to będą: temperatura, wilgotność, ciśnienie, prędkość i kierunek wiatru, suma opadów, czujnik pyłów i wskaźnik promieniowania UVA UVB, czujnik wyładowań atmosferycznych. Wszystko obsługiwać będzie ESP8266
  19. Witam Państwa, Jestem na etapie przygotowywania się do projektu, który będzie polegał na zbieraniu danych i kumulowania ich w jednym miejscu. Wątek ten zakładam, aby poszukać ram tego projektu i skupić się już na szczegółach. Nigdy nie byłem elektronikiem/automatykiem, wszystkiego nauczyłem się poprzez zajawkę i chęć poznawania czegoś nowego, co zaowocowało sporą wiedza dodatkową, ale przez chodzenie "po łebkach" - nigdy nie zgłębiłem żadnej z konkretnych 'odnóg' elektroniki i nie wiem czy potrafię dany element wykorzystać "do cna" czy nie. Meritum: - Mamy czujnik typu SCT013-000 (natężenia prądu), który zapinamy na przewodzie fazowym. Interesują mnie dane z czujnika (ilość rozruchów/użycia). - Gromadzi/odczytuje je arduino lub raspberry i przesyła za pomocą WiFi lub GSM do chmury/MySQL/serwer, które mogę sobie odczytać z poziomu aplikacji, przeglądarki lub inaczej. - Z czasem tych czujników będzie więcej - a dokładniej odczytów, każdy z niezależnej lokalizacji, więc odczyta musi mieć możliwość segregacji lokalizacji. Być może dla Wielu z Was jest za mało szczegółów - więc pytajcie, podpowiadajcie. Będę wdzięczny. Chcę ten projekt umieścić w "workflow", więc będzie dalszy ciąg. Będę wdzięczny za pomoc, pozdrawiam :)
  20. Cześć. Poszukuję możliwości skrócenia czasu inicjalizacji magistrali i2c, działam na esp 07 i podłączonym do niego bme280. Esp odczytuje dane, wysyła do funkcji espnow i jest usypiane. Problemem jest długi według mnie czas działania funkcji bme.begin(); Sprawdzałem to oscyloskopem, jak i prostym liczeniem czasu od startu funkcji do jej zakończenia. msTime = millis(); Wire.setClock(400000L); bme.begin(0x76, &Wire); //+113mS msTime = millis() - msTime; Serial.print("T= ");Serial.println(msTime); Czy jest możliwość aby inicjalizacja bme przebiegała "w tle" np jakieś funkcje callback? Przecież te 113mS to cała wieczność dla mikrokontrolera i w tej "wieczności" pobiera około 50mA a tym czasie mógłby nawiązywać połączenie z espnow czy robić bardziej pożyteczne rzeczy.
  21. Cześć. Piszę program obsługujący czujniki, gdzie dane są odbierane za pomocą funkcji espnow a następnie wysyłane ze stacji bazowej na serwer RemoteMe. Działa to tak że po odebraniu danych z czujnika, stacja bazowa przełącza się w tryb WIFISTA, łączy z serwerem RemoteMe i odsyła dane. Przełączanie trybów pracy realizuję w taki sposób że po odebraniu danych z czujnika, zapisuję je do pamięci RTC a następnie resetuję ESP aby po resecie znów mógł działać jako stacja. Ogólnie to działa elegancko jednak pewna rzecz nie daje mi spokoju: jest struktura do której zapisuję lub czytam z niej typedef struct { char name[SIZENAMETAB]; // nazwa czujnika float temp; // temperatura float press; // cisnienie int humm; // wilgotnosc uint16_t vbat; // U zas czujnika uint16_t timeToRestart; // czas do nast wysylki danych bool okno; // okno 0 -> zamkniete, 1->otwrte } readNow_t; typedef struct { readNow_t data; uint8_t stat; // status co ma sie dziac po resecie } sysMem_t; sysMem_t g_structData; Oraz kluczowe miejsce gdzie następuje błąd: void OnDataRecv(unsigned char *mac, unsigned char *incomingData, unsigned char len) { // dane z czujnikow kopiowanie do pamieci rtc i restart g_structData.stat = 1; // przy nastepnym resecie uruchom jako stacja memcpy(&g_structData.data, incomingData, sizeof(readNow_t)); // kopiowanie do struktury system_rtc_mem_write(RTCSTARTADRESS, &g_structData, sizeof(sysMem_t)); // kopiowanie do pamieci rtc // digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // test Serial.println("Nowe dane"); ESP.restart(); } błąd polega na tym że jakby następowało przeciążenie stosu? nie bardzo rozumiem te komunikaty wygląda to tak: --------------- CUT HERE FOR EXCEPTION DECODER --------------- Exception (28): epc1=0x4020757f epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000 >>>stack>>> ctx: cont sp: 3ffffdf0 end: 3fffffc0 offset: 0190 3fffff80: 00000000 00000000 00000001 4010017c 3fffff90: 3fffdad0 00000000 3ffee618 4010019d 3fffffa0: 3fffdad0 00000000 3ffee618 402057d4 3fffffb0: feefeffe feefeffe 3ffe84ec 40100cdd <<<stack<<< --------------- CUT HERE FOR EXCEPTION DECODER --------------- ets Jan 8 2013,rst cause:2, boot mode:(3,7) load 0x4010f000, len 3584, room 16 tail 0 chksum 0xb0 csum 0xb0 v2843a5ac ~ld Ten system działa, jednak to mi się nie bardzo podoba, czuję że gdzieś robię błąd podczas kopiowania do pamięci RTC.
  22. Cześć, problem jest taki że po przyznaniu statycznego IP urządzenie nie jest widziane w zakładce Devices na stronie remoteme.org. Urządzenie jest za to widoczne w otoczeniu sieciowym, działa nawet upload OTA. Wklejam część kodu, pewnie trzeba coś ustawić w klasach RemoteMe ale nie radzę sobie z tym const char *ssid = "*****"; const char *password = "*****"; IPAddress staticIP(192,168,0,22); IPAddress gateway(192,168,0,9); IPAddress subnet(255,255,255,0); Adafruit_BME280 bme; RemoteMe& remoteMe = RemoteMe::getInstance(TOKEN, DEVICE_ID); Ticker tmr,timeout; // timer dziala tylko gdy g_BootBit jest w stanie wysokim ADC_MODE(ADC_VCC); void readSens(char * bf); void RemoteTimeOut(void); void onBMEzewnetrznyChange(String s); //*************** CODE FOR COMFORTABLE VARIABLE SET ********************* inline void setBMEzewnetrzny(String s) {remoteMe.getVariables()->setText("BMEzewnetrzny", s); } bool g_BootBit = false; // bit ustawiony gdy ma dzialac arduino OTA char buf[50]; // bufor na tekst bool g_BMEstatus; // status bme void setup() { pinMode(OTAPIN,INPUT_PULLUP); g_BootBit = !digitalRead(OTAPIN); // g_boot jest w stanie wysokim gdy pin zwarty Serial.begin(115200); Serial.println("Booting..."); WiFi.config(staticIP, gateway, subnet); WiFi.begin(ssid, password); WiFi.mode(WIFI_STA); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Sleep..."); ESP.deepSleep(SLEEPTIME); // jesli nie powiodlo sie laczenie z siecia. (Todo: uruchomic kreatora WiFi?) } ArduinoOTA.onStart([]() { Serial.println("OTA Start"); }); ArduinoOTA.onEnd([]() { Serial.println("OTA End"); Serial.println("Rebooting..."); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r\n", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); Serial.print("ESP Board MAC Address: "); Serial.println(WiFi.macAddress()); Wire.begin(); g_BMEstatus = bme.begin(0x76); if(g_BMEstatus)Serial.println("BME OK");else Serial.println("BME False"); remoteMe.getVariables()->observeText("BMEzewnetrzny" ,onBMEzewnetrznyChange); remoteMe.setConnector(new RemoteMeSocketConnector); remoteMe.sendRegisterDeviceMessage(DEVICE_NAME); if(g_BootBit)tmr.attach(5,readSens, buf); } bool pomiar = true; // bit pomocniczy zeby nie dublowac pomiarow void loop() { ArduinoOTA.handle(); if (remoteMe.loop() && pomiar) { if (!g_BootBit) { // jesli Boot bit w stanie wysokim to funkcje odczytu sensorow przejmuje timer readSens(buf); pomiar = false; // jednorazowo } } } wołam kolegę @remoteme_org
  23. Cześć. Buduję sobie czujniczek zewnętrzny na esp 07 i BME280. System jest zasilany z dwóch baterii AA 1.5V działa elegancko, bez problemów udało się "zjechać" z poborem w stanie uśpienia do 15µA. Pytanie dotyczy poboru prądu w stanie aktywnym, a dokładniej który z zaprezentowanych na zdjęciu wyników powinienem uwzględnić w obliczeniach? Oczywiście chcę sobie wyliczyć jak długo wystarczy zestaw "paluszków" przy różnych czasach odczytu, w tej chwili mam co 10minut. Mam prąd skuteczny 80.2mA oraz parametr VrmsP 85.7mA Czy może do wyliczeń wziąć parametr z 53.1mAs?
  24. Ten artykuł jest częścią serii "Tworzenie interfejsu sieciowego z wykorzystaniem ESP" #1 - część 1 #2 - część 2 (właśnie to czytasz) Jak wspominałem w poprzedniej części, tym razem omówię trochę bardziej zaawansowane zagadnienia. Od razu zaznaczam że mogą się pojawić trochę bardziej zaawansowane pojęcia, będę starał się je w miarę przybliżyć, ale nie wykluczam że będzie konieczne zaczerpnięcie dodatkowej wiedzy z innych źródeł. Będę zasięgał do funkcji jakie daje nam uprzednio użyta biblioteka ESP Async Web Server i do nich się odwoływał. Omówię trzy problemy, a konkretnie, ich potencjalne zastosowanie, trudności jakie nas mogą napotkać oraz w jaki sposób można je zrealizować uwzględniając dostępne technologie. Przedstawione rozwiązania będą miały charaktery teoretyczny, bazujący na moich doświadczeniach. Nie ukrywam zatem, że niekoniecznie muszą być najlepsze. Ten artykuł bierze udział w naszym konkursie! 🔥 Na zwycięzców czekają karty podarunkowe Allegro, m.in.: 2000 zł, 1000 zł i 500 zł. Potrafisz napisać podobny poradnik? Opublikuj go na forum i zgłoś się do konkursu! Czekamy na ciekawe teksty związane z elektroniką i programowaniem. Sprawdź szczegóły » Co omówimy? Tak jak wspominałem w poprzedniej części poruszę trzy poniższe zagadnienia: jak można stworzyć prosty konfigurator urządzenia jak zrealizować prostą przeglądarkę plików z możliwością ich pobierania i usuwania jak zrealizować provisioning i co to właściwie jest No to do roboty! Konfigurator W przypadku prostych projektów, czy niedużej ilości sztuk docelowego rozwiązania, może nie być to konieczny aspekt, aby móc konfigurować urządzenie w prosty sposób. Inaczej sprawa się przedstawia w sytuacji gdy chcemy rozwijać projekt typu open-source, tworzyć urządzenie które ma pracować w zależności od preferencji użytkownika, czy realizować duży projekt składający się z wielu urządzeń o podobnym działaniu. Warto zauważyć że nie zawsze docelowy „klient” może mieć wystarczające umiejętności programistyczne aby dostosować używany kod do jego potrzeb, jak również modyfikacja i skompilowanie dużego projektu pobranego z ogólnodostępnego repozytorium, może nieraz nas przyprawić o ból głowy. W takiej sytuacji korzystanie z graficznych konfiguratorów lub plików konfiguracyjnych zawierających tylko konkretne parametry może ułatwić nasze zadanie. W tym momencie z pomocą może nam przyjść format JSON którego to akronim możemy rozwinąć do JavaScript Object Notation. Jak już pewnie część z was zauważyła jego nazwa posiada w sobie „JavaScript”, nie bez przypadku, ponieważ powstał z myślą o korzystaniu wraz z nim. Zaletami tego formatu jest jest przede wszystkim łatwość wykorzystania po stronie przeglądarki, jest przyjazny do czytania przez człowieka, jak i jest bezproblemowo przetwarzany w innych językach jak C czy C++ z wykorzystaniem bibliotek jak cJSON czy też ArduinoJSON. Przykładowa struktura pliku JSON wygląda jak niżej { "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } } Wydaje się raczej przyjaźniejszy dla oka niż analogiczna struktura XML <!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook V3.1//EN"> <glossary><title>example glossary</title> <GlossDiv><title>S</title> <GlossList> <GlossEntry ID="SGML" SortAs="SGML"> <GlossTerm>Standard Generalized Markup Language</GlossTerm> <Acronym>SGML</Acronym> <Abbrev>ISO 8879:1986</Abbrev> <GlossDef> <para>A meta-markup language, used to create markup languages such as DocBook.</para> <GlossSeeAlso OtherTerm="GML"> <GlossSeeAlso OtherTerm="XML"> </GlossDef> <GlossSee OtherTerm="markup"> </GlossEntry> </GlossList> </GlossDiv> </glossary> Wykorzystując format JSON jesteśmy w stanie definiować konkretne parametry i odczytywać je z pamięci w celu modyfikacji parametrów naszych funkcji. W ten sposób możemy umożliwić np. proste ustawianie hasła do docelowej sieci WiFi, serwera gdzie chcemy przesyłać dane, czy np. klucza wybranego przez nas API z którego korzystamy. { "ssid": "nazwa sieci", "password": "haslo sieci", "mqtt-broker": "nasz.broker", } Jako że format JSON jest bardzo przyjazny w użytkowaniu wraz z JavaScriptem, możemy łatwo tworzyć formularze które będą tworzyć gotowy plik i przesyłać do naszego urządzenia. Na poniższym zdjęciu widzimy niezbyt urodziwie sformatowany plik konfiguracyjny drukarki 3D w postaci pliku JSON, można go pobrać i wyedytować w zewnętrznym edytorze, dzięki temu możemy skonfigurować drukarkę bez konieczności modyfikacji oprogramowania. Przeglądarka plików Przeglądarka plików z drukarki 3D Gdy wykonujemy urządzenie pomiarowe które zapisuje pliki, bądź jego działanie opiera się na różnych plikach, np. profile pracy urządzenia. W takiej sytuacji bardzo przydatna jest możliwość wgrywania plików, jak i podgląd co tam ukrywa w swojej pamięci nasz elektroniczny potworek. Tutaj z pomocą przyjdą nam metody HTTP. Do pobierania plików użyteczna będzie metoda GET, do wysyłania POST, zaś do usuwanie DELETE. Dociekliwe osoby pewnie zauważą, że próbując zrealizować przeglądarkę plików z wykorzystaniem analogicznych metod jak w pierwszej części, pojawia się problem iż liczba plików jest zmienna, a dla każdego pliku powinniśmy oddzielnie zainicjować obsługę zapytań. O ile w teorii moglibyśmy skanować po uruchomieniu naszą pamięć w poszukiwaniu plików i kilkukrotnie powtarzać proces inicjacji zapytania dla każdego wykrytego pliku, to w praktyce byśmy byli zmuszeni do resetu urządzenia po każdej zmianie w pamięci (dodaniu bądź usunięciu pliku). Na szczęście biblioteka ta przewiduje takie sytuacje i posiada funkcję: AsyncWebServer::serveStatic() Funkcja ta działa w taki sposób iż mamy dostęp do całej pamięci, w ten sposób nie musimy martwić się o inicjowanie obsługi zapytań do każdego pliku, musimy jedynie znać ścieżkę która do niego prowadzi, resztą zajmie się biblioteka. Z pewnością ułatwia to pracę oraz korzystnie wpływa na wydajność programu. Szczególnie gdy mamy stronę składającą się z wielu plików .css .js czy też plików graficznych. Ponadto wybaczy nam to błędy gdybyśmy zapomnieli uruchomić obsługę dla wybranego pliku, a nasza strona by niepoprawnie działała. Jak wspomniałem, wykorzystując funkcję serveStatic() wystarczy że znać będziemy położenie pliku który chcemy znaleźć. Pytanie, skąd wiedzieć jak się nasz plik nazywa lub jakie mamy pliki dostępne? Teoretycznie możemy strzelać, szanse, jeżeli znamy systematykę nazywania plików, mogą być nawet większe niż trafienie 6 w totolotka, w innym wypadku może być krucho. W tym momencie z pomocą przyjdzie nam JSON. Zarówno biblioteka obsługująca SPIFFS czy też karty SD, bazuje na bibliotece FS.h, która nam pozwala na poziomie mikrokontrolera przeskanować pamięć i wskazać „ścieżki” poszczególnych plików. Teraz zostaje kwestia skąd użytkownik ma wiedzieć jakie ma dostępne pliki. W takiej sytuacji możemy wysłać zapytanie do serwera o to, aby nam zwrócił listę plików, serwer na podstawie zawartości pamięci wygeneruje nam listę w postaci pliku JSON i ją odeśle. Skrypt po stronie klienta będzie mógł nam wygenerować listę odnośników do poszczególnych plików w pamięci. Z tego punktu jesteśmy w stanie w miarę swobodnie manipulować plikami w pamięci urządzenia. Warto zwrócić uwagę również na kwestie bezpieczeństwa w takim rozwiązaniu. Jeżeli mamy np. plik konfiguracyjny w pamięci SPIFFS w którym zawarte są np. dane do logowania do sieci WiFi czy też API, jest ryzyko iż w łatwy sposób mogą zostać wykradzione, szczególnie jeżeli planujemy urządzenie włączyć do sieci publicznej. Oczywiście na każdy problem jest rozwiązanie, lepsze lub gorsze, ale dalsze rozważania tego problemu zostawiam do własnej analizy 🙂 Provisioning Provisioning może brzmieć bardzo nietypowo dla większości osób, nawet tych co znają język angielski. Posiłkując się Wikipedią można to określić jako proces polegający na przygotowywaniu sieci w taki sposób, aby po wykonaniu pewnych operacji, nadać jej nowe funkcjonalności. Wciąż może to brzmieć trochę niejasno. Praktycznym przykładem który przychodzi mi do głowy, aczkolwiek może nie być do końca poprawnym, jest sytuacja, gdy jesteśmy np. w centrum handlowym i chcemy skorzystać z dostępnej sieci WiFi. Zazwyczaj podłączenie się do tej sieci skutkuje wyskoczeniem nam okna przeglądarki, gdzie musimy zaakceptować regulamin, aby móc korzystać z sieci. Czyli w pewien sposób jesteśmy zmuszeni dokonać pewnej konfiguracji, aby otrzymać możliwość dostępu do internetu. Dużo lepszy przykładem takiego zabiegu jest to o czym będę pisał poniżej. Przychodzi do nas nowe urządzenie, np. asystent głosowy w postaci głośnika. Chcemy jak najszybciej zacząć cieszyć się z jego korzystania, ale najpierw musimy podłączyć do sieci. Część osób która orientuje się w temacie powie żeby skorzystać np. z WPS. Niestety taka opcja może budzić pewne obiekcje pod względem bezpieczeństwa, a po drugie musimy mieć fizyczny dostęp do urządzenia. Inną opcją jest podłączenie urządzenia np. do komputera poprzez port USB i jego konfiguracja, to z pewnością by wiązało się z koniecznością pobrania oprogramowania bądź przygotowania pliku konfiguracyjnego, a dla osoby mniej obeznanej może być problematyczne. Trzecią opcją jest provisioning, uruchamiamy urządzenie, pojawia się nowa sieć WiFi utworzona przez urządzenie, łączymy się do niej za pomocą np. smartfona, wyskakuje nam okno przeglądarki, podajemy dane sieci, akceptujemy i mamy skonfigurowaną sieć. Urządzenie jest gotowe do pracy. Analogiczną procedurę można też wykonać np. z wykorzystaniem bluetooth i aplikacji na telefon. Przykład autorskiej realizacji Aby zrealizować taki proces i był on jak najbardziej zautomatyzowany, czyli po podłączeniu się do urządzenia, pokazuje się nam okno konfiguracji, musimy zrealizować dwa główne etapy. Po pierwsze nasze urządzenie musi być uruchomione jako punkt dostępu (Acces Point), po drugie uruchomić serwer DNS w naszym urządzeniu, odpowiednio go konfigurując. Oczywiście musimy również dodać obsługę naszego interfejsu oraz komunikacji z urządzeniem w celu wymiany danych. W tym momencie zachęcam do samodzielnej lektury dokumentacji bibliotek oraz sieci w celu poszukania, jak to zrealizować oraz przekonania się, że wcale nie trzeba dedykowanych bibliotek do realizacji takiego zadania, które wbrew pozorom takie straszne nie jest 🙂 Podpowiem tylko że w przypadku provisioningu, najlepiej stronę do obsługi konfiguracji zrobić możliwie prostą oraz aby zawierała się w jednym pliku .html. Podsumowanie Cieszę się znów jeżeli tu dotarłeś. Wbrew pozorom jest całkiem obszerny materiał. W tym momencie zakończę moje wywody głównie oparte na własnych doświadczeniach oraz mojej wiedzy. Jak już niejednokrotnie wspominałem, nie muszą to być najlepsze rozwiązania, jak i nie są to wszystkie możliwe rozwiązania. Jest to bardzo szeroki temat i myślę że lekką ręką można by było napisać na ten temat książkę i to tylko starając się opisywać temat w sposób przyjazny przeciętnemu czytelnikowi. Starałem się korzystać z jak najbardziej przyjaznego języka, część kwestii to skróty myślowe, które uważam że w miarę rzeczowo oddają tematykę poszczególnych problemów. Liczę że większych błędów merytorycznych nie popełniłem (ale za stylistyczne czy gramatyczne nie mogę ręczyć :)), z chęcią przyjmę wszelkie uwagi odnośnie poprawności treści. Jeżeli byłoby zainteresowanie kontynuacją tematu, myślę że znajdę trochę kwestii wartych poruszenia przy realizacji takich zagadnień, a może nawet rozważę przedstawienie realizacji jednego z problemów. M. S.
  25. Witam, potrzebuję pomocy w naprawie mojego NodeMCU v3, na płytce eksplodowała jedna część i nie mogę zorientować czy to była dioda czy kondensator. Będę bardzo wdzięczny za link do zakupu nowej części. Pozdrawiam bardzo serdecznie.
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.