Temperature monitoring and device controlling over WiFi through Android App using nodeMCU and NTC thermistor
/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com/esp8266-nodemcu-access-point-ap-web-server/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <EEPROM.h>


String header;

const char* ssid     = "Cooling-Fan-Controller";
const char* password = "123456789";

#define DHTPIN 5     // Digital pin connected to the DHT sensor

// For NodeMCU
#define LED_OUT D0

// For my board
//#define LED_OUT LED_BUILTIN

#define lowerThresholdAddr 1
#define upperThresholdAddr 2
#define delayValueAddr 3

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

int delayTimeCounter = 0;
int upperThresholdDelayCheckCounter = 0;
int lowerThresholdDelayCheckCounter = 0;
int tempThresholdValue = 0;
int delayValue = 0;
int loopDelayCounter = 0;

int lowerThresholdValue, upperThresholdValue;

float vref = 3.3;
float resolution = vref/1023;

String information = "";

const char* value = "";

// Auxiliar variables to store the current output state
String output4State = "off";
String output12State = "off";
String output13State = "off";
String output14State = "off";
String output16State = "off";

// Assign output variables to GPIO pins
const int output4 = 4;
const int output12 = 12;
const int output13 = 13;
const int output14 = 14;
const int output16 = 16;

bool upperThresholdCheck = false;
bool lowerThresholdCheck = false;

int ThermistorPin = A0;
int Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf = 0;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;



DHT dht(DHTPIN, DHTTYPE);

// current temperature & humidity, updated in loop()
float t = 0.0;
float h = 0.0;

String fanState = "OFF";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncClient client;
AsyncWebServerRequest request(&server, &client);

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;    // will store last time DHT was updated

// Updates DHT readings every 10 seconds
const long interval = 10000;  

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 2.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .units_in_table { font-size: 8px; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }




table.blueTable {
  border: 1px solid #1C6EA4;
  background-color: #075f73;
  width: 100%;
  text-align: left;
  border-collapse: collapse;
}
table.blueTable td, table.blueTable th {
  border: 0px solid #AAAAAA;
  padding: 3px 2px;
}
table.blueTable tbody td {
  font-size: 13px;
}
table.blueTable tr:nth-child(even) {
  background: #D0E4F5;
}
table.blueTable thead {
  background: #1C6EA4;
  background: -moz-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
  background: -webkit-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
  background: linear-gradient(to bottom, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
  border-bottom: 2px solid #444444;
}
table.blueTable thead th {
  font-size: 15px;
  font-weight: bold;
  color: #FFFFFF;
  border-left: 2px solid #D0E4F5;
}
table.blueTable thead th:first-child {
  border-left: none;
}

table.blueTable tfoot td {
  font-size: 14px;
}
table.blueTable tfoot .links {
  text-align: right;
}
table.blueTable tfoot .links a{
  display: inline-block;
  background: #1C6EA4;
  color: #FFFFFF;
  padding: 2px 8px;
  border-radius: 5px;
}

.information
{
  color: #f01f1f;
}


  </style>
</head>
<body onload="myFunction()">



  <h2>FAN CONTROLLER</h2>
  <p>
    <span class="dht-labels">Temperature</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">°C</sup>
  </p>


    FAN STATUS : <span id = "fanState">%FAN_STATE%</span>


<br/>
<br/>


<table class="blueTable" id = "upperThresholdTable">
<thead>
<tr>
<th>Upper threshold ( <sup class="units_in_table">°C</sup> ) </th>
<th>%UPPER_THRESHOLD_VALUE%</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id ="upperThresholdValueTextBox" type="number" name="fname" ></td>
<td><input type="button" class="button" name="setUpperThreshold" id="setUpperThreshold" value="Set Upper Threshold" onclick="location.href='/setUpperThreshold?upperThresholdValue='+ document.getElementById('upperThresholdValueTextBox').value;">
</td>
</tr>
</tbody>
</table>


<br/>
<br/>

<table class="blueTable" id = "lowerThresholdTable">
<thead>
<tr>
<th>Lower threshold ( <sup class="units_in_table">°C</sup> ) </th>
<th>%LOWER_THRESHOLD_VALUE%</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id ="lowerThresholdValueTextBox" type="number" name="fname" ></td>
<td><input type="button" class="button" name="setLowerThreshold" id="setLowerThreshold" value="Set Lower Threshold" onclick="location.href='/setLowerThreshold?lowerThresholdValue='+ document.getElementById('lowerThresholdValueTextBox').value;">
</td>
</tr>
</tbody>
</table>


<br/>
<br/>


<table class="blueTable" id = "delayTable">
<thead>
<tr>
<th>Delay value ( s )</th>
<th>%DELAY_VALUE%</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id ="delayValueTextBox" type="number" name="fname" ></td>
<td><input type="button" class="buttonDelay" name="delayValue" id="setDelay" value="   Set On/Off Delay   " onclick="location.href='/setDelay?delayValue='+ document.getElementById('delayValueTextBox').value;">
</td>
</tr>
</tbody>
</table>

<br/>
    
<span class = "information">%INFORMATION%</SPAN>

  
</body>
<script>

function myFunction() {


  var cell1 = document.getElementById("upperThresholdTable").rows[0].cells;      
  document.getElementById("upperThresholdValueTextBox").value = cell1[1].innerHTML;

  var cell2 = document.getElementById("lowerThresholdTable").rows[0].cells;      
  document.getElementById("lowerThresholdValueTextBox").value = cell2[1].innerHTML;

  var cell3 = document.getElementById("delayTable").rows[0].cells;      
  document.getElementById("delayValueTextBox").value = cell3[1].innerHTML;
}


setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 100 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 100 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("fanState").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/fanState", true);
  xhttp.send();
}, 100 ) ;

</script>
</html>)rawliteral";

const char setLowerThresholdHTML[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 2.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>

    <p>
     Lower Threshold set successfully 
   </p>

   <p>
      <a href = "/">Home</a>
   </p>
</body>

</html>)rawliteral";


const char setUpperThresholdHTML[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 2.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>

    <p>
     Upper Threshold set successfully 
   </p>

   <p>
      <a href = "/">Home</a>
   </p>
</body>

</html>)rawliteral";



const char delayValueHTML[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 2.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>

    <p>
     Delay set successfully 
   </p>

   <p>
      <a href = "/">Home</a>
   </p>
</body>

</html>)rawliteral";


// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }
  else if(var == "LOWER_THRESHOLD_VALUE")
  {
    return String(lowerThresholdValue);
  }

  else if(var == "FAN_STATE")
  {
    return String(fanState);
  }

  else if(var == "UPPER_THRESHOLD_VALUE")
  {
    return String(upperThresholdValue);
  }

  else if(var == "DELAY_VALUE")
  {
    return String(delayValue);
  }

  else if(var == "INFORMATION")
  {
    return String(information);
  }
  
  return String();
}


float calculateTemperature()
{
  float temp_adc_value;
  float temp_val;
  float temp_sum = 0;
  float returnTemp;
  float returnTempRounded;

  for(int i=0;i<100;i++)
  {
    temp_adc_value = analogRead(ThermistorPin);


    // NTC thermistor
    R2 = R1 * (1023.0 / (float)temp_adc_value - 1.0);
    logR2 = log(R2);
    T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
    Tc = T - 273.15;

/*
    //  LM35
    //temp_adc_value  *= resolution;
    //Tc = temp_adc_value * 100;

    temp_adc_value = temp_adc_value * 3.2 * 1000 / 1024;
    Tc = temp_adc_value / 10;
  */

    temp_sum = temp_sum + Tc;
    
    //Serial.println(temp_sum);
    delay(10);
  }

  //Serial.println(temp_sum / 20);
  returnTemp = (temp_sum / 100) - 1.50;
  returnTempRounded = ((float )((int)(returnTemp * 10))) / 10;

  //Serial.println(returnTempRounded, 1);

  return (returnTempRounded);
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  EEPROM.begin(512);
  
  lowerThresholdValue = EEPROM.read(lowerThresholdAddr);
  upperThresholdValue = EEPROM.read(upperThresholdAddr);
  
  delayValue = EEPROM.read(delayValueAddr);
  
  dht.begin();

  pinMode(LED_OUT, OUTPUT);
  
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(t).c_str());
  });
  
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(h).c_str());
  });
  
  server.on("/fanState", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(fanState).c_str());
  });

  // Route for root / web page
  server.on("/setLowerThreshold", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", setLowerThresholdHTML, processor);

    //Serial.println(request -> arg("tempValue"));
    String strLowerThresholdValue = request -> arg("lowerThresholdValue");
    int intLowerThresholdValue = strLowerThresholdValue.toInt();

    // Serial.println(intTempValue);

    EEPROM.write(lowerThresholdAddr, intLowerThresholdValue);
    EEPROM.commit();

    lowerThresholdValue = EEPROM.read(lowerThresholdAddr);
    
  });


  // Route for root / web page
  server.on("/setUpperThreshold", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", setUpperThresholdHTML, processor);

    //Serial.println(request -> arg("tempValue"));
    String strUpperThresholdValue = request -> arg("upperThresholdValue");
    int intUpperThresholdValue = strUpperThresholdValue.toInt();

    // Serial.println(intTempValue);

    EEPROM.write(upperThresholdAddr, intUpperThresholdValue);
    EEPROM.commit();

    upperThresholdValue = EEPROM.read(upperThresholdAddr);
    
  });




  // Route for root / web page
  server.on("/setDelay", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", delayValueHTML, processor);

    //Serial.println(request -> arg("tempValue"));
    String strDelayValue = request -> arg("delayValue");
    int intDelayValue = strDelayValue.toInt();

    // Serial.println(intTempValue);

    EEPROM.write(delayValueAddr, intDelayValue);
    EEPROM.commit();

    delayValue = EEPROM.read(delayValueAddr);
    
  });
  

  // Route for root / web page
  server.on("/paul", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", setLowerThresholdHTML, processor);

    //if(request.arg(1))
    //{
    Serial.println(request -> arg("value1"));
    //}
  });

  // Start server
  server.begin();
  
}
 
void loop(){  

  int loopDelayCountLimit = 4;

  if(loopDelayCounter % loopDelayCountLimit == 0)
  {
    t = calculateTemperature();
    loopDelayCounter++;
  }

  else
  {
    loopDelayCounter++;
    if(loopDelayCounter >= loopDelayCountLimit)
      loopDelayCounter = 0;
    delay(1000); 
  }

  //Serial.print(loopDelayCounter);

  if(upperThresholdValue > lowerThresholdValue)
  {
    if(t >= upperThresholdValue)
    {

      //Serial.print(lowerThresholdDelayCheckCounter);
      //Serial.print(" ");
      //Serial.println(upperThresholdDelayCheckCounter);
      
      upperThresholdDelayCheckCounter++;
      
      upperThresholdCheck = true;
      lowerThresholdCheck = false;

      lowerThresholdDelayCheckCounter = 0;
  
      if(upperThresholdDelayCheckCounter >= delayValue)
      {
          digitalWrite(LED_OUT, HIGH); 
          
          fanState = "ON";
  
          upperThresholdDelayCheckCounter = delayValue;
      }
    } 
    
    else if(t <= lowerThresholdValue)
    {

      //Serial.print(lowerThresholdDelayCheckCounter);
      //Serial.print(" ");
      //Serial.println(upperThresholdDelayCheckCounter);
      
      lowerThresholdDelayCheckCounter++;

      upperThresholdCheck = false;
      lowerThresholdCheck = true;

      upperThresholdDelayCheckCounter = 0;
  
      if(lowerThresholdDelayCheckCounter >= delayValue) 
      {
        digitalWrite(LED_OUT, LOW);    
        
        fanState = "OFF";
  
        lowerThresholdDelayCheckCounter = delayValue;
      }
    }
  
    else
    {
      if(upperThresholdCheck == true)
      {
        if(upperThresholdDelayCheckCounter > 0)
        { 
          upperThresholdDelayCheckCounter--; 
        }
      }

      else if(lowerThresholdCheck == true)
      {
        if(lowerThresholdDelayCheckCounter > 0)
        {
          lowerThresholdDelayCheckCounter--;
        }
      }

      //Serial.print(lowerThresholdDelayCheckCounter);
      //Serial.print(" ");
      //Serial.println(upperThresholdDelayCheckCounter);
      
    }

    information = "";
  }

  else 
  {
    information = "Warning : Lower threshold must be less than upper threshold";
  }
  
  //Serial.println(delayTimeCounter);
  
  //delay(4000);
  
/*  
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;
    // Read temperature as Celsius (the default)
    float newT = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    //float newT = dht.readTemperature(true);
    // if temperature read failed, don't change t value
    if (isnan(newT)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      t = newT;
      Serial.println(t);
    }
    // Read Humidity
    float newH = dht.readHumidity();
    // if humidity read failed, don't change h value 
    if (isnan(newH)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      h = newH;
      Serial.println(h);
    }
  }
  
*/

}

Published by

Leave a Reply

X