Probleme mit der millis()-Funktion

Hi,

ich habe vor einiger Zeit ein Projekt zur Steuerung meiner Gartenpumpe umgesetzt. Verwendet wird ein ESP-12F, welcher über WiFi-OTA mit Updates via Webbrowser versorgt werden kann. Die gesamte Steuerung läuft auch über HTTP ab.

Der Code dient zum Schalten von 3 Relais. Relais 1 = Ventil NO, Relais 2 = Ventil NC, Relais 3 = Ansteuerung der Pumpe.
Um die Pumpe und beide Ventile für 10 Minuten zu schalten, habe ich mich der millis()-Funktion bedient und einen kleinen Timer damit erstellt.

Das Problem ist, dass es nicht mehr möglich ist die Pumpe einzuschalten, solange die “TimerTeichON()”-Funktion nicht vorher kurz aktiviert und anschließend wieder deaktiviert wurde. Irgendwie schaltet also mein Timer immer nach 10 Minuten alle Relais dauerhaft ab, bis er über die Funktion neu gestartet wird.

Ich finde meinen Fehler leider nicht. Kann mir einer von euch sagen, woran das liegen könnte?

Anbei noch der Code:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

const int relay1_gpio = 5; //Valve NO
const int relay2_gpio = 4; //Valve NC
const int relay3_gpio = 14; //Garden-Pump

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 600000; //(10 Minutes)

const char* host = "Pumpe-WebUpdate";
const char* ssid     = "WLAN";
const char* password = "******";

ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;

void handle_root() {
  server.send(200, "text/plain", "Pumpensteuerung");
  delay(100);
}

void RelayOneON() {
  digitalWrite(relay1_gpio, LOW);
  server.send(200, "text/plain", "Relay ONE (Valve NO) activated");
  delay(100);
}
void RelayTwoON() {
  digitalWrite(relay2_gpio, LOW);
  server.send(200, "text/plain", "Relay TWO (Valve NC) activated");
  delay(100);
}
void RelayThreeON() {
  digitalWrite(relay3_gpio, LOW);
  server.send(200, "text/plain", "Relay THREE (Garden-Pump) activated");
  delay(100);
}


void RelayOneOFF() {
  digitalWrite(relay1_gpio, HIGH);
  server.send(200, "text/plain", "Relay ONE (Valve NO) deactivated");
  delay(100);
}
void RelayTwoOFF() {
  digitalWrite(relay2_gpio, HIGH);
  server.send(200, "text/plain", "Relay TWO (Valve NC) deactivated");
  delay(100);
}
void RelayThreeOFF() {
  digitalWrite(relay3_gpio, HIGH);
  server.send(200, "text/plain", "Relay THREE (Garden-Pump) deactivated");
  delay(100);
}

void TimerTeichON() {
  digitalWrite(relay1_gpio, LOW);
  digitalWrite(relay2_gpio, LOW);
  digitalWrite(relay3_gpio, LOW);
  server.send(200, "text/plain", "All Relays activated");
  startMillis = millis();
}
void TimerTeichOFF() {
  digitalWrite(relay1_gpio, HIGH);
  digitalWrite(relay2_gpio, HIGH);
  digitalWrite(relay3_gpio, HIGH);
  server.send(200, "text/plain", "All Relays deactivated");
}

void setup()
{
  pinMode(relay1_gpio, OUTPUT);
  pinMode(relay2_gpio, OUTPUT);
  pinMode(relay3_gpio, OUTPUT);

  digitalWrite(relay1_gpio, HIGH);
  digitalWrite(relay2_gpio, HIGH);
  digitalWrite(relay3_gpio, HIGH);

  Serial.begin(115200);

  // Connect to WiFi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("\nConnecting to WIFI");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("WIFI OK \n\n");
  Serial.print("IP address:\n");
  Serial.println(WiFi.localIP());

  server.on("/", handle_root);
  server.on("/r1-on", RelayOneON);
  server.on("/r2-on", RelayTwoON);
  server.on("/r3-on", RelayThreeON);

  server.on("/r1-off", RelayOneOFF);
  server.on("/r2-off", RelayTwoOFF);
  server.on("/r3-off", RelayThreeOFF);

  server.on("/teich", TimerTeichON);
  server.on("/alloff", TimerTeichOFF);

  server.begin();
  Serial.println("HTTP Server started");
  delay(500);

  MDNS.begin(host);

  httpUpdater.setup(&server);
  server.begin();

  MDNS.addService("http", "tcp", 80);
  Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
}


void loop()
{
  currentMillis = millis();
  if (currentMillis - startMillis >= period) {
    digitalWrite(relay1_gpio, HIGH);
    digitalWrite(relay2_gpio, HIGH);
    digitalWrite(relay3_gpio, HIGH);
  }
  server.handleClient();
}

Wenn Du verschiedene Sachen unabhängig voneinander über millis steuern willst, braucht jede Ihre eigene Startvariable.

Gruß Tommy

Okay, danke dir erstmal.
Aber ich verstehe leider nicht so ganz wie du das meinst, da ich die anderen Elemente ja nicht über einen Timer schalten will. :confused:
Die Relais sollen ja im Normalfall entweder dauerhaft eingeschaltet, oder eben ausgeschaltet sein.

Kannst du mir vielleicht ein Beispiel reinschreiben, damit ich es verstehe? :slight_smile:

LG

Ridgeback09:
Kannst du mir vielleicht ein Beispiel reinschreiben, damit ich es verstehe? :slight_smile:

Letztlich läuft es auf einen endlichen Automaten hinaus. Vielleicht hilft das hier. Eine sehr gute Erläuterung dieser „Programmierstrategie“ ist die Nachtwächter-Erklärung.

Gruß

Gregor

gregorss:
Letztlich läuft es auf einen endlichen Automaten hinaus. Vielleicht hilft das hier. Eine sehr gute Erläuterung dieser „Programmierstrategie“ ist die Nachtwächter-Erklärung.

Gruß

Gregor

Vielen Dank für die super Erklärung. Das ist wirklich hilfreich und ausführlich geschrieben.

Trotzdem verstehe ich nicht, warum ich die Relais in den anderen Funktionen nicht einfach unabhängig von meinem Timer verwenden kann, da die anderen Funktionen ja unendlich laufen sollen :confused:

Wahrscheinlich habe ich irgendeinen Denkfehler und komm nicht drauf…

LG

Deine Bedingung in der If Anweisung bleibt immer wahr, wenn sie einmal erreicht.

mfG Thorsten

Hi

Wie mein Vorredner schon schrieb:
Du startest die Relais und merkst Dir die Uhrzeit.
Nach zehn Minuten stopst Du die Relais alle.
Was hättest Du alternativ von diesem Sketch erwartet?
Die IF ist eindeutig - 10 Minuten nach dem Start wird Diese (für immer) gültig - und schaltet alle Relais ab - in jedem loop()-Durchgang auf's Neue.

Was willst Du wirklich erreichen?
Nach 'dauernd AN oder dauernd AUS' sieht'S schon Mal nicht aus - bisher sieht's eher nach 'Teich nach 10 Minuten wieder abschalten' aus - blöd ist halt, daß nach dieser Abschaltung die Ausgänge immer wieder abgeschaltet werden - egal, welche Funktion Du noch so aufrufst.
Vll. hilft Dir ein Flag - ein Merker, daß Du die 'Teich-Automatik' gestartet hast und Diese eben NUR beenden willst, wenn Diese läuft.

if (teichautomatik==high && millis()-startmillis>wartezeit){
   teichautomatik=low;
   stoppe ALLES
}

Dann musst Du natürlich bei TeichON dieses Flag auch setzen - und zum Testen würde ich eher 10 Sekunden, als zehn Minuten einstellen.

MfG

postmaster-ino:
Vll. hilft Dir ein Flag - ein Merker, daß Du die ‘Teich-Automatik’ gestartet hast und Diese eben NUR beenden willst, wenn Diese läuft.

if (teichautomatik==high && millis()-startmillis>wartezeit){

teichautomatik=low;
  stoppe ALLES
}



Dann musst Du natürlich bei TeichON dieses Flag auch setzen - und zum Testen würde ich eher 10 Sekunden, als zehn Minuten einstellen.

Vielen Dank! Das war genau das Beispiel was ich gebraucht habe um es endlich zu kapieren :slight_smile:
Eigentlich wurde mir die Lösung ja schon vorgelegt, aber ich habe einfach nicht verstanden wie ich es anwenden muss…

gregorss:
Letztlich läuft es auf einen endlichen Automaten hinaus. Vielleicht hilft das hier. Eine sehr gute Erläuterung dieser „Programmierstrategie“ ist die Nachtwächter-Erklärung.

Hier noch mal der fertige Code, falls jemand anderes es vielleicht noch mal gebrauchen kann:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

const int relay1_gpio = 5; //Valve NO
const int relay2_gpio = 4; //Valve NC
const int relay3_gpio = 14; //Garden-Pump

unsigned long startMillis;
unsigned long currentMillis;
int timer = LOW;
const unsigned long period = 600000; //(10 Minutes = 600000ms)

const char* host = "Pumpe-WebUpdate";
const char* ssid     = "WLAN";
const char* password = "******";

ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdater;

void handle_root() {
  server.send(200, "text/plain", "Hi there, try something else!");
  delay(100);
}

void RelayOneON() {
  digitalWrite(relay1_gpio, LOW);
  server.send(200, "text/plain", "Relay ONE (Valve NO) activated");
  delay(100);
}
void RelayTwoON() {
  digitalWrite(relay2_gpio, LOW);
  server.send(200, "text/plain", "Relay TWO (Valve NC) activated");
  delay(100);
}
void RelayThreeON() {
  digitalWrite(relay3_gpio, LOW);
  server.send(200, "text/plain", "Relay THREE (Garden-Pump) activated");
  delay(100);
}


void RelayOneOFF() {
  digitalWrite(relay1_gpio, HIGH);
  server.send(200, "text/plain", "Relay ONE (Valve NO) deactivated");
  delay(100);
}
void RelayTwoOFF() {
  digitalWrite(relay2_gpio, HIGH);
  server.send(200, "text/plain", "Relay TWO (Valve NC) deactivated");
  delay(100);
}
void RelayThreeOFF() {
  digitalWrite(relay3_gpio, HIGH);
  server.send(200, "text/plain", "Relay THREE (Garden-Pump) deactivated");
  delay(100);
}

void TimerTeichON() {
  digitalWrite(relay1_gpio, LOW);
  digitalWrite(relay2_gpio, LOW);
  digitalWrite(relay3_gpio, LOW);
  server.send(200, "text/plain", "All Relays activated");
  timer = HIGH;
  startMillis = millis();
}
void TimerTeichOFF() {
  digitalWrite(relay1_gpio, HIGH);
  digitalWrite(relay2_gpio, HIGH);
  digitalWrite(relay3_gpio, HIGH);
  server.send(200, "text/plain", "All Relays deactivated");
}

void setup()
{
  pinMode(relay1_gpio, OUTPUT);
  pinMode(relay2_gpio, OUTPUT);
  pinMode(relay3_gpio, OUTPUT);
  digitalWrite(relay1_gpio, HIGH);
  digitalWrite(relay2_gpio, HIGH);
  digitalWrite(relay3_gpio, HIGH);

  Serial.begin(115200);

  // Connect to WiFi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("\nConnecting to WIFI");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("WIFI OK \n\n");
  Serial.print("IP address:\n");
  Serial.println(WiFi.localIP());

  server.on("/", handle_root);
  server.on("/r1-on", RelayOneON);
  server.on("/r2-on", RelayTwoON);
  server.on("/r3-on", RelayThreeON);

  server.on("/r1-off", RelayOneOFF);
  server.on("/r2-off", RelayTwoOFF);
  server.on("/r3-off", RelayThreeOFF);

  server.on("/teich", TimerTeichON);
  server.on("/alloff", TimerTeichOFF);

  server.begin();
  Serial.println("HTTP Server started");
  delay(500);

  MDNS.begin(host);

  httpUpdater.setup(&server);
  server.begin();

  MDNS.addService("http", "tcp", 80);
  Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host);
}


void loop()
{
  currentMillis = millis();
  if (timer == HIGH && currentMillis - startMillis >= period) {
    timer = LOW;
    digitalWrite(relay1_gpio, HIGH);
    digitalWrite(relay2_gpio, HIGH);
    digitalWrite(relay3_gpio, HIGH);
  }
  server.handleClient();
}

Hi

Super, daß Das jetzt funktioniert und für Deine Rückmeldung.
Wir sehen uns dann beim nächsten Problem :wink:

MfG