ESP8266 WiFi OneWire AP Client Server HTML Scheme Eagle DS18B20 Thermometer

Wifi teplomer v STA/AP móde s ESP8266


  • Teplomer využíva wifi čip ESP8266 vo verzii 12E na vývojovej doske NodeMCU v3 Lolin. Wifi čip okrem získavania údajov z teplotných senzorov drží aj webový server, kde vypisuje namerané údaje. Údaje sa odmerajú vždy pri načítaní stránky. V nečinnosti sa dáta nezaznamenávajú. Webový server umožňuje spúšťať HTML + CSS kód, čo umožňuje do istej miery spraviť aj pekné grafické rozhranie pre vykreslenie teplôt používateľovi napríklad do tabuľky.
  • Existujú dve verzie tohto projektu, pričom funkčnosť webstránky ako takej je totožná. V oboch prípadoch na ESP8266 beží webserver, ktorý vykreslí teploty do tabuľky. Pri verziách sa rozlišuje konektivita. V jednom prípade je možné využiť už existujúcu LAN sieť, do ktorej sa doska pripojí a na statickej, alebo dynamickej IP adrese drží webserver. Používateľ po zadaní IP do okna prehliadača dostane na požadovanú stránku od ESP s teplotami, prípadne pri využití mDNS je možné využiť aj hostname - doménové meno.
  • V druhom prípade doska vysiela vlastnú SSID v AP móde ako prístupový bod. Používateľ k doske pristúpi zadaním hesla do siete (je obsiahnuté v programe ESP8266). Doska vysiela SSID so šifrovaním WPA/WPA2 PSK, prípadne je možné vysielať otvorenú wifi sieť. Dáta sú prístupné iba v dosahu tejto wifi siete mimo LAN siete domácnosti. Na ESP beží aj DHCP server, ktorý po úspešnej autentizácii používateľa pridelí IP adresu z rozsahu. Webová stránka sa nachádza na IP adrese brány - ESP.
  • Dáta o teplote sú zaznamenávané z dvojice teplotných senzorov DS18B20, ktoré sú zapojené na OneWire zbernici, ktorá umožňuje zber dát po jednom vodiči s možnosťou ťahania vodiča na desiatky až stovky metrov. DS18B20 sa vyrábajú v dvoch hlavných verziách - tzv. interiérový senzor v obale tranzistora, alebo vo vodotesnom - exteriérovom vyhotovení v hliníkovej rúrke. Zbernica OneWire je vhodná do interferenčného prostredia a je možné na ňu zapojiť až 256 senzorov. Jednotlivé senzory sú rozdelené svojou adresou z výroby - sériovým číslom. Existujú 2 hlavné možnosti pripojenia senzorov. Normálne zapojenie a parazitné, u oboch je možné napájať na 3.3 - 5.5V. Pri normálnom zapojení je výsledok spoľahlivejší najmä na dlhšie vzdialenosti.
  • Rozdiely sú patrné už zo schém:
    Parametre projektu:
  • NodeMCU v úlohe prístupového bodu (AP) / alebo ako klient na vašej LAN sieti
  • Vlastné SSID a WPA2 PSK šifrovanie, alebo bez šifrovania
  • Vlastná IP (statická), možnosť rozšíriť o DNS príznak
  • Bezpečná webstránka prístupná v sieti ESP a jej dosahu s reponzívnym dizajnom
  • Vždy pri načítaní stránky aktuálne info
  • Ďalšie možné variácie:

    ESP8266 + DS18B20 WiFi teplomer - WPA/WPA2 PSK Client - Webserver:

    /*|---------------------------------|*/
    /*|Projekt: WiFi teplomer - ESP8266 |*/
    /*|Autor: Martin Chlebovec          |*/
    /*|E-mail: martinius96@gmail.com    |*/
    /*|Web: https://arduino.php5.sk     |*/
    /*|Licencia pouzitia: MIT           |*/
    /*|---------------------------------|*/
    
    #include <ESP8266WiFi.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #define ONE_WIRE_BUS 2
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    const char* ssid  = "MenoWifi";
    const char* password = "Heslo";
    WiFiServer server(80);
    String header;
    
    void setup() {
      Serial.begin(115200);
      Serial.println(ip);
      Serial.print("Connecting to ");
      Serial.println(ssid);
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      server.begin();
    }
    
    void loop(){
      WiFiClient client = server.available();
      if (client) {
        sensors.begin(); 
        sensors.requestTemperatures();  
        String currentLine = "";
        while (client.connected()) {
          if (client.available()) {
            char c = client.read();           
            header += c;
            if (c == '\n') { 
              if (currentLine.length() == 0) {
                client.println("HTTP/1.1 200 OK");
                client.println("Content-type:text/html");
                client.println("Connection: close");
                client.println();
                client.println("<head><meta charset='UTF-8'><meta name='author' content='Martin Chlebovec'><meta name='viewport' content='width=device-width, initial-scale=1.0'></head><style>body{  display: table;width: 100%;background: #dedede;text-align: center;}*{ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */-moz-box-sizing: border-box;    /* Firefox, other Gecko */box-sizing: border-box;         /* Opera/IE 8+ */}.aa_h2{  font:100 5rem/1 Roboto;  text-transform: uppercase;}table{   background: #fff;}table,thead,tbody,tfoot,tr, td,th{  text-align: center;  margin: auto;  border:1px solid #dedede;  padding: 1rem;  width: 50%;}.table    { display: table; width: 50%; }.tr       { display: table-row;  }.thead    { display: table-header-group }.tbody    { display: table-row-group }.tfoot    { display: table-footer-group }.col      { display: table-column }.colgroup { display: table-column-group }.td, .th   { display: table-cell; width: 50%; }.caption  { display: table-caption }.table,.thead,.tbody,.tfoot,.tr,.td,.th{ text-align: center; margin: auto; padding: 1rem;}.table{  background: #fff;  margin: auto;  border:none;  padding: 0; margin-bottom: 5rem;}.th{font-weight: 700;border:1px solid #dedede;&:nth-child(odd){border-right:none;}}.td{font-weight: 300;border:1px solid #dedede;border-top:none;&:nth-child(odd){border-right:none;}}.aa_htmlTable{background: tomato;padding: 5rem;display: table;width: 100%;height: 100vh;vertical-align: middle;}.aa_css{background: skyblue;padding: 5rem;display: table;width: 100%;height: 100vh;vertical-align: middle;}.aa_ahmadawais{display: table;width: 100%;font: 100 1.2rem/2 Roboto;margin: 5rem auto;}</style><div class='aa_htmlTable'><table width=100%><thead><tr><th>Teplota</th><th>Hodnota</th></tr></thead><tbody><tr><td>Dnu</td><td>"+(String)sensors.getTempCByIndex(0)+" °C</td></tr><tr><td>Von</td><td>"+(String)sensors.getTempCByIndex(1)+" °C</td></tr></tbody></table></div>");
                client.println();
                break;
              }else { // if you got a newline, then clear currentLine
                currentLine = "";
              }
              }else if (c != '\r') {  // if you got anything else but a carriage return character,
                currentLine += c;      // add it to the end of the currentLine
              }
            }
          }
      header = "";
      client.stop();
      Serial.println("");
      }
    }
    

    Schéma

    Schéma - WiFi teplomer - ESP8266

    Termostat - Tester - Offline

    //Projekt: Minimálna implementácia - termostat
    //Autor: Martin Chlebovec
    //Hardver: Arduino Uno + DS18B20 (1x OneWire bus)
    //Revizia: 23. Mar. 2020
    
    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    #define ONE_WIRE_BUS 5 //datovy vovod OneWire zbernica na pin D5
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensorsA(&oneWire);
    float nastavena_teplota = 24.50;
    float hystereza = 0.50;
    //float hystereza2 = 0.50;
    const int rele = 6;
    //const int rele2 = 7;
    unsigned long timer = 0;
    unsigned long interval = 15000; //ako casto chceme logiku spustit --> v ms (milisekundy)
    void setup() {
      sensorsA.begin();
      Serial.begin(115200);
      Serial.println("UART ready");
      pinMode(rele, OUTPUT);
      // pinMode(rele2, OUTPUT);
    }
    
    void loop() {
      if ((millis() - timer) >= interval || timer == 0) {
        timer = millis();
        sensorsA.requestTemperatures();
        delay(2000); //cakame na teploty
        float  teplota1 = sensorsA.getTempCByIndex(0);
        //float  teplota2 = sensorsA.getTempCByIndex(1);
        float rozdiel = nastavena_teplota - teplota1;
        if (rozdiel > hystereza) {
          digitalWrite(rele, HIGH); //zopnutie rele
          Serial.println("Rele bolo zopnute - Vystup aktivny");
        } else if (rozdiel < (-1 * hystereza)) {
          digitalWrite(rele, LOW); //rozopnutie rele
          Serial.println("Rele bolo rozopnute - Vystup neaktivny");
        }
    
        /*
          float rozdiel2 = nastavena_teplota2 - teplota2;
          if (rozdiel2 > hystereza2) {
          digitalWrite(rele2, HIGH); //zopnutie rele
          } else if (rozdiel2 < (-1 * hystereza2)) {
          digitalWrite(rele2, LOW); //rozopnutie rele
          }
        */
      }
    }