Proiect IOT cu Arduino pentru reglarea umiditatii, a temperaturii minime si a securitatii unei locatii.

Nu am experienta cu modulele arduino si nu sunt nici programator.
Nu am invatat C++ si nici html, deci este o adevarata provocare pentru mine acest project :).

Projectul nu este inca finalizat, este mai mult creat in scop personal pana la finalizare
(dar totusi este perfect functional deja :)))

Idea a pornit de la faptul ca in baie nu avem geam si ar fi nevoie de controlul umiditatii.
Codul este preluat de pe internet din mai multe locuri dupa care a fost usor modificat combinat, adaugat in proiect si schimbat ca sa si functioneze, banuiesc ca nimeni nu se va supara....

Ce ar trebui.. si ce face modulul ?
La "prima" pornire deschide un punct AP care poate fi accesat cu telefonul.
Telefonul se conecteaza la AP primeste automat un ip si se conecteaza la site-ul de configurare cu o parola simpla care in momentul de fata este 12345678 dar poate fi schimbat.
In modul AP se deschide un site unde se specifica numele retelei wifi si parola care se salveaza in memoria modulului. Dupa restart modulul se conecteaza automat la reteaua wifi existenta.
Modulul dupa repornire nu mai intreaba de retea (am avut nevoie de retea pentru afisarea ceasului care nu are modul RTC dar fiind conectat la net se actualizeaza dupa un server NTC).
Setarile de retea se pot reseta cu un buton sau prin reprogramare. (butonul inca nu este fizic montat)
In loc de ventilator si releuri momentan se cupleaza doar 4 LED-uri, in functie de scaderea temperaturii, in functie de cresterea umiditatii aerului peste un anumit nivel, manual din interfata web si senzor PIR .
Are un server http care afiseaza in timp real (intarziere de aprox 3 secunde) starea "aparatelor" conectate (momentan sunt doar LED-uri). Intarzierea se datoreaza faptului ca programul face refresh la pagina si devine deranjant daca o face prea des, din cauza ceasului am ales sa faca refresh la 3 secunde (se poate seta dupa preferinte).
Senzorul de prezenta umana PIR detecteaza orice miscare si urmeaza implementarea functiei cu care sa trimita un avertisment prin sms pe telefonul personal metoda aleasa este prin google...

PIR poate activa un dispozitiv (un bec de exemplu) si poate trimite si un avertisment prin sms in momentul in care detecteaza miscare, functioneaza si noaptea fara lumina.

Componente folosite:

  1. Modul NodeMCU Lua wifi V3 CH340 ~37 Ron (are 16MB)
  2. Breadboard 830 puncte MB102 ~9 Ron + 2 mai mici cu ~4ron
  3. Modul convertor sursă de alimentare 5-3.3V~ 5Ron
  4. Senzor temperatura si umiditate DHT11 ~9Ron
  5. Ecran OLED 0.96” ~23Ron   (nu este necesar dar arata bine)
  6. Modul senzor de prezenta PIR ~8Ron
  7. Led -uri
  8. Releu-uri
  9. Fire de conectare
Descrierea  cu legaturile intre circuit, senzor, display, tensiune etc.. va fi pe alta pagina
Descrierea de configurari, softuri (IDE) si librariile pentru a programa modulul vor fi pe alta pagina





 /* dht, OLED, Led on off etc.. webserver */  
   
 /*definire librarii utilizate */  
 #include <Wire.h> // Only needed for Arduino 1.6.5 and earlier  
 #include "SSD1306.h" // alias for `#include "SSD1306Wire.h"` SSD1306 OLED display (128×64 Pixel)  
 #include "DHT.h"  
 #include <ESP8266WiFi.h>  
 #include <WiFiServer.h>  
 #include <WebServer.h>  
 #include <DNSServer.h>  
 #include <WiFiManager.h>  
 #include <NTPClient.h> /*NTP Client library forked by Taranais https://randomnerdtutorials.com/esp32-ntp-client-date-time-arduino-ide/   
  am folosit dar ar trebui cel oficial este la https://github.com/arduino-libraries/NTPClient */  
 #include <WiFiUdp.h>  
   
 /* initializare display*/  
 SSD1306 display(0x3c, 5, 4); // Initialize the OLED display using Wire library  
   
   
 /*definire pini iesire pt comanda led sau releu */  
          // GPIO4 GPIO5 -D1 -D2 OLED Display  
 int ledPin = 13; // GPIO13 -D7 LED setat prin interfata web manual  
 int ledPin2 = 12; // GPIO12 -D6 LED sau Releu temperatura  
 int ledPin3 = 14; // GPIO14 -D5 LED sau Releu umiditate  
 int ledPin4 = 2; // GPIO2 -D4 LED sau Releu detetor de miscare PIR  
   
 //definire pin senzor PIR  
   
 int pirSensor = 16;//GPIO16 -D0  
   
 // definire buton reset wifi to ap  
 const int PIN_AP = 10;  
   
 /*definire port server http */  
   
 WiFiServer server(80);  
   
 // Definire Client NTP pentru data si ore  
 WiFiUDP ntpUDP;  
 NTPClient timeClient(ntpUDP);  
   
 // Definire Variabile pentru salvare data si timp  
 String formattedDate;  
 String dayStamp;  
 String timeStamp;  
 String timeStamp2;  
 String ipstring;  
 /* definitie senzor temperatura si umiditate DHT11 */  
   
 #define DHTPIN D3   
 #define DHTTYPE DHT11   
 DHT dht(DHTPIN, DHTTYPE);  
 int localHum = 0;  
 int localTemp = 0;  
   
 int varpir=0;  
   
 //DEFINIRE ALTE VARIABILE  
   int value = LOW;  
   int value2 = LOW;  
   int value3 = LOW;  
   int value4 = LOW;  
 /*  
  *   
  _________________________________________________________________________________________________________*   
  */  
 // Variable to store the HTTP request  
 String header;  
   
   
 /* ________________definire setari initiale nerepetitive___________________________________________________*/   
 void setup()   
 {  
    
  Serial.begin(115200);  
  display.init(); // Initialising the UI will init the display too.  
  display.flipScreenVertically();  
 delay(1000);  
   
 /*__________________________________________WifiManager________________________*/  
  WiFiManager wifiManager;  
 //wifiManager.setAPStaticIPConfig(IPAddress(192,168,100,9), IPAddress(192,168,100,1), IPAddress(255,255,255,0));  
   
  wifiManager.autoConnect("AutoConnectAP","12345678");  
  Serial.println(WiFi.localIP());  
  wifiManager.getSSID();  
    
  //definire pin senzor pir ca si intrare  
  pinMode(pirSensor, INPUT);  
    
  pinMode(ledPin, OUTPUT);  
  digitalWrite(ledPin, LOW);  
    
  pinMode(ledPin2, OUTPUT);  
  digitalWrite(ledPin2, LOW);  
   
  pinMode(ledPin3, OUTPUT);  
  digitalWrite(ledPin3, LOW);  
   
  pinMode(ledPin4, OUTPUT);  
  digitalWrite(ledPin4, LOW);  
   
   
  // Start the server  
  server.begin();  
  Serial.println("Server started");  
    
  // Print the IP address  
  Serial.print("Use this URL to connect: ");  
  Serial.print("http://");  
  Serial.print(WiFi.localIP());  
  Serial.println("/");  
   
  // Initializare ClientNTP pentru preluarea timpului  
  timeClient.begin();  
  // Set offset time in seconds to adjust for your timezone, for example:  
  // GMT +1 = 3600 GMT +8 = 28800 GMT -1 = -3600 GMT 0 = 0 GMT +2 (Bucuresti) = +7200  
  timeClient.setTimeOffset(7200);  
  }  
   
 /*___________________________________________________________________________________________________________*/  
 /* Repetari citiri scrieri in bucla */  
   
 void loop()   
 {  
   
  WiFiManager wifiManager;  
  //daca butonul a fost apasat  
   if ( digitalRead(PIN_AP) == HIGH ) {  
    Serial.println("reset"); //resetam si intram in mod ap  
    if(!wifiManager.startConfigPortal("AutoConnectAP","12345678") ){  
     Serial.println("Ne conectam");  
     delay(2000);  
     ESP.restart();  
     delay(1000);  
    }  
    Serial.println("Conectat la AutoConnectAP!!!");  
   }   
   
 // update ntc  
  timeClient.update();  
   
 // funtie detectare miscare cod la sfarsit  
 senzorPIR();  
   
 // functie preluarea temperaturii pentru a fi afisata si pentru a executa comenzi in functie de valori   
  getDHT();  
  display.clear();  
  drawDHT();   
  display.display();  
  delay (1000);  
    
     // functii NTP  
    
    
  // The formattedDate comes with the following format:  
  // 2018-05-28T16:00:13Z  
  // We need to extract date and time  
  formattedDate = timeClient.getFormattedDate();  
  // Serial.println(formattedDate);  
   
  // Extract date  
  int splitT = formattedDate.indexOf("T");  
  dayStamp = formattedDate.substring(0, splitT);  
  //Serial.print("DATE: ");  
  // Serial.println(dayStamp);  
  // Extract time  
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);  
  timeStamp2 = formattedDate.substring(splitT+1, formattedDate.length()-4);  
  //Serial.print("HOUR: ");  
  // Serial.println(timeStamp);  
  delay(1);  
   
  // Extract time  
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);  
   
 //  
  // Check if a client has connected  
  WiFiClient client = server.available();  
  if (!client) {  
   return;  
  }  
   
  /*___________________________________________________________________*/  
   
  /*___________________________________________________________________*/  
  // Read the first line of the request  
  String request = client.readStringUntil('\r');  
  Serial.println(request);  
  client.flush();  
   
  float h =0.0; //Humidity level  
  float t =0.0; //Temperature in celcius   
  float f =0.0; //Temperature in fahrenheit  
    
  // Match the request  
   
    
   // But Wait until the client sends some data  
  Serial.println("new client");  
  while(!client.available()){  
   delay(1);  
  }  
    
 // Set ledPin according to the request  
 if (localTemp < 23) {  
     value2 = HIGH;}  
  else{  
   value2 = LOW;  
  }  
   if (localHum > 40) {  
   value3 = HIGH;}  
  else{  
   value3 = LOW;  
  }  
   
  // Return the response  
    
  client.println("HTTP/1.1 200 OK");  
  client.println("Content-Type: text/html");  
  client.println(""); // do not forget this one  
  client.println("<!DOCTYPE HTML>");  
  client.println("<html>");  
  client.print ("<body style=background-color:#ffffcc>");  
 // client.println("<meta http-equiv=\"refresh\" content=\"5\">");  
    
 // am introdus de aici  
  // Match the request  
  // if (request.indexOf("/Up=ON") != -1) {  
    h = dht.readHumidity();  //Read humidity level  
    t = dht.readTemperature()-1 ; //Read temperature in celcius corectat  
    f = (h * 1.8) + 32;    //Temperature converted to Fahrenheit  
  // value = HIGH;  
 // }  
   
  // Return the response  
  client.println(""); // do not forget this one  
  client.println("<!DOCTYPE HTML>");  
  client.println("<html>");  
   client.println("<h1 align=center><font color=red>Web Server cu urmatoarele functii:</h1></font><br>");  
  client.println("<h3 align=center>Led ori releu pornit ori oprit din interfata web<br>");  
  client.println("Control de temperatura & umiditate cu senzorul DHT11 & Ceas functional NTC (necesita conectare wifi)<br> + detector de miscare PIR</h3><br>");  
   client.print("<center>Temperatura in Celsius =");  
  client.println(t);  
  // inseram codul pentru semnul de celsius &#8451;  
  client.println("&#8451; &nbsp;&nbsp; &#92;_/&nbsp;&nbsp; Temperatura in Fahrenheit = ");  
  client.println(f);  
  // inseram codul pentru semnul Farenheit  
  client.println("&#8457;<br>");  
    
      if(varpir == 1) {  
         client.println("<font color=\"red\", size=28>PIR Detectat miscare/prezen&#539;&#259;!!</font><br>");  
  } else { client.println("<font color=\"green\">PIR Nimic de raportat</font><br>");  
  }  
    
  
  //client.println("<br><br>");  
     
  // inserat de sus  
  client.print("Controlul manual al unui consumator Led ori releu prin interfata web :</font>");  
   client.print("Ledul acum este: <br>");  
    
  if(value == HIGH) {  
   client.print("<font color=red>Pornit</font>");  
  } else {  
   client.print("<font color=red>Oprit</font>");  
  }  
  client.println("<br><br>");  
  client.println("<a href=\"/LED=ON\"\"><button>Activeaza </button></a>");  
  client.println("<a href=\"/LED=OFF\"\"><button>Opreste </button></a><br /><br>");   
 // codul html pentru semnul celsius este : &#8451;  
   client.print(" Al doilea Led ori releu cupleaza cand temperatura scade sub 23 &#8451; ");  
  client.print("Ledul este acum: <br>");  
  if(value2 == HIGH) {  
   client.print("<font color=red>Pornit</font>");  
  } else {  
   client.print("<font color=red>Oprit</font>");  
  }  
  client.println("<br><br>");  
  client.print("<font color=red>Temperatura locala este: </font>");  
  client.println("<br>");  
 client.println(localTemp);  
 client.print("&#8451;");  
  client.println("<br>");  
   
  client.print("Al treilea Led ori releu cupleaza cand umiditatea este mai mare de 40% Ideal este intre 30 si 50% ");  
  client.print("Ledul este acum: <br>");  
  if(value3 == HIGH) {  
   client.print("<font color=red>Pornit</font>");  
  } else {  
   client.print("<font color=red>Oprit</font>");  
  }  
  client.println("<br><br>");  
  client.print("<font color=red>Umiditatea locala este acum de: </font>");  
  client.println(localHum);  
 client.print("%<br></br>");  
 // client.println("<br>");  
    // iar aici incerc data si ora  
  client.print("DATE: ");  
  client.println(dayStamp);  
   client.print("HOUR: ");  
  client.println(timeStamp);  
   
   // pana aici   
  client.println("</center></html>");  
    
  delay(1);  
  Serial.println("Client disonnected");  
  Serial.println("");  
  //________________________  
  if (request.indexOf("/LED=ON") != -1) {  
   digitalWrite(ledPin, HIGH);  
   value = HIGH;  
  }  
  if (request.indexOf("/LED=OFF") != -1) {  
   digitalWrite(ledPin, LOW);  
   value = LOW;  
  }  
  /*/ inainte de terminare dam refresh pentru citirea valorilor care se schimba si setarea caii http:// la cel initial ca sa nu afecteze alti clienti  
  ----------------------------------------------------reusit cu chinuiala proprie :)----------------------------------------------------------------*/  
  client.print("<meta http-equiv='Refresh' content='2; url=http://"+WiFi.localIP().toString()+"'> ") ;  
 }  
   
 /***************************************************  
 * Get indoor Temp/Hum data  
 ****************************************************/  
 void getDHT()  
 {  
  float tempIni = localTemp;  
  float humIni = localHum;  
    
  localTemp = dht.readTemperature()-1 ; //kijavitottam a homersekletet mert tul sokat mutatott  
  localHum = dht.readHumidity();  
  if (isnan(localHum) || isnan(localTemp))  // Check if any reads failed and exit early (to try again).  
  {  
   Serial.println("Failed to read from DHT sensor!");  
   localTemp = tempIni;  
   localHum = humIni;  
   return;  
  }  
    
 }  
   
 /***************************************************  
 * Draw Indoor Page  
 ****************************************************/  
 void drawDHT()   
 {  
  int x=0;  
  int y=0;  
  display.setFont(ArialMT_Plain_10);  
  display.setTextAlignment(TEXT_ALIGN_LEFT);  
  display.drawString(0 + x, 5 + y, "Hum");  
    
  display.setFont(ArialMT_Plain_10);  
  display.setTextAlignment(TEXT_ALIGN_LEFT);  
  display.drawString(43 + x, y, "INDOOR");  
   
  display.setFont(ArialMT_Plain_24);  
  String hum = String(localHum) + "%";  
  display.drawString(0 + x, 15 + y, hum);  
  int humWidth = display.getStringWidth(hum);  
   
  display.setFont(ArialMT_Plain_10);  
  display.setTextAlignment(TEXT_ALIGN_LEFT);  
  display.drawString(95 + x, 5 + y, "Temp");  
   
  display.setFont(ArialMT_Plain_24);  
  String temp = String(localTemp) + "°C";  
  display.drawString(70 + x, 15 + y, temp);  
  int tempWidth = display.getStringWidth(temp);  
    
  display.setFont(ArialMT_Plain_24);  
  String time1 = String(timeStamp2);  
  display.drawString(30 + x, 39 + y, time1);  
  int time1Width = display.getStringWidth(time1);  
   
  //deasemenea comanda trebuie sa mearga fara interfata web  
   int value = digitalRead(ledPin);  
   int value2 = LOW;  
   int value3 = LOW;  
   
   
 if (localTemp < 23) {  
   digitalWrite(ledPin2, HIGH);  
   value2 = HIGH;}  
  else{  
  digitalWrite(ledPin2, LOW);  
   value2 = LOW;  
  }  
   if (localHum > 40) {  
   digitalWrite(ledPin3, HIGH);  
   value3 = HIGH;}  
  else{  
  digitalWrite(ledPin3, LOW);  
   value3 = LOW;  
  }  
 }  
   
 /***************************************************  
 * Detectare miscare  
 ****************************************************/  
 void senzorPIR()  
 {  
  // bucla senzorPIR  
 long state = digitalRead(pirSensor);  
  if(state == HIGH) {  
  digitalWrite (ledPin4, HIGH);  
 // Serial.println("Miscare Detectata!");  
  varpir=1;  
  delay(1000);  
  }else{  
  digitalWrite(ledPin4, LOW);  
  //Serial.println("Absenta miscare, totul este in regula");  
  varpir=0;  
  delay(1000);  
  }  
  while(!timeClient.update()) {  
   timeClient.forceUpdate();  
  }   
    
 }