wieder mal eine Intervall-Frage

Hallo in die Runde,

blink without delay ist ja schon oft hilfreich gewesen, bei meinem aktuellen Problem hänge ich aber dennoch.

Ein Temperatursensor liefert mir die Temperatur eines Wärmeschrankes und wenn diese zwischen 25 und 40°C ist soll die Heizspirale für 1 Minute an und dann für 3 Minuten aus sein.

Die restlichen Aktionen des Sketches (Thingspeak-Upload und Temperaturmessung) sollen ganz normal weiterlaufen, daher möchte ich nicht für die 3 Minuten in der Schleife “festhängen”, sondern mittels Abfrage einfach nur Prüfen, ob die Heizspirale schon 3 Minuten aus ist, wie realisiere ich das am Besten?

Irgendwie habe ich einen Knoten im Hirn und kriege es nicht hin die notwendigen Variablen und Abfragen dieser richtig hintereinander zu biegen.

Bislang sieht der relevante Teil meines Sketches leider nur so aus (PIN 6 steuert das Relais der Heizleitung):

   if (celsius < 20) {   //bei Temperaturen <20°C soll Dauerheizung möglich sein
    
       digitalWrite(6, HIGH);
     }
  
  if (celsius >20) {      //ab 20°C Heizung für 1 Minute an und 3 Minuten aus
       
          if (celsius < 40) {

//hier so der Code zum Einschalten des Relais für 1 Minuten und Ausschalten für 3 Minuten hin
         
     
          }
    
          if (celsius > 40) {
          digitalWrite(6, LOW);
     
  }

 }

Ich Danke Euch für Eure Ideen!

sondern mittels Abfrage einfach nur Prüfen, ob die Heizspirale schon 3 Minuten aus ist, wie realisiere ich das am Besten?

Beim Abschalten den aktuellen millis() Wert abspeichern und evtl. eine Zustandsvariable (ob an oder aus). Dann kannst du einfach abfragen ob die Zeit schon abgelaufen ist

noiasca:
Ausschaltzeit bzw millis() in einer long Variable merken

Da passt die nicht richtig rein, das ergibt unter Umständen negative Werte.
Es muss eine unsigned long Vatiable (oder uint32_t) sein.
Gruß Tommy

Hi

Das ist doch genau das Probel, Welches mit 'Blink without delay' umgangen wird.
Deshalb befürchte ich, daß Dir der Grundgedanke dahinter doch noch nicht so ganz klar geworden ist.

Wie meine Vorschreiber schon äußerten, Du prüfst IMMER nur, ob ein Zeitpunkt erreicht wurde, wenn, arbeitest Du diesen Schritt ab und merkst Dir erneut, daß Du 'gearbeitet hast' - also den aktuellen millis()-Wert wieder aufschreiben.
Beim nächsten Loop-Durchlauf wird wieder genau die gleiche Prüfung durchgeführt, dieses Mal ist aber erst eine Millisekunde vergangen, weshalb die Abarbeitung hier erst wieder greift, wenn die Zeit um ist.

On Du Dir jetzt millis() nur merkst, wenn Du die Heizung einschaltest oder auch beim Umschalten, ist Dir überlassen - ändert dann aber die Abfragen nach der vergangenen Zeit,
Wenn Da Probleme auftauchen, können wir uns Das aber ebenfalls gerne Mal anschauen.

MfG

(deleted)

#include <CombieTimer.h>

// Puls Pausen Generator 
Combie::Timer::PpmGenerator ppg(1UL * 60 * 1000,2UL * 60 * 1000);

const byte heizung = 6;

void heizungsAbhandlung()
{
   int celsius = 32; // Messwert
   bool heizAnforderung = ppg;

   if (celsius < 20)
   {
       digitalWrite(heizung,HIGH);
       return;
   }

   if(celsius > 40)
   {
     digitalWrite(heizung,LOW);
     return;
   }
   
   digitalWrite(heizung,heizAnforderung);
}

void setup() 
{
  pinMode(heizung,OUTPUT);
}

void loop() 
{
  heizungsAbhandlung();
 }

CombieLib.zip (31.3 KB)

warum nimmst du keinen PID-Regler mit Relais-Steuerung. Damit kannst du die Temperatur genau auf einen festen Wert einstellen und musst nicht mit Intervallen arbeiten.

Das habe ich zuerst auch gemacht (unter 40° heizen, sonst abschalten). Das hatte aber zur Folge, dass die Heizung insgesamt so lange lief, dass die Luft im Wärmeschrank auf ca. 50°C erhitzt wird und durch die verzögerte Reaktion des Temperatursensors die Werte dann zwischen 37° und ca 50°C schwanken. Durch die rel. kurze Einschaltzeit von 1 Minute soll die Wärme im Schrank langsamer ansteigen und dann konstanter bei ca. 40° gehalten werden. Das genaue Verhältnis zwischen Ein- und Ausschaltzeit werden ich dann in längeren Versuchsreihen ausprobieren.

Das habe ich zuerst auch gemacht (unter 40° heizen, sonst abschalten).

Du hast nicht verstanden.

Das ist eine "Ein Punkt Regelung".
Das hat nichts mit PID und Relais-PWM zu tun.

(deleted)

Du hast nicht verstanden.

Das ist eine "Ein Punkt Regelung".
Das hat nichts mit PID und Relais-PWM zu tun.

Das stimmt, verstanden habe ich das wirklich nicht.

Dieser Passus hier

Damit kannst du die Temperatur genau auf einen festen Wert einstellen und

schien mir aber dem zu entsprechen was ich vorher versucht habe, sorry, war mir zu hoch.

Eifler:
sorry, war mir zu hoch.

Neben dem Blinken mit millis() brauchst Du noch eine Schrittkette (endlicher Automat, finite state machine). Ich mag die mit switch/case. Ist das was für Dich?

const byte pinEingang = A0;
const byte pinAusgang = 6;
const uint32_t einIntervall = 3000, ausIntervall = 5000, blinkIntervall = 200;
uint32_t aktMillis, schaltMillis, blinkMillis;
enum {WARTEN, EIN, AUS};
byte celsius, schritt = WARTEN;
bool einmal;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pinAusgang, OUTPUT);
}

void loop() {
  aktMillis = millis();
  switch (schritt)
  {
    case WARTEN:
      celsius = analogRead(A0) / 10;
      if (celsius < 20) {   //bei Temperaturen <20°C soll Dauerheizung möglich sein
        digitalWrite(pinAusgang, HIGH);
      }
      else if (celsius > 40) {
        digitalWrite(pinAusgang, LOW);
      }
      else if (celsius > 20) {     //ab 20°C Heizung für 1 Minute an und 3 Minuten aus
        einmal = true;
        schritt = EIN;
      }
      break;
    case EIN:
      if (einmal)
      {
        einmal = false;
        digitalWrite(pinAusgang, HIGH);
        schaltMillis = aktMillis;
      }
      if (aktMillis - schaltMillis >= einIntervall)
      {
        einmal = true;
        schritt = AUS;
      }
      break;
    case AUS:
      if (einmal)
      {
        einmal = false;
        digitalWrite(pinAusgang, LOW);
        schaltMillis = aktMillis;
      }
      if (aktMillis - schaltMillis >= ausIntervall)
      {
        einmal = true;
        schritt = WARTEN;
      }
      break;
  }
  if (aktMillis - blinkMillis >= blinkIntervall)  // Herzschlag als Beweis für blockadearmes Programmieren
  {
    blinkMillis = aktMillis;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}