Callback wird ungewollt ausgeführt

Hallo zusammen,

ich versuche mich gerade an meinem ersten eigenen Projekt.

Folgende Konfiguration:

  • Raspberry 4 mit mosquitto(MQTT) und ioBroker
  • Arduino WeMos D1 mini (Teststellung: Eine LED mit Taster, welcher bei Druck jeweils die LED ein oder ausschält)

Über vis (ioBroker) funktioniert alles, aber wenn ich den Taster auf den Board drücke (ein), geht die LED an, aber mein "Sketch" bekommt dann einen callback und schaltet die LED wieder aus. Ich vermute mal, das der callback von vis ausgelöst wird, wenn er den Status der LED ändert.

Wie kann ich es umgehen, das beim manuellen Drücken des Tasters der callback ausgeführt wird?
Anbei mal der Sketch. (ich habe viel Serial.print drin, um einfach das Ganze bei der Einlernphase mit dem seriellen Monitor zu überwachen, das kommt später dann raus. Auch MQTT (momentan 1883) wird später noch auf sichere Verbindung gestellt).

// Client ID
char* IdClient = "Demo01";
char* T_Taster = "Demo01/Taster";
char* T_Pir = "Demo01/PIR";

// WiFi Zugangsdaten
const char* ssid     = "xxxx";
const char* password = "xxxx";

// MQTT Zugagsdaten
const char* mqtt_serv = "xxxx";
const int mqtt_port = 1883;

// Zeit => Definierung
unsigned long now = millis();
unsigned long lastMeasure = 0;
boolean startTimer = false;
unsigned long currentTime = millis();
unsigned long previousTime = 0;

// Status LED zum Programmstart
bool LedAn = false;

// Funktion Wifi Verbindung aufbauen (Funktion; Aufruf in setup)
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Verbindungsaufbau zu SSID: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi verbunden: IP-Adresse => ");
  Serial.println(WiFi.localIP());
}

// Funktion MQTT Verbindung aufbauen (Funktion; Aufruf im Setup)
void connectToMQTT() {
  
  if (client.connect(IdClient , mqtt_user, mqtt_pass)) {
    Serial.println("MQTT verbunden");
  }
  else {
    Serial.print("MQTT nicht verbunden. Err: ");
    Serial.print(client.state());
    Serial.println(" Neuer Versuch in 3 Sek.");

    delay(3000);
  }
}

// Daten von Broker an MQTT senden
void callback(char* topic, byte* payload, unsigned int length) {
    String msg;
    for (byte i = 0; i < length; i++) {
        //char tmp = char(payload[i]);
        msg += (char)payload[i];
    }

    if(msg == "LED an")
    {
      Serial.print("Call LED an ");
      digitalWrite(Led, HIGH);
      Serial.println(topic);
    }
    
    if(msg == "LED aus")
    {
      Serial.print("Call LED aus ");
      Serial.println(topic);
      digitalWrite(Led, LOW);
    }
}

void setup() {
  // Definierung Status LED
  pinMode(Led, OUTPUT);
  pinMode(Taster, INPUT);
  pinMode(PIR, INPUT);
  
  digitalWrite(Led, LOW);
   
  // Seriale Portausgabe für Monitoring (debug)
  Serial.begin(115200);

  // Wifi- Verbindung herstellen
  setup_wifi();
  client.setServer(mqtt_serv, mqtt_port);
  client.setCallback(callback);
  
  // MQTT- Verbindung herstellen
  connectToMQTT();

  delay(1000);

  Serial.println("Fertig Setup ");
}

void loop() {
  // Verbindung Client zu MQTT aufbauen
  if (!client.connected()) {
    while (!client.connected()) {
      client.connect(IdClient);
      client.subscribe("Demo01/Taster");
      delay(250);
    }
  }
  client.loop();
    
  // Taster LED ein oder aus
  if(digitalRead(Taster) == HIGH) {
    Serial.print("Tastendruck ");
    
    if(digitalRead(Led) == HIGH)
    {
      digitalWrite(Led, LOW);
      Serial.println("LED aus");
      client.publish(T_Taster, "LED aus");
      //client.subscribe("Demo01/Taster");
    }
    else
    {
      digitalWrite(Led, HIGH);
      Serial.println("LED an");
      client.publish(T_Taster, "LED an");
      //client.subscribe("Demo01/Taster");
    }
  }

  // PIR Meldung
  if(digitalRead(PIR) == HIGH and digitalRead(Led) == HIGH) {
    Serial.println("Bewegung");

    client.publish(T_Pir, "Bewegung");
  }
  
  delay(250);
}

Wäre super, wenn ich hier ein paar Tipps, Ideen bekommen würde.
Gruß
Falke07

Kein Wunder:

  if(msg == "LED an")

So kann man keine Strings vergleichen, dazu nutzt man zum Beispiel strcmp()

https://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/strings-vergleichn/

Außerdem solltest du ohne deine delay() in der Loop auskommen.

Gruß

Hallo,
msg ist als String objekt definiert da ist das schon richtig so
https://www.arduino.cc/reference/de/language/variables/data-types/string/operators/comparison/

Heinz

Siehst du denn auch diesen Testausschrieb?

Sonst hängt es evtl. an der Dauer des Tastendrucks im Zusammenspiel mit deinem delay(250); je loop Durchlauf ...

Hallo,
ja den sehe ich. Ich vermute mal, das es eine Art "Rückkopplung" ist. Bord schält bei Tastendruck um, sendet an MQTT => ioBroker. ioBroker ändert den Status und sendet natürlich die Änderung, was den callback erklären würde. Es stellt sich nur die Frage wie ich das umgehen kann?
Denke es sollte so in die Richtung gehen:
if signal publish (also lokal vom Board, Tastendruck) reagiere nicht auf callback (vom ioBroker)

Habe da aber noch ein weiteres Problem entdeckt:
Kann es sein, das der WeMos D1 Mini bei einem Neustart generell in den deepsleep geht und erst nach einem Tastendrück dauerhaft erwacht? (Info: ich habe im Sketch keinerlei deepSleep- Anweisungen) Auch eine Brücke von RST auf D0 bringt keine Verbesserung.

Gruß
Falke07

Habe da aber noch ein weiteres Problem entdeckt:
Kann es sein, das der WeMos D1 Mini bei einem Neustart generell in den deepsleep geht und erst nach einem Tastendrück dauerhaft erwacht? (Info: ich habe im Sketch keinerlei deepSleep- Anweisungen) Auch eine Brücke von RST auf D0 bringt keine Verbesserung.

Nein das tut er nicht, entferne deine ganzen delay() erstma. Teste nochmal und zeige uns mal deine Ausgabe des seriellen Monitors.

Hallo,

genau das ist ja das Problem. Nach dem Neustart keine Reaktion am WeMos aus vis; somit auch keine serielle Ausgabe. Erst wenn ich 1 x die Taste am WeMos drücke. Dann funktionieret auch alles.

Serial.println("Fertig Setup ");

Also wenn nichtmal diese Ausgabe im setup() erscheint könnte es sein dass deine Schaltung irgendwie nicht stimmt. Kannst du mal deinen Aufbau zeigen?

Das hört sich fast so an, als würde der in einen anderen Mode gehen.
Beschaltung prüfen.
Vor allem GPIO0 / D3 muss HIGH sein.
Dazu dann noch und GPIO 15 / D8 und GPIO2 / D4

Hallo,

das Problem ist gelöst.
Es waren 2 Fehler:

  1. Ich bin etwas mit publish / subscribe durcheinander gekommen. (Wie im Sketch ersichtlich)
  2. Bei einem Neustart wurde nur der Status gesendet, jedoch nicht der Steuerbefehl gesetzt. (Einstellung vis => MQTT- Instanz => Broker)

Nun funktioniert alles, wie es soll.

THx an alle für die Unterstützung.

Gruß
Falke07

Was genau macht denn der callback überhaupt? kann mir das jemand erklären?

Darin wird eine Nachricht empfangen die er dann per if Anweisung auswertet.