====== WeMos D1 R2 UNO ESP8266 ====== Verze Arduino UNO, která místo procesoru využívá mikrokontroler a wifi modul ESP8266. Výrazným rozdílem je logika která místo 5V je 3,3V. Wemos D1 je Wifi vývojová deska, založená na ESP8266EX. WeMos D1 obsahuje rozložení pinů skoro identické s Arduino UNO. Všechny I/O piny mají přerušení, PWM, I2C a 1-Wire , mimo pin D0. Deska má USB Micro konektor a USB pro sériový (UART) převodník, takže je jednoduché tuto desku připojit ke svému počítači pomocí USB Micro kabelu. Destičku jsem koupil zde: https://www.laskakit.cz/wemos-d1-r2-uno-esp8266/ Pozor - destička používá 3,3 V logiku. ===== Specifikace: ===== * Napájecí napětí: 9-24V * Pracovní napětí pinů: 3.3V * Řadič ESP8266 * Flash paměť: 4 MB * I / O porty: 11 * PWM výstupy: 10 * Počet analogových vstupů: 1 (kanál A / C převodníku) * Konektor: microUSB * Řadič USB - UART: CH340G * Kompatibilní s: Arduino IDE a NodeMCU * Napájecí konektor: DC 5.5 x 2.1mm * Rozměry: 69 x 54 x 15 mm ===== Namapování Arudino pinů na ESP8266 ===== {{:it:iot:baxi:pasted:20231203-203740.png}} ===== Začátky s vývojovou destičkou Wemos ===== Při zprovozňování destičky mi pomohly tyto návody: * https://navody.dratek.cz/navody-k-produktum/esp8266-vyvojova-deska-wemos-d1.html * https://blog.laskakit.cz/zaciname-s-wemos-d1-mini-s-wifi-modulem-esp8266/ * https://blog.laskakit.cz/zaciname-s-arduinem/ {{youtube>kiZ5ZUkXfGI?}} ==== Instalace vývojového prostředí Arduino IDE ==== Na [[https://www.arduino.cc/en/software|této adrese]] jsem stáhnul vývojové prostředí Arduino IDE 2.2.1. Zvolil jsem ZIP file pro Linux. Uživatel, který spouští Arduino IDE musí být ve skupině **dialout**. Po rozbalení stačí spustit ./arduino-ide {{:it:iot:baxi:pasted:20231203-204332.png}} === Zprovoznění programování ESP8266 skrze Arduino IDE === Nejprve zvolit menu Soubor -> vlastnosti {{:it:iot:baxi:pasted:20231203-204703.png}} V nastavení přidat správce dalších desek tuto URL: http://arduino.esp8266.com/stable/package_esp8266com_index.json {{:it:iot:baxi:pasted:20231203-204812.png}} Skrze odkaz umožníme do prostředí IDE přidat podporu pro ESP8266. Skrze menu **Tools -> Board -> Board Manager** přidat destičky ESP8266. Napsat **esp8266** a nainstalovat. {{:it:iot:baxi:pasted:20231203-205056.png}} Jakmile je destička nainstalovaná, tak vybrat destičku skrze menu **Tools -> Board -> esp8266 -> LOLIN(WEMOS) D1 R2 & mini**. Pak je možné připojit přes USB kabel zařízení, psát kód a odesílat kód skrze tlačítko do zařízení. {{:it:iot:baxi:pasted:20231203-205340.png}} === Program blikání LED diod === Jako první ukázkový program je připraveno blikání dvěma dostupnými LED diodami. První LED dioda je přímo na modulu, ke které máme přístup v Arduino IDE přes klíčové slovo LED_BUILTIN. Tato LED dioda je zvláštní v tom, že má obrácenou logiku řízení, tedy pokud jí chceme zapnout, je nutné na ní přivést logickou nulu. Druhá LED dioda je připojena na pin 14 a je řízena klasickým způsobem. Po nastavení obou LED diod jako výstupních v podprogramu setup se přesuneme rovnou na nekonečnou smyčku loop, kde jako první blikneme rychleji vestavěnou LED diodou a následně blikneme pomaleji LED diodou na pinu 14. // ESP8266 blikání dvou LED diod // nastavení propojovacího pinu LED diody #define LEDka 14 void setup() { // nastavení obou LED diod jako výstupních pinMode(LED_BUILTIN, OUTPUT); pinMode(LEDka, OUTPUT); } void loop() { // blikání vestavěnou diodou na ESP, // pro zapnutí musíme přivést logickou 0 - LOW digitalWrite(LED_BUILTIN, LOW); delay(500); digitalWrite(LED_BUILTIN, HIGH); delay(500); // blikání LED diodou na desce, // pro zapnutí musíme přivést logickou 1 - HIGH digitalWrite(LEDka, HIGH); delay(1000); digitalWrite(LEDka, LOW); delay(1000); } === Program skenování Wi-Fi sítí === Druhý ukázkový program už je praktičtější a obsahuje skener WiFi sítí v okolí modulu ESP8266. Program na začátku obsahuje připojení potřebné knihovny a poté v podprogramu setup jako první nastavení komunikace po sériové lince. Pro úspěšné vyhledávání WiFi sítí je nutné jako další krok nastavit WiFi modul do módu stanice a pro jistotu provést odpojení od jakékoliv sítě. V nekonečné smyčce loop vytiskneme informaci o zahájení skenování po sériové lince a následně načteme do vytvořené proměnné počet sítí v okolí včetně všech dostupných informací o těchto sítích. Poté zkontrolujeme počet načtených sítí a v případě nuly pouze vypíšeme informaci o nedostupnosti viditelných sítí. Pokud ale máme nějaké sítě v dosahu, provedeme v následujících řádcích vytištění informací o nich. Jako první tedy vytiskneme celkový počet načtených sítí a následně pomocí for smyčky vytiskneme pro každou WiFi síť její název, sílu signálu a druh zabezpečení. Na konci celého programu pak už jen vyčkáme pět vteřin před novým načtením seznamu sítí. // ESP8266 WiFi skener // připojení potřebné knihovny #include "ESP8266WiFi.h" void setup() { // zahájení komunikace po sériové lince Serial.begin(9600); // nastavení WiFi do módu stanice a odpojení od předchozí sítě WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); } void loop() { Serial.println("Zahajeni skenovani.."); // načtení WiFi sítí v okolí a uložení jejich počtu do proměnné int n = WiFi.scanNetworks(); // v případě nulového počtu sítí vypíšeme informaci // po sériové lince if (n == 0) { Serial.println("Zadne viditelne WiFi site v okoli."); } // pokud byly nalezeny WiFi sítě v okolí, // vypíšeme jejich počet a další informace else { Serial.print(n); Serial.println(" WiFi siti v okoli. Seznam:"); // výpis všech WiFi sítí v okolí, // vypíšeme název, sílu signálu a způsob zabezpečení for (int i = 0; i < n; ++i) { Serial.print(i + 1); Serial.print(": "); Serial.print(WiFi.SSID(i)); Serial.print(" ("); Serial.print(WiFi.RSSI(i)); Serial.print(")"); Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*"); delay(10); } } // ukončení výpisu Serial.println(""); // pauza po dobu pěti vteřin před novým skenováním delay(5000); } Po nahrání druhého ukázkového kódu do Arduino ESP8266 desky dostaneme například tento výsledek: Zahajeni skenovani.. 3 WiFi siti v okoli. Seznam: 1: SilentB (-25)* 2: ** (-69)* 3: *** (-74)* === Program webserver v domácí síti === Třetí ukázkový kód obsahuje jednoduchý příklad využití ESP jako webserveru v domácí síti. Na začátku programu se nachází připojení všech potřebných knihoven a vytvoření proměnných s uloženým nastavením názvu a hesla pro WiFi síť, do které se budeme připojovat. Jako další je provedena inicializace webserveru na portu 80 a nastaven propojovací pin indikační LED diody. Podprogram zpravaHlavni obsahuje kód, který se provede při přístupu na hlavní stránku. Jako první tedy zapneme LED diodu a poté vytvoříme proměnné s načtením informací o analogové hodnotě z pinu A0 společně s časem od spuštění Arduina. Následně vytvoříme proměnnou se zprávou, do které postupně přidáme všechny chtěné informace. Na konci provedeme příkazem send vytištění zprávy se statusem 200, tedy OK, a vypneme LED diodu. Podprogram zpravaNeznamy funguje obdobným způsobem, jen slouží pro informování o přístupu na neexistující odkaz webserveru. Opět tedy blikneme LED diodou a vypíšeme kompletní informace o neexistujícím odkazu včetně metody a argumentů, s kterými bylo přistupováno. Podprogram setup na svém začátku obsahuje nastavení LED diody jako výstupní společně s jejím vypnutím. Následně zahájíme komunikaci po sériové lince a zahájíme komunikace s WiFi routerem pomocí našich uložených přihlašovacích údajů. Po zahájení následuje while smyčka, která vyčkává na potvrzení připojení a v mezičase tiskne tečky po sériové lince. Jakmile jsme úspěšné připojení, vytiskneme informace o připojení po sériové lince včetně názvu připojené sítě a přidělené IP adrese z routeru. Poté proběhne kontrola MDNS responderu. Jako další je nutné přidělit tištění zpráv k jednotlivým adresám. Pro přístup na IP adresu samotnou tedy například přidělíme volání podprogramu zpravaHlavni. Avšak není nutné pro každou zprávu vytvářet podprogram, proto tedy následuje ukázka s odkazem /ukázka, který obsahuje vytištění krátké zprávy. Pro přístup na jakoukoli jinou nedefinovanou stránku slouží nastavení onNotFound, ke kterému přidělíme náš podprogram zpravaNeznamy. Po veškerém nastavení pak stačí už jen zahájit aktivitu webserveru. Nekonečná smyčka loop v tomto případě obsahuje pouze kontrolování připojených klientů, kdy při detekci klienta už sám program provede veškerou práci skrze nastavení provedená v podprogramu setup. // ESP8266 Web Server // připojení potřebných knihoven #include #include #include #include // vytvoření proměnných s názvem WiFi sítě a heslem const char* nazevWifi = "nazev"; const char* hesloWifi = "12345"; // incializace webserveru na portu 80 ESP8266WebServer server(80); // propojovací pin indikační LED diody #define LEDka 14 // podprogram s hlavní zprávou, která je vytištěna // při zadání IP adresy do prohlížeče void zpravaHlavni() { // zapnutí LED diody digitalWrite(LEDka, HIGH); // načtení hodnoty analogového pinu a času // od spuštění Arduina ve formátu String String analog = String(analogRead(A0)); String cas = String(millis()/1000); // vytvoření zprávy, která bude vytištěna // v prohlížeči (\n znamená nový řádek) String zprava = "Ahoj Arduino svete!\n"; zprava += "Analogovy pin A0: "; zprava += analog; zprava += "\nCas od spusteni Arduina je "; zprava += cas; zprava += " vterin."; // vytištění zprávy se statusem 200 - OK server.send(200, "text/plain", zprava); // vypnutí LED diody digitalWrite(LEDka, LOW); } // podprogram s chybovou zprávou, která je vytištěna // při zadání IP adresy s neexistující podstránkou void zpravaNeznamy() { // zapnutí LED diody digitalWrite(LEDka, HIGH); // vytvoření zprávy s informací o neexistujícím odkazu // včetně metody a zadaného argumentu String zprava = "Neexistujici odkaz\n\n"; zprava += "URI: "; zprava += server.uri(); zprava += "\nMetoda: "; zprava += (server.method() == HTTP_GET)?"GET":"POST"; zprava += "\nArgumenty: "; zprava += server.args(); zprava += "\n"; for (uint8_t i=0; i Po nahrání třetího ukázkového kódu do Arduino ESP8266 desky dostaneme například tento výsledek v Sériovém monitoru a v prohlížeči při přístupu na samotnou IP adresu: Pripojeno k WiFi siti SilentB IP adresa: 10.0.0.31 MDNS responder je zapnuty. HTTP server je zapnuty. Ahoj Arduino svete! Analogovy pin A0: 3 Cas od spusteni Arduina je 54 vterin. ==== Připojení k zabezpečenému MQTT ==== Toto už jsem připravoval vlastní kód. Je to základní kód pro připojení k MQTT serveru. Tady je chování: * připojí se k nadefinované Wi-Fi. Pokud dojde k výpadku Wi-Fi, tak se pokouší znovu připojit. Měl by se o to pokoušet do té doby, dokud se nepodaří spojení obnovit. * poté se připojí k MQTT serveru. Opět může docházet k výpadkům MQTT serveru, takže se kód postará o vytvoření nového připojení. * připojení k MQTT je zabezpečeno pomocí [[it:iot:self-signed-certificate|]]. Dále je nakonfigurován MQTT server Mosquitto [[it:iot:mosquitto|pro použití uživatelského jména a hesla]]. Čip ESP8266 nezvládá ověření self signed certifikátu, proto jsem to musel v kódu vypnout. V článku o [[it:iot:self-signed-certificate|Self signed certifikátech]] mám vysvětleno, jak jsem je dostal do kódu pro Arduino. * program zapne LED diodu na zařízení a posílá zprávu každou vteřinu do MQTT kanálu Program řeší základní problematiku navázání a obnovení síťových spojení. #include #include #include #include "client_crt.h" // client certificate #include "client_key.h" // client key #include "ca_crt.h" // CA const char* WiFiName = "Wifi_IoT"; const char* WiFiPassword = "supersecurepassword"; // MQTT connection const char* clientName = "wemos"; const char* mqttBroker = "192.168.0.50"; const int mqttPort = 8883; const char* mqttUser = "user"; const char* mqttPassword = "users_password"; const char* mqttTopic = "building/room/wemos"; #define LED_SCK 14 WiFiClientSecure espClient; PubSubClient mqttClient(espClient); void setupWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(WiFiName, WiFiPassword); // connect to WiFi Serial.print("Connecting to WiFi..."); // wait for connecting to the server // during this waiting it will write dot to serial link while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // write new line, Wi-Fi network and IP address of connection Serial.println(""); Serial.print("Connected to WiFi "); Serial.println(WiFiName); Serial.print("IP address: "); Serial.println(WiFi.localIP()); WiFi.setAutoReconnect(true); WiFi.persistent(true); } void reconnectMQTT() { int retryCount = 0; while (!mqttClient.connected()) { Serial.println("Attempting to connect to MQTT server..."); // SSL/TLS certificate and key settings // The BearSSL::X509List and BearSSL::PrivateKey objects must be in scope (alive) // for the duration of their usage by espClient. If these objects are defined // within a separate function and used here, they will be destroyed when that // function exits, leading to undefined behavior and potential device resets. // A solution to this is to declare them as global variables if they need to // be used across multiple functions. BearSSL::X509List cert(cert_der, cert_der_len); BearSSL::PrivateKey key(key_der, key_der_len); BearSSL::X509List caCert(ca_der, ca_der_len); espClient.setInsecure(); //espClient.setTrustAnchors(&caCert); // Setting the CA certification espClient.setClientRSACert(&cert, &key); // Setting the client's cert and key mqttClient.setServer(mqttBroker, mqttPort); if (mqttClient.connect(clientName, mqttUser, mqttPassword)) { Serial.println("Connected"); // Subscribe to topics here if necessary // mqttClient.subscribe("some/topic"); } else { Serial.print("Failed, rc="); Serial.print(mqttClient.state()); Serial.println(" trying again in 5 seconds"); delay(5000); // 5-second delay between attempts retryCount++; if (retryCount > 5) { // Restart the ESP if it fails to connect 5 times //ESP.restart(); } } } } void setup() { // put your setup code here, to run once: // set LED diode as OUTPUT a turn on the diode pinMode(LED_SCK, HIGH); // start communication on serial line Serial.begin(9600); setupWiFi(); reconnectMQTT(); } void loop() { // put your main code here, to run repeatedly: if (!mqttClient.connected()) { reconnectMQTT(); } mqttClient.loop(); // Odesílání zprávy každou vteřinu static unsigned long lastMsg = 0; unsigned long now = millis(); if (now - lastMsg > 1000) { lastMsg = now; // Tvořte zde svou zprávu const char* message = "Hello MQTT"; mqttClient.publish(mqttTopic, message); } }