Problem mit ausführen von einem Timer

Hallo Zusammen,
ich habs schon in diversen anderen Foren probiert aber irgendwie kann mir keeiner helfen :slight_smile:

Dann bin ich auf dieses Forum gestossen und icch glaube hier kann mir geholfen werden!

Also ich mache meine ersten Schritte mit der Arduino IDE und einem D1mini und bin für meine Verhältnisse schon recht weit gekommen.

Ich erklär mal kurz was ich machen will:
Ich steuere mit einem D1mini MoodeAudio auf einem RPI über Buttons, das funktioniert!
Da das RPI und der Audioverstärker im Keller steht habe ich ein 433 Funkmodul installiert mit dem ich eine Funksteckdose steuern kann, damit mache icch das alles Stromlos, auch das funktioniert!
Jetzt hab ich aber das Problem das der mpd (player) auf dem RPI das nicht mag und sich nicht sauber beenden kann, darum brauch ich eine Variante wie ich das mit einem Soft Shutdown runterfahre und erst dann die Funksteckdose steuere.

Meine Idee war per Button ein Cmd über MQTT an das RPI zu senden (sudo poweroff), so kann das RPI sauber runterfahren, anschliessend soll das D1 ständig einen Ping auf die Adresse des PRI mmachen und sobald das nichtmehr antwortet soll das D1 die Funksteckdose dann ausschalten, somit ist alles Stromlos.

Leider bekomme ich die Funktion mit dem Ständig Pingen nicht hin, so wie ich das gebaut habe wird das nämlich nur einmal beim Buttonclick ausgeführt und dann läuft wieder der normale loop().

Kannn mir weiterhelfen wie ich diesen Timer bauen muss damit das funktioniert?

Hier mal der Teil aus dem Sketch vom Button Shutdown in loop() der mein Problem ist:

// Shutdown Button  
  bouncer_shutdown.update();
  if (bouncer_shutdown.rose()) {
    // Shutdown befehl senden
    if (client.publish(mqtt_topic, "shutdown")) {
      Serial.println("Send cmd für Soft Shutdown!");
    } else {
      Serial.println("Konnte nicht gesendet werden, Versuche es nochmal!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "shutdown");
    }  
      
    if(currentMillis - previousMillis > intervalPingForSwitchoff) {
     previousMillis = currentMillis; //wieder zurücksetzen

      //////////////////
      HTTPClient http;
      Serial.print("Waiting for Shutdown: ");
      http.begin(serverAdress);
      int httpCode = http.GET();
      if (httpCode > 0) {
        String answer = http.getString();
        Serial.print(answer);
        Serial.println(" > Server Online"); 
      } else {
        Serial.printf("Server now Offline > %s\n", http.errorToString(httpCode).c_str());
        Serial.println("Steckdose powerOffPlug ausführen!");
        powerOffPlug(); //Funktion zum Ausschalten der Funksteckdose aufrufen
      }
      http.end();
      ///////////////////// 
    }
  }

Ich hoffe jemand kann mir sagen wie und wo ich den Timer für den Ping auf den MoodAudio Server setzen muss damit der Nach dem Button Shutdown ausgeführt wird.

Danke euch!!

LG
TL

Hier combie timer solltest du das Richtige finden.

Danke dir für die schnelle Antwort, diesen Eintrag habe ich bereits bei meinen Recherchen geunden, aber leider reicht mein Verständnis nicht aus um das zu verwenden da ich den Unterschied nicht verstehe, es müsste doch auch mit meinem Weg möglich seine einen Timer zu verwenden.

Das Problem ist ja auch nicht der Timer selbst sondern die Art und weise wie/wo er eingebaut und aufgerufen werden muss damit er mit dem button zusammen funktioniert.

Hier der Großteil vom Sketch

#include <Bounce2.h> 
#include <ESP8266WiFi.h> 
#include <PubSubClient.h>
#include <ESP8266HTTPClient.h>

//Pin Settings
const int ledPin = D0; // LED wennn Pi Läuft
const int buttonPin_toggle = D6; // PIN für Play-Pause
const int buttonPin_volup = D2; //Pin für Lautstärke erhöhen
const int buttonPin_voldown = D5; // Pin für Lautstärke verringern
const int buttonPin_shutdown = D1; // Pin für ausschalten der Funcksteckdose

// WiFi Settings
const char* ssid = "xx";
const char* wifi_password = "xx";


// Check Onlinestatus from Server
const String serverAdress = "http://192.168.1.39/ping/ping_online_status.txt";


// MQTT Broker
const char* mqtt_server = "192.168.1.39";
const char* mqtt_topic = "/home/moode/terrasse/";
const char* clientID = "MoodeRemote";


// Buttons initailisieren
Bounce bouncer_toggle = Bounce();
Bounce bouncer_volup = Bounce();
Bounce bouncer_voldown = Bounce();
Bounce bouncer_shutdown = Bounce();

// Variable für den Interval zum Online Server Check
const long intervalCheckServerStatus = 30000;
const long intervalPingForSwitchoff = 1000;

//Timer bei Start auf 0 Stellen
unsigned long previousMillis = 0; 

// Wifi Initialisieren
WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, wifiClient); //1883




///////////////////////////////////////////////////////////////////////////////////////////////////
// SWITCH OFF WIFI PLUG (Neue Variante)
// Pi wir per Shudwon ausgeschalten, wenn nichtmehr erreichbar vom ESP dann soll 
// das CMD für die Funksteckdose gesendet werden
void powerOffPlug() {
  
Serial.println("Funksteckdose auschalten, Raspi Shutdown beendet, AMP Power OFF");
  HTTPClient http;
  // Variablen definieren 
  String vpg, vcom, vdevice, getData, Link;
  vpg = String("dosen");
  vcom ="0";
  vdevice="2";
  
  // GET Data - Querystring zusammenbauen
  getData = "?pg=" + vpg + "&com=" + vcom + "&device=" + vdevice ;  //querystring
  
  // Server Pfad
  Link = "http://192.168.1.34/home/index.php" + getData;
  Serial.println(Link); //Link prüfen
  
  // Request senden
  http.begin(Link); 
  int httpCode = http.GET();
  http.end();  //Close connection

}



// S E T U P
///////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  
  // PINS  definieren IN/OUT
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin_toggle, INPUT);
  pinMode(buttonPin_volup, INPUT);
  pinMode(buttonPin_voldown, INPUT);
  pinMode(buttonPin_shutdown, INPUT);

  // LED nach Start ein
  digitalWrite(ledPin, LOW);


  // Buttons Objekte erstellen
  bouncer_toggle.attach(buttonPin_toggle);
  bouncer_toggle.interval(5);
  bouncer_volup.attach(buttonPin_volup);
  bouncer_volup.interval(5);
  bouncer_voldown.attach(buttonPin_voldown);
  bouncer_voldown.interval(5);
  bouncer_shutdown.attach(buttonPin_shutdown);
  bouncer_shutdown.interval(5);

  // Baud Rate
  Serial.begin(115200);
  
  Serial.print("Connecting to ");
  Serial.println(ssid);


  // Verbinden mit WiFi
  WiFi.begin(ssid, wifi_password);


  // Verbindung herstellen, es geht erst weiter wenn Verbindung hergestellt
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  // Debugging - IP Anzeigen
  Serial.println("WiFi connected");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());


  // Verbinden mit dem MQTT Broker
  if (client.connect(clientID)) {
    Serial.println("Verbunden mit dem MQTT Broker!");
  } else {
    Serial.println("Keine Verbindung mit dem MQTT Broker hergestellt");
  }


  // Beim Booten Funksteckdose auf On schalten damit Raspi gestartet wird
  bootRaspi();


} // End Setup


// L O O P
///////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  
  // MoodAdio Server Status prüfen Online/Offline
  // millis() = Gibt Zeit seit Boot zurück
  // currentMillis = Zeit seit Boot
  // previousMillis = Aktuelle Zeit
  // Startzeit - Aktuelle Zeit > Intervall 
  // InvetrtalCheckServerStatus = Prüfintervall in Millisekundden
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > intervalCheckServerStatus) {
     previousMillis = currentMillis; //wieder zurücksetzen
     getStatusMoodeServer();     
  }

  
  // Toggle Play/Pause Button
  bouncer_toggle.update();
  if (bouncer_toggle.rose()) {
    // Sende über MQTT das cmd toggle
    if (client.publish(mqtt_topic, "toggle")) {
      Serial.println("Send cmd toggle");
    } else {
      Serial.println("cmd toggle konnte nicht gesendet werden, nochmal versuchen!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "toggle");
    }

}


  // Volumen UP Button
  bouncer_volup.update();
  if (bouncer_volup.rose()) {
    //digitalWrite(ledPin, LOW);
    // Sende über MQTT das cmd volup
    if (client.publish(mqtt_topic, "volup")) {
      Serial.println("Send cmd volup");
    } else {
      Serial.println("cmd volup konnte nicht gesendet werden, nochmal versuchen!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "volup");
    }
  }



  // Volumen DOWN Button  
  bouncer_voldown.update();
  if (bouncer_voldown.rose()) {
    //digitalWrite(ledPin, HIGH);
    // Sende über MQTT das cmd voldown
    if (client.publish(mqtt_topic, "voldown")) {
      Serial.println("Send cmd voldown");
    } else {
      Serial.println("cmd voldown konnte nicht gesendet werden, nochmal versuchen!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "voldown");
    }
  }



  // Shutdown Button  
  bouncer_shutdown.update();
  if (bouncer_shutdown.rose()) {
    // Shutdown befehl senden
    if (client.publish(mqtt_topic, "shutdown")) {
      Serial.println("Send cmd für Soft Shutdown!");
    } else {
      Serial.println("Konnte nicht gesendet werden, Versuche es nochmal!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "shutdown");
    }  
      
    if(currentMillis - previousMillis > intervalPingForSwitchoff) {
     previousMillis = currentMillis; //wieder zurücksetzen

      //////////////////
      HTTPClient http;
      Serial.print("Waiting for Shutdown: ");
      http.begin(serverAdress);
      int httpCode = http.GET();
      if (httpCode > 0) {
        String answer = http.getString();
        Serial.print(answer);
        Serial.println(" > Server Online"); 
      } else {
        Serial.printf("Server now Offline > %s\n", http.errorToString(httpCode).c_str());
        Serial.println("Steckdose powerOffPlug ausführen!");
        powerOffPlug(); //Funktion zum Ausschalten der Funksteckdose aufrufen
      }
      http.end();
      ///////////////////// 
    }
  }
  
} // End Loop()

Nimm doch einfach eine Variable doShutdown, gesetzt bei Meldung "shutdown", und teste sie gleich am Anfang von loop(), ob der Shutdown erfolgen soll. Falls ja pingen wie bisher im Shutdown Zweig, wenn fertig Variable wieder zurücksetzen. Ansonsten den Rest von loop() ausführen.

Danke Herr Dr. :slight_smile:

ich hab jetzt sofort versucht das umzusetzen, hab ich das richtig verstanden, wäre das so wie du das gemeint hast?

Hier nur der Loop mit den wichtigen Teilen

const int doShutdown = 0;


void loop() {

  //Prüfen den Wert von doShutdown wenn = 1 Ping auf Raspi auslösen, wenn = 0 nix
  
if (doShutdown = 1) { // >> HIER DIE VARIABLE PRÜFEN
    if (currentMillis - previousMillis > intervalPingForSwitchoff) {
      previousMillis = currentMillis; //wieder zurücksetzen

      //////////////////
      HTTPClient http;
      Serial.print("Waiting for Shutdown: ");
      http.begin(serverAdress);
      int httpCode = http.GET();
      if (httpCode > 0) {
        String answer = http.getString();
        Serial.print(answer);
        Serial.println(" > Server Online");
      } else {
        Serial.printf("Server now Offline > %s\n", http.errorToString(httpCode).c_str());
        Serial.println("Steckdose powerOffPlug ausführen!");
        powerOffPlug(); //Funktion zum Ausschalten der Funksteckdose aufrufen
        doShutdown = 0; // >> HIER DIE VARIABLE FÜR SHUTDOWN WIEDER AUF 0 STELLEN
      }
      http.end();
      /////////////////////
    }
  }

 

  // Shutdown Button
  bouncer_shutdown.update();
  if (bouncer_shutdown.rose()) {
    // Shutdown befehl senden
    if (client.publish(mqtt_topic, "shutdown")) {
      Serial.println("Send cmd für Soft Shutdown!");
      doShutdown = 1; // >> HIER DIE VARIABLE AUF 1 SETZEN WENNN BUTTON PUSH
    } else {
      Serial.println("Konnte nicht gesendet werden, Versuche es nochmal!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "shutdown");
    }
  }


} // End Loop()

So ähnlich war das gemeint. Ich würde allerdings eine Kleinigkeit ändern:

bool doShutdown = false;
...
  if (doShutdown) {
    ...
    return; //weiter warten
  }

weil doShutdown=1 in C eine Zuweisung ist, keine Abfrage.

Danke, ich habs umgebaut und funktioniert genau wie ich wollte!

Vielen Dank für die schnelle Hilfe, der Tipp war genau was ich wollte.

Hallo Leute,
ich hab das ganze etwas umgebaut, leider hab ich das Problem das das D1 manchmal den Shutdownbefehl sendet ohne das der Button gedrückt wurde.
Machmal direkt nach dem Starten, machmal auch erst nach einer halben Stunde.

Hier mal der Code mit dem ich das jetzt umsetzen wollte:

void setup() {
  // Beim Booten Funksteckdose auf On schalten damit AMP gestartet wird
  bootAMP();

  // Beim Booten Funksteckdose auf On schalten damit Raspi gestartet wird
  bootRaspi();
}

void loop() {
  // Shutdown Button
  bouncer_shutdown.update();
  if (bouncer_shutdown.rose()) {
    // Shutdown befehl senden
    if (client.publish(mqtt_topic, "shutdown")) {
      Serial.println("Send cmd für Soft Shutdown -h now!");
      delay(8000);
      powerOffRaspi(); //Steckdose des Raspi ausschalten
      delay(5000);
      powerOffAMP(); //Steckdose des Verstärkers ausschalten.
    } else {
      Serial.println("Shutdown konnte nicht gesendet werden, Versuche es nochmal!");
      client.connect(clientID);
      delay(10);
      client.publish(mqtt_topic, "shutdown");
      delay(8000);
      powerOffRaspi(); //Steckdose des Raspi ausschalten
      delay(5000);
      powerOffAMP(); //Steckdose des Verstärkers ausschalten.
    }
  }
}

void powerOffRaspi() {
  Serial.println("Funksteckdose auschalten, Raspi Power off!");
  HTTPClient http;
  // Variablen definieren
  String vpg, vcom, vdevice, getData, LinkPRIoff;
  vpg = String("dosen");
  vcom = "0";
  vdevice = "3";

  // GET Data - Querystring zusammenbauen
  getData = "?pg=" + vpg + "&com=" + vcom + "&device=" + vdevice ;  //querystring

  // Server Pfad
  LinkPRIoff = "http://192.168.1.34/home/index.php" + getData;
  Serial.println(LinkPRIoff); //Link prüfen

  // Request senden
  http.begin(LinkPRIoff);
  int httpCode = http.GET();
  http.end();  //Close connection
}

void powerOffAMP() {

  Serial.println("Funksteckdose ausschalten, AMP Power off");
  HTTPClient http;
  // Variablen definieren
  String vpg, vcom, vdevice, getData, LinkAMPoff;
  vpg = String("dosen");
  vcom = "0";
  vdevice = "2";

  // GET Data - Querystring zusammenbauen
  getData = "?pg=" + vpg + "&com=" + vcom + "&device=" + vdevice ;  //querystring

  // Server Pfad
  LinkAMPoff = "http://192.168.1.34/home/index.php" + getData;
  Serial.println(LinkAMPoff); //Link prüfen

  // Request senden
  http.begin(LinkAMPoff);
  int httpCode = http.GET();
  http.end();  //Close connection
}

Ich kann nichts sehen das dazu führen könnte das das D1 dden Befehl sendet :confused:

Vielleciht könnt ihr mir auf die Sprünge helfen.

Vielen Dank!

... wäre toll, wenn der Sketch zumindest die Chance hätte, das Kompilieren zu überleben.
bootAMP(); fehlt - mindestens.
Wahrscheilich wäre auch die Funktion bouncer_shutdown.update(); interessant - gibt's aber wohl auch nicht.

MfG

Hallo Postmaster,
danke für deine Antwort.
Du hast recht ich hab nicht alles gepostet weil es hier ja diese Beschränkung an Zeichen gibt.

Ich kann de Sketch aber gerne aufteilen, damit er zb. in 2 Postings platz hat.

Ich hab nur die Sachen reinkopiert die den Shutdown betreffen.

bootAMP(); reiche ich mit weiterem Code gerne nach.

bouncer_shutdown.update(); ist Bestandteil der Bouncer2 Library, das aktualisiert einfach den Status des Buttons soviel ich das verstanden habe.

Ich habe die Buttons schon mehrmals im Einsatz gehabt und immer gleich aufgebaut, da hats noch nie Probleme gegeben.

Es sind in diesem Sketch noch weitere 3 Buttons drin für andere Funktionen, da gibts keine Probleme.

Ich reiche mal den Code nach und vielleicht bist du so gut und schaust nochmal drüber ob dir was auffällt.
Wenn nicht muss irgendwas bei der Hardware nicht stimmen, vielleicht hab ich nicht sauber gelötet oder unsauber verkabelt oder sowas.

Danke dir jedenfalls schon mal fürs drüber schauen.