/* Name: Cores_Seperation.ino Created: 3/1/2024 12:12:09 PM Author: oskar */ #include #include #include #include #include #include "esp_task_wdt.h" const char* apSSID = "Fenstersteuerung-Setup"; const char* apPassword = "123456789"; // Kann leer sein für einen offenen AP bool isAPMode = false; // Flag, um zu überprüfen, ob wir im AP-Modus sind bool apmode = false; // Netzwerkeinstellungen const char* ssid = "B535_5AC8"; const char* password = "35LH494nbAm"; /* const char* ssid = "B535_5AC8_EXT"; const char* password = "35LH494nbAm"; */ /* const char* ssid = "12543"; const char* password = "Jesus123"; */ // Webserver auf Port 80 AsyncWebServer server(80); unsigned long connectStartTime = 0; // Time when connection attempt started unsigned long apModeStartTime = 0; // Time when AP mode started const unsigned long apModeTimeout = 180000; // 3 minutes in milliseconds //bool ledcInitialized = false; //const int ledPin = 4; // Der GPIO-Pin, an dem Ihre LED angeschlossen ist //const int ledChannel = 2; // PWM-Kanal (0-15). //int ledBrightness = 0; // Globale Variable zur Speicherung der LED-Helligkeit (0-255) //Kann weg //unsigned long automatikModeChangedTime = 0; // Zeitpunkt der letzten Änderung des Automatikmodus unsigned long startTime; // Motorsteuerungspins const int ERROR_FLAG_PIN = 18; const int forwardPin = 5; const int reversePin = 17; const int pwmChannelForward = 0; const int pwmChannelReverse = 1; const int pwmFreq = 10; const int pwmResolution = 8; // ADC-Pin Halleffekt const int ADC_PIN_1 = 32; //Halleffekt float testmess = 0; // Widerstand und Referenzspannung für Strommessung const float V_REF = 3.3; const int ADC_RESOLUTION = 4096; const float MAX_mA = 500; //380 worked 22_03 but stopped //550 // Taster und Infrarotempfänger-Pins const int ButtonOeffnen = 26; const int ButtonSchliessen = 25; const int RECV_PIN = 27; const int MIC_ADC_PIN = 33; const int AUTOMATIC_MODE_BUTTON = 13; // Deklaration const int AUTOMATIC_MODE_LED = 14; // GPIO-Pin für Automatik-LED // Schwellenwerte und Zeitkonstanten float HIGH_NOISE_THRESHOLD = 2.5; float LOWER_NOISE_THRESHOLD = 2.3; const unsigned long LONG_PRESS_DURATION = 2000; unsigned long MOTOR_RUN_DURATION = 1700; const unsigned long INRUSH_DELAY = 500; unsigned long LOW_NOISE_DURATION = 10000; unsigned long openingTimer = ULONG_MAX; // Zeitmarken für die Taster-Logik bool button1Pressed = false; unsigned long button1PressTime = 0; bool button2Pressed = false; unsigned long button2PressTime = 0; unsigned long CLOSE_TIME = ULONG_MAX; //VLLT Max wert vllt 0V // Zustände und Modi enum MotorState { FORWARD, REVERSE }; enum MotorState2 { OPEN, CLOSED }; MotorState currentMotorState; MotorState2 currentMotorState2 = OPEN; bool automaticModeEnabled = false; IRrecv irrecv(RECV_PIN); decode_results results; unsigned long lastButtonPress = 0; unsigned long motorStartTime = 999999; unsigned long last_LOW_NoiseTime = 99999; unsigned long halbeZeitZurMitte = 0; // Globale Variable unsigned long ledTimer = 0; // Timer für die LED //Timer high low schalten //Sleep und im sleep Hat weboberfläche priorität //Webinterface auf niedrigerer Priorität const char index_html[] PROGMEM = R"rawliteral( ESP32 Control

ESP32 Fenstersteuerung

Fensterstatus: Unbekannt
Automatikmodus: Unbekannt
Motor Fehler: Keiner
)rawliteral"; const char ap_mode_html[] PROGMEM = R"rawliteral( ESP32 WiFi Setup

ESP32 WiFi Configuration






Waiting for connection...
)rawliteral"; void startAPMode() { isAPMode = true; Serial.println("Starting AP Mode"); WiFi.softAP(apSSID, apPassword); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(200, "text/html", ap_mode_html); }); server.on("/setup", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasParam("ssid") && request->hasParam("password")) { String ssid = request->getParam("ssid")->value(); String password = request->getParam("password")->value(); Serial.println("Received WiFi credentials"); Serial.print("SSID: "); Serial.println(ssid); Serial.print("Password: "); Serial.println(password); WiFi.disconnect(); // Disconnect existing connections WiFi.mode(WIFI_AP_STA); // Switch to AP-STA mode WiFi.begin(ssid.c_str(), password.c_str()); // Wait for connection startTime = millis(); while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) { delay(500); Serial.print("."); } if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected to WiFi"); isAPMode = false; // Exit AP mode //apmode = true; //WiFi.softAPdisconnect(true); // Disable AP startTime = millis(); IPAddress wifiIP = WiFi.localIP(); String response = "Connection successful! IP Address for control page: " + wifiIP.toString(); request->send(200, "text/html", response); apModeStartTime = 0; // Reset AP mode start time } else { request->send(200, "text/html", "Connection failed! Back"); } } else { request->send(200, "text/html", "Missing data! Back"); } }); server.begin(); apModeStartTime = millis(); // Record the time when AP mode started } float messStrom() { const int numReadings = 25; // Anzahl der Messungen float totalVoltage = 0; // Summe der gemessenen Spannungen int raw_adc = 0; // Lese mehrere Werte und berechne die Summe for (int i = 0; i < numReadings; i++) { raw_adc = analogRead(ADC_PIN_1); totalVoltage += raw_adc * (V_REF / ADC_RESOLUTION); delay(5); // Kleine Verzögerung zwischen den Messungen } // Berechne den Durchschnitt der Spannung float averageVoltage = totalVoltage / numReadings; float currentAmps = (averageVoltage) / 0.8; // Umrechnung in Ampere, Annahme eines Offset von 0.25V // Wenn der Strom negativ ist, setze ihn auf 0 if (currentAmps < 0) { currentAmps = 0; } // Rückgabe des Stroms in Milliampere return currentAmps * 1000; // Umwandlung in Milliampere } void findeMittelpunkt() { Serial.println("Finde Mittelpunkt gestartet"); reverse(); delay(INRUSH_DELAY); // Warte auf Einschaltstrom while (messStrom() <= 500) { // Warte, bis der Anschlag erreicht ist delay(100); // Kurze Verzögerung für regelmäßige Überprüfung } stopMotor(); Serial.println("Anschlag 1 erreicht"); forward(); unsigned long startZeit = millis(); delay(INRUSH_DELAY); // Warte auf Einschaltstrom while (messStrom() <= 500) { // Warte, bis der Anschlag erreicht ist delay(100); // Kurze Verzögerung für regelmäßige Überprüfung } unsigned long gesamtZeit = millis() - startZeit; stopMotor(); Serial.println("Anschlag 2 erreicht"); halbeZeitZurMitte = gesamtZeit / 2; reverse(); delay(halbeZeitZurMitte); stopMotor(); CLOSE_TIME = millis(); Serial.println("Mittelpunkt erreicht"); currentMotorState2 = OPEN; MOTOR_RUN_DURATION = halbeZeitZurMitte - 140; } bool istAnschlagErreicht() { // Lies Stromstärke und überprüfe, ob ein Anschlag erreicht wurde float gemessenerStrom = messStrom(); Serial.print("Strom: "); Serial.println(gemessenerStrom); return gemessenerStrom > 500; } // Motorvorwärtsfunktion void forward() { // if (!ledcInitialized) return; // Frühzeitiger Abbruch, wenn LEDC nicht initialisiert ist if (currentMotorState != FORWARD) { currentMotorState = FORWARD; motorStartTime = millis(); ledcWrite(pwmChannelReverse, 255); delay(10); ledcWrite(pwmChannelForward, 0); Serial.println("Motor laeuft vorwaerts bei halber Geschwindigkeit"); } } // Motorrückwärtsfunktion void reverse() { // if (!ledcInitialized) return; // Frühzeitiger Abbruch, wenn LEDC nicht initialisiert ist if (currentMotorState != REVERSE) { currentMotorState = REVERSE; motorStartTime = millis(); ledcWrite(pwmChannelForward, 255); delay(10); ledcWrite(pwmChannelReverse, 0); Serial.println("Motor laeuft rueckwaerts bei halber Geschwindigkeit"); } } // Motorstoppfunktion void stopMotor() { ledcWrite(pwmChannelForward, 0); ledcWrite(pwmChannelReverse, 0); Serial.println("Motor gestoppt"); } void checkMotorError() { if (digitalRead(ERROR_FLAG_PIN) == LOW) { // Geht davon aus, dass der ErrorFlag LOW signalisiert, wenn ein Fehler vorliegt Serial.println("Motor Error Detected!"); stopMotor(); // weitere Maßnahmen? } } void handleButtons() { if (digitalRead(AUTOMATIC_MODE_BUTTON) == LOW) { automaticModeEnabled = !automaticModeEnabled; digitalWrite(AUTOMATIC_MODE_LED, automaticModeEnabled ? HIGH : LOW); ledTimer = millis(); delay(INRUSH_DELAY); Serial.print("Automatischer Modus: "); Serial.println(automaticModeEnabled ? "Aktiviert" : "Deaktiviert"); } if (millis() - ledTimer > 4000 && digitalRead(AUTOMATIC_MODE_LED) == HIGH) { digitalWrite(AUTOMATIC_MODE_LED, LOW); } int button1State = digitalRead(ButtonOeffnen); //Serial.println(button1State); // Serial.println("Button 1lesen"); // Button 1 Logik if (button1State == LOW && !button1Pressed) { button1Pressed = true; button1PressTime = millis(); if (currentMotorState2 != OPEN) { forward(); // Startet den Motor sofort in die eine Richtung, wenn Fenster nicht bereits offen Serial.println("Button 1 - Oeffnen gestartet"); } else { Serial.println("Fenster ist bereits offen."); } } else if (button1State == HIGH && button1Pressed) { button1Pressed = false; if (millis() - button1PressTime > 2000) { stopMotor(); // Stoppt den Motor, wenn Button 1 länger als 2 Sekunden gedrückt wurde currentMotorState2 = OPEN; } else { oeffnenZurMitte(); // Führe eine spezifische Aktion aus, wenn es ein kurzer Druck war } } int button2State = digitalRead(ButtonSchliessen); // Button 2 Logik //Serial.println(button2State); // Serial.println("Button 2lesen"); if (button2State == LOW && !button2Pressed) { button2Pressed = true; button2PressTime = millis(); if (currentMotorState2 != CLOSED) { reverse(); // Startet den Motor sofort in die andere Richtung, wenn Fenster nicht bereits geschlossen Serial.println("Button 2 - Schliessen gestartet"); } else { Serial.println("Fenster ist bereits geschlossen."); } } else if (button2State == HIGH && button2Pressed) { button2Pressed = false; if (millis() - button2PressTime > 2000) { stopMotor(); // Stoppt den Motor, wenn Button 2 länger als 2 Sekunden gedrückt wurde currentMotorState2 = OPEN; } else { schliessenVonMitte(); // Führe eine spezifische Aktion aus, wenn es ein kurzer Druck war } } } void handleIR() { if (irrecv.decode(&results)) { if (millis() - lastButtonPress > 500) { switch (results.value) { case 0xFF6897: schliessenVonMitte(); motorStartTime = millis(); break; //1 case 0xFF9867: oeffnenZurMitte(); motorStartTime = millis(); break; //2 case 0xFFB04F: stopMotor(); break; case 0xFF02FD: //OK automaticModeEnabled = !automaticModeEnabled; // Umschalten des automatischen Modus digitalWrite(AUTOMATIC_MODE_LED, HIGH); // Schalte die LED ein ledTimer = millis(); // Starte den Timer für die LED delay(500); // Entprellung und kurze Pause, um mehrfache Triggerungen zu verhindern Serial.println("Automatischer Modus:"); Serial.println(automaticModeEnabled); break; case 0xFF42BD: reverse(); motorStartTime = millis(); break; //* case 0xFF52AD: forward(); motorStartTime = millis(); break; //# default: break; } lastButtonPress = millis(); } irrecv.resume(); } } void handleCurrent() { if (millis() - motorStartTime > INRUSH_DELAY) { testmess = messStrom(); if (testmess > MAX_mA) { Serial.println("TEST5"); Serial.println(testmess); stopMotor(); currentMotorState2 = CLOSED; } } } void handleSerial() { if (Serial.available() > 0) { String command = Serial.readStringUntil('\n'); command.trim(); if (command == "f") { forward(); } else if (command == "r") { reverse(); } else if (command == "s") { Serial.println("TEST6"); stopMotor(); } else if (command == "m") { Serial.println(currentMotorState); Serial.println(currentMotorState2); //stopMotor(); } } } void handleNoiseControl() { float micADC = analogRead(MIC_ADC_PIN); float micVoltage = micADC * (V_REF / ADC_RESOLUTION); if (micVoltage > LOWER_NOISE_THRESHOLD) { Serial.println("LOW Noise detected"); last_LOW_NoiseTime = millis(); delay(100); } if (automaticModeEnabled) { // float micADC = analogRead(MIC_ADC_PIN); //float micVoltage = micADC * (V_REF / ADC_RESOLUTION); if (micVoltage > HIGH_NOISE_THRESHOLD && currentMotorState2 == OPEN && (millis() - CLOSE_TIME) > LOW_NOISE_DURATION) { schliessenVonMitte(); currentMotorState2 = CLOSED; } else if (micVoltage < LOWER_NOISE_THRESHOLD && currentMotorState2 == CLOSED && (millis() - last_LOW_NoiseTime) > LOW_NOISE_DURATION) { CLOSE_TIME = millis(); oeffnenZurMitte(); currentMotorState2 = OPEN; } } /*if (millis() >= motorRunOffTime3 || millis() >= motorRunOffTime4) { Serial.println("TEST9"); stopMotor(); motorRunOffTime3 = ULONG_MAX; motorRunOffTime4 = ULONG_MAX; }*/ } void setupWiFiAndWebServer() { WiFi.begin(newssid, newpw); // Wait for connection, but with a reasonable timeout unsigned long startTime = millis(); unsigned long timeout = 10000; // 10 seconds while ( WiFi.status() != WL_CONNECTED && millis() - startTime < timeout) { delay(500); Serial.print("."); } if (WiFi.status() == WL_CONNECTED&&apmode==false) { apmode = true; Serial.println("Connected to the WiFi network"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // Define routes server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(200, "text/html; charset=UTF-8", index_html); }); server.on("/low_noise_duration", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasParam("value")) { LOW_NOISE_DURATION = (request->getParam("value")->value().toFloat() * 60 * 1000); Serial.println("LOW_NOISE_DURATION: " + String(LOW_NOISE_DURATION)); } request->send(200, "text/plain", "OK"); }); server.on("/high_noise_threshold", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasParam("value")) { HIGH_NOISE_THRESHOLD = ((request->getParam("value")->value().toFloat() / 100) * 1.3) + 2; Serial.println("HIGH_NOISE_THRESHOLD: " + String(HIGH_NOISE_THRESHOLD)); } request->send(200, "text/plain", "OK"); }); server.on("/lower_noise_threshold", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasParam("value")) { LOWER_NOISE_THRESHOLD = ((request->getParam("value")->value().toFloat() / 100) * 1.3) + 2; Serial.println("LOWER_NOISE_THRESHOLD: " + String(LOWER_NOISE_THRESHOLD)); } request->send(200, "text/plain", "OK"); }); server.on("/oeffnen", HTTP_GET, [](AsyncWebServerRequest* request) { Serial.println("Oeffnen gestartet"); oeffnenZurMitte(); // Rufe die Funktion auf, um zur Mitte zu öffnen Serial.println("Oeffnen fertig"); request->send(200, "text/plain", "Öffnung zur Mitte gestartet"); }); server.on("/schliessen", HTTP_GET, [](AsyncWebServerRequest* request) { Serial.println("schliessen gestartet"); schliessenVonMitte(); // Rufe die Funktion auf, um von der Mitte zu schließen Serial.println("schliessen fertig"); request->send(200, "text/plain", "Schließung von der Mitte gestartet"); }); server.on("/stop", HTTP_GET, [](AsyncWebServerRequest* request) { stopMotor(); // Motorstoppfunktion aufrufen request->send(200, "text/plain", "Motor gestoppt"); }); server.on("/toggleAutomaticMode", HTTP_GET, [](AsyncWebServerRequest* request) { Serial.println("Automatikmodus umgeschaltet über Webserver"); automaticModeEnabled = !automaticModeEnabled; ledTimer = millis(); // Aktualisiere den Zeitpunkt der letzten Änderung digitalWrite(AUTOMATIC_MODE_LED, HIGH); // LED einschalten request->send(200, "text/plain", automaticModeEnabled ? "Automatikmodus aktiviert" : "Automatikmodus deaktiviert"); }); server.on("/status", HTTP_GET, [](AsyncWebServerRequest* request) { String statusJson = "{"; statusJson += "\"fenster\": \"" + String(currentMotorState2 == OPEN ? "Offen" : "Geschlossen") + "\","; statusJson += "\"automatik\": \"" + String(automaticModeEnabled ? "Aktiviert" : "Deaktiviert") + "\","; statusJson += "\"lowNoiseDuration\": " + String(LOW_NOISE_DURATION) + ","; statusJson += "\"highNoiseThreshold\": " + String(HIGH_NOISE_THRESHOLD) + ","; statusJson += "\"lowerNoiseThreshold\": " + String(LOWER_NOISE_THRESHOLD); statusJson += "}"; request->send(200, "application/json", statusJson); }); server.on("/setSetting", HTTP_GET, [](AsyncWebServerRequest* request) { if (request->hasParam("setting") && request->hasParam("value")) { String setting = request->getParam("setting")->value(); float value = request->getParam("value")->value().toFloat(); if (setting == "low_noise_duration") { LOW_NOISE_DURATION = value * 60 * 1000; // Konvertieren in Millisekunden Serial.println("LOW_NOISE_DURATION: " + String(LOW_NOISE_DURATION)); } else if (setting == "high_noise_threshold") { HIGH_NOISE_THRESHOLD = (value / 100) * 1.3 + 2; // Umrechnung von Prozent in Wert Serial.println("HIGH_NOISE_THRESHOLD: " + String(HIGH_NOISE_THRESHOLD)); } else if (setting == "lower_noise_threshold") { LOWER_NOISE_THRESHOLD = (value / 100) * 1.3 + 2; // Umrechnung von Prozent in Wert Serial.println("LOWER_NOISE_THRESHOLD: " + String(LOWER_NOISE_THRESHOLD)); } } request->send(200, "text/plain", "OK"); }); server.begin(); } } String processor(const String& var) { if (var == "LOW_NOISE_DURATION") { return String(LOW_NOISE_DURATION); } else if (var == "HIGH_NOISE_THRESHOLD") { return String(HIGH_NOISE_THRESHOLD); } else if (var == "LOWER_NOISE_THRESHOLD") { return String(LOWER_NOISE_THRESHOLD); } return String(); } void handleOeffnen() { if (openingTimer != ULONG_MAX && millis() - openingTimer > MOTOR_RUN_DURATION) { stopMotor(); // Stoppe den Motor currentMotorState2 = OPEN; // Aktualisiere den Zustand openingTimer = ULONG_MAX; // Setze den Timer zurück } } void oeffnenZurMitte() { if (currentMotorState2 != OPEN) { // Nur öffnen, wenn nicht bereits offen forward(); // Starte den Motor openingTimer = millis(); // Starte den Timer } } void schliessenVonMitte() { if (currentMotorState2 != CLOSED) { // Nur schließen, wenn nicht bereits geschlossen reverse(); // Starte den Motor vorwärts //delay(1000); delay(INRUSH_DELAY); currentMotorState2 = CLOSED; // Aktualisiere den Zustand Serial.println("Von Mitte geschlossen"); } } void handleAutomaticModeLED() { // Schaltet die LED aus, wenn 4 Sekunden oder mehr seit der letzten Änderung // vergangen sind, und die LED ist eingeschaltet. if (millis() - ledTimer >= 4000 && digitalRead(AUTOMATIC_MODE_LED) == HIGH) { digitalWrite(AUTOMATIC_MODE_LED, LOW); } } void WiFiConnectionTask(void* pvParameters) { for (;;) { if (WiFi.status() == WL_CONNECTED) { // Wenn bereits verbunden, Webserver einrichten setupWiFiAndWebServer(); // Set up the web server for normal operation } vTaskDelay(pdMS_TO_TICKS(1000)); // Check the status every second } /* if (isAPMode && millis() - apModeStartTime >= apModeTimeout) { // Close AP mode after 3 minutes Serial.println("Closing AP Mode due to timeout."); WiFi.mode(WIFI_OFF); isAPMode = false; delay(1000); // Short delay to reset everything ESP.restart(); // Restart to try connecting with the original data } if (isAPMode && millis() - apModeStartTime >= apModeTimeout) { WiFi.mode(WIFI_STA); // Wechsel zu STA-Modus, deaktiviert AP isAPMode = false; Serial.println("AP Mode closed due to timeout."); }*/ } void initializeComponents() { ledcSetup(pwmChannelForward, pwmFreq, pwmResolution); ledcSetup(pwmChannelReverse, pwmFreq, pwmResolution); ledcAttachPin(forwardPin, pwmChannelForward); ledcAttachPin(reversePin, pwmChannelReverse); pinMode(ERROR_FLAG_PIN, INPUT_PULLUP); pinMode(ADC_PIN_1, INPUT); pinMode(ButtonOeffnen, INPUT_PULLUP); pinMode(ButtonSchliessen, INPUT_PULLUP); pinMode(AUTOMATIC_MODE_BUTTON, INPUT_PULLUP); analogReadResolution(12); pinMode(AUTOMATIC_MODE_LED, OUTPUT); digitalWrite(AUTOMATIC_MODE_LED, LOW); irrecv.enableIRIn(); findeMittelpunkt(); } void ComponentsTask(void* pvParameters) { initializeComponents(); // Initialisiert Ihre Komponenten for (;;) { checkMotorError(); handleButtons(); handleIR(); handleCurrent(); handleSerial(); handleNoiseControl(); handleAutomaticModeLED(); handleOeffnen(); // Fügen Sie hier weitere Funktionen hinzu, die zyklisch aufgerufen werden sollen. vTaskDelay(pdMS_TO_TICKS(10)); // Kurze Verzögerung, um den Core nicht zu überlasten. } } void setup() { Serial.begin(115200); esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); // Task für den Webserver auf Core 0 starten startAPMode(); // Task für die Verwaltung der WLAN-Verbindung und des Web-Servers starten, auf Core 0 xTaskCreatePinnedToCore( WiFiConnectionTask, "WiFiConnectionTask", 10000, NULL, 1, NULL, 0); // Task für die anderen Komponenten auf Core 1 starten xTaskCreatePinnedToCore( ComponentsTask, "OtherComponents", 10000, NULL, 1, NULL, 1); } // the loop function runs over and over again until power down or reset void loop() { }