it:iot:baxi:arduino-wemos-d1-r2-uno-esp8266

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
it:iot:baxi:arduino-wemos-d1-r2-uno-esp8266 [2023/12/03 19:45] Petr Nosekit:iot:baxi:arduino-wemos-d1-r2-uno-esp8266 [2024/01/01 21:19] (aktuální) Petr Nosek
Řádek 44: Řádek 44:
   * https://blog.laskakit.cz/zaciname-s-wemos-d1-mini-s-wifi-modulem-esp8266/   * https://blog.laskakit.cz/zaciname-s-wemos-d1-mini-s-wifi-modulem-esp8266/
   * https://blog.laskakit.cz/zaciname-s-arduinem/   * https://blog.laskakit.cz/zaciname-s-arduinem/
 +
 +
 +{{youtube>kiZ5ZUkXfGI?}}
  
  
Řádek 50: Řádek 53:
 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.  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. 
  
-Po rozbalení stačí spustit+Uživatel, který spouští Arduino IDE musí být ve skupině **dialout**. Po rozbalení stačí spustit
  
 <code bash> <code bash>
Řádek 59: Řádek 62:
  
  
 +=== 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.
 +
 +<code c>
 +// 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);
 +}
 +</code>
 +
 +
 +=== 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í.
 +
 +<code c>
 +// 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);
 +}
 +</code>
 +
 +Po nahrání druhého ukázkového kódu do Arduino ESP8266 desky dostaneme například tento výsledek:
 +
 +<code>
 +Zahajeni skenovani..
 +3 WiFi siti v okoli. Seznam:
 +1: SilentB (-25)*
 +2: ** (-69)*
 +3: *** (-74)*
 +</code>
 +
 +
 +=== 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.
 +
 +<code c>
 +// ESP8266 Web Server
 +
 +// připojení potřebných knihoven
 +#include <ESP8266WiFi.h>
 +#include <WiFiClient.h>
 +#include <ESP8266WebServer.h>
 +#include <ESP8266mDNS.h>
 +
 +// 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<server.args(); i++){
 +    zprava += " " + server.argName(i) + ": " + server.arg(i) + "\n";
 +  }
 +  // vytištění zprávy se statusem 404 - Nenalezeno
 +  server.send(404, "text/plain", zprava);
 +  // vypnutí LED diody
 +  digitalWrite(LEDka, LOW);
 +}
 +
 +void setup(void) {
 +  // nastavení LED diody jako výstupní a její vypnutí
 +  pinMode(LEDka, OUTPUT);
 +  digitalWrite(LEDka, LOW);
 +  // zahájení komunikace po sériové lince
 +  Serial.begin(9600);
 +  // zahájení komunikace po WiFi s připojením
 +  // na router skrze zadané přihl. údaje
 +  WiFi.begin(nazevWifi, hesloWifi);
 +  // čekání na úspěšné připojení k routeru,
 +  // v průběhu čekání se vytiskne každých
 +  // 500 milisekund tečka po sériové lince
 +  while (WiFi.status() != WL_CONNECTED) {
 +    delay(500);
 +    Serial.print(".");
 +  }
 +  // odřádkování a výpis informací o úspěšném připojení
 +  // včetně přidelené IP adresy od routeru
 +  Serial.println("");
 +  Serial.print("Pripojeno k WiFi siti ");
 +  Serial.println(nazevWifi);
 +  Serial.print("IP adresa: ");
 +  Serial.println(WiFi.localIP());
 +  // kontrola funkčnosti MDNS
 +  if (MDNS.begin("esp8266")) {
 +    Serial.println("MDNS responder je zapnuty.");
 +  }
 +  // nastavení vytištění hlavní zprávy po přístupu
 +  // na samotnou IP adresu
 +  server.on("/", zpravaHlavni);
 +  // pokud chceme vytisknout pouze menší zprávy, není
 +  // nutné je vytvářet v podprogramech jako zpravaHlavni,
 +  // viz. ukázka níže
 +  
 +  // nastavení vytištění jiné zprávy po přístupu na
 +  // podstránku ukazka, tedy např. 10.0.0.31/ukazka
 +  server.on("/ukazka", []() {
 +    String zprava = "Ukazka odkazu pro vice stranek.";
 +    server.send(200, "text/plain", zprava);
 +  });
 +  // nastavení vytištění informací o neznámém
 +  // odkazu pomocí podprogramu zpravaNeznamy  
 +  server.onNotFound(zpravaNeznamy);
 +  // zahájení aktivity HTTP serveru
 +  server.begin();
 +  Serial.println("HTTP server je zapnuty.");
 +}
 +
 +void loop(void) {
 +  // pravidelné volání detekce klienta,
 +  // v případě otevření stránky se provedou
 +  // funkce nastavené výše
 +  server.handleClient();
 +  delay(10);
 +}
 +</code>
 +
 +
 +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:
 +
 +<code>
 +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.
 +</code>
 +
 +
 +
 +==== 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í.
 +
 +<code cpp>
 +#include <ESP8266WiFi.h>
 +#include <WiFiClientSecure.h>
 +#include <PubSubClient.h>
 +
 +
 +#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);
 +  }
 + 
 +
 +}
 +
 +</code>
  
  • it/iot/baxi/arduino-wemos-d1-r2-uno-esp8266.1701632738.txt.gz
  • Poslední úprava: 2023/12/03 19:45
  • autor: Petr Nosek