Input Signal wir nach Eingier Zeit nicht mehr erkannt

Hallo,

ich nutzen den unten angeführten code für die Steuerung einer Gegensprechanlage.

Leider wird mein Inputsignal nach einiger Zeit nicht mehr erkannt.
Erst nach dem Reset des ESP 8266 funktioniert die Erkennung wieder.

woran könnte es liegen?

//DoorBell.ino
#include <Homie.h>
#include "FS.h"

//#define RELAY_PIN 14 //D5

int readDelay = 50;
int buttonPressDelay = 3000;
int openingDelay = 3000;
int inputPin = 0; //D3; 
int relayPin = 4; //D1=5,D6=12,D2=4;
int inputValue = 0;
bool opened = false;
int timeOpened = 0;
//int relayState = LOW;


const int PIN_RELAY = 14; //14


HomieNode doorbellNode("button", "button");
HomieNode openerNode("switch", "switch");
HomieNode switchNode("plug", "switch");
HomieNode resetNode("reset", "switch");


//-----------Reset ESP
bool resetHandler(HomieRange range, String value) {
 if (value == "true") {
//    resetNode.setProperty("on").send("true");
   Serial.println("resetting");
   ESP.restart();
 }
 return false;
}

//----------Klingel lautlos---------
bool lightOnHandler(HomieRange range, String value) {
 Serial.println("Klingel 1");
   if (value == "true") {
       digitalWrite(PIN_RELAY, HIGH);
       switchNode.setProperty("on").send("true");
       Serial.println("Light is on");
       // switchState = true;
   } else if (value == "false") {
       digitalWrite(PIN_RELAY, LOW);
       switchNode.setProperty("on").send("false");
       Serial.println("Light is off");
       // switchState = false;
   } else {
       Serial.print("Error Got: ");
//       Serial.println(value);
       return false;
   }
   
   return true;
}


//--------Tueroffnerrelais
boolean openerHandler(const HomieRange& range, const String& value) {
 if(value != "true" && value != "false") return false;

 if(value == "true") {
   digitalWrite(relayPin, HIGH);
   openerNode.setProperty("on").send("true");
   Serial.println("Opener started ...");
   opened = true;
   timeOpened = millis();
 }

 return true;
}



void setup() {
 Serial.begin(115200);
 Serial.println();


 pinMode(inputPin, INPUT_PULLUP);
 pinMode(BUILTIN_LED, OUTPUT);
 pinMode(relayPin, OUTPUT); //Pin connected to relay
 pinMode(PIN_RELAY, OUTPUT);

//pinMode(BUTTON, INPUT); //Button for manual garage open
//digitalWrite(relayPin, HIGH); // Keep relay off while device turning on
//digitalWrite(relayPin, LOW);

//  digitalWrite(relayPin, HIGH); // Realis boot active problem 
//  pinMode(relayPin, OUTPUT); // Realis boot active problem 

//pinMode(RELAY_PIN, OUTPUT); // In Relais

 
 
 digitalWrite(relayPin, LOW);
 digitalWrite(PIN_RELAY, LOW);
//digitalWrite(RELAY_PIN, LOW); // In Relais


 Homie_setBrand("doorbell");
 Homie_setFirmware("Doorbell", "1.0.0");



 switchNode.advertise("on").settable(lightOnHandler);
 openerNode.advertise("on").settable(openerHandler);
 resetNode.advertise("on").settable(resetHandler);
 
 Homie.setLoopFunction(loopHandler);

 Homie.setup();
}

//--------Klingelsignal
void loopHandler() {
 inputValue = digitalRead(inputPin);

 digitalWrite(BUILTIN_LED, inputValue);

 if(inputValue == 0) {
   Serial.println("Doorbell pressed ...");
   doorbellNode.setProperty("pressed").send("true");
   delay(buttonPressDelay);
   doorbellNode.setProperty("pressed").send("false");
 }

 delay(readDelay);
}

void loop() {
 int timeNow = millis();

   if (digitalRead(inputPin) == LOW) {
        //Serial.println("LOW");
        Serial.println("Doorbell pressed ...");
       doorbellNode.setProperty("pressed").send("true");
       delay(buttonPressDelay);
       doorbellNode.setProperty("pressed").send("false");
     }
     // Sonst, schreibe L
     else {
        //Serial.println("LOW");
        delay(readDelay);
     }


 if(timeOpened > 0 && (timeNow - timeOpened) > 3000) {
   Serial.println("Close ...");
   Serial.println(timeNow);
   Serial.println(timeOpened);
   timeOpened = 0;

   digitalWrite(relayPin, LOW);
   openerNode.setProperty("on").send("false");
   Serial.println("Opener finished ...");
 }

 Homie.loop();
}

Hallo,

ich schätze mal das liegt an der falschen Verwendung von millis was sich durch das gesamte Programm zieht. millis erfordert den Datentyp unsigned long. int ist nicht ausreichend, dass heißt Variable timeNow und timeOpened korrigieren.

timeOpened darf man auch nicht auf 0 setzen sondern auf den aktuellen Stand von millis. Also timeNow.

if (timeNow - timeOpened > 3000) {
    Serial.println("Close ...");
    Serial.println(timeNow);
    Serial.println(timeOpened);
    timeOpened = timeNow;

Theseus erklärt millis()

GuntherB - BlinkwithoutDelay - Die Nachtwächtererklärung

Nicht dein eigentliches Problem, aber das hier solltest du konsequent anwenden:

boolean openerHandler(const HomieRange& range, const String& value)

Objekte (im Gegensatz zu primitiven Datentypen) immer als Referenz übergeben. Hier ist du das getan aber bei den anderen Event Handlern nicht

millis erfordert den Datentyp unsigned long. int ist nicht ausreichend,

Naja…
Eigentlich reicht der Datentype unsigned vollkommen aus.
Meint dann das, was du als unsigned int kennst.

Das int oder long hinter dem unsigned sind HIER* (eigentlich überflüssige) Füllwörter, welche exakt das gleiche meinen.
Also bedenkenlos austauschbar/weglassbar sind.

Die klügste Lösung wäre wohl:

using Millis = decltype(millis());

Millis readDelay = 50;
Millis buttonPressDelay = 3000;
Millis openingDelay = 3000;

Das läuft dann auf jeder Gießkanne, welche Arduino spricht.

Nachtrag:
HIER*
Das “Hier” meint: Dieser µC und dieser Kompiler.
Andere Kombinationen mögen/werden das anders sehen.

combie:
Das int oder long hinter dem unsigned sind HIER (eigentlich überflüssige) Füllwörter, welche exakt das gleiche meinen.

Da solltest du aber deutlich machen dass das nur so ist weil es sich um einen 32 Bit Prozessor handelt

Vielen Dank.

Ich werde es heute gleich probieren.

i habe jetzt den code ausgebessert:

#include <Homie.h>
#include "FS.h"

int inputPin = 0; //D3; 
int relayPin = 4; //D1=5,D6=12,D2=4;
int inputValue = 0;
bool opened = false;
//TEST int timeOpened = 0;


using Millis = decltype(millis());

Millis readDelay = 50;
Millis buttonPressDelay = 3000;
Millis openingDelay = 3000;
Millis timeOpened = 1;

const int PIN_RELAY = 14; //14

HomieNode doorbellNode("button", "button");
HomieNode openerNode("switch", "switch");
HomieNode switchNode("plug", "switch");
HomieNode resetNode("reset", "switch");

//-----------Reset ESP
//bool resetHandler(HomieRange range, String value) {
bool resetHandler(const HomieRange& range, const String& value) {
 if (value == "true") {
   Serial.println("resetting");
   ESP.restart();
 }
 return false;
}

//----------Klingel lautlos---------
//bool lightOnHandler(HomieRange range, String value) {
bool lightOnHandler(const HomieRange& range, const String& value) {
 Serial.println("Klingel 1");
   if (value == "true") {
       digitalWrite(PIN_RELAY, HIGH);
       switchNode.setProperty("on").send("true");
       Serial.println("Light is on");
       // switchState = true;
   } else if (value == "false") {
       digitalWrite(PIN_RELAY, LOW);
       switchNode.setProperty("on").send("false");
       Serial.println("Light is off");
       // switchState = false;
   } else {
       Serial.print("Error Got: ");
//       Serial.println(value);
       return false;
   }
   
   return true;
}


//--------Tueroffnerrelais
boolean openerHandler(const HomieRange& range, const String& value) {
 if(value != "true" && value != "false") return false;

 if(value == "true") {
   digitalWrite(relayPin, HIGH);
   openerNode.setProperty("on").send("true");
   Serial.println("Opener started ...");
   opened = true;
   timeOpened = millis();
 }

 return true;
}



void setup() {
 Serial.begin(115200);
 Serial.println();


 pinMode(inputPin, INPUT_PULLUP);
 pinMode(BUILTIN_LED, OUTPUT);
 pinMode(relayPin, OUTPUT); //Pin connected to relay
 pinMode(PIN_RELAY, OUTPUT);
 
 digitalWrite(relayPin, LOW);
 digitalWrite(PIN_RELAY, LOW);
//digitalWrite(RELAY_PIN, LOW); // In Relais


 Homie_setBrand("doorbell");
 Homie_setFirmware("Doorbell", "1.0.0");

 switchNode.advertise("on").settable(lightOnHandler);
 openerNode.advertise("on").settable(openerHandler);
 resetNode.advertise("on").settable(resetHandler);
 
 Homie.setLoopFunction(loopHandler);

 Homie.setup();
}

//--------Klingelsignal
void loopHandler() {
 inputValue = digitalRead(inputPin);

 digitalWrite(BUILTIN_LED, inputValue);

 if(inputValue == 0) {
   Serial.println("Doorbell pressed ...");
   doorbellNode.setProperty("pressed").send("true");
   delay(buttonPressDelay);
   doorbellNode.setProperty("pressed").send("false");
 }

 delay(readDelay);
}

void loop() {
//TEST int timeNow = millis();
 Millis timeNow = millis();

   if (digitalRead(inputPin) == LOW) {
        //Serial.println("LOW");
        Serial.println("Doorbell pressed ...");
       doorbellNode.setProperty("pressed").send("true");
       delay(buttonPressDelay);
       doorbellNode.setProperty("pressed").send("false");
     }
     // Sonst, schreibe L
     else {
        //Serial.println("LOW");
        delay(readDelay);
     }


 if(timeOpened > 0 && (timeNow - timeOpened) > 3000) {
   Serial.println("Close ...");
   Serial.println(timeNow);
   Serial.println(timeOpened);
//TEST    timeOpened = 0;
   timeOpened = timeNow;

   digitalWrite(relayPin, LOW);
   openerNode.setProperty("on").send("false");
   Serial.println("Opener finished ...");
 }

 Homie.loop();
}

Leider erhalte ich dann ständig folgende Benachrichtigung:

Opener finished ...
Close ...
146407
143399
Opener finished ...
Close ...
149416
146407
Opener finished ...
Close ...
152428
149416
Opener finished ..

.

Hallo,

naja, dass ist das was du programmiert hast. Aller 3 Sekunden erscheint genau diese Ausgabe und der Relaispin wird auf Low geschalten.
Und lass das stimeOpened > 0 weg.

du hast mir doch empfohlen "timeOpened darf man auch nicht auf 0".

Es soll der Ausgang nur für eine gewissen Zeit auf HIGH gesetzt werden.

Wie würdet ihr mir sonst empfehlen den timer zu starte , so dass das Relais nur für eine gewisse Zeit auf HIGH ist und dann wieder auf LOW gesetzt wird.

Warum darf man timeOpener nicht auf 0 setzten?

Hallo,

ich weiß ehrlich gesagt gerade nicht wie ich da anfangen soll.

Was hat stimeOpened > 0 mit "timeOpened darf man auch nicht auf 0" zu tun?

Eben weil man es nicht auf Null setzen muss, darf, sollte ist die Abfrage überflüssig. Eine unsigned Variable kann nie negativ sein. Deswegen würde ich hier decltype nicht verwenden, man sieht es einfach nicht mehr. Gut, wenn man es richtig behandelt interessiert es auch nicht mehr. :wink: Egal.

Zu deinem Problem. Dir fehlt eine Statusvariable die dem Programm sagt, jetzt erst wurde geklingelt und jetzt erst darf die Wartezeit loslaufen. Lies nochmal die Links in #1.

Da ich deine Lib nicht habe, habe ich alles nicht benötigte erstmal rausgewurfen.
Das liest du solange bist du es nachvollziehen kannst. Zeile für Zeile.
Danach bauste dein "Homie" wieder ein.

Habe mich bemüht es einfach zu halten und dennoch mehr Ordnung reinzubringen.

using Millis = decltype(millis());
Millis timeNow;

struct DOOR
{
  const byte pinBell = 0;       // D3;
  const byte pinRelais = 4;     // D1=5, D6=12, D2=4
  const Millis openTime = 3000;
  Millis timeOpened = 0;
  bool stateOpening = false;
} door;


void setup() {
  Serial.begin(115200);
  Serial.println();

  pinMode(door.pinBell, INPUT_PULLUP);
  pinMode(door.pinRelais, OUTPUT);
}



void loop()
{
  timeNow = millis();

  updateTasterBell(30);
  
  if (door.stateOpening)
  {
    closingDoor(door.openTime);
  }
}


// ****** Funktionen ******
void closingDoor (const Millis interval)
{
  if (timeNow - door.timeOpened > interval)
  {
    door.stateOpening = false;
    digitalWrite(door.pinRelais, LOW);
    Serial.println(F("Closing ..."));
  }
}


void updateTasterBell (const Millis interval)
{
  static unsigned long lastMillis = 0;

  if (timeNow - lastMillis >= interval)
  {
    lastMillis = timeNow;

    if ( !door.stateOpening && (!digitalRead(door.pinBell)) )
    {
      door.timeOpened = timeNow;
      door.stateOpening = true;
      Serial.print(F("Doorbell pressed "));
      digitalWrite(door.pinRelais, HIGH);
      Serial.println(F("... Door opening"));
    }
  }
}

Vielen Dank für deine Hilfe.

Mir ist leider aufgefallen dass in der Funktion: void closingDoor (const Millis interval) timeNow immer den Wert 0 hat.
Kann es daran liegen dass der Wert nicht von void loop übergeben wird?

Kann es daran liegen dass der Wert nicht von
void loop
übergeben wird?

Suchtipp "Geltungsbereich von Variablen in C++"

Oder die Kurzfassung: Jain!

Wenn ich mir den Wert TimeNow anzeigen lasse ist dieser Wert in der Funktion

void closingDoor (const Millis interval)

immer 0. Somit ändert sich der Wert in der Funktion nicht.

Handelt es sich dabei nicht um eine globale Variable?

Wie kann ich das Problem beheben, bzw wo ist mein Denkfehler?

Trainer_h:
Wie kann ich das Problem beheben, bzw wo ist mein Denkfehler?

Das hat Dir doch combie in #12 geschrieben. Lesen musst Du selbst, sonst hast Du ja keine Chance es zu verstehen.

Gruß Tommy

Hallo,

ich weiß wirklich nicht wie du zu der Annahme kommst das timeNow immer 0 bleibt.
Wie und wo läßt du dir den Wert anzeigen?
Zeige bitte deinen Sketch, dass wäre das Einfachste für alle.

Tommy56:
Das hat Dir doch combie in #12 geschrieben. Lesen musst Du selbst, sonst hast Du ja keine Chance es zu verstehen.

Gruß Tommy

Danke aber ich habe schon drüber gelesen. Bei mir sollte es eine globale Variable sein, jedoch ist der Wert 0.

Doc_Arduino:
Hallo,

ich weiß wirklich nicht wie du zu der Annahme kommst das timeNow immer 0 bleibt.
Wie und wo läßt du dir den Wert anzeigen?
Zeige bitte deinen Sketch, dass wäre das Einfachste für alle.

ich habe mittels

Serial.println(timeNow)

den Wert kontrolliert.
Den Wert lass ich mir dann bei Serialler Monitor anzeigen.

Hier ist mein Sketch:

#include <Homie.h>
#include "FS.h"

int inputPin = 0; //D3; 
int relayPin = 4; //D1=5,D6=12,D2=4;
int inputValue = 0;


using Millis = decltype(millis());
Millis timeNow;

const int PIN_RELAY = 14; //14


struct DOOR
{
  const Millis openTime = 3000;
  Millis timeOpened = 0;
  bool stateOpening = false;
} door;

HomieNode doorbellNode("button", "button");
HomieNode openerNode("switch", "switch");
HomieNode switchNode("plug", "switch");
HomieNode resetNode("reset", "switch");

//-----------Reset ESP
bool resetHandler(const HomieRange& range, const String& value) {
  if (value == "true") {
    Serial.println("resetting");
    ESP.restart();
  }
  return false;
}

//----------Klingel lautlos---------
bool lightOnHandler(const HomieRange& range, const String& value) {
  Serial.println("Klingel 1");
    if (value == "true") {
        digitalWrite(PIN_RELAY, HIGH);
        switchNode.setProperty("on").send("true");
        Serial.println("Light is on");
    } else if (value == "false") {
        digitalWrite(PIN_RELAY, LOW);
        switchNode.setProperty("on").send("false");
        Serial.println("Light is off");
    } else {
        Serial.print("Error Got: ");
        return false;
    }
    return true;
}


//--------Tueroffnerrelais
boolean openerHandler(const HomieRange& range, const String& value) {
  if(value != "true" && value != "false") return false;

  if(value == "true") {
    digitalWrite(relayPin, HIGH);
    openerNode.setProperty("on").send("true");
    Serial.println("Türöffnungsrelais started ...");
    door.stateOpening = true;
    Serial.println("sateOpening");
    Serial.println(door.stateOpening);
  }
  return true;
}



void setup() {
  Serial.begin(115200);
  Serial.println();

  pinMode(inputPin, INPUT_PULLUP);
  pinMode(BUILTIN_LED, OUTPUT);
  pinMode(relayPin, OUTPUT); //Pin connected to relay
  pinMode(PIN_RELAY, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(PIN_RELAY, LOW);

  Homie_setBrand("doorbell");
  Homie_setFirmware("Doorbell", "1.0.0");

  switchNode.advertise("on").settable(lightOnHandler);
  openerNode.advertise("on").settable(openerHandler);
  resetNode.advertise("on").settable(resetHandler);

  Homie.setup();
}


void loop() {
  Millis timeNow = millis();
//  Serial.println("TimeNOWloop");
//  Serial.println(timeNow);
  updateTasterBell(30);
  if (door.stateOpening)
    {
      closingDoor(door.openTime);
    }

  Homie.loop();
}

// ****** Funktionen ******
void closingDoor (const Millis interval)
{
  Serial.println("TimeNOW");
  Serial.println(timeNow);
  Serial.println("TimeOpened");
  Serial.println(door.timeOpened);
  if (timeNow - door.timeOpened > interval)
  {
    door.stateOpening = false;
    digitalWrite(relayPin, LOW);
    Serial.println(F("Closing ..."));
  }
}

void updateTasterBell (const Millis interval)
{
  static unsigned long lastMillis = 0;
  Serial.println("TimeNOW");
  Serial.println(timeNow);
  if (timeNow - lastMillis >= interval)
  {
    lastMillis = timeNow;
      Serial.println("stateOpening");
      Serial.println(door.stateOpening);
      Serial.println(inputPin);
    if ( !door.stateOpening && (!digitalRead(inputPin)) )
    {
      door.timeOpened = timeNow;
      door.stateOpening = true;
      Serial.print(F("Doorbell pressed "));
      digitalWrite(relayPin, HIGH);
      Serial.println(F("... Door opening"));
    }
  }
}
void loop() {

Millis timeNow = millis();

Schade, dass du die von mir gelieferte Information nicht verstanden hast.

Also mal klar:
Wenn du eine lokale timeNow erzeugst ....
So wie du es in loop() tust.

Und eine globale

Millis timeNow;

Und dann nur die lokale änderst, warum sollte sich dann die globale, mit ändern?

Hier mal ein Irrweg um das zu verdeutlichen:

timeNow = millis(); // ändert die Variable im lokalen Geltungsbereich
timeNow = millis(); // ändert die Variable im übergeordneten Geltungsbereich, wenn keine lokale Variable dieses Namens existiert
::timeNow = millis(); // ändert die Variable im übergeordneten Geltungsbereich, egal ob eine lokale existiert.

Serenifly:
Da solltest du aber deutlich machen dass das nur so ist weil es sich um einen 32 Bit Prozessor handelt

Hatte extra das HIER schon groß geschrieben um das zu verdeutlichen.

Aber danke für den Hinweis, ich machs dann mal zusätzlich fett und rot.