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í

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


TOP produkty

Arduino DUE

Arduino DUE
696 Kč s DPH

NodeMCU s ESP8266

NodeMCU s ESP8266
350 Kč s DPH

Kontakt

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