Advertisement
DuboisP

ESP32_DHT_NTP_Clock_LCD2004

Dec 6th, 2024 (edited)
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.47 KB | Source Code | 0 0
  1. /*********
  2.    title    :   ESP32_DHT_NTP_Clock_LCD2004      
  3.    target   :   ESP32 Dev Module
  4.                 ESP32 pinout
  5.                 LCD1602 display on I2C
  6.    
  7.    author   :   Patrick Dubois
  8.    license  :   public domain
  9.                  
  10. *********/
  11.  
  12. // Import required libraries
  13. // if the library is global   use <>
  14. // if the library is local    use ""
  15.  
  16. #include <ArduinoOTA.h>
  17. #include <AsyncTCP.h>
  18. #include <DHT.h>
  19. #include <ESPmDNS.h>
  20. #include <ESPAsyncWebServer.h>
  21. #include <LiquidCrystal_I2C.h>
  22. #include <time.h>
  23. #include <WiFi.h>
  24. #include <Wire.h>
  25.  
  26. #include "html_js.html"
  27. #include "STAcredentials.h"
  28.  
  29. #define button0Pin        0      // GPIO 0 or PRG button
  30. #define BuiltInLed        2      // GPIO led allumée par erreur dans la boucle Wifi not connected ?
  31. #define tempo           1000     // 1 seconde
  32. #define tempo1          60000    // 1 minute
  33. #define baudrateSerial  115200   // vitesse communication Arduino - PC  
  34.  
  35. #define SCL_GPIO  32  
  36. #define SDA_GPIO  33
  37. #define numCols   20                                     // for lcd
  38. #define numRows    4
  39. LiquidCrystal_I2C lcd(0x27, numCols, numRows);           // use this for I2C LCD.
  40.  
  41. #define DHTPin1 26     // GPIO used for the DHT sensor
  42. #define DHTPin2 27     // GPIO used for the DHT sensor
  43. #define DHTPin3 14     // GPIO used for the DHT sensor
  44.  
  45. #define DHTType1 DHT11     // DHT 11                     // from left to right : data vcc gnd
  46. #define DHTType2 DHT22     // DHT 22  (AM2302), AM2321   // from left to right : vcc data gnd
  47.  
  48. DHT dht[] = {  DHT(DHTPin1, DHT22),
  49.                DHT(DHTPin2, DHT22),
  50.                DHT(DHTPin3, DHT11)};
  51.  
  52. // Create AsyncWebServer object on port 8092 instead of 80 already used on the network
  53. AsyncWebServer server(8092);
  54.  
  55. #define ntpServer "europe.pool.ntp.org"
  56. char dtDateTime[21];
  57.  
  58. bool bLCDDisplay = false;
  59. bool bButton0Pressed = false;
  60. bool bInit = true;
  61. byte nIndex = 0;
  62. uint32_t newMillis, oldMillis, oldMillis1;
  63. const uint32_t webDuration = 1000 * 60 * 1;          // was 60 sec duration for web update, now 1 minute
  64.  
  65. // function prototype declarations
  66. void Display_Init(void);
  67. void DisplayIMessage(String sMessage, bool bClear, bool bCRLN);
  68. void OTA_Init(void);
  69. String processor(const String& var);
  70. String readDHTTemperature(byte nIndex);
  71. String readDHTHumidity(byte nIndex);
  72. String readLocalTime(void);
  73. int WiFi_Init(byte nIndex);
  74. // end declarations
  75.  
  76. void IRAM_ATTR onButton0Event() {
  77.    bButton0Pressed = true;
  78. }
  79.  
  80. void setup() {
  81.    btStop();
  82.    Wire.begin(SDA_GPIO, SCL_GPIO);  
  83.    Serial.begin(baudrateSerial);    // Serial0
  84.  
  85.    for (auto& sensor : dht) {                               // https://forum.arduino.cc/t/multiple-dht22-sensors/525773/4
  86.       sensor.begin();
  87.    }
  88.  
  89.    Display_Init();
  90.    oldMillis = oldMillis1 = newMillis = millis();
  91.    WiFi_Init(nIndex);
  92.    OTA_Init();
  93.    configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", ntpServer);   // "Europe/Paris","CET-1CEST,M3.5.0,M10.5.0/3"  
  94.                                                             // https://raw.githubusercontent.com/nayarsystems/posix_tz_db/master/zones.csv
  95.    pinMode(BuiltInLed, OUTPUT);    
  96.    digitalWrite(BuiltInLed, LOW);                           // ON after Wifi connection so I set it OFF
  97.    pinMode(button0Pin, INPUT_PULLDOWN);                     // GPIO 0
  98.    attachInterrupt(digitalPinToInterrupt(button0Pin), onButton0Event, RISING);  
  99.  
  100.    // Route for root / web page
  101.    server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
  102.       request->send_P(200, "text/html", index_html, processor);
  103.    });
  104.    server.on("/temperature0", HTTP_GET, [](AsyncWebServerRequest * request) {
  105.       request->send_P(200, "text/plain", readDHTTemperature(0).c_str());
  106.    });
  107.    server.on("/humidity0", HTTP_GET, [](AsyncWebServerRequest * request) {
  108.       request->send_P(200, "text/plain", readDHTHumidity(0).c_str());
  109.    });
  110.    server.on("/temperature1", HTTP_GET, [](AsyncWebServerRequest * request) {
  111.       request->send_P(200, "text/plain", readDHTTemperature(1).c_str());
  112.    });
  113.    server.on("/humidity1", HTTP_GET, [](AsyncWebServerRequest * request) {
  114.       request->send_P(200, "text/plain", readDHTHumidity(1).c_str());
  115.    });
  116.    server.on("/temperature2", HTTP_GET, [](AsyncWebServerRequest * request) {
  117.       request->send_P(200, "text/plain", readDHTTemperature(2).c_str());
  118.    });
  119.    server.on("/humidity2", HTTP_GET, [](AsyncWebServerRequest * request) {
  120.       request->send_P(200, "text/plain", readDHTHumidity(2).c_str());
  121.    });
  122.    server.on("/date_time", HTTP_GET, [](AsyncWebServerRequest * request) {
  123.       request->send_P(200, "text/plain", readLocalTime().c_str());
  124.    });
  125.    // Start server
  126.    server.begin();
  127. }
  128.  
  129. // Replaces placeholder with BME values
  130. String processor(const String& var) {
  131.  
  132.    // Serial.println(var);
  133.    if (var == "TEMPERATURE0") {
  134.       return readDHTTemperature(0);
  135.    }
  136.    else if (var == "HUMIDITY0") {
  137.       return readDHTHumidity(0);
  138.    }
  139.    else if (var == "TEMPERATURE1") {
  140.       return readDHTTemperature(1);
  141.    }
  142.    else if (var == "HUMIDITY1") {
  143.       return readDHTHumidity(1);
  144.    }
  145.    else if (var == "TEMPERATURE2") {
  146.       return readDHTTemperature(2);
  147.    }
  148.    else if (var == "HUMIDITY2") {
  149.       return readDHTHumidity(2);
  150.    }
  151.    else if (var == "DATE_TIME") {
  152.       return readLocalTime();
  153.    }
  154.    return String();
  155. }
  156.  
  157. void loop() {
  158.    String sString;
  159.    static char sBuffer[24];
  160.  
  161.    ArduinoOTA.handle();
  162.    newMillis = millis();
  163.     if (bButton0Pressed) {
  164.        nIndex = nIndex < 3 ? ++nIndex : 0;
  165.        bButton0Pressed = false;
  166.        detachInterrupt(digitalPinToInterrupt(button0Pin));
  167.        WiFi_Init(nIndex);
  168.        bInit = true;
  169.        attachInterrupt(digitalPinToInterrupt(button0Pin), onButton0Event, RISING);
  170.     }
  171.    if (newMillis > oldMillis + tempo) {
  172.       oldMillis = newMillis;
  173.       sString = readLocalTime();
  174.       lcd.setCursor(0, 3);                   // cols, rows
  175.       lcd.print(sString);
  176.    }  
  177.    if ((newMillis > oldMillis1 + tempo1) || bInit) {
  178.       oldMillis1 = newMillis;
  179.       bInit = false;
  180.       // to have the degree and percent caracter https://www.letscontrolit.com/forum/viewtopic.php?t=2368
  181.       for (byte nIndex = 0; nIndex < 3; nIndex++) {
  182.          sprintf(sBuffer,"Capt.%d %s%c %s%c", nIndex+1, readDHTTemperature(nIndex), byte(223), readDHTHumidity(nIndex), byte(37));  
  183.          lcd.setCursor(0, nIndex); lcd.print(sBuffer);
  184.       }    
  185.    }
  186. }
  187.  
  188. String readLocalTime() {
  189.    struct tm timeinfo;
  190.    if (getLocalTime(&timeinfo)) {
  191.       strftime(dtDateTime, sizeof(dtDateTime), "%H:%M.%S  %d/%m/%Y", &timeinfo);
  192.    }
  193.    return dtDateTime;
  194. }
  195.  
  196. String readDHTTemperature(byte nIndex) {
  197.    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  198.    // Read temperature as Celsius (the default)
  199.    // Read temperature as Fahrenheit (isFahrenheit = true)
  200.    float t;
  201.    String sResult = "--";
  202.    t = dht[nIndex].readTemperature();
  203.    if (!(isnan(t))) {
  204.       sResult = String(t);
  205.    }
  206.    return sResult;
  207. }
  208.  
  209. String readDHTHumidity(byte nIndex) {
  210.    float h;
  211.    String sResult = "--";
  212.    h = dht[nIndex].readHumidity();
  213.    if (!(isnan(h))) {
  214.       sResult = String(h);
  215.    }
  216.    return sResult;
  217. }
  218.  
  219. int WiFi_Init(byte nIndex) {
  220.    int iResult = 0;
  221.    String SSID_NAME = WifiID[nIndex][0];
  222.    DisplayIMessage("Connecting to", true, true);
  223.    DisplayIMessage(SSID_NAME, false, true );
  224.    WiFi.setHostname(HOSTNAME);
  225.    WiFi.begin(SSID_NAME, WifiID[nIndex][1]);    // Password
  226.    while (WiFi.status() != WL_CONNECTED) {
  227.       delay(500);
  228.       DisplayIMessage(".", false, false);
  229.         if (millis() > newMillis + 5000) {
  230.          iResult = -1;
  231.          break;
  232.       }
  233.    }
  234.    lcd.clear();
  235.     return iResult;
  236. }
  237.  
  238. void Display_Init() {
  239.    lcd.init();                      // I2C LCD init command
  240.    bLCDDisplay = true;
  241.    lcd.backlight();                 // I2C LCD turn backlight on
  242.    //lcd.setCursor(6, 0); lcd.print(HOSTNAME);  
  243.    delay(2000);
  244. }
  245.  
  246. void DisplayIMessage(String sMessage, bool bClear, bool bCRLN) {
  247.    static int nRow = 0;
  248.  
  249.    if (bLCDDisplay) {
  250.       if (bClear) {
  251.          lcd.clear();
  252.          lcd.setCursor(0, nRow=0);
  253.       }
  254.       if (bCRLN) {
  255.          lcd.setCursor(0, nRow++);
  256.          lcd.print(sMessage);
  257.       }
  258.       else
  259.          lcd.print(sMessage);
  260.    }
  261.    else
  262.       Serial.println(sMessage);
  263. }
  264.  
  265. void OTA_Init(){
  266.    // Port defaults to 3232
  267.    // ArduinoOTA.setPort(3232);
  268.    // Hostname defaults to esp3232-[MAC]
  269.    ArduinoOTA.setHostname(HOSTNAME);
  270.    // No authentication by default
  271.    // ArduinoOTA.setPassword("admin");
  272.    ArduinoOTA.setPassword(PASSWORD);  
  273.    // Password can be set with it's md5 value as well
  274.    // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  275.    // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
  276.  
  277.    ArduinoOTA
  278.    .onStart([]() {
  279.       String type;
  280.       if (ArduinoOTA.getCommand() == U_FLASH)
  281.          type = "sketch";
  282.       else // U_SPIFFS
  283.          type = "filesystem";
  284.  
  285.       // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
  286.       Serial.println("Start updating " + type);
  287.    })
  288.    .onEnd([]() {
  289.       Serial.println("\nEnd");
  290.    })
  291.    .onProgress([](unsigned int progress, unsigned int total) {
  292.       Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  293.    })
  294.    .onError([](ota_error_t error) {
  295.       Serial.printf("Error[%u]: ", error);
  296.       if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
  297.       else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
  298.       else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
  299.       else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
  300.       else if (error == OTA_END_ERROR) Serial.println("End Failed");
  301.    });
  302.    ArduinoOTA.begin();
  303. }
  304.  
  305. /* *********************************************
  306. /* to extract and name STAcredentials.h
  307. ***********************************************/
  308. #define HOSTNAME "ESP32_DHT_WebServer"
  309. #define PASSWORD "12345678"
  310.  
  311. String WifiID[4][2]= {  { "Mankell","password_to_change"},
  312.                         { "Box2",   "password_to_change"},
  313.                         { "Box3",   "password_to_change"},
  314.                         { "Box4",   "password_to_change"}};
  315.  
  316.  
  317. /* **********************************************
  318. /*  to extract and name html_js.html
  319. /*  html page conception and scripts
  320. ************************************************/
  321.  
  322. const char index_html[] PROGMEM = R"rawliteral(
  323. <!DOCTYPE HTML><html>
  324. <head>
  325.   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  326.   <meta charset="utf-8">
  327.   <meta http-equiv="refresh" content="60">
  328.   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
  329.    <style>
  330.       html {
  331.          font-family: Arial;
  332.          display: inline-block;
  333.          margin: 0px auto;
  334.          text-align: center;
  335.       }
  336.       h2 { font-size: 3.0rem; }
  337.       p { font-size: 3.0rem;}
  338.       .ref { font-size: 1.0rem; }
  339.       .units { font-size: 1.2rem; }
  340.       .bme-labels{
  341.          font-size: 1.5rem;
  342.          text-align: left;
  343.          vertical-align:middle;
  344.          padding-bottom: 15px;
  345.       }
  346.    </style>
  347. </head>
  348. <body>
  349.    <h2>Esp32 DHT Server</h2>
  350.    <p>
  351.       <i class="fas fa-thermometer-half" style="color:#059e8a;"></i>
  352.       <span class="bme-labels">Température 1</span>
  353.       <span id="temperature0">%TEMPERATURE0%</span>
  354.       <sup class="units">&deg;C</sup>
  355.    </p>
  356.    <p>
  357.       <i class="fas fa-tint" style="color:#00add6;"></i>
  358.       <span class="bme-labels">Humidité 1</span>
  359.       <span id="humidity0">%HUMIDITY0%</span>
  360.       <sup class="units">&percnt;</sup>
  361.    </p>
  362.    <p>
  363.       <i class="fas fa-temperature-half" style="color:#059e8a;"></i>
  364.       <span class="bme-labels">Température 2</span>
  365.       <span id="temperature1">%TEMPERATURE1%</span>
  366.       <sup class="units">&deg;C</sup>
  367.    </p>
  368.    <p>
  369.       <i class="fas fa-tint" style="color:#00add6;"></i>
  370.       <span class="bme-labels">Humidité 2</span>
  371.       <span id="humidity1">%HUMIDITY1%</span>
  372.       <sup class="units">&percnt;</sup>
  373.    </p>
  374.    <p>  
  375.       <i class="fas fa-temperature-half" style="color:#059e8a;"></i>
  376.       <span class="bme-labels">Température 3</span>
  377.       <span id="temperature2">%TEMPERATURE2%</span>
  378.       <sup class="units">&deg;C</sup>
  379.    </p>
  380.    <p>
  381.       <i class="fas fa-tint" style="color:#00add6;"></i>
  382.       <span class="bme-labels">Humidité 3</span>
  383.       <span id="humidity2">%HUMIDITY2%</span>
  384.       <sup class="units">&percnt;</sup>
  385.    </p>  
  386.    <p>
  387.       <i class="fas fa-clock"></i>
  388.       <span class="bme-labels">Relevé le</span>
  389.       <span id="date_time" class="bme-labels">%DATE_TIME%</span>
  390.       <!-- sup class="ref">UTC</sup -->
  391.    </p>
  392. </body>
  393.  
  394. <script>
  395.  
  396. setInterval(function () {
  397.    var xhttp = new XMLHttpRequest();
  398.    xhttp.onreadystatechange = function() {
  399.       if (this.readyState == 4 && this.status == 200) {
  400.          document.getElementById("temperature1").innerHTML = this.responseText;
  401.       }
  402.    };
  403.    xhttp.open("GET", "/temperature1", true);
  404.    xhttp.send();
  405. }, webDuration ) ;
  406.  
  407. setInterval(function () {
  408.    var xhttp = new XMLHttpRequest();
  409.    xhttp.onreadystatechange = function() {
  410.       if (this.readyState == 4 && this.status == 200) {
  411.          document.getElementById("humidity1").innerHTML = this.responseText;
  412.       }
  413.    };
  414.    xhttp.open("GET", "/humidity1", true);
  415.    xhttp.send();
  416. }, webDuration ) ;
  417.  
  418. setInterval(function () {
  419.    var xhttp = new XMLHttpRequest();
  420.    xhttp.onreadystatechange = function() {
  421.       if (this.readyState == 4 && this.status == 200) {
  422.       document.getElementById("temperature2").innerHTML = this.responseText;
  423.       }
  424.    };
  425.    xhttp.open("GET", "/temperature2", true);
  426.    xhttp.send();
  427. }, webDuration ) ;
  428.  
  429. setInterval(function () {
  430.    var xhttp = new XMLHttpRequest();
  431.    xhttp.onreadystatechange = function() {
  432.       if (this.readyState == 4 && this.status == 200) {
  433.          document.getElementById("humidity2").innerHTML = this.responseText;
  434.       }
  435.    };
  436.    xhttp.open("GET", "/humidity2", true);
  437.    xhttp.send();
  438. }, webDuration ) ;
  439.  
  440. setInterval(function () {
  441.    var xhttp = new XMLHttpRequest();
  442.    xhttp.onreadystatechange = function() {
  443.       if (this.readyState == 4 && this.status == 200) {
  444.       document.getElementById("date_time").innerHTML = this.responseText;
  445.       }
  446.    };
  447.    xhttp.open("GET", "/date_time", true);
  448.    xhttp.send();
  449. }, webDuration ) ;
  450.  
  451. </script>
  452. </html>)rawliteral";
  453.  
  454. /* end html page conception and scripts ****************************************/
  455.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement