====== 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);
}
}