Wifi teploměr
Pro reálné otestování možností modulu ESP8266, o kterém se zmiňuji v předchozím článku, jsem se rozhodl navrhnout velmi jednoduché schéma, které k Arduino NANO připojuje 2 digitální teploměry DS18B20. Údaje z těchto teploměrů jsou pak prezentovány na interním webu, který je implementován částečně do ESP8266 a částešně do Arduino NANO. Prakticky jsem využil poznatků z testování modulku ESP8266 a tyto znalosti pak převedl do rálného projektu.
Schéma
Shcéma je velice jednoduché a aplikuje použití modulu ESP8266 spolu s Arduino NANO, přičemž jsou pro ESP8266 vytvořeny podmínky externího napájení 3.3V stablizátorem LF33CDT pro vykrývání napěťových špiček při zvýšených proudových odběrech, zejména při registrci modulu ESP8266 k wifi síti. Důležitou součástkou je zde kondenzátor C1 o kapacitě 1000M, který se jeví jako dostatečný právě pro vykrývání proudových špiček. Modul ESP8266 je s Arduino NANO spojen na svém UARTu a je rovněž ošetřen pin RESET - mít možnost HW restartu se jeví jako prospěšné z důvodu korektní inicializace ESP8266 při startu programu a po ustabilizování napájecích poměrů po zapnutí napájení.
Dále jsou k Arduino NANO připojeny dva digitální teploměry DS18B20 dle doporučení výrobce, tedy s pull up resistorem sběrnice 1Wire. Teploměry jsou napájeny +5V.
ESP8266 samotné je napájeno +3,3V, Arduino pak přes mini USB +5V a to pak zajišťuje i napájení pro teploměry. ESP8266 se jeví jako tolerantní k +5V úrovním, takže jsem nevkládal žádný konvertor úrovní mezi 3,3V a 5V.
Deska plošného spoje
Plošný spoj se podařilo udělat jako jednostranný a protože jen vyjímečně používám klasickou montáž, tak veškeré SMD komponenty jsou na spodní straně.
Firmware
Nejprve je potřeba nalinkovat všechny důležité knihovny používané v projektu:
#include <TextFinder.h> #include <OneWire.h> #include <DallasTemperature.h> #include <SoftwareSerial.h>
ESP 8266 je na portu 2,3 - připomínám, že je potřeba mít flashlou verzi, která podporuje rychlost 9600b/s - SoftwareSerial nelze použít s vyšší rychlostí, než 19200!!!
SoftwareSerial espSerial(2,3); // RX, TX //#define DEBUG
Dále inicializujeme komponenty pro zacházení s 1Wire rozhraním a teploměry DS18B20
//pro teploměr #define ONE_WIRE_BUS 6 #define TEMPERATURE_PRECISION 9 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer, outsideThermometer; float teplota;
Definujeme SSID a Heslo pro Wifi a pár dalších nezbytností ...
//pro WiFi #define SSID "Master" #define PASS "**************" #define RESET 5 #define LED 13 //ledka na Arduinu bool wifiConnected; uint8_t cnt; String addr; char channel; TextFinder finder(espSerial);
... a jdeme na úvodní nastavení systému...
void setup()
{ wifiConnected = false; pinMode(LED, OUTPUT); digitalWrite(LED,LOW); pinMode(RESET,OUTPUT); delay(500); reset(); Serial.begin(115200); // Serial monitor espSerial.begin(9600); // ESP8266 //espSerial.println("AT+RST");
Po zapnutí napájení si počkáme, až se nám ESP8266 ohlásí ...
Serial.println(F("ESP8266 & DS18B20 Web.")); for (int i = 0; i < 5; i++) { delay(1000); if (espSerial.find("ready")) break; clearSerialBuffer(); } //otestuj dostupnost ESP8266 Serial.print("AT : "); Serial.println(ATCommandSend("AT",500) ); clearSerialBuffer();
Pokusíme se připojit k WiFi jako klient.
wifiInit(); //ESP8266 je od této chvíle viditelný na síti Serial.println(F("Webserver bezi")); digitalWrite(LED,HIGH);
Pohledáme teploměry ...
//teploměr sensors.begin(); Serial.println("***************************************************"); Serial.print("Pocet teplomeru: "); Serial.println(sensors.getDeviceCount(), DEC); //zjisti adresy oneWire.reset_search(); if (!oneWire.search(insideThermometer)) Serial.println("Vnitrni teplomer nenalezen!"); if (!oneWire.search(outsideThermometer)) Serial.println("Vnejsi teplomer nenalezen!"); Serial.print("Adresa teplomeru 1: "); printAddress(insideThermometer); Serial.println(); Serial.print("Adresa teplomeru 2: "); printAddress(outsideThermometer); Serial.println(); //nastav rozlišení sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION); sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION); //načti všechny teploměry sensors.requestTemperatures(); //vytiskni data na seriák printData(insideThermometer); printData(outsideThermometer); //vyčisti buffery if (Serial.available()>0) Serial.flush(); clearSerialBuffer(); cnt = 0; }
... a jedem do smyčky, kde čekáme na příchod sekvence +IPD - to je odezva na dotaz od webového prohlížeče, resp. její začátek. Další znak, který z ESP8266 dorazí je číslo kanálu, na který budeme "tisknout" HTML kód stránky.
void loop() { if (espSerial.available()>0) { if( finder.find("+IPD,") ) { delay(20); channel=espSerial.read(); homepage(channel-'0'); homepage(channel-'0'+1); delay(20); clearSerialBuffer(); #ifdef DEBUG Serial.println("WEB! "+String(channel)); Serial.print(F("AT+CIPMUX=1 : ")); Serial.println( ATCommandSend("AT+CIPMUX=1", 100) ); Serial.print(F("AT+CIPSERVER=1,8888 : ")); Serial.println( ATCommandSend("AT+CIPSERVER=1,8888", 100) ); delay(20); clearSerialBuffer(); #endif // DEBUG } } keepAlive(); }
Osvědčilo se do hlavní smyčky vložit takový keepAlive() - masáž srdce, kdyby náhodou modul vytuhnul, což se občas stane. Tato utilitka jej udrží při životě.
void keepAlive() { delay(100); cnt++; if (cnt>50) { cnt = 0; espSerial.println("AT"); delay(50); if (!finder.find("OK")) { #ifdef DEBUG Serial.println("ESP8266 ERROR!"); #endif // DEBUG wifiInit(); } espSerial.println("AT+CIPSERVER=1,8888"); delay(50); if (!finder.find("nochange")) wifiInit(); } }
Tady poskládáme WWW stránku, která je pak dostupná na IP adrese vypisující se v úvodní inicializaci a na portu 8888, což je zřejmé z inicializační procedury modulku.
void homepage(int ch_id) { sensors.requestTemperatures(); teplota = sensors.getTempC(insideThermometer); String term = String(teplota,2); clearSerialBuffer(); String Header; Header = "HTTP/1.1 200 OK\r\n"; Header += "Content-Type: text/html\r\n"; Header += "Connection: close\r\n"; String Content; Content = "<h1>Teplota = "; Content += term; char degree = 176; Content += String(degree); Content += "C</h1>"; Header += "Content-Length: "; Header += (int)(Content.length()); Header += "\r\n\r\n"; espSerial.print("AT+CIPSEND="); espSerial.print(String(ch_id)); #ifdef DEBUG Serial.println("Kanal: "+String(ch_id)); #endif // DEBUG espSerial.print(","); espSerial.println(Header.length()+Content.length()); delay(1000); if (espSerial.find(">")) { espSerial.print(Header); espSerial.print(Content); delay(20); clearSerialBuffer(); //espSerial.println("AT+CIPCLOSE"); //delay(50); //clearSerialBuffer(); } }
Touto funkcí s ESP8266 komunikuji - posílám do něho AT příkazy...
//AT příkaz s odpovědí a vyčasováním String ATCommandSend(String AT_Command, int wait) { String tmpData = ""; espSerial.println(AT_Command); delay(wait); while (espSerial.available() >0 ) { char c = espSerial.read(); tmpData += c; if ( tmpData.indexOf(AT_Command) > -1 ) tmpData = ""; else tmpData.trim(); } return tmpData; }
Funkce pro HW reset - ten je tedy třeba na začátku po zapnutí napájení a taky při zmíněném vytuhnutí modulku.
//restart modulu ESP8266 void reset() { digitalWrite(RESET,LOW); delay(100); digitalWrite(RESET,HIGH); }
A tady máme jádro pudla :-). Mrkněte na kód a pochopíte, co se v něm dějí za manévry. Není úplně jednoduché ten ESP8266 donutit korektně komunikovat, zkrátka je rozdíl, když na něj začnete sypat příkazy jeden za druhým z procesoru, nebo si s ním jen hrajete na nějakém převodníku a on má na všechno dost času. Pokud je vše OK, pak obdržíte IP adresu, kterou modul dostane přidělenou z DHCP Vašeho WiFi routeru, nastartuje se interní server a od této chvíle již můžete jít do browseru a mrknout na výsledek.
//inicializace wifi void wifiInit() { wifiConnected = false; digitalWrite(LED,LOW); //ověř asociaci na AP dle zvoleného SSID for (int i = 0; i < 10; i++) { espSerial.println("AT+CWJAP?"); if (finder.find(SSID)) { delay(20); clearSerialBuffer(); digitalWrite(LED,HIGH); wifiConnected = true; break; } delay(100); } delay(1000); //není asociace, pokus se připojit na AP if (wifiConnected == false) { //Serial.print("Timeout: "); //Serial.println(ATCommandSend("AT+CIPSTO=60",100)); Serial.print("Mode 1: "); Serial.println(ATCommandSend("AT+CWMODE=1",100)); for (int i = 0; i < 5; i++) { if (connectWiFi() == true) { wifiConnected = true; clearSerialBuffer(); digitalWrite(LED,HIGH); break; } delay(400); } } //wifiConnected = true; if (wifiConnected == true) { Serial.println("Pripojeno!"); clearSerialBuffer(); //set the server of port 8888 check "no change" or "OK" Serial.print(F("AT+CIPMUX=1 : ")); Serial.println( ATCommandSend("AT+CIPMUX=1", 100) ); Serial.print(F("AT+CIPSERVER=1,8888 : ")); Serial.println( ATCommandSend("AT+CIPSERVER=1,8888", 100) ); //set time out //Serial.print("AT+CIPSTO=15 : "); //Serial.println( ATCommandSend("AT+CIPSTO=15",10) ); //print the ip addr Serial.print(F("IP addresa : ")); addr = ATCommandSend("AT+CIFSR", 1000); addr = addr.substring(0,(addr.length()-2)); Serial.println(addr); delay(200); } //připojení se nezdařilo else { Serial.println("WiFi ERROR!"); digitalWrite(LED,LOW); while (true); } } void clearSerialBuffer(void) { while ( espSerial.available() > 0 ) { delay(20); espSerial.flush(); } } boolean connectWiFi() { String cmd="AT+CWJAP=\""; cmd+=SSID; cmd+="\",\""; cmd+=PASS; cmd+="\""; espSerial.println(cmd); delay(2000); if(finder.find("OK")) { clearSerialBuffer(); return true; } else { return false; } return true; }
A tady ještě pár funkcí pro obsluhu teploměrů.
//pro teploměry void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { // zero pad the address if necessary if (deviceAddress[i] < 16) Serial.print("0"); Serial.print(deviceAddress[i], HEX); } } void printData(DeviceAddress deviceAddress) { Serial.print("Adresa teplomeru "); printAddress(deviceAddress); Serial.print(":"); printTemperature(deviceAddress); } void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); Serial.print("Teplota: "); Serial.print(tempC); Serial.write(176); Serial.println("C"); }
Přidat komentář
Přehled komentářů
-
web server
(Martin, 5. 10. 2015 23:09:31)
Odpovědět
Dobrý den, zaujal mne Váš článek a tak jsem se rozhodl, že podobný senzor zkusím sestrojit také ale prozatím s arduino Mega 2560. Teploměry Dallas jsem nahradil termistory, a tedy metody pro jejich obsluhu i onewire sběrnice nepoužívám. (odstraneno z kódu)
Zatím jsem ve stavu kdy je vše zapojeno na nepájivém poli. Objevilo se však několik problémů - nejdříve zamrznutí po testování při restartu. Prakticky po odstranění všech "clearSerialBuffer();" z wifiInit zamrzávání přestalo. Na SerialMonitoru toto:
AT : OK
Pripojeno!
AT+CIPMUX=1 : OK
AT+CIPSERVER=1,8888 : OK
IP addresa : 192.168.1.2
Webserver bezi
Pripojeno!
AT+CIPMUX=1 : OK
AT+CIPSERVER=1,8888 : nochange
IP addresa : 192.168.1.2
Na zmíněnou adresu se však nelze připojit. Je tedy potřeba nějakého programu pro vytvoření lokálního serveru, nebo se lze k senzoru připojit přímo pomocí telefonu pokud je v kombinovaném režimu?
Předem děkuji za odpověď. -
využití jako laboratorní úloha
(Bohumil Horák, 13. 10. 2016 11:13:18)
Odpovědět
Zaujalo mne vaše využití Arduino a realizace wifi teploměru se dvěma snímači dallas. Máme zájem realizovat zapojení jako demonstrační úlohu pro studenty. Za jakých podmínek je možno poskytnout detailní informace? Kontaktujte mne prosím. B.Horák
-
ethernet teploměr
(machula, 23. 11. 2016 16:21:31)
Odpovědět
dobrý den, mám zájem o zkompletovaná ethernet teploměr. z nedostatku času :( děkuji
Dobrý den, trpím stejným problémem :-). PF -
Oznacenie kondenzatora
(Martin, 31. 1. 2017 15:35:19)
Odpovědět
| Zobrazit odpovědi
Dobry den, to ake oznacovanie nasobku jednotky kapacity pouzivate ? To je podla metrickej normy vo Vanuatu ? Co je to 1000M, Mega ?, Mili, Mikro...clovek keby si to aj chcel postavit, tak nema sancu...musi skusat vsetky dostupne kondenzatory. Bolo by viac ako vhodne to tam uviest poriadne. Ďakujem.
-
Re: Oznacenie kondenzatora
(dufisek, 25. 4. 2017 9:15:32)
Odpovědět
M(m)... znamená mikrofarad a navíc je to elektrolyt, v napájecí větvi....., ostatní jsou s označením "n" tak keramika nanofarad, jinak látka 1.ročníku na SPŠE.......
-
Re: Oznacenie kondenzatora
(Martin, 15. 10. 2017 20:42:55)
Odpovědět
Co je to 1000M? No to je 1000 mikro faradů, nebo také 1 mili farad. Je to jen blokovací kondenzátor ke stabilizátoru.
-
Re: Oznacenie kondenzatora
(LH, 27. 10. 2017 15:43:51)
Odpovědět
M se u kondenzatoru pouziva misto reckeho znaku pro micro. Je to de-facto standard.
-
Re: Oznacenie kondenzatora
(Taurus, 15. 3. 2018 15:20:56)
Odpovědět
Aj úplný začiatočník, ktorý sa chce vrtať v elektronike, už vie že M je mikrofarad. Ak sa dotyčnému niečo nepozdáva, tak nech sa do problematiky nesere, alebo nech sa spýta slušne, keď je už taký bulo....
-
Dotaz
(Jan Čížek, 19. 12. 2017 10:33:44)
Odpovědět
Dobrý den, uvedený program se nahraje do desky arduina nebo do modulu ESP8266?
Zkouším různé příklady a vždy narazím na problém co a jak připojit a co kam dát. Se samotným arduinem nemám problém ale s tímto modulem jsem zatím nepohnul. Prosím o vysvětlení jak na tento modul.
Předem díky za pomoc. Honza