Interrupt-Nachhilfe für Wemos D1 Mini gesucht

Hallo liebes Forum,

ich stehe gerade auf der Leitung, vielleicht kann mich jemand von euch runter schupsen?

Ich versuche über einen Wemos D1 Mini eine Steckdose mit einem Timer zu bauen die über das Internet oder alternativ über einen Taster eingeschaltet werden kann. Dazu verwende ich einen Wemos D1 mini, ein TM1637 Display um die verbleibende Laufzeit anzuzeigen und ein Relais-Shield.
Da ich mich mit der Programmierung nicht ganz so gut auskenne nutze ich als Grundlage den Beispiel-Skeetch zum WebServer aus dem ESP Sammelsurium und passe ihn entsprechend an.

Der Skeetch fragt ständig den Client ab, ob die Webseite aufgerufen wurde und ändert darauf hin den Ausgabe-Pin und startet den Timer. Wenn die Zeit abgelaufen ist geht die Steckdose aus und es wird wieder die Webseite abgefragt.

Jetzt suche ich eine Möglichkeit, um den Taster an der Steckdose priorisiert abzufragen. D.h. der Timer soll gestartet werden sobald der Taster gedrückt wird. Mein Versuch ist nun, dies über einen Interrupt umzusetzen. Leider klappt das nicht zufriedenstellend. Wenn ich als Bedingung zum auslösen des Interruptes CHANGE wähle, wird er auch mal zufällig ausgelöst, wähle ich HIGH oder LOW klappt es irgendwie gar nicht. Und wenn der Interrupt einmal ausgelöst wurde und die Timer-Funktion für den Interrupt läuft bleibt diese nach einer kurzen Zeit einfach stehen und spuckt im Seriellen Monitor folgendes aus:

14:15:16.176 -> ets Jan 8 2013,rst cause:4, boot mode:(1,6)
14:15:16.176 ->
14:15:16.176 -> wdt reset

/*
    This sketch demonstrates how to set up a simple HTTP-like server.
    The server will set a GPIO pin depending on the request
      http://server_ip/gpio/0 will set the GPIO2 low,
      http://server_ip/gpio/1 will set the GPIO2 high
    server_ip is the IP address of the ESP8266 module, will be
    printed to Serial when the module is connected.
*/

#include <ESP8266WiFi.h>
#include <Arduino.h>
#include <TM1637Display.h>

// Display connection pins (Digital Pins)
#define CLK D2
#define DIO D3

// Relais pin (Digital Pins)
#define relais D7

TM1637Display display(CLK, DIO);

const char* ssid = "SSID";
const char* password = "PASSWORT";

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);

  // prepare GPIO2
  pinMode(relais, OUTPUT);
  digitalWrite(relais, 1);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());

  // Display ausschalten
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  display.setBrightness(7, false);
  display.setSegments(data);


  attachInterrupt(D1, TimerAnInt, HIGH);
}

void TimerAn()
{
  Serial.println("Starte Timer");
  int test = 0;
  int timer = 0;
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  display.setBrightness(0x0f);
  for (test = 360; test > 0; test--) {
    display.showNumberDec(test, false);
    for (timer = 0; timer <= 60; timer++) {
      delay(1);
    }
  }
  //Relais aus
  digitalWrite(relais, 1);

  // Display ausschalten
  display.setBrightness(7, false);
  display.setSegments(data);
}

void TimerAnInt()
{
  Serial.println("Starte Timer Interrupt");
  delay(10);
  volatile int test = 0;
  volatile int timer = 0;
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  digitalWrite(relais, 0);
  display.setBrightness(0x0f);
  for (test = 360; test > 0; test--) {
    display.showNumberDec(test, false);
    for (timer = 0; timer <= 60; timer++) {
      delay(1);
    }
  }
  //Relais aus
  digitalWrite(relais, 1);

  // Display ausschalten
  display.setBrightness(7, false);
  display.setSegments(data);
}

void loop() {

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }

  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  // Match the request
  int val;
  if (req.indexOf("/gpio/0") != -1) {
    val = 1;
    // Set GPIO2 according to the request
    digitalWrite(relais, val);
  } else if (req.indexOf("/gpio/1") != -1) {
    val = 0;
    // Set GPIO2 according to the request
    digitalWrite(relais, val);
    TimerAn();
  } else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nAutomat ist jetzt ";
  s += (val) ? "aus" : "an";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

Ich wäre dankbar für einen Tip, was ich beim Interrupt falsch machen. Alternativ würde ich mich auch über einen Tip freuen, wie man das Problem auch anders oder einfacher lösen könnte.

Viele Grüße
Michel

Es gibt für den ESP8266 komfortablere Webserver. Da setzt Du dann eine Stausveriable, ob eingeschaltet werden soll.

Außerdem ist ein Interrupt für eine Tastenbetätigung in 99% der Fälle unnötig.
Du kannst doch ganz normal im loop() Deinen Taster einlesen.

Wenn Du beide Infos hast, entscheidest Du, wie Du schalten musst.
Kannst Su uns mal ein Bild von der Unterseite des Relais-Shields zeigen, ob das überhaupt für 230V geeignet ist? Du verfügst über genügend Kenntnisse in der Elektrotechnik für 230V?

Gruß Tommy

Danke für die flotte Antwort. Den anderen Webserver probiere ich gleich mal aus, komfortabel braucht es aber eigentlich nicht sein.

Das Problem bei der normalen Abfrage im loop ist, dass der kurze Tastendruck eventuell "übersehen" wird, oder? Wenn das Programm zum Beispiel mit dem WLAN beschäftigt ist kann der Timer nicht mehr vor Ort ausgelöst werden?

Danke für deine Sorge über meine Elektrokenntnisse, die ist aber unbegründet. Nur beim tippen des Codes tue ich mich etwas schwer. :wink:

Grüße
Michel

Der ist nicht nur komfortabler, sondern dürfte auch weniger Zeit mit Abfragen des Clients brauchen.
Du musst ja keine Romane hin und her schicken.
Dein Loop sollte wesentlich schneller sein, als Dein Finger auf dem Taster.

Gruß Tommy