Das Forum für Zigarren und andere Genüsse dieser Welt
Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Das smarte DIY Hygrometer
#4
(17.08.2024, 08:00)CigarNerd schrieb: Schönes Hygrometer das du da gebastelt hast. Proxy_007
Verwendest du die Heizung des SHT4x?
Ich kann das nur empfehlen, da der Sensor sonst wegdriftet: https://zigarren-community.de/thread-177...l#pid73822

Die Heitzungsfunktionen sind im Code implementiert, ich habe sie aber noch nicht eingesetzt, da ich mich gerade erst mit der Frage auseinandersetze, welchen Effekt die Heitzung genau hat.

Du hattest dich mit dem Thema schon auseinander gesetzt, oder?

Für interessierte hier der Code in Version 0.96:
Code:
/*********
  Various code snipped frankensteined together with a lot of try & error by Crix1990.
  Modded for Humidor use by Crix1990.
*********/

// Load Wi-Fi library
#include <ESP8266WiFi.h>
#include <Wire.h>
#include "Adafruit_SHT4x.h"
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#include <ESP_Mail_Client.h>

#include <time.h>                   // time() ctime()
time_t now;                         // this is the epoch
tm myTimeInfo;                      // the structure tm holds time information in a more convient way




Adafruit_SHT4x sht4 = Adafruit_SHT4x();
#define SDA_PIN 14 //GPIO14 / 5
#define SCL_PIN 12 //GPIO12 / 6
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL_PIN, SDA_PIN, U8X8_PIN_NONE);
int intervalOledRun = 10000;
unsigned long previousOledRun = 0;
String HumidityPrint = "Humidity:";
String TemperaturePrint = "Temperature:";

//Humidor Setup
//Name you Humidor:
String HumidorName = "Tisch Humidor";
//Define target humidity
double TargetHumidity = 69;
//Define your humidity tolerance (1 = 1% tolerance, 2 = 2% tolerance, etc.)
double TargetTolerance = 5;
//Define your Mail delay in Miliseconds
int MailDelay = 300000;


// Replace with your network credentials
const char* ssid     = "WIFINAME";
const char* password = "WIFIPW";

// Configure NTP services
const char* ntpServer = "10.10.70.1";
const long  gmtOffset_sec = 1;
const int   daylightOffset_sec = 7200;

//Configure mail credentials
#define RECIPIENT_EMAIL "REC@MAIL.de"
#define AUTHOR_EMAIL "SEND@MAIL.de"
#define AUTHOR_PASSWORD "MAILPW"
#define SMTP_HOST "smtp.xxx.de"
#define SMTP_PORT 465


// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Declare the global used SMTPSession object for SMTP transport
SMTPSession smtp;
// Declare global message class
SMTP_Message message;

unsigned long previousMillis = 0;
unsigned long AlarmStateMillis = 0;
unsigned long currentMillis = 0;
const long interval = 60000;  // 30 seconds

//Alert states
int AlarmState = 0;
int AlarmStateOld = 0;

// Declare the Session_Config
// GLOBAL for user defined session credentials */
Session_Config config;

void setup() {
  Serial.begin(115200);
  bool status;

  PrintFileNameDateTime();

  // default settings
   Serial.println("Adafruit SHT4x test");
  if (! sht4.begin()) {
    Serial.println("Couldn't find SHT4x");
    while (1) delay(1);
  }
  Serial.println("Found SHT4x sensor");
  Serial.print("Serial number 0x");
  Serial.println(sht4.readSerial(), HEX);
   // You can have 3 different precisions, higher precision takes longer
  sht4.setPrecision(SHT4X_HIGH_PRECISION);
  switch (sht4.getPrecision()) {
     case SHT4X_HIGH_PRECISION:
       Serial.println("High precision");
       break;
     case SHT4X_MED_PRECISION:
       Serial.println("Med precision");
       break;
     case SHT4X_LOW_PRECISION:
       Serial.println("Low precision");
       break;
  }

  // You can have 6 different heater settings
  // higher heat and longer times uses more power
  // and reads will take longer too!
  sht4.setHeater(SHT4X_NO_HEATER);
  switch (sht4.getHeater()) {
     case SHT4X_NO_HEATER:
       Serial.println("No heater");
       break;
     case SHT4X_HIGH_HEATER_1S:
       Serial.println("High heat for 1 second");
       break;
     case SHT4X_HIGH_HEATER_100MS:
       Serial.println("High heat for 0.1 second");
       break;
     case SHT4X_MED_HEATER_1S:
       Serial.println("Medium heat for 1 second");
       break;
     case SHT4X_MED_HEATER_100MS:
       Serial.println("Medium heat for 0.1 second");
       break;
     case SHT4X_LOW_HEATER_1S:
       Serial.println("Low heat for 1 second");
       break;
     case SHT4X_LOW_HEATER_100MS:
       Serial.println("Low heat for 0.1 second");
       break;
  }


  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  u8g2.begin();
  u8g2.enableUTF8Print();


  synchroniseWith_NTP_Time();
  MailClient.networkReconnect(true);
  setupEmailConfig();
  sendEmail();
  AlarmState = 1;

}

void loop(){
currentMillis = millis();
  sensors_event_t humidity, temp;
  sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  if(currentMillis - previousOledRun >= intervalOledRun) {




  //Display Configuration
  HumidityPrint = "Hum: " + String(humidity.relative_humidity) + " %";
  TemperaturePrint = "Temp: " + String(temp.temperature) + " °C";
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_t0_16_tf);
  if (humidity.relative_humidity < TargetHumidity - TargetTolerance) {
      u8g2.drawButtonUTF8(0, 13, U8G2_BTN_INV, 0,  2,  2, HumidorName.c_str());
      u8g2.drawButtonUTF8(0, 36, U8G2_BTN_INV, 0,  2,  5, TemperaturePrint.c_str());
      u8g2.drawButtonUTF8(0, 60, U8G2_BTN_INV, 0,  2,  5, HumidityPrint.c_str());

            }
  else if (humidity.relative_humidity > TargetHumidity + TargetTolerance) {
      u8g2.drawButtonUTF8(0, 13, U8G2_BTN_INV, 0,  2,  2, HumidorName.c_str());
      u8g2.drawButtonUTF8(0, 36, U8G2_BTN_INV, 0,  2,  5, TemperaturePrint.c_str());
      u8g2.drawButtonUTF8(0, 60, U8G2_BTN_INV, 0,  2,  5, HumidityPrint.c_str());

            }
  else {
     u8g2.drawUTF8(0,13,HumidorName.c_str());
     u8g2.drawUTF8(0,36,TemperaturePrint.c_str());
     u8g2.drawUTF8(0,60,HumidityPrint.c_str());
            }



  u8g2.sendBuffer();

  }
    currentMillis = millis();

  if(currentMillis - previousOledRun >= intervalOledRun) {



  }
    delay(1000);
  //Mail Config
  currentMillis = millis();
  //Too Low
  if (humidity.relative_humidity < TargetHumidity - TargetTolerance) {
    if (AlarmState == 2){
    }
    else if (AlarmState == 20) {
      if (currentMillis >= AlarmStateMillis + MailDelay || currentMillis < AlarmStateMillis) {
      AlarmState = 2;
      sendEmail();
      }
    }
    else if (AlarmState == 10 && AlarmStateOld == 2) {
    AlarmState = 2; 
    }
    else {
    AlarmState = 20;
    AlarmStateMillis = currentMillis;
    }


    }
  //Too High         
  else if (humidity.relative_humidity > TargetHumidity + TargetTolerance) {
    if (AlarmState == 3){
    }
    else if (AlarmState == 30) {
      if (currentMillis >= AlarmStateMillis + MailDelay || currentMillis < AlarmStateMillis) {
      AlarmState = 3;
      sendEmail();
      }
    }
    else if (AlarmState == 10 && AlarmStateOld == 3) {
    AlarmState = 3; 
    }   
    else {
    AlarmState = 30;
    AlarmStateMillis = currentMillis;
    }


    }

  //Normal         
  else {
    if (AlarmState == 20 || AlarmState == 30) {
      AlarmState = 1;
      AlarmStateMillis = currentMillis;
    }
    else if (AlarmState == 2 || AlarmState == 3) {
      AlarmStateOld = AlarmState;
      AlarmState = 10;
      AlarmStateMillis = currentMillis;
    }
    else if (AlarmState == 10) {
      if (currentMillis >= AlarmStateMillis + 300000 || currentMillis < AlarmStateMillis) {
      AlarmState = 1;
      sendEmail();
      }
    }

       }


  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected

//Serial.println("1");



      if (client.available()) {             // if there's bytes to read from the client,
      Serial.println("2");
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
           
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
           // client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<head><meta http-equiv=refresh content=1>");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the table
            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
            client.println("table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }");
            client.println("th { padding: 12px; background-color: #0043af; color: white; }");
            client.println("tr { border: 1px solid #ddd; padding: 12px; }");
            client.println("tr:hover { background-color: #0088FF; }");
            client.println("td { border: none; padding: 12px; }");
            if (humidity.relative_humidity < TargetHumidity - TargetTolerance) {
              client.println(".sensor { color:black; font-weight: bold; background-color: #CC3333; padding: 1px; }");

            }
            else if (humidity.relative_humidity > TargetHumidity + TargetTolerance) {
              client.println(".sensor { color:black; font-weight: bold; background-color: #CC3333; padding: 1px; }");

            }
            else {
              client.println(".sensor { color:black; font-weight: bold; background-color: #FFFFFF; padding: 1px; }");
            }

            // Web Page Heading
            client.println("</style></head><body><h1>");
            client.println(HumidorName);
            client.println("</h1>");
            client.println("<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>");
            client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
            client.println(temp.temperature);
            client.println(" *C</span></td></tr>"); 
            client.println("<tr><td>Temp. Fahrenheit</td><td><span class=\"sensor\">");
            client.println(1.8 * temp.temperature + 32);
            client.println(" *F</span></td></tr>");       
            client.println("<tr><td>Humidity</td><td><span class=\"sensor\">");
            client.println(humidity.relative_humidity);
            client.println(" %</span></td></tr>");
            client.println("<tr><td>Target Humidity</td><td><span class=\"sensor\">");
            client.println(TargetHumidity);
            client.println(" %</span></td></tr>");
            client.println("<tr><td>Humidity Tolerance</td><td><span class=\"sensor\">");
            client.println(TargetTolerance);
            client.println(" %</span></td></tr>");
            client.println("</body></html>");
           
            // The HTTP response ends with another blank line
            client.println();
           

            // Break out of the while loop
            Serial.println("3");
            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
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

void synchroniseWith_NTP_Time() {
  Serial.print("configTime uses ntpServer ");
  Serial.println(ntpServer);
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.print("synchronising time");

  while (myTimeInfo.tm_year + 1900 < 2000 ) {
    time(&now);                       // read the current time
    localtime_r(&now, &myTimeInfo);
    delay(100);
    Serial.print(".");
  }
  Serial.print("\n time synchronsized \n");
  showTime();
}

String getTimeString() {
  unsigned long currentTime = millis();  // Get the current time in milliseconds
  int seconds = (currentTime / 1000) % 60;
  int minutes = (currentTime / 60000) % 60;
  int hours = (currentTime / 3600000) % 24;

  // Create a formatted time string
  String timeStr = String(hours) + ":" + (minutes < 10 ? "0" : "") + String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds);
  return timeStr;
}

void showTime() {
  time(&now);                       // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time
  Serial.print("year:");
  Serial.print(myTimeInfo.tm_year + 1900);  // years since 1900
  Serial.print("\tmonth:");
  Serial.print(myTimeInfo.tm_mon + 1);      // January = 0 (!)
  Serial.print("\tday:");
  Serial.print(myTimeInfo.tm_mday);         // day of month
  Serial.print("\thour:");
  Serial.print(myTimeInfo.tm_hour);         // hours since midnight  0-23
  Serial.print("\tmin:");
  Serial.print(myTimeInfo.tm_min);          // minutes after the hour  0-59
  Serial.print("\tsec:");
  Serial.print(myTimeInfo.tm_sec);          // seconds after the minute  0-61*
  Serial.print("\twday");
  Serial.print(myTimeInfo.tm_wday);         // days since Sunday 0-6
  if (myTimeInfo.tm_isdst == 1)             // Daylight Saving Time flag
    Serial.print("\tDST");
  else
    Serial.print("\tstandard");

  Serial.println();
}

void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) ); 
}

void setupEmailConfig() {
  // Enable the debug via Serial port
  //   0 for no debugging
  //   1 for basic level debugging
  //   Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h 
  smtp.debug(1);

  // Set the config
  config.server.host_name  = SMTP_HOST;
  config.server.port       = SMTP_PORT;
  config.login.email       = AUTHOR_EMAIL;
  config.login.password    = AUTHOR_PASSWORD;
  config.login.user_domain = "";

  message.addRecipient(F("Me-myself-and-I"), RECIPIENT_EMAIL);
}

void sendEmail() {
  sensors_event_t humidity, temp;
  sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  // Set the message headers

  String StyleBody = "";
  String MessageSubject = "Humidor Control System of " + HumidorName + " just started.";

if (AlarmState == 0) {
  MessageSubject = "Humidor Control System of " + HumidorName + " just started.";
  StyleBody = "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }th { padding: 12px; background-color: #0043af; color: white; }tr { border: 1px solid #ddd; padding: 12px; }tr:hover { background-color: #0088FF; }td { border: none; padding: 12px; }.sensor { color:black; font-weight: bold; background-color: #FFFFFF; padding: 1px; }";
            }

  else if (AlarmState == 1) {
      MessageSubject = HumidorName + " went back to normal conditions.";
      StyleBody = "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }th { padding: 12px; background-color: #0043af; color: white; }tr { border: 1px solid #ddd; padding: 12px; }tr:hover { background-color: #0088FF; }td { border: none; padding: 12px; }.sensor { color:black; font-weight: bold; background-color: #FFFFFF; padding: 1px; }";
            }

  else if (AlarmState == 2) {
      MessageSubject = "WARNING: " + HumidorName + " has too low humidity!";
      StyleBody = "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }th { padding: 12px; background-color: #0043af; color: white; }tr { border: 1px solid #ddd; padding: 12px; }tr:hover { background-color: #0088FF; }td { border: none; padding: 12px; }.sensor { color:black; font-weight: bold; background-color: #CC3333; padding: 1px; }";
            }

  else if (AlarmState == 3) {
      MessageSubject = "WARNING: " + HumidorName + " has too high humidity!";
      StyleBody = "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }th { padding: 12px; background-color: #0043af; color: white; }tr { border: 1px solid #ddd; padding: 12px; }tr:hover { background-color: #0088FF; }td { border: none; padding: 12px; }.sensor { color:black; font-weight: bold; background-color: #CC3333; padding: 1px; }";
            }

  else {
      MessageSubject = "Unknown Mail Reason " + String(AlarmState);
      StyleBody = "<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }th { padding: 12px; background-color: #0043af; color: white; }tr { border: 1px solid #ddd; padding: 12px; }tr:hover { background-color: #0088FF; }td { border: none; padding: 12px; }.sensor { color:black; font-weight: bold; background-color: #FFFFFF; padding: 1px; }";
            }           

  message.sender.name = HumidorName;
  message.sender.email = AUTHOR_EMAIL;
  //Send HTML message
  message.subject = MessageSubject;
  String Mail1 = "</style></head><body><h1>" + HumidorName + "</h1><table><tr><th>MEASUREMENT</th><th>VALUE</th></tr><tr><td>Temp. Celsius</td><td><span class=\"sensor\">" + temp.temperature + " *C</span></td></tr><tr><td>Temp. Fahrenheit</td><td><span class=\"sensor\">" + 1.8 * temp.temperature + 32 + " *F</span></td></tr><tr><td>Humidity</td><td><span class=\"sensor\">" + humidity.relative_humidity;
  String Mail2 = " %</span></td></tr><tr><td>Target Humidity</td><td><span class=\"sensor\">" + String(TargetHumidity) + " %</span></td></tr><tr><td>Humidity Tolerance</td><td><span class=\"sensor\">" + String(TargetTolerance) + " %</span></td></tr></body></html>";

  String htmlMsg = StyleBody + Mail1 + Mail2;
  message.html.content = htmlMsg.c_str();
  message.html.content = htmlMsg.c_str();
  message.text.charSet = "us-ascii";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_high;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

  // Connect to the server
  if (!smtp.connect(&config)) {
    ESP_MAIL_PRINTF("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
    return;
  }
  Serial.println("smtp.connect(&config) done");

  Serial.print("sending email to #");
  Serial.print(RECIPIENT_EMAIL);
  Serial.println("#");
  /* Start sending Email and close the session */
  if (!MailClient.sendMail(&smtp, &message)) {
    Serial.println("error MailClient.sendMail(&smtp, &message)");
    ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
  }
  Serial.print("sending email to #");
  Serial.print(RECIPIENT_EMAIL);
  Serial.println("# done");

  Serial.println("MailClient.sendMail(&smtp, &message) done");
}

Einen kleinen Fehler habe ich noch im Code:
Schaut man sich das Webinterface an und beendet den Browser, statt das Fenster zu schließen, denkt der ESP, dass die Websession noch offen ist, da der Browser sie nicht geschlossen hat, und der Code hängt für ca. eine Minute, bis der ESP die Session auf timeout setzt.

Grüße,
Felix
[+] 2 Mitglieder gefällt Crix1990's Beitrag
Zitieren


Nachrichten in diesem Thema
Das smarte DIY Hygrometer - von Crix1990 - 17.08.2024, 02:00
RE: Das smarte DIY Hydrometer - von CigarNerd - 17.08.2024, 08:00
RE: Das smarte DIY Hydrometer - von Crix1990 - 17.08.2024, 14:38
RE: Das smarte DIY Hydrometer - von Bayuvare - 17.08.2024, 14:54
RE: Das smarte DIY Hydrometer - von Bayuvare - 17.08.2024, 11:37
RE: Das smarte DIY Hygrometer - von Crix1990 - 17.08.2024, 15:02

Möglicherweise verwandte Themen…
Thema Antworten Letzter Beitrag
  Govee Thermo-Hygrometer 0 09.06.2022, 22:41
Letzter Beitrag: digitaL
  hygrometer kalibrieren 14 11.11.2021, 13:12
Letzter Beitrag: Grossinquisitor
  Billig-Hygrometer - ein kleiner Erfahrungsbericht 1 08.04.2020, 09:38
Letzter Beitrag: Zerocool
  Empfehlung Hygrometer 21 17.12.2019, 21:44
Letzter Beitrag: Zerocool



Benutzerbereich Nachrichten