Hallo G,
ZitatLow gleich zu, high = öffnen.
Ja das kommt auf den Trigger drauf an wie dein Board geschalten ist. Da gibts verschiedenste. Manche mit Jumper zum Einstellen oder fest definierte. Kann man natürlich auch von der Logik im Script dann drehen. Bei dir müsste es dann ein High Trigger Board sein?
ZitatFunktioniert besser so. Alle ca 15 Sekunden verliert der ESP die WLAN Verbindung und verbindet sich dann wieder, wenn während dieser 5 Sekunden, bis er wieder Verbindung, hat derTüröffner betätigt wird, passiert nix, bis er wieder verbunden ist ... wo sitzt da der Timeout ?
Also das Phänomen hatte ich leider auch immer wieder. Bin da auch noch teilweise am Fehler suchen. Allerdings kann ich mir da nicht wirklich ein Reim draus bilden, warum das WLAN bei den ESP Chips so instabil immer wieder ist. Habe bestimmt um die 5 ESPs daheim laufen. Aber beim Türöffner ist es am instabilsten. Habe auch bereits das Script schon teilweise neu aufgesetzt. Was sein könnte, ist dass durch den Deepsleep bedingt das WLAN nicht so sauber startet. Da bei mir das über Batterien läuft, muss ich damit leben. Weil Lust habe ich nicht wirklich den LiPo Akku alle Woche aufzuladen. Der ESP zieht dann doch einiges wenn er im IDLE Modus rumdümpelt.
Eins muss dir aber bewusst sein. Das Klingelsignal wird über WLAN immer eine gewisse Zeit benötigen. Der ESP muss aufwachen, kurz booten <1s und dann das WLAN aufbauen/connecten. Das benötigt dann mit unter 5s in der Regel dann doch die meiste Zeit. Falls du das fast in Echtzeit haben möchtest, kann man das um einiges beschleunigen wenn man das Signal der LoRa überträgt. Falls du da Interesse dran hast, kann ich dir die Unterlagen auch bereitstellen. Das habe ich mittlerweile bei mir am laufen.
Kurz zusammengefasst: Es klingelt, der ESP wacht auf und innerhalb von der 1s Bootzeit wird parallel auch das LoRa Modul gestartet. Also sind beide gleichzeitig im RUN Mode. Dadurch kann sofort das LoRa Modul energiesparend (<10mA) die Nachricht an den Receiver senden, dass es geklingelt hat. Erstaunlich fand ich selber wie schnell das geht. Wenn es an der Innenstation klingelt (summt), dann kommt meine Pushnachricht meist gerade schon auf dem Handy an, wenn es aufhört zu summen. Gefühlt wie gesagt innerhalb von 1s maximal 2s.
ZitatAlles anzeigenKlingelsignal : wenn ich die Klingeltast drücke , resettet der ESP, das soll ja so sein, aber er sendet keine Meldung an den MQTTbroker und somit auch keine Meldung im Homekit. Da bin ich jetzt noch etwas überfragt, wenn du da nen Tip hast, wäre super ... ich habe im MQTTthing config diese Zeilen :
"type": "statelessProgrammableSwitch",
"name": "Türklingel",
"logMqtt": true,
"topics": {
"getSwitch": "Klingelgedrueckt"
},
"restrictSwitchValues": [
0
],
"accessory": "mqttthing"
Sorry, mein Fehler. Da kann auch nichts gehen, da ich dir mein Script mit dem LoRa Modul in reinen WLAN Mode angepasst habe. Ich habe im Script vergessen das Klingelsignal per MQTT rauszuschicken.
Da kannst du natürlich noch so oft es testen. Da wird nichts kommen. Sorry für das verschlampen..
Übrigens.. Ich hab beim PinSetup für dich bereits Vordefiniert ob du ein High oder Low Trigger Board anschließt.
Im Grunde müsste es so ausreichen, HIGH ist schon vordefiniert.
Falls dir da auffällt dass noch was von der Logik falsch ist, gern bescheid geben. Generell bin ich offen für Bugs. Dann kann ich wieder Tüfteln.
Hier aber das Script in der nun alles gehen sollte:
20210119_ESP8622_Tueroeffner.zip
/*********
©Adrian Zilly
@Tueroeffner
Hardware Lib: ESP8622 NodeMCU 1.0 (ESP12E-Module)
Script v3.1
Letzte Aenderung 2021-01-19
*********/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoOTA.h>
#include <WiFiUdp.h>
#include <ESP8266mDNS.h>
//--------------------------------------------------
//Define Variables
int Digits = 0;
int BattVolt = 0;
int BattPerc = 0;
int valA0 = 0;
int StartMerker = 0;
int Start = 0;
int Start2 = 0;
int Start3 = 0;
unsigned long sleepMillis = 10, Sendertime = 10, previousMillis = 10, currentMillis = 10;
const long intervalon = 1000;
const long intervaloff = 1000;
int SendeDelay = 5000;
int WLANTimeout = 30;
int WLANCounts = 0;
int SetSleep = 0;
//--------------------------------------------------
//PARAMETER EINSTELLUNGEN
//Parameter Analogwertauslesen (Digit Korrektur)
int DigitsCor = 0;
//Sleep Delay Parameter
unsigned long currentSleep, SenderSleep;
const long gosleepdelay = 120000; //Verzoegerung Schlafen gehen 1000ms = 1s - Set to 100000 (2min.)
//WLAN Setup
const char* SSID = "MYSUPERWLANISTHEBESTOFTHEPLANET"; //WLAN Name
const char* PSK = "LOLOLOLOLOLOHOHOHOHOHOHOHOHO"; //Passwort WLAN
//Pin Setup
#define BattVoltIn A0 //Analog Input
int Rot = 4; //GPIO LED Rot
int Gelb = 5; //GPIO Bereitschaft
int Gruen = 12; //GPIO Klingelgedrueckt/Reserve
int Tueroeffner = 15; //GPIO 15 Tueroeffner --- HIGH
bool TueroeffnerRelais = HIGH; //Relaisboard HIGH or LOW Trigger
bool TueroeffnerRelaisOpen, TueroeffnerRelaisClose;
//--------------------------------------------------
//---------------
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
int wifi_retry;
//---------------
/*Unterprogramm Akkulevel auslesen
ggf. Kalibrieren mit Hilfe von "DigitsCor = Digits + 0;" hier hinter dem + entsprechende Korrektur eintragen
Messgeraet an Akku direkt anschließen. Spannung messen und entsprechenden Korrekturwert ermitteln.
Weitere Moeglichkeit, direkt die Punkte definieren.
BattVolt = map(DigitsCor, 0, 282, 0, 4089); - map(Analogwert, LowDigit, HighDigit, LowValue, HighValue);
Folglich dann die zwei Werte anpassen: map(DigitsCor, 0, !!hier Ausgegebener Digitwert bei gleichzeitiger Akkumessung eintragen!!, 0, !!hier gemessener Messwert eintragen!!);
Nicht vergessen die gleichen Werte bei Battperc einzutragen.
*/
void AkkuStand() {
//Volt auslesen
Digits = analogRead(BattVoltIn);
DigitsCor = Digits + 0; // + 0 mit Korrektur versehen.
BattVolt = map(DigitsCor, 0, 282, 0, 4089);
// 1d = 14,4mV / 230d = 3312mV / 284d = 4089mV
BattPerc = map(DigitsCor, 230, 282, 0, 100);
if (BattPerc == 0) {
AkkuStand();
}
Serial.print("AkkuStand\nDigit: ");
Serial.print(Digits);
Serial.print("Batt Volt");
Serial.print(BattVolt);
}
//---------------
void Klingel() {
//Unterprogramm Klingelsignal senden
digitalWrite(Gruen, HIGH);
client.publish("Klingelgedrueckt", "1");
Serial.println("It ringed for you!");
delay(1000);
digitalWrite(Gruen, LOW);
client.publish("Klingelgedrueckt", "0");
}
//---------------
void Close() {
//Unterprogramm Tuer schließen
Serial.println("I close it for you!");
client.publish("Haustuerstatuslaueft", "gesichert");
digitalWrite(Tueroeffner, TueroeffnerRelaisClose);
//delay(500);
client.publish("Haustuerstatusist", "gesichert");
client.publish("Haustuer", "Sicherung durchgefuehrt!");
}
//---------------
void Open() {
//Unterprogramm Tuer oeffnen
Serial.println("I open it for you!");
client.publish("Haustuerstatuslaueft", "offen");
client.publish("Haustuerstatuslaueft", "offen");
//delay(500);
digitalWrite(Tueroeffner, TueroeffnerRelaisOpen);
client.publish("Haustuerstatusist", "offen");
client.publish("Haustuerstatusist", "offen");
Serial.println("Haustuer wurde geoeffnet!");
delay(3000);
digitalWrite(Tueroeffner, TueroeffnerRelaisClose);
client.publish("Haustuerstatuslaueft", "gesichert");
client.publish("Haustuerstatuslaueft", "gesichert");
Serial.println("Haustuer wird geschlossen!");
//delay(500);
client.publish("Haustuerstatusist", "gesichert");
client.publish("Haustuerstatusist", "gesichert");
Serial.println("Haustuer wurde gesichert!");
//delay(500);
}
void SendAkku() {
//Unterprogramm Akkulevel uebertragen
client.publish("BatterieLevelTuer", String(BattPerc).c_str(), true);
client.publish("HaustuerAkkuDigit", String(Digits).c_str(), true);
String mV = ("mV: " + String(BattVolt));
client.publish("HaustuerAkku", String(mV).c_str(), true);
String Perc = ("Perc: " + String(BattPerc));
client.publish("HaustuerAkku", String(Perc).c_str(), true);
Serial.print("\nHaustuerAkku:");
Serial.print(BattPerc);
Start3++;
}
//---------------
//Unterprogramm Callback MQTT
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Received message [");
Serial.print(topic);
Serial.print("] ");
char msg[length + 1];
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
msg[i] = (char)payload[i];
}
msg[length] = '\0';
Serial.println(msg);
client.publish("Haustuer", "I got an Order!");
if (strcmp(msg, "gesichert") == 0) {
Close();
}
else if (strcmp(msg, "offen") == 0) {
Open();
}
else {
Serial.print("Nichts kam an");
}
}
//---------------
void setup() {
//Cleanup
ESP.eraseConfig();
WiFi.disconnect();
Serial.begin(115200);
//PIN Setup
pinMode(Tueroeffner, OUTPUT); //Relais Tueroeffner
pinMode(Gelb, OUTPUT); //Bereitschaft
pinMode(Rot , OUTPUT); //LED Tueroeffner
pinMode(Gruen, OUTPUT); //Klingelsignal
if (TueroeffnerRelais == HIGH){
TueroeffnerRelaisOpen = HIGH;
TueroeffnerRelaisClose = LOW;
}
else if (TueroeffnerRelais == LOW){
TueroeffnerRelaisOpen = LOW;
TueroeffnerRelaisClose = HIGH;
}
else{
Serial.print("Error Set TueroeffnerRelais Output");
}
digitalWrite(Tueroeffner, TueroeffnerRelaisClose); //
//------- END Pin Setup ---------
delay(100);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PSK);
while (WiFi.status() != WL_CONNECTED && WLANTimeout > WLANCounts) {
delay(500);
WLANCounts++;
Serial.print("\n Wifi Connecting..");
Serial.print("\n Trys:");
Serial.print(WLANCounts);
Serial.print("/");
Serial.print(WLANTimeout);
}
if (WLANCounts >= WLANTimeout) {
ESP.restart();
}
else {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
WLANCounts = 0;
}
client.setServer("192.167.1.15", 1883);
client.setCallback(callback);
AkkuStand();
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.setHostname("ESP-Haustuere");
ArduinoOTA.setPassword("nimda");
ArduinoOTA.begin();
}
//---------------
//Unterprogramm Neu Verbinden MQTT
void reconnect() {
while (!client.connected()) {
Serial.println("\nReconnecting MQTT...");
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
if (!client.connect(clientId.c_str())) {
Serial.print("failed, rc=");
Serial.print(client.state());
delay(1000);
}
else {
client.subscribe("Haustueroeffnen");
client.publish("HaustuerStatus", "MQTT Connected");
char buf[16];
sprintf(buf, "%d", StartMerker);
const char* SendMerker = buf;
client.publish("HaustuerStatus", SendMerker);
Serial.println("MQTT Connected...");
Close();
}
}
}
//----------------------------------------
void loop() {
//WLAN noch verbunden? Andernfalls neu verbinden
if (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("WLAN not connected, reconnecting...");
wifi_retry = 0;
while (WiFi.status() != WL_CONNECTED && wifi_retry < 30) {
Serial.println(wifi_retry);
wifi_retry++;
Serial.println("WiFi not connected. Try to reconnect");
delay(500);
}
//Falls zu oft Verbindungsversuch durchgefuehrt wurde, ESP neu starten
if (wifi_retry >= 30) {
Serial.println("\nReboot");
ESP.restart();
}
}
//MQTT noch verbunden? Andernfalls neu verbinden
if (!client.connected()) {
reconnect();
}
client.loop();
//Over Air Programmierung
ArduinoOTA.handle();
delay(100);
//Unterprogramme abrufen
AkkuStand();
SendAkku();
//Bereitschaftsanzeige
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= intervaloff) {
previousMillis = currentMillis;
digitalWrite(Gelb, HIGH);
}
else if (currentMillis - previousMillis >= intervalon) {
digitalWrite(Gelb, LOW);
}
//Variable ablegen mit der aktuellen Zeit fuer Ueberpruefung Schlafengehen
currentSleep = millis();
//Ueberpruefen ob zeit zum schlafen ist
if (currentSleep - sleepMillis >= gosleepdelay && client.connected() && WiFi.status() == WL_CONNECTED) {
//WLAN und MQTT noch verbunden? Andernfalls neu verbinden
if (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("WLAN not connected, reconnecting...");
while (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi not connected. Try to reconnect");
delay(500);
}
}
if (!client.connected()) {
reconnect();
}
//Ausgaenge für Schlafen vorbereiten
sleepMillis = currentSleep;
//Ausgaenge für Schlafen vorbereiten
digitalWrite(Tueroeffner, TueroeffnerRelaisClose);
digitalWrite(Gruen, LOW);
digitalWrite(Gelb, LOW);
digitalWrite(Rot, LOW);
//Mitteliung dass Deepsleep gestartet wird.
client.publish("Haustuer", "END WIFI NOW and go Sleep...");
client.publish("Haustuer", "go sleeping...");
//ESP schlafen legen
delay(1000);
Serial.println("END WIFI");
WiFi.mode(WIFI_OFF);
delay(1000);
Serial.println("Deepsleep Now..");
delay(500);
ESP.deepSleep(0);
delay(200000);
}
}
//--------------------------------------------------
Alles anzeigen
ZitatSonst sieht's soweit gut aus , die ganze Batteriemessung und so habe ich mal auskommentiert , vielleicht brauche ich das gar nicht , je nachdem woher ich den Strom bekomme....
Super! Also demnach kannst du die Tür Öffnen/Schließen?
Auch hier kann es je nach WLAN Timeout dazu führen, dass da ca. 5s vergehen bis die Tür öffnet.. Wie gesagt. Das ist für mich auch ein Rätsel mit der Hardware. Im Netz hab ich dazu auch nicht richtig Informationen finden können.
Grüße aus Freiburg