ESP8266 - MQTT Subscribe: Delay Problem

Hallo,
ich arbeite mich gerade in dem ESP8266 ein. Mit diesem kommuniziere ich über MQTT mit PubSubClient. Das Publisher/Subscriben klappt soweit auch ohne Probleme, allerdings habe ich ein Problem mit der Verarbeitung.

Hier mal der Callback-Code:

void callback(char* topic, byte* payload, unsigned int length) {
    char message_buff[100];
    char* oeffnungen[4];
    int i;

    for (i = 0; i < length; i++) {
        message_buff[i] = payload[i];
    }
    
    message_buff[i] = '\0';
    
    
    // Aktionen
    // Position
    if (strcmp(topic, subcribeStatus) == 0) {
        
        i = 0;
        char* y = strtok(message_buff, "/");
        
        while (y != NULL) {
            oeffnungen[i++] = y;
            y = strtok (NULL, "/");
        }
        
        // schließen
        if (strcmp(oeffnungen[0], oeffnungen[1]) > 0) {
            digitalWrite(zu, LOW);
            delay(20000);
            digitalWrite(zu, HIGH);
            client.publish(topicPosition, position);
        }
    }
}

Ich möchte gerne, dass sich bei einem Topic der GPIO ausschaltet und verzögert (ca. 25 sec) wieder einschaltet. Das Ausschalten klappt soweit ohne Probleme. Allerdings habe ich mit dem Delay Schwierigkeiten. Wenn ich das Delay auf <20 Sekunden programmiere, dann wird der Befehl normal ausgeführt. Bei >20 Sekunden wird der ESP8266 nach dem Delay neugestartet.

Warum ist das so?
Ich habe es auch schon mit Millisekunden probiert, allerdings mit dem gleichen Ergebnis.

Vielen Dank im voraus
arokh12

Welche Version der ESP-Software hast Du? Eigentlich sollte in delay der Aufruf von yield drin sein. Ansonsten baue eine ganz normale Zeitsteuerung mit millis(). Schau Dir dazu BlinkWithoutDelay an und [u]verstehe[/u] es.

Gruß Tommy

Hallo,

ich habe den PubSubClient zwar auch mal auf dem ESP8266 benutzt, aber ich würde generell keine solchen Wartezeiten in irgendein CallBack packen. Da wird nur ein Flag gesetzt und das Warten und das Schalten sowie der publish im Loop erledigt und dort mit millis() oder auf dem ESP8266 meist mit Ticker erledigt.

Gruß aus Berlin
Michael

Tommy56:
Welche Version der ESP-Software hast Du? Eigentlich sollte in delay der Aufruf von yield drin sein.
Ansonsten baue eine ganz normale Zeitsteuerung mit millis(). Schau Dir dazu BlinkWithoutDelay an und verstehe es.

Gruß Tommy

Danke erstmal für die Hilfe. Ich habe jetzt mal delay mit Hilfe von Millis umprogrammiert. Allerdings ist der Fehler genau der gleiche. Nachdem der Unterschied 25000 ist, startet der ESP sich neu.

void callback(char* topic, byte* payload, unsigned int length) {
    char message_buff[100];
    int i;

    for (i = 0; i < length; i++) {
        message_buff[i] = payload[i];
    }
    
    message_buff[i] = '\0';
    
    
    // Aktionen
    // Position
    if (strcmp(topic, subcribeStatus) == 0) {
        
        i = 0;
        char* y = strtok(message_buff, "/");
        
        while (y != NULL) {
            oeffnungen[i++] = y;
            y = strtok (NULL, "/");
        }
        
        fahrt = true;
        
        
        // schließen
        if (strcmp(oeffnungen[0], oeffnungen[1]) > 0) {
            unsigned long letzteMillis = millis();
            unsigned long jetztigeMillis = millis();
            
            while (true) {
                unsigned long jetztigeMillis = millis();
                yield();
                
                if (jetztigeMillis - letzteMillis >= 25000) {
                    letzteMillis = jetztigeMillis;
                    digitalWrite(zu, HIGH);
                    client.publish(topicPosition, "0");
                    break;
                }
            }
        }
    }
}

Als ESP Version hatte ich als erstes 2.4.2 und bin jetzt zu 2.5.0 Beta gewechselt → ist aber immer noch da das Problem.

amithlon:
Hallo,

ich habe den PubSubClient zwar auch mal auf dem ESP8266 benutzt, aber ich würde generell keine solchen Wartezeiten in irgendein CallBack packen. Da wird nur ein Flag gesetzt und das Warten und das Schalten sowie der publish im Loop erledigt und dort mit millis() oder auf dem ESP8266 meist mit Ticker erledigt.

Gruß aus Berlin
Michael

Leider kam ich erst heute dazu meinen Code umzubauen. Ich habe es jetzt so:

Callback:

void callback(char* topic, byte* payload, unsigned int length) {
    char message_buff[100];
    int i;
    for (i = 0; i < length; i++) {
        message_buff[i] = payload[i];
    }
    
    message_buff[i] = '\0';
    
    
    // Aktionen
    // Position
    if (strcmp(topic, subcribeStatus) == 0) {
        char* y = strtok(message_buff, "/");
        while (y != NULL) {
            oeffnungen[i++] = y;
            y = strtok (NULL, "/");
        }
        
        // schließen
        if (strcmp(oeffnungen[0], oeffnungen[1]) > 0) {
            bewegungZu = true;
            zuLetzteMillis = millis();
            digitalWrite(zu, LOW);
        }
        
        // öffnen
        else if (strcmp(oeffnungen[0], oeffnungen[1]) < 0) {
            bewegungAuf = true;
            aufLetzteMillis = millis();
            digitalWrite(auf, LOW);
        }
    }
    
    // Reboot
    else if (strcmp(topic, subcribeReboot) == 0 && strcmp(message_buff, "reboot") == 0) {
        ESP.restart();
    }
}
void loop() {
    zuJetztigeMillis = millis();
    aufJetztigeMillis = millis();
    
    // Rollade bewegen
    if (bewegungZu == true) {
        if (zuJetztigeMillis - zuLetzteMillis >= 27000) {
            digitalWrite(zu, HIGH);
            client.publish(topicPosition, oeffnungen[1]);
            bewegungZu = false;
        }
    }
    
    else if (bewegungAuf == true) {
        if (aufJetztigeMillis - aufLetzteMillis >= 27000) {
            digitalWrite(auf, HIGH);
            client.publish(topicPosition, oeffnungen[1]);
            bewegungAuf = false;
        }
    }
}

Der Fehler ist leider gleich geblieben und hat sich nicht geändert. Wo kann der Fehler noch liegen?

Gruß,
arokh12

amithlon:
Hallo,

ich habe den PubSubClient zwar auch mal auf dem ESP8266 benutzt, aber ich würde generell keine solchen Wartezeiten in irgendein CallBack packen. Da wird nur ein Flag gesetzt und das Warten und das Schalten sowie der publish im Loop erledigt und dort mit millis() oder auf dem ESP8266 meist mit Ticker erledigt.

Gruß aus Berlin
Michael

Hallo,
das mit dem Ticker klappt jetzt super. Der Code sieht jetzt folgendermassen aus:

char* oeffnungen[3];
void callback(char* topic, byte* payload, unsigned int length) {
  char message_buff[100];
  int i;
  
  for (i = 0; i < length; i++) {
    message_buff[i] = payload[i];
  }

  message_buff[i] = '\0';
  i = 0;
  
  // Aktionen
  // Position
  if (strcmp(topic, subcribePosition) == 0) {
    char* y = strtok(message_buff, "/");
    while (y != NULL) {
      oeffnungen[i++] = y;
      y = strtok (NULL, "/");
    }

    // schließen
    if (strcmp(oeffnungen[0], oeffnungen[1]) > 0) {
      digitalWrite(zu, LOW);
      positionZu = true;
      flipper.attach(20, position);
    }
    
    // öffnen
    else if (strcmp(oeffnungen[0], oeffnungen[1]) < 0) {
      digitalWrite(auf, LOW);
      positionAuf = true;
      flipper.attach(20, position);
    }
  }
  
  // Reboot
  else if (strcmp(topic, subcribeReboot) == 0 && strcmp(message_buff, "reboot") == 0) {
    ESP.restart();
  }
}


void position() {
  if (positionZu == true) {
    digitalWrite(zu, HIGH);
    client.publish(topicPosition, (const char*)oeffnungen[1]);
    positionZu = false;
  }
  else if (positionAuf == true) {
    digitalWrite(auf, HIGH);
    client.publish(topicPosition, (const char*)oeffnungen[1]);
    positionAuf = false;
  }

  flipper.detach();
}

Allerdings klappt das publishen nicht wirklich. Er published zwar was, allerdings hat es keinen Inhalt. Wie kann ich das beheben? Wenn ich direkt aus dem callback Publishe, macht er es ohne Probleme.

Mit freundlichen Grüßen
arokh12