Programování | Pojďme programovat elektroniku | Wi-Fi

Pojďme programovat elektroniku: Vyrobíme Wi-Fi světýlko s nastavitelným jasem

  • Už jsme zbastlili ledacos, ale zapomněli jsme na Wi-Fi
  • Namísto Arduina použijeme NodeMCU za 80 korun
  • Jeho mozkem je populární čip s Wi-Fi ESP8266

Za poslední tři měsíce jsme si v našem seriálu Pojďme programovat elektroniku vyzkoušeli ledacos od primitivního sledování teploty pomocí tepelného senzoru po ultrazvukový dálkoměr, infračervený detektor pohybu anebo bezdrátovou komunikaci pomocí Bluetooth.

Při svých jednoduchých demonstracích jsem však zapomněl na to nejdůležitější – na internet. Co by to bylo za chytrou krabičku, kdyby nebyla dostupná v síti jako další z mnoha prvků internetu věcí?

Hlavním důvodem bylo Arduino samotné, jehož základní modely zpravidla komunikovat v internetu neumějí. Abyste tedy třeba takové Arduino UNO připojili do domácího LANu, musíte si nejprve obstarat ethernetový modul, shield, anebo některý z drobných obvodů, které připojí mikropočítač do Wi-Fi.

Bastlíři milovaný čip ESP8266

Jedním z těch nejpopulárnějších je 2,4GHz 802.11bgn čip ESP8266 (komunitní fórum) od společnosti Espressif, který se v posledních letech dočkal ohromné popularity mezi domácími bastlíři zejména proto, že je levný a sakra výkonný!

699526336
Samotný ESP8266

Výrobce jej totiž navrhnul tak, aby měl čip dostatečný výkon a prostředky nejen k samotné bezdrátové komunikaci, ale i pro kód nějakého dalšího programu, který do něj nahrajete. Třeba kód ovladače bezdrátové RGB žárovky a dalších IoT drobností, které budou mít k dispozici až 80 % prostředků.

O výpočty se proto stará 32bitový procesor Tensilica L106, který lze taktovat až na 160 MHz. Suma sumárum, samotný ESP8266 je mnohem výkonnější než obvyklé modely čipů ATmega, které se starají o běh prototypovacích mikropočítačů Arduino, a tak by byla škoda, kdybych třeba k Arduino UNO připojil ESP8266 jen jako Wi-Fi vysílač.

365457962
A takto ESP8266 vypadá v jednom z mnoha minimalistických provedení Wi-Fi vysílače ESP-01 nejen pro bastlíře. Přibyla destička s anténou, flash pamětí a piny pro SPI komunikaci.

Holý ESP8266 je nicméně maličký – je opravdu určený pro instalaci v nějakém hotovém zařízení a nikoliv pro rychlé domácí prototypování. Proto se před lety na scéně objevil celý zástup modulů a prototypovacích desek, které se podobají těm od Arduina, mají USB konektor pro komunikaci s PC a napájení, hlavně ale piny pro analogovou a digitální komunikaci a jako mozek ESP8266 (zpravidla z šenčenské fabriky Ai-Thinker).

Na internetu tak dnes seženete třeba Wemos D1 R2, který supluje Arduino UNO, maličký Wemos D1 Mini, který je zase odpovědí spíše na Arduino Nano a Arduino Pro Mini, nebo destičky NodeMCU.

29979431 733079669 705957047
Wemos D1 R2, D1 Mini Pro a NodeMCU

Všechny tyto prototypovací mikropočítače postavené na ESP8266 lze zároveň snadno a tradiční cestou programovat v editoru Arduino IDE, což potěší zejména začátečníky, kteří po dlouhém učení konečně oživili třeba zrovna Arduino UNO a děsí se představy, že by měli rázem studovat něco naprosto odlišného. Třeba (sic jednoduchý) jazyk Lua, který používají zmíněné destičky NodeMCU.

V Arduino IDE stačí nastavit dodatečný zdroj (http://arduino.esp8266.com/stable/package_esp8266com_index.json) programovatelných desek a v manažeru desek poté zvolit k instalaci nový balíček ESP8266. Po stažení všech dat potřebných pro překládání programů pro tuto architekturu pak již v seznamu desek najdete i ty s ESP8266 a můžete začít psát svůj první program.

288748832 473144754 779092698
Instalace podpory desek s ESP8266 v Arduino IDE

Kupuji NodeMCU

Mikropočítač NodeMCU seženete na eBay za částku okolo 80 korun. Wemos D1 je pak o něco dražší – stojí asi dvojnásobek. Já se rozhodl pro tu první možnost a do schránky mi po několika týdnech dorazila obálka s několika exempláři.

653845077
Cena mikropočítače NodeMCU se na eBay pohybuje okolo 80 korun

Na internetu se potuluje hned několik variant NodeMCU, přičemž dnes se zpravidla dostanete k neoficiální modifikaci v3 od výrobce LoLin, která přináší vedle pracovního 3,3V zdroje napětí i 5V (resp. napětí z připojeného USB). Rozdíly mezi jednotlivými verzemi najdete třeba na tomto blogu.

780800877 101478365
Model LoLin NodeMCU v3 a rozložení jeho pinů (kroužkem je vyznačena změna oproti předchozím verzím: pin VU s napětím USB portu)

Světýlko s ovládáním ve webovém prohlížeči

Takže mám mikropočítač s nativní podporou Wi-Fi a nastavené Arduino IDE pro jeho vývoj, čili teď už se konečně mohu vrhnout na psaní prvního programu. Nebude to nic složitého.

K mikropočítači připojím červenou LED diodu, kterou budu ovládat z webového prohlížeče. Aby to bylo možné, NodeMCU se po spuštění připojí do domácí Wi-Fi a spustí si jednoduchý webový server. Jakmile zadám do prohlížeče IP adresu mikropočítače, webový server vrátí HTML kód s tlačítkem pro zapnutí a vypnutí světla.

818894681 70113479 640186483
Primitivní zapojení: červená LED dioda je skrze 220R rezistor připojená na digitální pin D1 a obvod uzavírá pin G, tedy ground (zem). Po spuštění se mikropočítač připojí k domácí Wi-FI a spustí jednoduchý webový server, na který se budu moci připojit z prohlížeče a pomocí webového formuláře zapnout/vypnout LED diodu. Zcela vpravo pak výstup sériové linky s provozními informacemi.

Jinými slovy si postavím jednoduchý Wi-Fi spínač a je už vlastně docela jedno, jestli se bude spínat jednoduchá LED dioda, anebo pomocí magnetického relé velká lampa či jakýkoliv jiný 230V spotřebič.

Komentovaný kód aplikace

#include <ESP8266WiFi.h>

 // Nazev Wi-Fi site, do ktere se mam pripojit
const char* ssid = "Klobouk";

 // Heslo Wi-Fi site, do ktere se mam pripojit
const char* password = "***********";

// Ma svitit lampicka?
bool svetlo = false;

// Webovy server pobezi na portu 80 (HTTP komunikace)
WiFiServer server(80);
 
void setup(){
 // Nastartuj seriovou linku, do ktere budu vypisovat provozni informace
 Serial.begin(9600);

 // Nastav pin D1 na zapis a nastav nizkou hodnotu (LED dioda nesviti)
 pinMode(D1, OUTPUT);
 digitalWrite(D1, LOW);
 
 // Pripojeni k Wi-Fi
 Serial.println();
 Serial.print("Pripojuji k ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);

 // Dokud nejsem pripojeny k Wi-Fi,zapisuj do seriove linky tecky progressbaru
 while (WiFi.status() != WL_CONNECTED) {
 delay(100);
 Serial.print(".");
 }

 // Jsem pripojeny k Wi-Fi a mohu pokracovat
 Serial.println();
 Serial.println("WiFi pripojena!");
 
 // Spusteni serveru
 server.begin();
 Serial.println("Server spusten");
 
 // Napis IP adresu, kterou mikropocitac dostal
 Serial.print("Pouzij k pripojeni tuto adresu: ");
 Serial.print("http://");
 Serial.println(WiFi.localIP());
}

// Smycka loop se opakuje stale dokola 
void loop() {
 // Pokud ma promenna svetlo hodnotu pravda, posli na pin D1 napeti a rozsvit LED diodu
 if(svetlo == true) digitalWrite(D1, HIGH);
 else digitalWrite(D1, LOW);
 
 // Cekej, dokud se nepripoji nejaky klient
 WiFiClient client = server.available();
 if (!client) {
 return;
 }
 
 // Cekej, dokud klient neposle nejaka data
 Serial.println("Novy klient!");
 while(!client.available()){
 delay(1);
 }
 
 // Precti a vypis prvni radek od klienta s URL dotazem
 String request = client.readStringUntil('\r');
 Serial.println(request);
 client.flush();
 
 // Pokud je v radku vyraz ZapnoutSvetlo, nastav promennou svetlo na pravdu
 if(request.indexOf("ZapnoutSvetlo") > -1) svetlo = true;
 // Pokud je v radku vyraz VypnoutSvetlo, nastav promennou svetlo na nepravdu
 if(request.indexOf("VypnoutSvetlo") > -1) svetlo = false;

 // Posli pripojenemu klientu HTML kod stranky s tlacitky
 client.println("HTTP/1.1 200 OK");
 client.println("Content-Type: text/html");
 client.println("");
 client.println("<!DOCTYPE html>");
 client.println("<html><body>");
 client.print("<h1>Moje Wi-Fi lampicka</h2>");
 // Tlacitko pro zapnuti lampicky vede na adresu /ZapnoutSvetlo
 client.println("<a href=\"/ZapnoutSvetlo\"><button>Zapni svetlo</button></a>");
 // Tlacitko pro vypnuti lampicky vede na adresu /VypnoutSvetlo
 client.println("<a href=\"/VypnoutSvetlo\"><button>Vypni svetlo</button></a><br />");
 client.println("</body></html>");

 // To je vse, ted jeste 1 ms pockam a cela smycka se muze zopakovat
 delay(1);
 Serial.println("Klient odpojen");
 Serial.println("");
}

Stmívatelná lampička pomocí PWM

Každá chytrá žárovka toho ale umí více. Ty, které jsou vybavené RGB diodou, dokážou měnit barevný odstín, ale i ty bílé nabízejí alespoň nastavení úrovně jasu.

To samé zvládne i hloupá LED dioda připojená na digitální pin. Stačí, když mikropočítač ovládá PWM – pulzně-šířkovou modulaci. Digitální piny, které jsou k PWM určené, jsou na mikropočítačích Arduino označené vlnkou ~ a v případě NodeMCU to není třeba, PWM totiž nabízení všechny.

Pokud pro zapnutí LED diody použiji funkci digitalWrite(D1, HIGH), do vodiče začne proudit pracovní napětí 3,3 voltů. Díky PWM ale mohu použít i funkci analogWrite(D1, 0-255). Jak je to možné? V digitálním světě přece platí, že obvodem buď prochází proud a jedná se o logickou jedničku, anebo neprochází (nebo je velmi nízký) a jedná se o logickou nulu. To jsou dva možné stavy a já jich najednou mohu mít 256?

To je právě kouzlo PWM modulace. Která těchto 256 možných stavů moduluje – „zakóduje“ pomocí elektrických pulzů. Při nízkých hodnotách číselného parametru budou krátké pulzy střídat delší proluky a při vyšších hodnotách naopak krátké proluky. LED dioda bude vlastně podle délky těchto pulzů blikat, bude to však natolik rychlé, že si toho nevšimnete. Podstatné je to, že se to projeví jejím sníženým, anebo naopak zvýšeným jasem.

--241208438
Princip fungování PWM na Arduinu s pracovním napětím 5V (Více na stránkách arduino.cc)

Namísto binárních tlačítek pro zapnutí a vypnutí světýlka bych tedy mohl do kódu ovládací stránky umístit HTML5 značku posuvníku <input type="range">, která bude mít číselný rozsah 0-255. Na hodnotě 0 bude lampička zhasnutá, na hodnotě 255 pak bude díky PWM svítit na plný výkon.

454282684
Namísto on/off tlačítka posuvník pro nastavení jasu v rozmezí 0-255

Obdobně upravím i kód mikropočítače. Namísto proměnné světlo se stavy pravda/nepravda použiji proměnnou osmibitového celého čísla jas a namísto posílání URL adres /ZapnoutSvetlo a /VypnoutSvetlo budu na server posílat adresu ve formátu /svetlo=XXX při každé změně posuvníkového ovladače.

344964234 135845448 361064375
Různý jas LED diody od 0 po 255

Komentovaný kód se stmívatelnou LED diodou

#include <ESP8266WiFi.h>

const char* ssid = "Klobouk";
const char* password = "***********";

// Nova promenna pro hodnotu jasu
uint8_t jas = 0;

WiFiServer server(80);
 
void setup() {
 Serial.begin(9600);
 pinMode(D1, OUTPUT);
 digitalWrite(D1, LOW);
 
 // Pripojeni k Wi-Fi
 Serial.println();
 Serial.print("Pripojuji k ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);
 
 while (WiFi.status() != WL_CONNECTED) {
 delay(100);
 Serial.print(".");
 }

 Serial.println();
 Serial.println("WiFi pripojena!");
 
 // Spusteni serveru
 server.begin();
 Serial.println("Server spusten");
 
 // Vypis IP adresu
 Serial.print("Pouzij k pripojeni tuto adresu: ");
 Serial.print("http://");
 Serial.println(WiFi.localIP());
}
 
void loop() {
 // Namisto digitalWrite nyni pouziji analogWrite pro PWM
 analogWrite(D1, jas);
 
 // Pripojil se nejaky klient?
 WiFiClient client = server.available();
 if (!client) {
 return;
 }
 
 // Cekej, dokud klient neposle nejaka data
 Serial.println("Novy klient!");
 while(!client.available()){
 delay(1);
 }
 
 // Precti a vypis prvni radek od klienta s URL dotazem
 String request = client.readStringUntil('\r');
 Serial.println(request);
 client.flush();

 // Pokud odpoved klienta obsahuje HTTP pozadavek na adresu /svetlo=XXX,
 // Ziskam hodnotu XXX, prevedu ji na cislo a ulozim do promenne jas
 if(request.indexOf("svetlo") > -1){
 jas = request.substring(12, request.lastIndexOf(' ')).toInt();
 Serial.print("Jas nastaveny na: ");
 Serial.println(jas);
 }
 
 client.println("HTTP/1.1 200 OK");
 client.println("Content-Type: text/html");
 client.println("");
 client.println("<!DOCTYPE html>");
 client.println("<html><body>");
 client.print("<h1>Nastav jas lampicky</h2>");
 // Pri zmene hodnoty posuvniku se stranka pomoci Javascriptu presmeruje na adresu /svetlo=XXX
 client.print("<input onchange=\"javascript:location.href='/svetlo=' + this.value\" type=\"range\" min=\"0\" max=\"255\" value=\"");
 client.print(jas);
 client.println("\" />");
 client.println("</body></html>");
 
 delay(1);
 Serial.println("Klient odpojen");
 Serial.println("");
}

A to je celé. Při každé změně posuvníku se během okamžiku změní i jas LED diody.

Dnes jsme si tedy vyzkoušeli jednoduché spuštění webového serveru na mikropočítači připojeném do Wi-Fi. Stejně tak by mohl NodeMCU sám aktivně posílat data kamsi na web pomocí HTTP GET a POST a provádět mnohem sofistikovanější úkony. To je ale námět zase pro jiný článek.

LED dioda se stala součástí mého IoT, tak ať svítí co nejdéle.

Diskuze (29) Další článek: Rozpoznávání hlasu v Newton Dictate: Týden Živě klip

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,