Temperature monitoring and device controlling over WiFi through Android App using nodeMCU and NTC thermistor

Same temperature monitoring system through HABEROCEAN mobile App can be seen on my latest post https://haberocean.com/2020/04/real-time-temperature-monitoring-and-device-control-from-mobile-app-developed-on-flutter-through-nodemcu/. App screenshots are shown in the following image.

Upload the following program to your NodeMCU. It is a direct communication between your mobile device and NodeMCU. So, after uploading the program, search for available WiFi devices on your Android device. In the available WiFi devices, you could see a device named Cooling-Fan-Controller. Connect to that device by using the password given at the beginning of program. Then open a web browser on your Mobile device and open 192.168.4.1. There you could see the interface.

Same temperature monitoring system with an advanced interface using JQuery is given in my new blog. Programs are developed as an Arduino Library so that it can be installed easily in Arduino. Circuit, Programs and details can be obtained from the following link :

https://haberocean.com/2020/04/temperature-monitoring-system-over-wifi-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);
    }
  }
  
*/

}
0 0 vote
Article Rating

Published by

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
X