Pillzucht- Steuerung | Problem mit Relais Schaltung | art installation | GELÖST!

Das sind keine Dioden, sondern MOSFET und als solche sind sie genau so wenig geeignet, wie die, die Du hast.
Warum macht man Dir überhaupt noch Vorschläge, wenn Du dann doch etwas Anderes machst?

Gruß Tommy

:confused: Sry, ich meinte, dass das die Mosfet sind, welche ich bestellen will:
HUAREW 10 Stück IRFZ44N N Kanal Gleichrichter leistung MOSFET Transistor 49A 55V : Amazon.de: Gewerbe, Industrie & Wissenschaft

Oh holy shit, und die falschen, sry habe mich verlesen :confused:
Zum Glück habe ich nochmal gefragt :smiley:

Jetzt aber:
10x IRLZ44N Transistor N-LogL- MOSFET 55V 47A 110W TO220 AB IRLZ44 : Amazon.de: Gewerbe, Industrie & Wissenschaft

Dann pass aber auf, was Du geliefert bekommst. Auf dem Bild sind IRFZ44N.
Also bei Lieferung erst drauf schauen (und. evtl. zurück senden) und dann löten!

Gruß Tommy

Wahrhaftig, ich fasse es nicht :D. Habt Ihr einen Shop des Vertrauens wo Ihr so etwas bestellt?

Das muss nichts zu sagen haben. Evtl. hat er nur das gleiche Bild für verschiedene Typen benutzt. Ich habe nur gesagt: Nachschauen, wenn es kommt.

Ansonsten Fachhandel z.B. Reichelt

Gruß Tommy

Okay, vielen Dank für Deine Geduld :slight_smile: .

Wenn die Umbaumaßnahmen abgeschlossen sind, melde ich mich.
Vielen Dank bis hierhin! :slight_smile:

Ich hab mal ein wenig zusammengefasst und Temp von Humi getrennt.
Dein PWM-setzen im setup() wirft bei mir ne Warnung aus. Darum kümmer ich mich aber nicht :wink:
Ich hab mich eines (unsauberen) Kniffes bedient und Humi-Fruchtung als eigenständiges Merkmal genutzt. Das merkst Du wenn Du in den Schleifen die Sensorkreise siehst...
Mal sehen, ob das so funktioniert.

// Watchdog
#include <avr/wdt.h> // geht mit Arduino Uno, nicht mit Arduino Nano!

//Bibliotheken und Definieren von DHT22
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 3 //==> Der DHT22 Sensor wird an Pin 3 angeschlossen
#define DHTTYPE DHT22//==> Es handelt sich um einen DHT22 Sensor
DHT dht(DHTPIN, DHTTYPE); // Der Sensor wird ab jetzt mit "dht" angesprochen

// Bibliotheken und Definieren von LCD1602
#include <Wire.h> // Bibliothek für 1602 LCD Display
#include <OneWire.h> // OneWire- Bibliothek für DS18B20
#include <DallasTemperature.h> // DallasTemperature- Bibliothek für DS18B20
#include <LiquidCrystal_I2C.h> // LiquidCrystal Bibliothek laden für LCD Display
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // so wenn ein 1602 display genutzt wird

// Bibliotheken und Definieren für DS18B20
#define ONE_WIRE_BUS 2 // Das Datenkabel vom DS18B20 ist an Pin 2 angeschlossen
#define TEMPERATURE_PRECISION 12 // ?
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress one, two; // bei mir sind zwei Temperatursensoren angeschlossen

// Regelkreise für Temperatursteuerung
enum {t_wchstm1, t_wchstm2, t_frchtng, h_frchtng};
const byte kreise = 4; // Anzahl der Regelkreise (3x temp, 1x hygro)
const byte steckdose[kreise] = {4, 5, 6, 7}; //==> Pin 4 ist "Steckdose 1", Pin 5 ist "Steckdose 2", Pin 6 ist "Steckdose 3", pin 7 ist Steckdose 4, darin steckt der Wasservernebler
const byte minimalWert[kreise] = {24, 24, 10, 85}; // Festlegen der minimalWerte
const byte maximalWert[kreise] = {26, 26, 16, 92}; //Festlegen der maximalWerte
int16_t sensorWert[kreise] = {0}; // T - Wachstum1, T - Wachstum2, T - Fruchtung, H - Fruchtung
int16_t altSensorWert[kreise] = {0};

const byte luefter1 = 9;
const byte luefter2 = 10;


// LUEFTERSTEUERUNG- STUFEN:
// digitalWrite(luefter1,HIGH); // maximal
// analogWrite(luetfer1,190);   //Stufe 5
// analogWrite(luetfer1,150);   // Stufe 4
// analogWrite(luetfer1,90);    // Szufe 3
// analogWrite(luetfer1,40);    // Stufe 2
// analogWrite(luetfer1,20);    // Stufe 1
// digitalWrite (leufter, LOW); //aus

void setup()
{
  // Sensoren und LCD starten
  sensors.begin(); // DS18B20 Sensoren starten
  sensors.setWaitForConversion(true);
  dht.begin(); //DHT22 Sensor starten
  lcd.init(); // für den LCD- Monitor
  lcd.backlight(); // für den LCD- Monitor
  TCCR1B = TCCR1B & B11111000 | B00000001; // Diese Zeile regelt die PWM Frequenz für Pin9 & 10/ luefter1 und luefter2
  //Pins deklarieren und Anfangszustand deklarieren (Alle Steckdosen einschalten am Anfang!!!)
  for (byte b = 0; b < kreise; b++)
  {
    pinMode(steckdose[b], OUTPUT);  // Regelkreise
  }
  pinMode(luefter1, OUTPUT);  // Pin 9 als Ausgang definieren (Lüfter1)
  pinMode(luefter2, OUTPUT); // Pin 10 als Ausgang definieren (Lüfter2)
  analogWrite(luefter2, 40); // Lüfter2 soll kontinuirlich auf kleinster Stufe laufen
  delay(1000); // kleine Pause für Sensoren ready
  sensors.requestTemperatures(); // Ersten Wert bereitstellen
  delay(1000); // kleine Pause für Bereitstellung
  pinMode(LED_BUILTIN, OUTPUT);
  // Watchdog aktivieren
  wdt_reset();                       //
  wdt_enable(WDTO_8S);               // Auslösen nach Zeit _8S (8sekunden)
}

void loop()
{
  getSensors();
  setTempSwitch();
  setHumiSwitch();
  setDisplay();
  wdt_reset();                       // WatchdogTimer neu starten
}

void getSensors()
{
  sensorWert[t_wchstm1] = sensors.getTempCByIndex(0);
  sensorWert[t_wchstm2] = sensors.getTempCByIndex(1);
  sensorWert[t_frchtng] = dht.readTemperature();
  sensorWert[h_frchtng] = dht.readHumidity();
  sensors.requestTemperatures();
}

void setTempSwitch()
{
  for (byte b = 0; b < h_frchtng; b++)
  {
    if (sensorWert[b] >= maximalWert[b])    // Wenn die Temperatur gleich oder höher des festgelegten Maximums...
    {
      digitalWrite(steckdose[b], HIGH);
    }
    else if (sensorWert[b] <= minimalWert[b])    // Wenn die Temperatur gleich oder kleiner des festgelegten Minimus...
    {
      digitalWrite(steckdose[b], LOW);
    }
  }
}

void setHumiSwitch() // die Aktoren befehligen
{
  enum {warten, belueften, befeuchten, umluft, aus};
  static byte status = warten;
  static uint32_t timeMerker = 0;
  if (sensorWert[h_frchtng] >= maximalWert[h_frchtng])   // Wenn der HygroWert über oder gleich 92 ist
  {
    status = aus;
  }
  switch (status)
  {
    case warten:
      if (sensorWert[h_frchtng] <= minimalWert[h_frchtng])   // Wenn der Sensorwert unter oder gleich 85 ist
      {
        status = belueften;
      }
      break;
    case belueften:
      //Durchblasen des Zeltes
      digitalWrite(luefter1, HIGH); // Lüfter1 auf maximale Stufe schalten
      timeMerker = millis(); // ZeitspeicherBelueftung auf null setzen
      status = befeuchten;
      break;
    case befeuchten:
      //Befeuchtung
      if (millis() - timeMerker >= 10000)   // Wenn 10 Sekunden lang belüftet wurde
      {
        digitalWrite(luefter1, LOW); // Lüfter1 ausschalten
        digitalWrite(steckdose[h_frchtng], HIGH); // Wasservernebler anschalten
        timeMerker = millis(); // Zeitspeichernebelaufbereitung auf null setzen
        status = umluft;
      }
      break;
    case umluft:
      if (millis() - timeMerker >= 5000)   // Wenn 5 Sekunden lang Wassernebel aufbereitet wurde
      {
        analogWrite(luefter1, 20); // Luefter1 auf Stufe 1 schalten
        status = warten;
      }
      break;
    case aus:
      digitalWrite(steckdose[h_frchtng], LOW); // Wasservernebler ausschalten
      digitalWrite(luefter1, LOW); // Lüfter1 ausschalten
      status = warten;
      break;
  }
}

void setDisplay()
{
  bool isNew = false;
  for (byte b = 0; b < kreise; b++)
  {
    if (altSensorWert[b] != sensorWert[b])
    {
      isNew = true;
      altSensorWert[b] = sensorWert[b];
    }
  }
  if (isNew)
  {
    lcd.setCursor(0, 0);
    for (byte b = 0; b < h_frchtng; b++)
    {
      if (sensorWert[b] < 10)
      {
        lcd.print(' ');
      }
      lcd.print(sensorWert[b]); // Temperatur  anzeigen
      lcd.print("\337C "); // Grad und dahinter Leerzeichen
    }
    lcd.setCursor(10, 1);
    if (sensorWert[h_frchtng] < 10)
    {
      lcd.print(' ');
    }
    lcd.print(sensorWert[h_frchtng]); // LF von Fruchtung anzeigen
    lcd.print(" %"); //
    for (byte b = 0; b < kreise; b++)
    {
      switch (b)
      {
        case 0:
          lcd.setCursor(3, 1);
          break;
        case 1:
          lcd.setCursor(8, 1);
          break;
        case 2:
          lcd.setCursor(15, 0);
          break;
        case 3:
          lcd.setCursor(15, 1);
          break;
      }
      if (digitalRead(steckdose[b]) == HIGH)
      {
        lcd.print(' ');  // das w überschreiben
      }
      else
      {
        lcd.print('w');
      }
    }
  }
}

Vielen Dank! :). Ich werde den Sketch testen, sobald die Umbaumaßnahmen abgeschlossen sind und melde mich dann zurück. Es ist immer wieder aufregend und lehrreich zu sehen, was Ihr für Tricks und Kniffe parat habt um einen Sketch zu strukturieren und zu optimieren. Ich bin begeistert!

Ich habe die IRF520 - Mosfet durch IRLZ44N- Mosfet auf den Modulen ersetzt.

So hat der Lüfter- Test- Sketch zwei modifizierten Mosfet- Modulen dann endlich funktioniert: :slight_smile:

Also habe ich die modifizierten Mosfet- Module dann so auch in meine Steuerung integriert:

1 Like

@my_xy_projekt: Ich habe Deinen Sketch aus post #336 draufgespielt.

Dein PWM-setzen im setup() wirft bei mir ne Warnung aus.

Bei mir wirft es keine Warnung aus.

Ich hab mich eines (unsauberen) Kniffes bedient und Humi-Fruchtung als eigenständiges Merkmal genutzt. Das merkst Du wenn Du in den Schleifen die Sensorkreise siehst...

Danke, das habe ich wahrgenommen :slight_smile: .

Ich habe Deinen Sketch auf den Arduino Uno hochgeladen.
Irgendwo hakt es leider noch.
Ich habe folgende Beobachtungen gemacht:

  • Die LF lag zum Zeitpunkt des Tests bei 72%
  • Lüfter1 ging in ständigem Wechsel 10 Sekunden lang an und 5 Sekunden lang aus
  • Der Wasservernebler wurde nicht angeschaltet
  • Lüfter2 lief wie erwünscht kontinuierlich auf niedriger Stufe

Schau ichh drauf - gibt von mir ein Update
Vielleicht heute Abend.
Morgen früh bestimmt.

Cool, vielen Dank :slight_smile: !!!
Keinen Stress! Es befindet sich gerade noch nichts im Fruchtungszelt und das wird auch die nächsten zwei Wochen so bleiben :wink: .

Hallo,
danke für den Report. Die Beschreibung war sehr genau und hilfreich! :smiling_face_with_three_hearts:

Deine 5 Sekunden Lüfter1 an und aus kamen aus dem case umluft:
Dort kommt er nur hin, wenn er davor befeuchten gestartet hatte.
In befeuchten wird eigentlich der Nebler gestartet. Wenn der nicht anläuft, ist die Schaltlogik falsch. Um zu vermeiden, das ich etwas anderes denke, als Du tatsächlich hast, gibt es jetzt die Variablen stDseAn und stDseAus in Zeile 39 und 40.
Ich hab jetzt für Steckdose AN den Pegel auf HIGH. Wenn die Steckdosen auf LOW angehen, dann einfach das HIGH gegen LOW tauschen. Nicht mehr.
Für den Lüfter habe ich das in Zeile 37 und 38 genauso gemacht.

Im case umluft ist mir dabei aufgefallen, das Du keine Bedingung hast, das bei zu trockener Luft darauf gewartet wird erstmal die Minimalvorgabe zu erreichen.
Ich hab Dir in Zeile 150 eine Bedingung eingefügt, sodas Dir nicht dauernd das "durchblasen" anspringt.
Wenn Du auf dem Seriellen Monitor die Ausgabe bekommst "Starte belüften" muss der Lüfter1 voll Speed laufen
Wenn die Ausgabe "Starte befeuchten" kommt, muss der Lüfter ausgehen und erst bei "Starte Umluft" wieder langsam anlaufen.

Wenn ich was übersehen habe, sag Bescheid.

Die Warnung siehst Du, wenn Du unter DATEI - VOREINSTELLUNGEN - Ausführliche Ausgabe während [X] Kompilierung und da drunter Compilerwarnungen auf ALLE stellst.
Vermutlich fehlt eine Klammer.

Na denne.

// Watchdog
#include <avr/wdt.h> // geht mit Arduino Uno, nicht mit Arduino Nano!

//Bibliotheken und Definieren von DHT22
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 3 //==> Der DHT22 Sensor wird an Pin 3 angeschlossen
#define DHTTYPE DHT22//==> Es handelt sich um einen DHT22 Sensor
DHT dht(DHTPIN, DHTTYPE); // Der Sensor wird ab jetzt mit "dht" angesprochen

// Bibliotheken und Definieren von LCD1602
#include <Wire.h> // Bibliothek für 1602 LCD Display
#include <OneWire.h> // OneWire- Bibliothek für DS18B20
#include <DallasTemperature.h> // DallasTemperature- Bibliothek für DS18B20
#include <LiquidCrystal_I2C.h> // LiquidCrystal Bibliothek laden für LCD Display
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // so wenn ein 1602 display genutzt wird

// Bibliotheken und Definieren für DS18B20
#define ONE_WIRE_BUS 2 // Das Datenkabel vom DS18B20 ist an Pin 2 angeschlossen
#define TEMPERATURE_PRECISION 12 // ?
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress one, two; // bei mir sind zwei Temperatursensoren angeschlossen

// Regelkreise für Temperatursteuerung
enum {t_wchstm1, t_wchstm2, t_frchtng, h_frchtng};
const byte kreise = 4;                             // Anzahl der Regelkreise (3x temp, 1x hygro)
const byte steckdose[kreise] = {4, 5, 6, 7};       //==> Pin 4 ist "Steckdose 1", Pin 5 ist "Steckdose 2", Pin 6 ist "Steckdose 3", pin 7 ist Steckdose 4, darin steckt der Wasservernebler
const byte minimalWert[kreise] = {24, 24, 10, 85}; // Festlegen der minimalWerte
const byte maximalWert[kreise] = {26, 26, 16, 92}; //Festlegen der maximalWerte
int16_t sensorWert[kreise] = {0};                  // T - Wachstum1, T - Wachstum2, T - Fruchtung, H - Fruchtung
int16_t altSensorWert[kreise] = {0};

const byte luefter1 = 9;
const byte luefter2 = 10;

const bool luefterAn = HIGH;                       // Wenn der Luefter falsch anspringt Logik tauschen!
const bool luefterAus = !luefterAn;
const bool stDseAn = HIGH;                         // Wenn Steckdose falsch schaltet Logik tauschen
const bool stDseAus = !stDseAn;

// LUEFTERSTEUERUNG- STUFEN:
// digitalWrite(luefter1,HIGH); // maximal
// analogWrite(luetfer1,190);   //Stufe 5
// analogWrite(luetfer1,150);   // Stufe 4
// analogWrite(luetfer1,90);    // Szufe 3
// analogWrite(luetfer1,40);    // Stufe 2
// analogWrite(luetfer1,20);    // Stufe 1
// digitalWrite (leufter, LOW); //aus

void setup()
{
  // Sensoren und LCD starten
  sensors.begin(); // DS18B20 Sensoren starten
  sensors.setWaitForConversion(true);
  dht.begin(); //DHT22 Sensor starten
  lcd.init(); // für den LCD- Monitor
  lcd.backlight(); // für den LCD- Monitor
  TCCR1B = TCCR1B & B11111000 | B00000001;         // Diese Zeile regelt die PWM Frequenz für Pin9 & 10/ luefter1 und luefter2
  //Pins deklarieren und Anfangszustand deklarieren (Alle Steckdosen einschalten am Anfang!!!)
  for (byte b = 0; b < kreise; b++)
  {
    pinMode(steckdose[b], OUTPUT);                 // Regelkreise
    digitalWrite(steckdose[b], stDseAus);
  }
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(luefter1, OUTPUT);                       // Pin 9 als Ausgang definieren (Lüfter1)
  pinMode(luefter2, OUTPUT);                       // Pin 10 als Ausgang definieren (Lüfter2)
  analogWrite(luefter2, 40);                       // Lüfter2 soll kontinuirlich auf kleinster Stufe laufen
  delay(1000);                                     // kleine Pause für Sensoren ready
  sensors.requestTemperatures();                   // Ersten Wert bereitstellen
  delay(1000);                                     // kleine Pause für Bereitstellung
  // Watchdog aktivieren
  wdt_reset();
  wdt_enable(WDTO_8S);                             // Auslösen nach Zeit _8S (8sekunden)
}

void loop()
{
  getSensors();
  setTempSwitch();
  setHumiSwitch();
  setDisplay();
  wdt_reset();                                     // WatchdogTimer neu starten
}

void getSensors()
{
  sensorWert[t_wchstm1] = sensors.getTempCByIndex(0);
  sensorWert[t_wchstm2] = sensors.getTempCByIndex(1);
  sensorWert[t_frchtng] = dht.readTemperature();
  sensorWert[h_frchtng] = dht.readHumidity();
  sensors.requestTemperatures();
}

void setTempSwitch()
{
  for (byte b = 0; b < h_frchtng; b++)
  {
    if (sensorWert[b] >= maximalWert[b])            // Wenn die Temperatur gleich oder höher des festgelegten Maximums...
    {
      digitalWrite(steckdose[b], stDseAn);
    }
    else if (sensorWert[b] <= minimalWert[b])       // Wenn die Temperatur gleich oder kleiner des festgelegten Minimus...
    {
      digitalWrite(steckdose[b], stDseAus);
    }
  }
}

void setHumiSwitch() // die Aktoren befehligen
{
  enum {warten, belueften, befeuchten, umluft, aus};
  static byte status = warten;
  static uint32_t timeMerker = 0;
  switch (status)
  {
    case warten:
      if (sensorWert[h_frchtng] <= minimalWert[h_frchtng])   // HygroWert unter Grenzwert
      {
        Serial.println(F("Starte belüften"));
        status = belueften;
      }
      if (sensorWert[h_frchtng] >= maximalWert[h_frchtng])   // HygroWert über Grenzwert
      {
        status = aus;
      }
      break;
    case belueften:                                 // Durchblasen des Zeltes
      digitalWrite(luefter1, luefterAn);            // Lüfter1 auf maximale Stufe schalten
      timeMerker = millis();                        // ZeitspeicherBelueftung auf null setzen
      status = befeuchten;
      break;
    case befeuchten:
      //Befeuchtung
      if (millis() - timeMerker >= 10000)           // Wenn 10 Sekunden lang belüftet wurde
      {
        Serial.println(F("Starte befeuchten"));
        digitalWrite(luefter1, luefterAus);         // Lüfter1 ausschalten
        digitalWrite(steckdose[h_frchtng], stDseAn);// Wasservernebler anschalten
        timeMerker = millis();                      // Zeitspeichernebelaufbereitung auf null setzen
        status = umluft;
      }
      break;
    case umluft:
      if (millis() - timeMerker >= 5000)            // Wenn 5 Sekunden lang Wassernebel aufbereitet wurde
      {
        Serial.println(F("Starte Umluft"));
        analogWrite(luefter1, 20);                  // Luefter1 auf Stufe 1 schalten
        if (sensorWert[h_frchtng] < minimalWert[h_frchtng]) // Erst wenn minimale Befeuchtung erreicht ist gehts weiter
        { status = warten; }
      }
      break;
    case aus:
      Serial.println(F("Nebler und Lüfter1 aus"));
      digitalWrite(steckdose[h_frchtng], stDseAus); // Wasservernebler ausschalten
      digitalWrite(luefter1, luefterAus);           // Lüfter1 ausschalten
      status = warten;
      break;
  }
}

void setDisplay()
{
  bool isNew = false;
  for (byte b = 0; b < kreise; b++)
  {
    if (altSensorWert[b] != sensorWert[b])
    {
      isNew = true;
      altSensorWert[b] = sensorWert[b];
    }
  }
  if (isNew)
  {
    lcd.setCursor(0, 0);
    for (byte b = 0; b < h_frchtng; b++)
    {
      if (sensorWert[b] < 10)
      {
        lcd.print(' ');
      }
      lcd.print(sensorWert[b]); // Temperatur  anzeigen
      lcd.print("\337C "); // Grad und dahinter Leerzeichen
    }
    lcd.setCursor(10, 1);
    if (sensorWert[h_frchtng] < 10)
    {
      lcd.print(' ');
    }
    lcd.print(sensorWert[h_frchtng]); // LF von Fruchtung anzeigen
    lcd.print(" %"); //
    for (byte b = 0; b < kreise; b++)
    {
      switch (b)
      {
        case 0:
          lcd.setCursor(3, 1);
          break;
        case 1:
          lcd.setCursor(8, 1);
          break;
        case 2:
          lcd.setCursor(15, 0);
          break;
        case 3:
          lcd.setCursor(15, 1);
          break;
      }
      if (digitalRead(steckdose[b]) == HIGH)
      {
        lcd.print(' ');  // das w überschreiben
      }
      else
      {
        lcd.print('w');
      }
    }
  }
}

Die Schaltlogik war falsch! Die Steckdose des Neblers wird über das SSR- Relais mit LOW angeschaltet.
Danke für die smarte Lösung in Zeile 39 und 40!
Bei dem Lüfter stimmte die Schaltlogik :slight_smile: .

Wenn Du auf dem Seriellen Monitor die Ausgabe bekommst "Starte belüften" muss der Lüfter1 voll Speed laufen
Wenn die Ausgabe "Starte befeuchten" kommt, muss der Lüfter ausgehen und erst bei "Starte Umluft" wieder langsam anlaufen.

Danke für das Einbeziehen des seriellen Monitors! Das macht die Sache viel überschaubarer!

Im case umluft ist mir dabei aufgefallen, das Du keine Bedingung hast, das bei zu trockener Luft darauf gewartet wird erstmal die Minimalvorgabe zu erreichen.
Ich hab Dir in Zeile 150 eine Bedingung eingefügt, sodas Dir nicht dauernd das "durchblasen" anspringt.

Das ist mit dem Sketch leider trotzdem noch passiert:

Ich habe aber mit Hinzunahme von static boolean Umluftfunktion eine Möglichkeit gefunden wie es funktioniert:

// Watchdog
#include <avr/wdt.h> // geht mit Arduino Uno, nicht mit Arduino Nano!

//Bibliotheken und Definieren von DHT22
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 3 //==> Der DHT22 Sensor wird an Pin 3 angeschlossen
#define DHTTYPE DHT22//==> Es handelt sich um einen DHT22 Sensor
DHT dht(DHTPIN, DHTTYPE); // Der Sensor wird ab jetzt mit "dht" angesprochen

// Bibliotheken und Definieren von LCD1602
#include <Wire.h> // Bibliothek für 1602 LCD Display
#include <OneWire.h> // OneWire- Bibliothek für DS18B20
#include <DallasTemperature.h> // DallasTemperature- Bibliothek für DS18B20
#include <LiquidCrystal_I2C.h> // LiquidCrystal Bibliothek laden für LCD Display
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // so wenn ein 1602 display genutzt wird

// Bibliotheken und Definieren für DS18B20
#define ONE_WIRE_BUS 2 // Das Datenkabel vom DS18B20 ist an Pin 2 angeschlossen
#define TEMPERATURE_PRECISION 12 // ?
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress one, two; // bei mir sind zwei Temperatursensoren angeschlossen

// Regelkreise für Temperatursteuerung
enum {t_wchstm1, t_wchstm2, t_frchtng, h_frchtng};
const byte kreise = 4;                             // Anzahl der Regelkreise (3x temp, 1x hygro)
const byte steckdose[kreise] = {4, 5, 6, 7};       //==> Pin 4 ist "Steckdose 1", Pin 5 ist "Steckdose 2", Pin 6 ist "Steckdose 3", pin 7 ist Steckdose 4, darin steckt der Wasservernebler
const byte minimalWert[kreise] = {24, 24, 10, 85}; // Festlegen der minimalWerte
const byte maximalWert[kreise] = {26, 26, 16, 92}; //Festlegen der maximalWerte
int16_t sensorWert[kreise] = {0};                  // T - Wachstum1, T - Wachstum2, T - Fruchtung, H - Fruchtung
int16_t altSensorWert[kreise] = {0};

const byte luefter1 = 9;
const byte luefter2 = 10;

const bool luefterAn = HIGH;                       // Wenn der Luefter falsch anspringt Logik tauschen!
const bool luefterAus = !luefterAn;
const bool stDseAn = LOW;                         // Wenn Steckdose falsch schaltet Logik tauschen
const bool stDseAus = !stDseAn;

static boolean Umluftfunktion = false; 

// LUEFTERSTEUERUNG- STUFEN:
// digitalWrite(luefter1,HIGH); // maximal
// analogWrite(luetfer1,190);   //Stufe 5
// analogWrite(luetfer1,150);   // Stufe 4
// analogWrite(luetfer1,90);    // Szufe 3
// analogWrite(luetfer1,40);    // Stufe 2
// analogWrite(luetfer1,20);    // Stufe 1
// digitalWrite (leufter, LOW); //aus

void setup()
{
  Serial.begin(9600);// seriellen Monitor starten
  // Sensoren und LCD starten
  sensors.begin(); // DS18B20 Sensoren starten
  sensors.setWaitForConversion(true);
  dht.begin(); //DHT22 Sensor starten
  lcd.init(); // für den LCD- Monitor
  lcd.backlight(); // für den LCD- Monitor
  TCCR1B = TCCR1B & B11111000 | B00000001;         // Diese Zeile regelt die PWM Frequenz für Pin9 & 10/ luefter1 und luefter2
  //Pins deklarieren und Anfangszustand deklarieren (Alle Steckdosen einschalten am Anfang!!!)
  for (byte b = 0; b < kreise; b++)
  {
    pinMode(steckdose[b], OUTPUT);                 // Regelkreise
    digitalWrite(steckdose[b], stDseAus);
  }
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(luefter1, OUTPUT);                       // Pin 9 als Ausgang definieren (Lüfter1)
  pinMode(luefter2, OUTPUT);                       // Pin 10 als Ausgang definieren (Lüfter2)
  analogWrite(luefter2, 40);                       // Lüfter2 soll kontinuirlich auf kleinster Stufe laufen 
  delay(1000);                                     // kleine Pause für Sensoren ready
  sensors.requestTemperatures();                   // Ersten Wert bereitstellen
  delay(1000);                                     // kleine Pause für Bereitstellung
  // Watchdog aktivieren
  wdt_reset();
  wdt_enable(WDTO_8S);                             // Auslösen nach Zeit _8S (8sekunden)
}

void loop()
{
  getSensors();
  setTempSwitch();
  setHumiSwitch();
  setDisplay();
  wdt_reset();                                     // WatchdogTimer neu starten
}

void getSensors()
{
  sensorWert[t_wchstm1] = sensors.getTempCByIndex(0);
  sensorWert[t_wchstm2] = sensors.getTempCByIndex(1);
  sensorWert[t_frchtng] = dht.readTemperature();
  sensorWert[h_frchtng] = dht.readHumidity();
  sensors.requestTemperatures();
}

void setTempSwitch()
{
  for (byte b = 0; b < h_frchtng; b++)
  {
    if (sensorWert[b] >= maximalWert[b])            // Wenn die Temperatur gleich oder höher des festgelegten Maximums...
    {
      digitalWrite(steckdose[b], stDseAn);
    }
    else if (sensorWert[b] <= minimalWert[b])       // Wenn die Temperatur gleich oder kleiner des festgelegten Minimus...
    {
      digitalWrite(steckdose[b], stDseAus);
    }
  }
}

void setHumiSwitch() // die Aktoren befehligen
{
  enum {warten, belueften, befeuchten, umluft, aus};
  static byte status = warten;
  static uint32_t timeMerker = 0;
  switch (status)
  {
    case warten:
      if (sensorWert[h_frchtng] <= minimalWert[h_frchtng])   // HygroWert unter Grenzwert
      {
        Serial.println(F("Starte belüften"));
        status = belueften;
      }
      if (sensorWert[h_frchtng] >= maximalWert[h_frchtng])   // HygroWert über Grenzwert
      {
        status = aus;
      }
      break;
    case belueften:                                 // Durchblasen des Zeltes
      digitalWrite(luefter1, luefterAn);            // Lüfter1 auf maximale Stufe schalten
      timeMerker = millis();                        // ZeitspeicherBelueftung auf null setzen
      status = befeuchten;
      break;
    case befeuchten:
      //Befeuchtung
      if (millis() - timeMerker >= 10000)           // Wenn 10 Sekunden lang belüftet wurde
      {
        Serial.println(F("Starte befeuchten"));
        digitalWrite(luefter1, luefterAus);         // Lüfter1 ausschalten
        digitalWrite(steckdose[h_frchtng], stDseAn);// Wasservernebler anschalten
        timeMerker = millis();                      // Zeitspeichernebelaufbereitung auf null setzen
        status = umluft;
      }
      break;
    case umluft: // hier
      if (millis() - timeMerker >= 5000 && Umluftfunktion == false) // Wenn 5 Sekunden lang Wassernebel aufbereitet wurde und die Umluftfunktion nicht aktiv ist // okay, das klappt schonmal
      {
        Umluftfunktion = true;                                      // merken, dass die Umluftfunktion aktiv ist
        Serial.println(F("Starte Umluft"));
        analogWrite(luefter1, 90);                  // Luefter1 auf Stufe 1 schalten // 20 klappt nicht, 40 klappt nicht, 90 klappt nicht!; mit HIGH klappt es!
        if (sensorWert[h_frchtng] > minimalWert[h_frchtng]) // Erst wenn minimale Befeuchtung erreicht ist gehts weiter
        {status = warten;}
      }
      break;
    case aus:
      Serial.println(F("Nebler und Lüfter1 aus")); // Das "F" vor der Nachricht ist eine Makrofunktion in Arduino, die verwendet wird, um die Nachricht im Flash-Speicher anstelle des RAMs zu speichern. Dies hilft, den Speicherplatz auf dem Mikrocontroller zu sparen.
      digitalWrite(steckdose[h_frchtng], stDseAus); // Wasservernebler ausschalten
      digitalWrite(luefter1, luefterAus);           // Lüfter1 ausschalten
      status = warten;
      break;
  }
}

void setDisplay()
{
  bool isNew = false;
  for (byte b = 0; b < kreise; b++)
  {
    if (altSensorWert[b] != sensorWert[b])
    {
      isNew = true;
      altSensorWert[b] = sensorWert[b];
    }
  }
  if (isNew)
  {
    lcd.setCursor(0, 0);
    for (byte b = 0; b < h_frchtng; b++)
    {
      if (sensorWert[b] < 10)
      {
        lcd.print(' ');
      }
      lcd.print(sensorWert[b]); // Temperatur  anzeigen
      lcd.print("\337C "); // Grad und dahinter Leerzeichen
    }
    lcd.setCursor(10, 1);
    if (sensorWert[h_frchtng] < 10)
    {
      lcd.print(' ');
    }
    lcd.print(sensorWert[h_frchtng]); // LF von Fruchtung anzeigen
    lcd.print(" %"); //
    for (byte b = 0; b < kreise; b++)
    {
      switch (b)
      {
        case 0:
          lcd.setCursor(3, 1);
          break;
        case 1:
          lcd.setCursor(8, 1);
          break;
        case 2:
          lcd.setCursor(15, 0);
          break;
        case 3:
          lcd.setCursor(15, 1);
          break;
      }
      if (digitalRead(steckdose[b]) == HIGH)
      {
        lcd.print(' ');  // das w überschreiben
      }
      else
      {
        lcd.print('w');
      }
    }
  }
}

Hier ist ein Screenshot des seriellen Monitors wenn dieser Sketch hochgeladen ist:

Die PWM- Steuerung der beiden PC- Lüfter klappt leider noch garnicht:

  • Ich habe festgestellt, dass Lüfter2 doch kontinuierlich auf der höchsten Stufe läuft, obwohl er in void setup() mit analogWrite(luefter2, 40); gestartet wird
  • Lüfter 1 dreht in case umluft, per analogWrite(luefter1, 20); nicht los. Auch bei Werten von 40, oder 90 dreht er nicht los. Mit digitalWrite(luefter1, HIGH) lässt er sich aber problemlos starten.

Die Warnung siehst Du, wenn Du unter DATEI - VOREINSTELLUNGEN - Ausführliche Ausgabe während [X] Kompilierung und da drunter Compilerwarnungen auf ALLE stellst.
Vermutlich fehlt eine Klammer.

Obwohl ich die Voreinstellungen vorgenommen habe, bleibt die Fehlermeldung aus. Es läuft zwar kurzzeitig ein Text beim Kompilieren aber er bleibt nicht dauerhaft stehen.

Vielleicht kannst Du ja bitte noch etwas zu der vermutlich fehlenden Klammer sagen :slight_smile:

Da ich mit den Registern und den Bitschiebern nicht arbeite, kann ich da wenig beisteuern.
Ich hab aber mal die Codezeile ins google gekippt. Du bist anscheinend nicht allein, der das so schreibt. Das die nicht funktioniert, sagt der Compiler aber. Ich hab das jetzt geändert, wie das andere machen...

Aehm doch.
Die Meldung war an der falschen Stelle, aber das Zeitfenster stimmte.
Ich hab auch hier überarbeitet, das die Meldung immer dann kommt, wenn der Teil aufgerufen wird und nicht wenn es zu Ende ist.

So wie das jetzt ist, würde der Nebler die ganze Zeit laufen, bis der maximale Feuchtewert erreicht ist. Ich gehe davon aus, dass das so gewollt ist.

Versuch, ob das jetzt mit dem geänderten setup funktionert.
Wenn nicht, haben wir ein Problem...

Aehm doch. :wink:
Das schwarze Fenster lässt sich an der Trennlinie mit der Maus größer machen.
Und Du kannst nach einem Klick in das schwarze Fenster da durchscrollen.
Alternativ rechts den Schieber bewegen.
grafik

Neuer Code.

// Watchdog
#include <avr/wdt.h> // geht mit Arduino Uno, nicht mit Arduino Nano!

//Bibliotheken und Definieren von DHT22
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 3 //==> Der DHT22 Sensor wird an Pin 3 angeschlossen
#define DHTTYPE DHT22//==> Es handelt sich um einen DHT22 Sensor
DHT dht(DHTPIN, DHTTYPE); // Der Sensor wird ab jetzt mit "dht" angesprochen

// Bibliotheken und Definieren von LCD1602
#include <Wire.h> // Bibliothek für 1602 LCD Display
#include <OneWire.h> // OneWire- Bibliothek für DS18B20
#include <DallasTemperature.h> // DallasTemperature- Bibliothek für DS18B20
#include <LiquidCrystal_I2C.h> // LiquidCrystal Bibliothek laden für LCD Display
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // so wenn ein 1602 display genutzt wird

// Bibliotheken und Definieren für DS18B20
#define ONE_WIRE_BUS 2 // Das Datenkabel vom DS18B20 ist an Pin 2 angeschlossen
#define TEMPERATURE_PRECISION 12 // ?
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress one, two; // bei mir sind zwei Temperatursensoren angeschlossen

// Regelkreise für Temperatursteuerung
enum {t_wchstm1, t_wchstm2, t_frchtng, h_frchtng};
const byte kreise = 4;                             // Anzahl der Regelkreise (3x temp, 1x hygro)
const byte steckdose[kreise] = {4, 5, 6, 7};       //==> Pin 4 ist "Steckdose 1", Pin 5 ist "Steckdose 2", Pin 6 ist "Steckdose 3", pin 7 ist Steckdose 4, darin steckt der Wasservernebler
const byte minimalWert[kreise] = {24, 24, 10, 85}; // Festlegen der minimalWerte
const byte maximalWert[kreise] = {26, 26, 16, 92}; //Festlegen der maximalWerte
int16_t sensorWert[kreise] = {0};                  // T - Wachstum1, T - Wachstum2, T - Fruchtung, H - Fruchtung
int16_t altSensorWert[kreise] = {0};

const byte luefter1 = 9;
const byte luefter2 = 10;

const bool luefterAn = HIGH;                       // Wenn der Luefter falsch anspringt Logik tauschen!
const bool luefterAus = !luefterAn;
const bool stDseAn = LOW;                          // Wenn Steckdose falsch schaltet Logik tauschen
const bool stDseAus = !stDseAn;

// LUEFTERSTEUERUNG- STUFEN:
// digitalWrite(luefter1,HIGH); // maximal
// analogWrite(luetfer1,190);   //Stufe 5
// analogWrite(luetfer1,150);   // Stufe 4
// analogWrite(luetfer1,90);    // Szufe 3
// analogWrite(luetfer1,40);    // Stufe 2
// analogWrite(luetfer1,20);    // Stufe 1
// digitalWrite (leufter, LOW); //aus

void setup()
{
  // Sensoren und LCD starten
  sensors.begin(); // DS18B20 Sensoren starten
  sensors.setWaitForConversion(true);
  dht.begin(); //DHT22 Sensor starten
  lcd.init(); // für den LCD- Monitor
  lcd.backlight(); // für den LCD- Monitor
  TCCR1B = (TCCR1B & B11111000) | B00000001;       // Diese Zeile regelt die PWM Frequenz für Pin9 & 10/ luefter1 und luefter2
  //Pins deklarieren und Anfangszustand deklarieren (Alle Steckdosen einschalten am Anfang!!!)
  for (byte b = 0; b < kreise; b++)
  {
    pinMode(steckdose[b], OUTPUT);                 // Regelkreise
    digitalWrite(steckdose[b], stDseAn);
  }
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(luefter1, OUTPUT);                       // Pin 9 als Ausgang definieren (Lüfter1)
  pinMode(luefter2, OUTPUT);                       // Pin 10 als Ausgang definieren (Lüfter2)
  analogWrite(luefter2, 40);                       // Lüfter2 soll kontinuirlich auf kleinster Stufe laufen
  delay(1000);                                     // kleine Pause für Sensoren ready
  sensors.requestTemperatures();                   // Ersten Wert bereitstellen
  delay(1000);                                     // kleine Pause für Bereitstellung
  // Watchdog aktivieren
  wdt_reset();
  wdt_enable(WDTO_8S);                             // Auslösen nach Zeit _8S (8sekunden)
}

void loop()
{
  getSensors();
  setTempSwitch();
  setHumiSwitch();
  setDisplay();
  wdt_reset();                                     // WatchdogTimer neu starten
}

void getSensors()
{
  sensorWert[t_wchstm1] = sensors.getTempCByIndex(0);
  sensorWert[t_wchstm2] = sensors.getTempCByIndex(1);
  sensorWert[t_frchtng] = dht.readTemperature();
  sensorWert[h_frchtng] = dht.readHumidity();
  sensors.requestTemperatures();
}

void setTempSwitch()
{
  for (byte b = 0; b < h_frchtng; b++)
  {
    if (sensorWert[b] >= maximalWert[b])            // Wenn die Temperatur gleich oder höher des festgelegten Maximums...
    {
      digitalWrite(steckdose[b], stDseAus);         // Heizung stoppen
    }
    else if (sensorWert[b] <= minimalWert[b])       // Wenn die Temperatur gleich oder kleiner des festgelegten Minimus...
    {
      digitalWrite(steckdose[b], stDseAn);          // Heizung starten
    }
  }
}
//
void serialSensorWert()                       // Ausgabefunktion zur Kontrolle
{
  Serial.print(F("Sensorwerte: "));
  for (byte b = 0; b < kreise; b++)
  {
    Serial.print(sensorWert[b]);
    Serial.print('\t');
  }
  Serial.println();
}
//
void setHumiSwitch() // die Aktoren befehligen
{
  enum {warten, belueften, befeuchten, umluft, aus};
  static byte status = warten;
  static uint32_t timeMerker = 0;
  switch (status)
  {
    case warten:
      if (sensorWert[h_frchtng] <= minimalWert[h_frchtng])   // HygroWert unter Grenzwert
      {
        timeMerker = millis();                               // Zeit Belueftung Start merken
        serialSensorWert();                                  // Kontrolle der Werte
        Serial.println(F("Starte belüften"));
        status = belueften;
      }
      if (sensorWert[h_frchtng] >= maximalWert[h_frchtng])   // HygroWert über Grenzwert
      {
        Serial.println(F("...mache alles aus"));
        status = aus;
      }
      break;
    case belueften:                                 // Durchblasen des Zeltes
      digitalWrite(luefter1, luefterAn);            // Lüfter1 auf maximale Stufe schalten
      if (millis() - timeMerker >= 10000)           // Wenn 10 Sekunden lang belüftet wurde
      {
        Serial.println(F("Starte befeuchten"));
        timeMerker = millis();                      // Zeit Start Nebelaufbereitung merken
        status = befeuchten;
      }
      break;
    case befeuchten:                                
      digitalWrite(luefter1, luefterAus);           // Lüfter1 ausschalten
      digitalWrite(steckdose[h_frchtng], stDseAn);  // Wasservernebler anschalten
      if (millis() - timeMerker >= 5000)            // Wenn 5 Sekunden lang Wassernebel aufbereitet wurde
      {
        Serial.println(F("Starte Umluft"));
        status = umluft;
      }
      break;
    case umluft:
      analogWrite(luefter1, 20);                    // Luefter1 auf Stufe 1 schalten
      if (sensorWert[h_frchtng] > minimalWert[h_frchtng]) // Erst wenn minimale Befeuchtung erreicht ist gehts weiter
      {
        serialSensorWert();
        Serial.println(F("...gehe warten"));
        status = warten;
      }
      break;
    case aus:
      Serial.println(F("Nebler und Lüfter1 aus"));
      digitalWrite(steckdose[h_frchtng], stDseAus); // Wasservernebler ausschalten
      digitalWrite(luefter1, luefterAus);           // Lüfter1 ausschalten
      status = warten;
      break;
  }
}

void setDisplay()
{
  bool isNew = false;
  for (byte b = 0; b < kreise; b++)
  {
    if (altSensorWert[b] != sensorWert[b])
    {
      isNew = true;
      altSensorWert[b] = sensorWert[b];
    }
  }
  if (isNew)
  {
    lcd.setCursor(0, 0);
    for (byte b = 0; b < h_frchtng; b++)
    {
      if (sensorWert[b] < 10)
      {
        lcd.print(' ');
      }
      lcd.print(sensorWert[b]); // Temperatur  anzeigen
      lcd.print("\337C "); // Grad und dahinter Leerzeichen
    }
    lcd.setCursor(10, 1);
    if (sensorWert[h_frchtng] < 10)
    {
      lcd.print(' ');
    }
    lcd.print(sensorWert[h_frchtng]); // LF von Fruchtung anzeigen
    lcd.print(" %"); //
    for (byte b = 0; b < kreise; b++)
    {
      switch (b)
      {
        case 0:
          lcd.setCursor(3, 1);
          break;
        case 1:
          lcd.setCursor(8, 1);
          break;
        case 2:
          lcd.setCursor(15, 0);
          break;
        case 3:
          lcd.setCursor(15, 1);
          break;
      }
      if (digitalRead(steckdose[b]) == HIGH)
      {
        lcd.print(' ');  // das w überschreiben
      }
      else
      {
        lcd.print('w');
      }
    }
  }
}

Danke für die Erläuterung, jetzt habe ich die Fehlermeldung gefunden :slight_smile: .

Versuch, ob das jetzt mit dem geänderten setup funktionert.
Wenn nicht, haben wir ein Problem...

Die PWM- Steuerung funktioniert leider noch nicht.

Hier ist ein Screenshot des seriellen Monitors mit Deinem neuen Sketch


und dies sind meine Beobachtungen:

  • Lüfter 2 läuft kontinuierlich auf vollem Speed
  • Lüfter 1 läuft garnicht (bei allen durchlaufenen cases, die ja dank Dir jetzt am seriellen Monitor angezeigt werden :slight_smile: )
  • Der Wasservernebler läuft kontinuierlich, sogar während des Belüftens

So wie das jetzt ist, würde der Nebler die ganze Zeit laufen, bis der maximale Feuchtewert erreicht ist. Ich gehe davon aus, dass das so gewollt ist.

Der Nebler soll während case belueften und natürlich bei case aus nicht laufen, aber ansonsten die ganze Zeit. In Deinem Sketch aus post #342 war das schon richtig, aber jetzt leider nicht mehr :slight_smile: .

Mir ist gerade etwas sehr wichtiges aufgefallen:
Dem Tutorial von Bastelbruder zur PWM- Steuerung eines PC- Lüfters Lüftersteuerung temperaturgeregelt über einen Arduino einfach zum nachbauen - YouTube ) liegt ein anderer Schaltplan zu Grunde. Wie dumm, dass mir das jetzt erst auffällt! :confused: .

Der Arduino Uno wird hier über GND und VIN vom 12 VDC Netzteil mitversorgt. Ich habe die Logik jetzt mal in meinen Schaltplan integriert.
So probiere ich es morgen aus und bin sehr zuversichtlich, dass es klappt.