Temperatur und Zeit steuern

Kompiliert der Code bei dir?

z.B:
pinMode(StartP1ButtonPin, INPUTPULLUP);
Wirft eigentlich dir ein Fehler um die Ohren. Zumindest bei mir.

Da hast du natürlich Recht, Sorry.

Ob etwas gleich ist prüft man mit ==
Mit = weist man etwas zu

Warum nicht gleich gerade stellen? INPUT_PULLUP

pinMode(StartP1ButtonPin, INPUT_PULLUP);

Das:

#include <DallasTemperature.h>
#include <MobaTools.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

muss weiter höher. Am besten ganz nach oben.

Wenn ich Deinen Code nehme und da STRG-R drücke, kommen soviele Fehler.

const byte RelaisPin = 2;              
int StartP1ButtonPin =3;
int StartP2ButtonPin =4;
int StopButtonPin =5;
#define TempSensorPin = 6;

das relais ist noch richtig initialisiert, danach ist schon nicht gut, aber beim TempSensorPin ist es falsch.

Und dann gibts noch: Schreibfehler.
Einige wurden Dir ja schon genannt.
Fehlende Variablen.
usw.
Mach mal den Code einmal STRG-T, einmal STRG-R und dann solange, bis Du den Code fehlerfrei compilieren kannst.

Mich wundert, wie Du das festgestellt hast, da der Code ja zu viele Fehler enthält, und absolut nicht compilierbar ist. Vielleicht solltest Du den Code posten, mit dem Du das getestet hast.
Grundsätzlich kannst Du ja feststellen, ob der Timer bereits läuft ( timer.running() ), und ihn so nur starten, wenn er nicht schon läuft.
Und dann ist die Frage, was passieren soll, wenn der Timer abläuft. Dazu steht in deinem Code ja gar nichts.
Die Timer der MobaTools sind ja nicht blockierend wie ein delay. Der läuft sozusagen im HIntergrund, und in deinem Code musst Du abfragen, ob er inzwischen abgelaufen ist, und dann entsprechend reagieren.

P.S. ein paar Kommentare, was an den entsprechenden Stellen passieren soll, würden die Übersichlichkeit auch deutlich erhöhen. Auch macht es Sinn, deinen verschiedenen Status - Werten vernünftige Namen zu geben, und nicht nur 'magic numbers' zu verwenden. Das erhöht ebenfalls deutlich die Übersicht. Das wirst Du alles insbesondere dann schätzen lernen, wenn dein Programm erstmal läuft, und Du es in ein paar Monaten erweitern/ verbessern willst.

Hallo
Ich habe deinen Sketch gelesen und versucht ihn zu verstehen, dabei bin ich entgleist. :slight_smile:
Schreibe mit einfachen Worten das auf, was passieren soll und das ganz einfach.

Warnungen aktivieren dann bekommst du auch das angemeckert (es sei denn du hast einen 32 Bit Prozessor):

const long EinMaischZeit = 5*60*1000;     
...

Richtig:

const unsigned long EinMaischZeit = 5*60*1000UL;   

Wie schon gesagt alles, ertmal grob entworfen und noch nicht versucht zu kompilieren. Trotzdem Danke für die Hinweise. Der Hinweis, abzufragen ob der Timer schon läuft , sollte mich weiter bringen.
Grüße
Gerald

Das solltest Du regelmässig tun.
Dazu braucht es kein Board. einfach STRG-R.

Aber gut, wenn das nächste STRG-R hier nicht geht, dann brauch ich auch nicht nachsehen warum.
:frowning:

Hallo
Für das Design der Brauanlage schaue dir am Besten das EVA Prinzip an.
Damit kann man den Sketch sauber strukturieren.

So, hab es soweit umgeschrieben, dass es kompiliert werden konnte.
Die übrigen Prozessschritte muss ich noch ergänzen.
Zum testen fehlt mir auch noch die Hardware.
Aber ich denke die Rchtung stimmt jetzt.

#include <DallasTemperature.h>
#include <OneWire.h>
#include <MobaTools.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Button.h>

Button TasterProgramm1(2); 
Button TasterProgramm2(3); 
Button TasterStop(4); 
const byte RelaisPin = 5;
#define TempSensorPin 6

unsigned  long      EinMaischZeit = 5*60*1000;     
unsigned long      FerulaRastZeit = 5*60*1000; 
unsigned long      EiWeisRastZeit = 20*60*1000; 
unsigned long      MaltoseRastZeit = 40*60*1000; 
unsigned long      ZuckerRastZeit = 45*60*1000; 
unsigned long      AbMaischZeit = 35*60*1000; 
unsigned long      LaeuterRuheZeit = 20*60*1000; 
unsigned long      BitterHopfenZeit = 10*60*1000;
unsigned long      AromaHopfenZeit = 70*60*1000;
unsigned long      WhirlPoolZeit = 20*60*1000;

const byte      EinMaischTemp = 50;     
const byte      FerulaRastTemp = 51; 
const byte      EiWeisRastTemp = 57; 
const byte      MaltoseRastTemp = 63; 
const byte      ZuckerRastTemp = 72; 
const byte      AbMaischTemp = 78; 
const byte      LaeuterRuheTemp = 0; 
const byte      BitterHopfenTemp = 0;
const byte      AromaHopfenTemp = 0;
const byte      WhirlPoolTemp = 0;

float IstTemp;

OneWire           oneWire(TempSensorPin);
DallasTemperature sensors(&oneWire);
DeviceAddress     tempDeviceAddress;


int Status;
int TempStatus;
int StatusName;

// 0 -> Stop
// 1 -> Programm 1 Maischen usw.
// 2 -> Programm 2 Kochen
// 11 -> Einmaischen
// 12 -> Ferularast
// 13 -> Eiweisrast
// 14 -> Maltoserast
// 15 -> Zuckerrast
// 16 -> Abmaischen
// 17 -> Laeutern
// 21 -> Bitterhopfenkochen
// 22 -> AromahopfenKochen
// 23 -> Whirlpool

LiquidCrystal_I2C lcd(0x27, 16, 2);
MoToTimer Zeitgeber;
//Grad Symbol
byte Degree[] = {
  B00111,
  B00101,
  B00111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

void setup()
{
  TasterProgramm1.begin();
  TasterProgramm2.begin();
  TasterStop.begin();
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print(" Brauprogramm ");
  sensors.begin();
  pinMode(RelaisPin, OUTPUT);
  Status = 0;
  lcd.createChar(0, Degree);
}

void loop()
{
  sensors.requestTemperatures();
  IstTemp = sensors.getTempCByIndex(0);

  
// 11 -> Einmaischen
// 12 -> Ferularast
// 13 -> Eiweisrast
// 14 -> Maltoserast
// 15 -> Zuckerrast
// 16 -> Abmaischen
// 17 -> Laeutern
// 21 -> Bitterhopfenkochen
// 22 -> AromahopfenKochen
// 23 -> Whirlpool
 if (Status = 0)
  {
    lcd.setCursor(0,0);
    lcd.print("Start P1 o P2   ");
  }
  else if (Status=11)
  {
    lcd.setCursor(0,0);
    lcd.print("Einmaischen     ");
  }
  else if (Status=12)
  {
    lcd.setCursor(0,0);
    lcd.print("Ferularast      ");
  }
  else if (Status=13)
  {
    lcd.setCursor(0,0);
    lcd.print("Eiweisrast      ");
  }
  else if (Status=14)
  {
    lcd.setCursor(0,0);
    lcd.print("Maltoserast     ");
  }
  else if (Status=15)
  {
    lcd.setCursor(0,0);
    lcd.print("Zuckerrast      ");
  }
  else if (Status=16)
  {
    lcd.setCursor(0,0);
    lcd.print("Abmaischen      ");
  }
  else if (Status=17)
  {
    lcd.setCursor(0,0);
    lcd.print("Laeutern        ");
  }
  else if (Status=21)
  {
    lcd.setCursor(0,0);
    lcd.print("Bitterhopfenkoch");
  }
  else if (Status=22)
  {
    lcd.setCursor(0,0);
    lcd.print("Aromahopfenkoch");
  }
  else if (Status=23)
  {
    lcd.setCursor(0,0);
    lcd.print("Whirlpool      ");
  }
  else
  {
    lcd.setCursor(0,0);
    lcd.print("unbekannter Stat");
  }
  
  
  lcd.setCursor(1,0);
  lcd.print("Isttemp.: ");
  lcd.print(IstTemp);
  lcd.write(0); //schreibt das Gradzeichen
  lcd.print("C");
  delay(30);
  if (TasterProgramm1.pressed() || Status == 11)
  {
    Status = 11;
    digitalWrite(RelaisPin, LOW);
    if (IstTemp==EinMaischTemp && Zeitgeber.running()== false)
    {
      Zeitgeber.setTime(EinMaischZeit);
    }
    if (IstTemp<EinMaischTemp+1)
    {
      digitalWrite(RelaisPin, LOW);
    }
    else
    {
      digitalWrite(RelaisPin, HIGH);
    }
    if (IstTemp>EinMaischTemp-1)
    {
      digitalWrite(RelaisPin, HIGH);
    }
    else
    {
      digitalWrite(RelaisPin, LOW);
    }
   
  }
  if ( Zeitgeber.expired() )
  {
   Status = 12;
  }
 if (Status=12)
 {

 }
}

Schau Dir #8 nochmals an.

Heißt das jetzt dein Eröffnungspost ist geklärt?
Oder steckst du noch bei

Edit: Wo und wie wird eigentlich die Variable Status geändert? Dies erkenne ich nicht im Code.

Das allein sagt noch nicht viel. Zwischen 'compilierbar' und 'funktioniert' ist noch ein weiter Weg. Als erstes solltest Du mal die Warnungen einschalten. In den allermeisten Fällen verbergen sich dahinter handfeste Fehler - auch wenn es syntaktisch richtig ist. Und Warnungen gibt es in deinem Sketch reichlich. Auf das meiste wurde auch schon hingewiesen.

für so eine Aufzählung::

bietet sich eine Enumeration, ein enum oder enum class an.

enum {
  STOP,                    // 0 -> Stop
  MAISCHEN,                // 1 -> Programm 1 Maischen usw.
  KOCHEN,                  // 2 -> Programm 2 Kochen
  EINMAISCHEN = 11,        // 11 -> Einmaischen
  FERULARAST,              // 12 -> Ferularast
  EIWEISRAST,              // 13 -> Eiweisrast
  MALTOSERAST,             // 14 -> Maltoserast
  ZUCKERRAST,              // 15 -> Zuckerrast
  ABMAISCHEN,              // 16 -> Abmaischen
  LAEUTERN,                // 17 -> Laeutern
  BITTERHOPFENKOCHEN = 21, // 21 -> Bitterhopfenkochen
  AROMAHOPFENKOCHEN,       // 22 -> AromahopfenKochen
  WHIRLPOOL                // 23 -> Whirlpool
};

verzichte auf "magic numbers", wenn was ABMAISCHEN heißt, nenn es so und verwende es so. Nicht im Code "16" verteilen.

1 Like

Ich finde, es hat auch Vorteile den Status mit Zahlen zu belegen. Die einzelnen Schritte beim Maischen müssen in einer exakten Reihenfolge ablaufen. Beim Programmieren muss ich nur auf die Zahlenfolge achten und nicht darauf welche Braustufe wann kommt.
Das Programm ist noch lange nicht fertig.
Mir ging es bei meiner Frage nur darum wie ich den Timer händeln muss ohne ihn im Zweipunktreglerteil immer neu zu starten. Ich denke, dass sollte jetzt funktionieren.
Danke für die Hilfe

Das eine hat mit dem anderen nicht viel zu tun.

Das ganze schreit nach endlichen Automaten.
Vielleicht auch nach einem Dutzend (oder mehr) davon.
Diese Automaten kann man schön in Arrays stopfen.
Nennt sich dann u.U. Schrittkette
Womit dann die Reihenfolge angenagelt ist.
Ganz ohne magische Zahlen im Programm.

Meine Erfahrung:
Magische Zahlen rächen sich.
Sie lauern im Schatten, im inneren von Funktionen, und schlagen genau dann zu, wenn man nicht mehr an sie denkt.
Und ja, das merken sie.

Das tun sie.
Innerhalb der enumeration legst Du die Position fest.

Was mich verwirrt, was ist mit Status 1-10 und 18-20?
Das mit dem Unterschied zwischen Zuweisung und Vergleich wurde Dir bereits mehrfach gesagt.

Lade Dir von hier: Code ausfüren wen 2 Bedinungen erfült sind(if) - #14 by my_xy_projekt das pdf am Ende meines Beitrages runter und lese Seite 15/16

Das hier:

  if (Status = 0)
  {
    lcd.setCursor(0, 0);
    lcd.print("Start P1 o P2   ");
  }
  else if (Status = 11)
  {
    lcd.setCursor(0, 0);
    lcd.print("Einmaischen     ");
  }
  else if (Status = 12)
  {
    lcd.setCursor(0, 0);
    lcd.print("Ferularast      ");
  }

kannst Du auslagern und dann runterkürzen:

  lcd.setCursor(0, 0);
  if (Status = 0)
  {
    lcd.print("Start P1 o P2   ");
  }
  else if (Status = 11)
  {
    lcd.print("Einmaischen     ");
  }
  else if (Status = 12)
  {
    lcd.print("Ferularast      ");
  }
[...]

Ob das mit if /else if oder mit switch case gemacht wird, dürfte da Geschmackssache sein.

Der Rest wurde ja bereits gesagt...

Das ist in meinen Augen ziemlicher Bullshit. Die Schritte beim Maischen müssen doch nicht in der Nummernfolge ablaufen, sondern entsprechend der Maischeschritte. Also z.B.
erst EINMAISCHEN
dann FERULARAST
dann EIWEISRAST
usw ...
Die Nummern dahinter sind im Prinzip doch vollkommen egal. Und mit diesen Begriffen sollte dann auch dein Status bezeichnet und weitergeschaltet werden. Dann erkennt man auch gleich, was da abläuft.