Arduino Temperatur und Zeitsteuerung

Hallo,

Ich bin Frank und bastel an einer Temperatur und Zeitsteuerung für unsere Heizung. Im Momemt läuft sie nur Zeit gesteuert. Die Tage kommen die Temperaturfühler.
Nun weiss ich aber nicht wie ich beides zusammen bekomme.
Wie kann ich zwischen 10.00 und 20.00 die Temperatur messen und daraus dann laufend den Mittelwert bilden?

Ich benutze einen Nano mit Echtzeituhr.

Viele Grüße

Frank

obelixus:
Nun weiss ich aber nicht wie ich beides zusammen bekomme.
Wie kann ich zwischen 10.00 und 20.00 die Temperatur messen und daraus dann laufend den Mittelwert bilden?

Wie fit bist Du in Sachen Programmierung?

Für die Mittelwertbildung würde ich einen „Container“ programmieren - ein Array mit sagen wir mal 10 Elementen, die regelmäßig (alle 10 Minuten oder so) mit Messwerten befüllt werden. Alle 10 Minuten den Durchschnitt zu errechnen ist trivial.

Das Ganze würde ich wohl in einen endlichen Automaten tun. Evtl. hilft mein Geschreibsel dazu.

Gruß

Gregor

Hallo,
wenn Dir Std/Min als int zur Verfügung steht, dann kannst Du mit modulo die Zeitabstände festlegen.
Den Rest machst Du wie gregorss schon sagte.
Das Array würde ich als Ringpuffer füllen. Der neuste Wert wirft den ältesten hinten raus. So hast Du es lfd.
Gruß und Spaß
Andreas

Hi

Für den Mittelwert gibt's auch eine Lib.
Die RTC kannst Du Dir mit einem Beispiel-Sketch zu der RTC 1x stellen.
Eine Korrektur sollte danach eigentlich nicht mehr nötig sein - ich würde mir eine Uhrzeit-Setz-Routiene deshalb im Heizungs-Sketch später sparen.

MfG

postmaster-ino:
Für den Mittelwert gibt's auch eine Lib.

Wieso zur Hölle braucht man eine Bibliothek, um einen Durchschnitt auszurechnen?! Enthält die Bibliothek irgendwelche Sachen, die über eine simple Division hinausgehen?

Gruß

Gregor

tschuldigung - zur Hölle, gibt's Das - MEHR steht dort nicht, was Du Dir Da rein interpretierst, solltest Du vll. Zuhause bei einer Tasse Kaffee mit Deiner Spülmaschine klären.

postmaster-ino:
tschuldigung - zur Hölle, gibt's Das - MEHR steht dort nicht, was Du Dir Da rein interpretierst, solltest Du vll. Zuhause bei einer Tasse Kaffee mit Deiner Spülmaschine klären.

Du hast anscheinend meine Fragen nicht verstanden. Macht nichts.

Gruß

Gregor

Hallo,
vielleicht hat er MedianLib gemeint- den ICH bei der Steuerung vorziehe, und sich unglücklich ausgedrückt.
Gruß und Spaß
Andrea

Hi

Nein, Die Median-Lib (Die, bzw. auch den 'Median' selber, ich hier im Forum erst kennen lernen durfte) ist ganz gut für z.B. Echo-Sensoren (HC-SR04), um Ausreißer abzuwehren.
Welche Lib ist für einen 'normalen' Mittelwert gefunden hatte, müsste ich nachsehen.
Mir ist durchaus bewusst, daß ein Mittelwerk jetzt keine größeren Hexen-Kuststückchen verlangen - mir stieß das 'zur Hölle' irgendwie ungesund auf - hier, ich werde Da Mal ein Nächtle drüber schlafen - ist eh wieder spät genug geworden.

MfG

Danke für eure Antworten!

Ich hab nicht wirklich Ahnung vom Programmieren, noch nicht.
Ich muss mir das was ihr schreibt genau durchlesen und dann im Internet was dazu suchen und dann hoffen das ich es verstehe und dann hin bekomme.
Ich kann ja gleich auch mal meinen Sketch reinstellen wie ich das bis jetzt mit den Temperaturen habe. Da fehlt aber noch die Zeit und die Durchschnittstemperatur.

obelixus:
Ich hab nicht wirklich Ahnung vom Programmieren, noch nicht.

Dann hast Du vermutlich erst damit angefangen, mit dem Arduino zu spielen.

Nachdem ich meine Merkzettel aufgebohrt und dabei gemerkt habe, dass mir die Schreiberei Spaß macht, habe ich ein paar Sachen ins Netz geworfen. Evtl. ist da auch etwas für Dich dabei. Siehe hier und hier.

Gruß

Gregor

Am Anfang wollte ich ja nur fertigen Code benutzen, das hat aber nie gepasst. Dann hab ich mir alles zusammen gesucht für meine Temperatursteuerung.
Die würde wohl auch funktionieren. Wir haben aber jetzt gemerkt das wir ab so 5 Grad Tagestemperatur Nachts keine Heizung brauchen, da bringt der Holzofen genug wärme.
Das soll denn nun auch mit rein.

Das ist so mein Ziel im Moment. Und wenn ich es dann wirklich mal ganz gut kann ubd ich Lust hab könnte ich ja noch die Funkthermostate mit rein programmieren, aber das ist mir jetzt noch viel zu viel...

//Pin Definition
int Umwaelzp         = 9;    //output relais Umwälzpumpe
int Brenner         = 10;    //output relais Brenner
int Infrarotheizung = 11;    //Schütz Infrarotheizungen
int Nele_Bad        = 12;    //Elektroheizung Nele Bad
int Taster_Urlaub = 4;       //input Taster Urlaub (Frostschutz)

//Variablen
int Kessel          = 0;       //Temperatur Kessel   
int Aussen          = 0;       //Temperatur Aussen
int Wasser          = 0;       //Temperatur Warmwasser
int R_Soll_Temp     = 0;       //Sollwert Temperatur Kessel
int Bad_Nele_Temp   = 0;       //Sollwert Temperatur Nele Bad

// später Urlaubstaster
unsigned long Zeit_Tdruck = 0; //Zeitpunkt Taster betätigt

/*******************************************************************************************************************************************************/

int Hyst         = 2;         //Hysterese Brenner, gewünschte Hysterese durch 2 geteilt

/*******************************************************************************************************************************************************/

void setup() 
{                
  pinMode(Brenner, OUTPUT);
  pinMode(Umwaelzp, OUTPUT);
  pinMode(Infrarotheizung, OUTPUT);
  pinMode(Nele_Bad, OUTPUT);
  pinMode(Taster_Urlaub, INPUT);    //Pulldown Hardwaremäßig, HIGH bei betätigtem Taster

  digitalWrite(Brenner, LOW); 
  digitalWrite(Umwaelzp, LOW);
  digitalWrite(Infrarotheizung, LOW);
  digitalWrite(Nele_Bad, LOW);  
}

void loop() {
  /*******************************************************************************************************************************************************/
  //Berechnung der Temperaturen je Dezimalwert (10-Bit A/D), Faktor hundert, da 10mV SesorSignal = 1°C (LM35 ohne Verstärkung, TMP36 für Aussen)
  Kessel           = analogRead(A1) * (5.00/1023) * 100;   
  Aussen           = analogRead(A2) * (200/409) - 50;
  Wasser           = analogRead(A3) * (5.00/1023) * 100;
  Bad_Nele_Temp    = analogRead(A3) * (5.00/1023) * 100;  

  //R_Soll_Temp aus Aussentemperatur berechnen
  R_Soll_Temp = map(Aussen,-20,20,85,55);      //Sollwert Kessel nach Aussentemperatur.

  /*******************************************************************************************************************************************************/
  //Umwälzpumpe-/ Sommerregelung
  if      (Aussen <= 19) //Aussentemperatur unter 19°C Umwälzpumpe EIN
  { 
    digitalWrite(Umwaelzp,  HIGH);  
  }
  else if (Aussen >= 20) //Aussentemperatur über 20°C Umwälzpumpe AUS
  { 
    digitalWrite(Umwaelzp,  LOW);   
  }

  /*******************************************************************************************************************************************************/
  //Brenner Regelung
  if      (Kessel <= R_Soll_Temp - Hyst || Wasser <= 45) //Wenn Rücklauf oder Wasser zu kalt, Brenner EIN
  { 
    digitalWrite(Brenner,  HIGH);  
  }
  else if (Kessel == R_Soll_Temp + Hyst && Wasser >=55) //Wenn Rücklauf warm und Kessel und Wasser >=55°C Brenner AUS
  { 
    digitalWrite(Brenner,  LOW);   
  }
}

Das ist mal mein Code. Nele Bad und Infrarotheizungen gibt es noch nicht. Da kann ich doch Uhrzeiten wann was schalten soll mit in die "IF" Zeilen nehmen?
Kann ich das nicht so machen wie in dem Code unten, aber nur die Stunden nutzen? Oder muß ich auch Minuten nutzen?

{
  RTC.getTime();
  // Start Pumpe
  if (int(RTC.hour) == pumphour && int(RTC.minute) == pumpminute && int(RTC.second) == pumpsecond)
  {
    digitalWrite(pumppin, HIGH);
    timenow = RTC.time2000;
  }

Und dann kann ich doch wenn die RTC Zeit >= Einschaltzeit ist einschalten und wenn die RTC Zeit >=Auschaltzeit ist ausschalten?

Deine Code-Idee schaltet eine Sekunde lang den pumppin ein und lässt ihn in der übrigen Zeit unverändert.
Das ist besonders beim Neustart ungünstig, da du bis zu einem ganzen Tag lang warten musst. (Ausserdem fehlt das Ausschalten).

Deine andere Idee ist einfacher, wenn du aus Stunde:Minute eine einzelne Zahl machst.
Da gibt es zwei Glaubensrichtungen: stunde100+minute ist leichter lesbar, stunde60+minute gibt mehr Sinn, da es die Anzahl Minuten im aktuellen Tag sind.
Diese Zahl mit entsprechenden Start und Endezahlen vergleichen.

const unsigned int TAG = 455;  // 04:55  Einschaltzeitpunkt
const unsigned int NACHT = 2130;  // Ausschaltzeitpunkt
...
unsigned int dt = RTC.hour*100 + RTC.minute;

bool tagnacht = ( TAG <= dt && dt < NACHT );  // TRUE ist tagsüber

oder

const unsigned int TAG = 4*60+55;  // 04:55  Einschaltzeitpunkt
const unsigned int NACHT = 21*60+30;  // Ausschaltzeitpunkt
...
unsigned int dt = RTC.hour*60 + RTC.minute;

bool tagnacht = ( TAG <= dt && dt < NACHT );  // TRUE ist tagsüber

tagnacht kann man übersichtlich mit anderen Bedingungen ( Temperatur ) verknüpfen.

Danke an alle!

@ michael_X

Das mit bool ist ja eine gute Sache! Das hilft mir bei einem Problem auf jedenfall weiter. Aber ich verstehe nicht warum das bei mir in "IF" nicht funktioniert. Ich wollte die Pumpe, bzw. Brenner ausschalten wenn bool nachtaus nicht True ist...

bool nachtaus = ( TAG <= dt && dt < NACHT && Aussen <= 5);  // TRUE ist tagsüber

  /*******************************************************************************************************************************************************/
  //Umwälzpumpe-/ Sommerregelung
  if      (Aussen <= 19) //Aussentemperatur unter 19°C Umwälzpumpe EIN
  { 
    digitalWrite(Umwaelzp,  HIGH);  
  }
  else if (Aussen >= 20  || nachtaus ! true) //Aussentemperatur über 20°C oder Nachtabschaltung über 5°C Umwälzpumpe AUS
  { 
    digitalWrite(Umwaelzp,  LOW);   
  

  /*******************************************************************************************************************************************************/
  //Brenner Regelung
  if      (Kessel <= R_Soll_Temp - Hyst || Wasser <= 45) //Wenn Kessel oder Wasser zu kalt, Brenner EIN
  {
    digitalWrite(Brenner,  HIGH);
  }
  else if (Kessel == R_Soll_Temp + Hyst && Wasser >=55  || nachtaus ! true) //Wenn Kessel warm und Wasser >=55°C Brenner AUS
  { 
    digitalWrite(Brenner,  LOW);   
  }

Meinst du vielleicht

else if (Aussen >= 20  || ! nachtaus )

Auch möglich nachtaus != true
oder nachtaus == false
zu schreiben.

Ich hab es glaube ich nun:

bool nachtaus = ( TAG <= dt && dt < NACHT && Aussen <= 5);  // TRUE ist tagsüber

  /*******************************************************************************************************************************************************/
  //Umwälzpumpe-/ Sommerregelung
  if      (Aussen <= 19) //Aussentemperatur unter 19°C Umwälzpumpe EIN
  { 
    digitalWrite(Umwaelzp,  HIGH);  
  }
  else if (Aussen >= 20 || ! (nachtaus=true)) //Aussentemperatur über 20°C oder Nachtabschaltung über 5°C Umwälzpumpe AUS
  { 
    digitalWrite(Umwaelzp,  LOW);   
  

  /*******************************************************************************************************************************************************/
  //Brenner Regelung
  if      (Kessel <= R_Soll_Temp - Hyst || Wasser <= 45) //Wenn Kessel oder Wasser zu kalt, Brenner EIN
  {
    digitalWrite(Brenner,  HIGH);
  }
  else if (Kessel == R_Soll_Temp + Hyst && Wasser >=55  || ! (nachtaus=true)) //Wenn Kessel warm und Wasser >=55°C Brenner AUS
  { 
    digitalWrite(Brenner,  LOW);   
  }

michael_x:
Meinst du vielleicht

else if (Aussen >= 20  || ! nachtaus )

Auch möglich nachtaus != true
oder nachtaus == false
zu schreiben.

Ach, so einfach kann ich das da mit rein nehmen?
Ohne die Klammern die ich jetzt da habe?
Das geht ja wirklich mit "nachtaus==false". Vielleicht hab ich vorhin das zweite= vergessen, auf jedenfall ging es vorher nicht...

Wenn ich dann mal die Echtzeituhr am laufen habe könnte ich ja für den Durchschnitt der Aussentemperatur das ja dann auch mit "Bool" machen.

bool tagtemp = ( TAGTEMP <= dt1 && dt2< NACHTTEMP); // TRUE ist tagsüber

So lange wie tagtemp == true ist kann ich dann den Tagesdurchschnitt messen lassen???

Ich hab es glaube ich nun

Ich glaube nicht :slight_smile:

(nachtaus=true) ist formal gültig, aber keine Abfrage! Du meinst evtl.

(nachtaus==true)

Ausserdem suggeriert der Name nachtaus für mich, dass etwas gemacht wird, weil es nachts auszuschalten ist. (?)

Was du definierst, ist
( TAG <= dt && dt < NACHT && Aussen <= 5);  // tagsüber bei großer Kälte.

Wenn du stattdessen meinst "tagsüber oder wenn es ziemlich kalt ist", wäre das

bool pumpBetrieb = ( TAG <= dt && dt < NACHT) || (Aussen <= 5);

Aber ich würde eine Zeit-Bedingung isTagsueber unabhängig von einer Temperatur-Prüfung machen.
Logik ist generell kompliziert, selbst wenn man die Bedeutung einer Variablen einfach erkennen kann.
Lieber bei Bedarf noch eine weitere Variable erfinden.

Das else if in deiner Zeile 8 hat einen nicht geschlossenen Block, daher kann ich nicht erkennen, ob ein abschließendes else fehlt oder nicht.

Aber trauen würde ich deiner dadurch unverständlichen Programmlogik erstmal nicht, sorry :wink:

( TAG <= dt && dt < NACHT && Aussen <= 5); // tagsüber bei großer Kälte.

Damit sage ich doch das etwas ausgeschaltet wird wenn es tagsüber ist und es tagsüber kälter ist wie 5 Grad.
Und wenn ich das dann als false nehme wird die Pumpe und der Brenner ausgeschaltet wenn es NICHT tagsüber ist und es tagsüber NICHT kälter als 5 Grad war?

Hier ist mal alles was ich habe:

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);  //(Adresse/Zeichen pro Zeile/Anzahl Zeilen)
#include <Wire.h>
#include <DS3231.h>
DS3231  rtc(SDA, SCL);  // Init the DS3231 using the hardware interface
Time t;


//Pin Definition
int Umwaelzp         = 9;    //output relais Umwälzpumpe
int Brenner         = 10;    //output relais Brenner
int Infrarotheizung = 11;    //Schütz Infrarotheizungen
int Nele_Bad        = 12;    //Elektroheizung Nele Bad
int Taster_Urlaub = 4;       //input Taster Urlaub (Frostschutz)

//Variablen
int Kessel          = 0;       //Temperatur Kessel   
int Aussen          = 0;       //Temperatur Aussen
int Wasser          = 0;       //Temperatur Warmwasser
int R_Soll_Temp     = 0;       //Sollwert Temperatur Kessel
int Bad_Nele_Temp   = 0;       //Sollwert Temperatur Nele Bad
int dt              = 0;       //Uhrzeit zum Schalten und Messen
const unsigned int TAG = 6*60+0;  // 06:00  Einschaltzeitpunkt
const unsigned int NACHT = 21*60+0;  // 21:00 Ausschaltzeitpunkt
const unsigned int TAGTEMP = 8*60+0;  // 08:00  Mess beginn
const unsigned int NACHTTEMP = 18*60+0;  // 18:00 Mess Ende

// später Urlaubstaster
unsigned long Zeit_Tdruck = 0; //Zeitpunkt Taster betätigt
/*******************************************************************************************************************************************************/

int Hyst         = 0;         //Hysterese Brenner nach Aussentemperatur, gewünschte Hysterese durch 2 geteilt

/*******************************************************************************************************************************************************/

void setup() 
{                
  pinMode(Brenner, OUTPUT);
  pinMode(Umwaelzp, OUTPUT);
  pinMode(Infrarotheizung, OUTPUT);
  pinMode(Nele_Bad, OUTPUT);
  pinMode(Taster_Urlaub, INPUT);    //Pulldown Hardwaremäßig, HIGH bei betätigtem Taster

  digitalWrite(Brenner, LOW); 
  digitalWrite(Umwaelzp, LOW);
  digitalWrite(Infrarotheizung, LOW);
  digitalWrite(Nele_Bad, LOW);
  lcd.init();
  lcd.backlight(); //Hintergrundbeleuchtung einschalten (0 schaltet die Beleuchtung aus).  
  rtc.begin();			// Initialize the rtc object
}

void loop() {

  /*******************************************************************************************************************************************************/
  //Berechnung der Temperaturen je Dezimalwert (10-Bit A/D), Faktor hundert, da 10mV SesorSignal = 1°C (LM35 ohne Verstärkung, TMP36 für Aussen)
  Kessel           = analogRead(A1) * (5.00/1023) * 100;   
  Aussen           = analogRead(A2) * (200/409) - 50;
  Wasser           = analogRead(A3) * (5.00/1023) * 100;
  Bad_Nele_Temp    = analogRead(A3) * (5.00/1023) * 100;  

  //R_Soll_Temp aus Aussentemperatur berechnen
  R_Soll_Temp = map(Aussen,-20,20,85,55);      //Sollwert Kessel nach Aussentemperatur.

  //Hyst aus Aussentemperatur berechnen
  Hyst = map(Aussen,-20,20,1,5);      //Hysterese nach Aussentemperatur.

  //Schaltzeiten Pumpe und Brenner ab 5°C Aussentemperatur
  bool nachtaus = (TAG <= dt && dt < NACHT && Aussen <= 5);  // TRUE ist tagsüber
  bool tagtemp = (TAGTEMP <= dt && dt < NACHTTEMP);  // TRUE ist tagsüber
  
  /*******************************************************************************************************************************************************/
  //Umwälzpumpe-/ Sommerregelung
  if      (Aussen <= 19) //Aussentemperatur unter 19°C Umwälzpumpe EIN
  { 
    digitalWrite(Umwaelzp,  HIGH);  
  }
  else if (Aussen >= 20 || nachtaus==false) //Aussentemperatur über 20°C oder Nachtabschaltung über 5°C Umwälzpumpe AUS
  { 
    digitalWrite(Umwaelzp,  LOW);   


    /*******************************************************************************************************************************************************/
    //Brenner Regelung
    if      (Kessel <= R_Soll_Temp - Hyst || Wasser <= 45) //Wenn Kessel oder Wasser zu kalt, Brenner EIN
    {
      digitalWrite(Brenner,  HIGH);
    }
    else if (Kessel == R_Soll_Temp + Hyst && Wasser >=55  || nachtaus==false) //Wenn Kessel warm und Wasser >=55°C Brenner AUS
    { 
      digitalWrite(Brenner,  LOW);   
    }

    /*******************************************************************************************************************************************************/
  
  //Uhrzeit holen
  t = rtc.getTime();	// Get data from the DS3231
  int stunden = t.hour;
  int minuten = t.min;
  int sekunden = t.sec;
  int sekseitmit = sekunden + (minuten * 60) + (stunden * 60 * 60);
  int dt = t.hour*60 + t.min; 
  long unixzeit = rtc.getUnixTime(t);
 

   
    //Display Anzeige
    {
      lcd.setCursor(0,0);             //Erste Ziffer Position, Zweite Ziffer Zeile
      lcd.print("Aussen");
      lcd.setCursor(0,1);
      lcd.print("Kessel");
      lcd.setCursor(0,2);
      lcd.print("Wasser");
      lcd.setCursor(0,3);
      lcd.print("Brenner");
      lcd.setCursor(11,3);
      lcd.print("Pumpe");
    }
  }
}

Hi

EINschalten wenn Tagsüber UND kälter als 4 Grad
NICHT EINschalten wenn NICHT Tagsüber ODER NICHT kälter als 4 Grad

Durch das Negieren drehst Du ALLES um - aus dem UND wird ein ODER.
ALLES wird dabei 'umgedreht' !!

MfG