OK

Při poskytování služeb nám pomáhají soubory cookie. Používáním našich služeb vyjadřujete souhlas s naším používáním souborů cookie. Více informací

Úvodní stránka » Projekty » WiFi teploměr

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.

Wifi teploměr 

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ě.

 

PCB WiFi Termo

 

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ář

Zvýrazněné položky jsou povinné.

Přehled komentářů

  1. 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ěď.

  2. 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

  3. 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

  4. 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.

    1. 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.......

    2. 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.

    3. 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.


TOP produkty

Kontakt

Ing. Petr Foltýn
Kunčice pod Ondřejníkem 814, 73913
TOPlist