Control my terraria with an Arduino Nano

Hey all,

I am trying to control my 3 terraria with an Arduino Nano and the use of 6 DHT22 (2 for each terrarium) , 7 relais (for heating, light and the waterpumps), a DS3231 RTC, some LEDs and switches for the water level.

Where is the problem? My code does not do what I want it to do :smiley: . My Arduino is a little short on inputs/outputs. So I have to use Pin 0/1 for some funktions.
I implemented the necessary libraries and made a (you might laugh at me) noob-like code to run. I already used a similar code for my other two terraria and it runs for years now. It is way simpler though, only for controlling the humidity with DHT22, a DS3231 and a Display to show it all.

I cannot, for the love of God, figure out what I made wrong with my code (other than looking funny to all of you I guess). Is it because of the pins 0/1 I used? They should be ok to use since I don't use a Serial connection.

What I did so far:
I reduced the code to it's minimum(from top to bottom). And it works as far as showing all the temperatures and humidities on the display, also the time and light-level of the lightsensor. The LEDs for my water-tank work fine (of course the two switches work fine, too).
I added more and more code but when I get to the part with the if-statements it gets funny. I tried simplifying the if-statements as to only look for the time and then switch the relais on. It does it but only for a fraction of a second. Same with the light.
I tried using a different DS3231 library but I had no luck with it either. (although updating my current library made my code run less 'funny')
At first I tried switching all the relais on the way they are wired and it worked.
As a last resort I tried replacing all the temperature floats with integers. Didn't work either.

I checked all the wiring, looked for shorts. The wiring is good. My guess is that it has something to do with my code and/or the libraries.

My code: (sorry for all the german comments :sweat_smile: )

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);  // Set the LCD I2C address

RTC_DS3231 rtc;

#define DHT1_Pin 2                                                // Datenpin des DHT22(1) ist Pin 2
#define DHT2_Pin 3                                                // Datenpin des DHT22(2) ist Pin 3
#define DHT3_Pin 4                                                // Datenpin des DHT22(3) ist Pin 4
#define DHT4_Pin 5                                                // Datenpin des DHT22(4) ist Pin 5
#define DHT5_Pin 6                                                // Datenpin des DHT22(5) ist Pin 6
#define DHT6_Pin 7                                                // Datenpin des DHT22(6) ist Pin 7
#define DHT_Typ DHT22                                             // DHT 22 als Sensortyp festlegen

DHT dht1(DHT1_Pin, DHT_Typ);                                      // Sensor 1 initialisieren
DHT dht2(DHT2_Pin, DHT_Typ);                                      // Sensor 2 initialisieren
DHT dht3(DHT3_Pin, DHT_Typ);                                      // Sensor 3 initialisieren
DHT dht4(DHT4_Pin, DHT_Typ);                                      // Sensor 4 initialisieren
DHT dht5(DHT5_Pin, DHT_Typ);                                      // Sensor 5 initialisieren
DHT dht6(DHT6_Pin, DHT_Typ);                                      // Sensor 6 initialisieren

// Merker
unsigned long mil1;
unsigned int STD;
unsigned int MIN;
int Fuellstandswert;
int Fuellstandswert1;
int Intervallmerker;

// Sensoren
int Sensor = A7;                                                   //Umgebungslichtsensor
int Fuellstand_low = 14;
int Fuellstand_empty = 15;

// Relais
int Sprueh1 = 8;
int Sprueh2 = 10;
int Heizung1 = 13;
int Heizung2 = 16;
int Heizung3 = 17;
int Beleuchtung_Tag = 1;
int Beleuchtung_Abend = 0;

// Sonstige Outputs
int LED_low = 11;
int LED_empty = 12;
int Display_Licht = 9;                                            // PIN9 ist belegt von der DisplayLED


void setup() {

  dht1.begin();                                                   // Sensor 1 starten
  dht2.begin();                                                   // Sensor 2 starten
  dht3.begin();                                                   // Sensor 3 starten
  dht4.begin();                                                   // Sensor 4 starten
  dht5.begin();                                                   // Sensor 5 starten
  dht6.begin();                                                   // Sensor 6 starten

  lcd.begin();

  pinMode(Fuellstand_low, INPUT);
  pinMode(Fuellstand_empty, INPUT);
  pinMode(Sensor, INPUT);
  pinMode(Sprueh1, OUTPUT);
  pinMode(Sprueh2, OUTPUT);
  pinMode(Heizung1, OUTPUT);
  pinMode(Heizung2, OUTPUT);
  pinMode(Heizung3, OUTPUT);
  pinMode(Beleuchtung_Tag, OUTPUT);
  pinMode(Beleuchtung_Abend, OUTPUT);
  pinMode(Display_Licht, OUTPUT);
  pinMode(LED_low, OUTPUT);
  pinMode(LED_empty, OUTPUT);

  digitalWrite(Sprueh1, HIGH);
  digitalWrite(Sprueh2, HIGH);
  digitalWrite(Heizung1, HIGH);
  digitalWrite(Heizung2, HIGH);
  digitalWrite(Heizung3, HIGH);
  digitalWrite(Beleuchtung_Tag, HIGH);
  digitalWrite(Beleuchtung_Abend, HIGH);

  DateTime now = rtc.now();
}

void loop() {

  DateTime now = rtc.now();        

  STD = now.hour();
  MIN = now.minute();

  float h1 = dht1.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 1)
  float t1 = dht1.readTemperature();                            // Auslesen der Temperatur (Sensor 1)
  float h2 = dht2.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 2)
  float t2 = dht2.readTemperature();                            // Auslesen der Temperatur (Sensor 2)
  float h3 = dht3.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 3)
  float t3 = dht3.readTemperature();                            // Auslesen der Temperatur (Sensor 3)
  float h4 = dht4.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 4)
  float t4 = dht4.readTemperature();                            // Auslesen der Temperatur (Sensor 4)
  float h5 = dht5.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 5)
  float t5 = dht5.readTemperature();                            // Auslesen der Temperatur (Sensor 5)
  float h6 = dht6.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 6)
  float t6 = dht6.readTemperature();                            // Auslesen der Temperatur (Sensor 6)

  Sensor = analogRead(A7);                                      // Lichtsensor für Displaybeleuchtung
  Fuellstandswert = digitalRead(Fuellstand_empty);              // Merker für Füllstand der Sprühanage
  Fuellstandswert1 = digitalRead(Fuellstand_low);

// Beleuchtungsregelung fürs Display
    
  Sensor = map(Sensor, 0, 600, 10, 255);
  analogWrite(9, Sensor);

// Platzhalter für Lichtlevelanzeige im Display
    
    if (Sensor <=99) {
    lcd.setCursor(17,3);
    lcd.print(" ");
    lcd.setCursor(18,3);
    lcd.print(Sensor);
    }
    else {
    lcd.setCursor(17,3);
    lcd.print(Sensor);  
    }

// Platzhalterstriche

    lcd.setCursor(17, 2);
    lcd.print("---");

// Anzeige der Temperatur und Luftfeuchtigkeit

  // Sensor1
    lcd.setCursor(0, 0);                                          // 1. Zeichen, 1. Zeile
    lcd.print(t1);                                                // Temperaturwert anzeigen
    lcd.setCursor(4, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(0, 1);                                          // 1. Zeichen, 2. Zeile
    lcd.print(h1);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(4, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  // Sensor2
    lcd.setCursor(0, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t2);                                                // Temperaturwert anzeigen
    lcd.setCursor(4, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(0, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h2);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(4, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  //Sensor3
    lcd.setCursor(6, 0);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t3);                                                // Temperaturwert anzeigen
    lcd.setCursor(10, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(6, 1);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h3);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(10, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  //Sensor4
    lcd.setCursor(6, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t4);                                                // Temperaturwert anzeigen
    lcd.setCursor(10, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(6, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h4);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(10, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  //Sensor5
    lcd.setCursor(12, 0);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t5);                                                // Temperaturwert anzeigen
    lcd.setCursor(16, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(12, 1);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h5);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(16, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  //Sensor6
    lcd.setCursor(12, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t6);                                                // Temperaturwert anzeigen
    lcd.setCursor(16, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(12, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h6);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(16, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

// Aktuelle Uhrzeit im Display anzeigen

    if (STD <= 9)                                               // Uhrzeit verschieben (STD)
  {
    lcd.setCursor(18, 0);
    lcd.print("0");
    lcd.setCursor(19, 0);
    lcd.print(now.hour(), DEC);
  }
  else
  {
    lcd.setCursor(18, 0);
    lcd.print(now.hour(), DEC);
  }

  if (MIN <= 9)                                                // Uhrzeit verschieben (MIN)
  {
    lcd.setCursor(18, 1);                                      // Zeichen, Spalte
    lcd.print("0");
    lcd.setCursor(19, 1);
    lcd.print(now.minute(), DEC);
  }
  else
  {
    lcd.setCursor(18, 1);
    lcd.print(now.minute(), DEC);
  }

// Anzeige-LEDs für geringen Füllstand
  
    if (Fuellstandswert == LOW) {
    digitalWrite(LED_empty, HIGH);
    }
    else {
    digitalWrite(LED_empty, LOW);
    }

    if (Fuellstandswert1 == LOW) {
    digitalWrite(LED_low, HIGH);
    }
    else {
    digitalWrite(LED_low, LOW);
    }

// Sprühintervall in Abhängigkeit von Uhrzeit und Füllstand
    
    if ((STD >= 8) && (STD <= 17) && (Fuellstandswert == HIGH)) {    // Uhrzeit zwischen 8:00 und 17:59 Uhr
      if ((millis() - mil1) >= 900000) {                             // if: viertel Stunde abgelaufen
      digitalWrite(Sprueh2, LOW);                                    // Sprühen
      delay(2000);
      digitalWrite(Sprueh2, HIGH);                                   // Sprühen beenden
      delay(500);
      mil1 = millis();                                               // Zeitstempel nullen
      delay(500);
        if (Intervallmerker == 1) {
        digitalWrite(Sprueh1, LOW);                                  // Sprühen
        delay(2000);
        digitalWrite(Sprueh1, HIGH);                                 // Sprühen beenden
        delay(500);
        Intervallmerker = 0;
        }
        else {
          Intervallmerker = 1;
        }
      }
    }

// Letztes Sprühen um 18 Uhr
  
    if ((STD == 18) && (MIN == 0) && (Fuellstandswert == HIGH)) {
    digitalWrite(Sprueh2, LOW);                                      // Sprühen
    delay(3000);
    digitalWrite(Sprueh2, HIGH);                                     // Sprühen beenden
    delay(500);
    digitalWrite(Sprueh1, LOW);                                      // Sprühen
    delay(3000);
    digitalWrite(Sprueh1, HIGH);                                     // Sprühen beenden
    delay(60000);
    mil1 = millis();                                                 // Zeitstempel nullen
    }

// Beleuchtung des Terrariums

    if ((STD >= 8) && (STD <= 17)) {
    digitalWrite(Beleuchtung_Tag, LOW); 
    }
    else {
    digitalWrite(Beleuchtung_Tag, HIGH);
    }

    if ((STD >= 18) && (STD <= 19)) {
    digitalWrite(Beleuchtung_Abend, LOW);
    }
    else {
    digitalWrite(Beleuchtung_Abend, HIGH);
    }

// Heizung im Terrarium

  // Tagsüber
  
    if ((STD >= 8) && (STD <= 17) && (t1 <= 27)) {                    // Entweder t1 oder t2 für Kornnattern
    digitalWrite(Heizung1, LOW);
    }
    else {
    digitalWrite(Heizung1, HIGH);
    }
    if ((STD >= 8) && (STD <= 17) && (t3 <= 30)) {                    // Entweder t3 oder t4 für Königspython 1 (unten)
    digitalWrite(Heizung2, LOW);
    }
    else {
    digitalWrite(Heizung2, HIGH);
    }
    if ((STD >= 8) && (STD <= 17) && (t5 <= 30)) {                    // Entweder t5 oder t6 für Königspython 2 (oben)
    digitalWrite(Heizung3, LOW);
    }
    else {
    digitalWrite(Heizung3, HIGH);
    }

  // Nachtabsenkung (Kornnattern ganz aus)
  
    if ((STD >= 18) && (t3 <= 26)) {                                  // für Königspython 1 (unten)
    digitalWrite(Heizung2, LOW);
    }
    else {
    digitalWrite(Heizung2, HIGH);
    }
    if ((STD >= 18) && (t5 <= 26)) {                                  // für Königspython 2 (oben)
    digitalWrite(Heizung3, LOW);
    }
    else {
    digitalWrite(Heizung3, HIGH);
    }

    if ((STD <= 7) && (t3 <= 26)) {                                  // für Königspython 1 (unten)
    digitalWrite(Heizung2, LOW);
    }
    else {
    digitalWrite(Heizung2, HIGH);
    }
    if ((STD <= 7) && (t5 <= 26)) {                                  // für Königspython 2 (oben)
    digitalWrite(Heizung3, LOW);
    }
    else {
    digitalWrite(Heizung3, HIGH);
    }

  delay(2500);
    
}

Also a picture of my 'wiring', well, at least how I planned it.

I hope you can help me.

Sorry for my bad english...

In principle using 0 & 1 is OK, but how do you debug this? I would certainly get stuck trying to and I'd much rather add a MCP23017 GPIO expander to the project to get 16 more pins for driving relays etc. so I could have my Serial back.

Furthermore, like many projects, yours is essentially a state machine, but programmed with a combination of nested if-statements and delays (notwithstanding your valiant attempt at harnessing millis()...) I myself have pretty much given up on trying to fix such a system whenever it breaks - which it invariably does. As you've noticed, all is nice and dandy as long as the system isn't too complex, but once it does become complex, you get pretty much stuck. A better approach is making a 'proper' finite state machine using for instance switch-case logic to have cleanly defined states in which only specific parts of code are executed. I'm personally quite fond of this page which gives a primer of the topic as well as a small example: State Machines and Arduino Implementation – Norwegian Creations

So, in short, my advice:

  • Get back Serial so you can debug properly
  • Fundamentally change your approach to how you've set up this program
1 Like

At first glance of the code suggest you do a rewrite.

  • Get rid of delay( )s
  • write the sketch as a State Machine
1 Like

PS: your English is fine! Don't worry about it :slight_smile:

1 Like

What does it do? What should it?

Your loop function is long and hard to read. I suggest that you break it out into several separate functions. The first easy change is to move all the LCD display code to a function of its own.

Maybe move the heating controller code out too. Keep going until each function fits on a page - so much easier to debug.

1 Like

Does this State Machine work with three different terraria on one chip? Or would you rather use three Arduinos for that?

I am currently reading the article you linked in your answer and am a little bit overwhelmed. But it makes sense. I just wonder how much longer it will take for me to fully grasp this potential :exploding_head:

For the serial... I started debugging with help from the I2C display. I changed the code so that I could see in which step the program was with little markers on the display. I would really like to keep the layout of my board, because I have made a pcb for it and all the ports. It defintely makes debugging harder, but apart from that I really don't need serial.
I thought about using an Arduino Mega for the sole purpose of debugging and testing the code, but I don't know if that makes sense though.

Really thank you for your help. I Will try my best so change the code accordingly.

Do it. Serial is just about the only tool you can debug a Nano with, so having to test without it will be a nightmare.

1 Like

It does show me the sensor values, the time (hour and minute) and the reading of the analog sensor on the display and managed to switch one relais (for Heizung1).
What it should do... Well, it should show all these things on the display. Furthermore it should regulate the temperature in each of the terraria accordnigly. 27°C for terrarium1 and 31°C for terrarium2&3 on daytime and 27°C only for terrarium 2&3 at night. Two more things it should do: Switch two different Light relais, one for the day, 8am-6pm (combined for all three terraria) and one for the evening, 6pm-8pm to light some spots. And last but not least controll the humidity in the terraria. From 8am-6pm it should switch two relais for 2-3 seconds. one of them in a 30 minutes interval, the other in a 15-20 minutes interval.

So heating, humidity, light and display.

I get that the loop part is really hard to read. Sorry about that :sweat: I think thats my problem, too. I started using different functions to keep the loop clean, but I did not manage to fit it on different pages.

I am very new to all this and it is rather hard to learn all the details and workarounds to get to my goal.

Thank you very much for your answer and advice. :slight_smile:

To be clear, it doesn't need to be on separate tabs - all your code can be in a single file. It's just easier to work with if you can view each function without having to scroll.

1 Like

Good morning dear helpers :slight_smile:

This is more difficult than I thought. Maybe for me it is just the first steps that are so difficult, because I can't really think about a good way to make use of the switch cases.

My first ideas were not in the slightest logical so in the end I came up with this:

  #include <Wire.h>
  #include "RTClib.h"
  #include <LiquidCrystal_I2C.h>
  #include <DHT.h>

  LiquidCrystal_I2C lcd(0x27, 20, 4);  // Set the LCD I2C address

  RTC_DS3231 rtc;

  #define DHT1_Pin 2                                                // Datenpin des DHT22(1) ist Pin 2
  #define DHT2_Pin 3                                                // Datenpin des DHT22(2) ist Pin 3
  #define DHT3_Pin 4                                                // Datenpin des DHT22(3) ist Pin 4
  #define DHT4_Pin 5                                                // Datenpin des DHT22(4) ist Pin 5
  #define DHT5_Pin 6                                                // Datenpin des DHT22(5) ist Pin 6
  #define DHT6_Pin 7                                                // Datenpin des DHT22(6) ist Pin 7
  #define DHT_Typ DHT22                                             // DHT 22 als Sensortyp festlegen
    
  DHT dht1(DHT1_Pin, DHT_Typ);                                      // Sensor 1 initialisieren
  DHT dht2(DHT2_Pin, DHT_Typ);                                      // Sensor 2 initialisieren
  DHT dht3(DHT3_Pin, DHT_Typ);                                      // Sensor 3 initialisieren
  DHT dht4(DHT4_Pin, DHT_Typ);                                      // Sensor 4 initialisieren
  DHT dht5(DHT5_Pin, DHT_Typ);                                      // Sensor 5 initialisieren
  DHT dht6(DHT6_Pin, DHT_Typ);                                      // Sensor 6 initialisieren

  // Merker
  unsigned long mil1;
  unsigned int STD;
  unsigned int MIN;
  int Fuellstandswert;
  int Fuellstandswert1;
  int Intervallmerker;
  int Temp1;
  int Temp3;
  int Temp5;
  float h1;
  float t1;
  float h2;
  float t2;
  float h3;
  float t3;
  float h4;
  float t4;
  float h5;
  float t5;
  float h6;
  float t6;

  // Sensoren
  int Sensor = A7;                                                   //Umgebungslichtsensor
  int Fuellstand_low = 14;
  int Fuellstand_empty = 15;

  // Relais
  int Sprueh1 = 8;
  int Sprueh2 = 10;
  int Heizung1 = 13;
  int Heizung2 = 16;
  int Heizung3 = 17;
  int Beleuchtung_Tag = 1;
  int Beleuchtung_Abend = 0;
  
  // Sonstige Outputs
  int LED_low = 11;
  int LED_empty = 12;
  int Display_Licht = 9;                                            // PIN9 ist belegt von der DisplayLED
  
  //Funktionen
  void Display();                                                   //Anzeigen auf dem Display
  void Heizung_1();                                                   //Heizprogramm
  void Heizung_2();
  void Heizung_3();
  void Licht();                                                     //Beleuchtung
  void Sensor_lesen();


void setup() {

  dht1.begin();                                                   // Sensor 1 starten
  dht2.begin();                                                   // Sensor 2 starten
  dht3.begin();                                                   // Sensor 3 starten
  dht4.begin();                                                   // Sensor 4 starten
  dht5.begin();                                                   // Sensor 5 starten
  dht6.begin();                                                   // Sensor 6 starten

  lcd.begin();

  pinMode(Fuellstand_low, INPUT);
  pinMode(Fuellstand_empty, INPUT);
  pinMode(Sensor, INPUT);
  pinMode(Sprueh1, OUTPUT);
  pinMode(Sprueh2, OUTPUT);
  pinMode(Heizung1, OUTPUT);
  pinMode(Heizung2, OUTPUT);
  pinMode(Heizung3, OUTPUT);
  pinMode(Beleuchtung_Tag, OUTPUT);
  pinMode(Beleuchtung_Abend, OUTPUT);
  pinMode(Display_Licht, OUTPUT);
  pinMode(LED_low, OUTPUT);
  pinMode(LED_empty, OUTPUT);

  digitalWrite(Sprueh1, HIGH);
  digitalWrite(Sprueh2, HIGH);
  digitalWrite(Heizung1, HIGH);
  digitalWrite(Heizung2, HIGH);
  digitalWrite(Heizung3, HIGH);
  digitalWrite(Beleuchtung_Tag, HIGH);
  digitalWrite(Beleuchtung_Abend, HIGH);

  DateTime now = rtc.now();

}

void loop() {

  Sensor_lesen();

  if(Temp1 <= 27){
    Heizung_1();
  }
  if(Temp3 <= 30){
    Heizung_2();
  }
  if(Temp5 <= 30){
    Heizung_3();
  }

  Display();

  delay(3000);

}


void Sensor_lesen() {
  
  // Sensoren auslesen
  DateTime now = rtc.now();        

  STD = now.hour();
  MIN = now.minute();

  h1 = dht1.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 1)
  t1 = dht1.readTemperature();                            // Auslesen der Temperatur (Sensor 1)
  h2 = dht2.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 2)
  t2 = dht2.readTemperature();                            // Auslesen der Temperatur (Sensor 2)
  h3 = dht3.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 3)
  t3 = dht3.readTemperature();                            // Auslesen der Temperatur (Sensor 3)
  h4 = dht4.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 4)
  t4 = dht4.readTemperature();                            // Auslesen der Temperatur (Sensor 4)
  h5 = dht5.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 5)
  t5 = dht5.readTemperature();                            // Auslesen der Temperatur (Sensor 5)
  h6 = dht6.readHumidity();                               // Auslesen der Luftfeuchtigkeit (Sensor 6)
  t6 = dht6.readTemperature();                            // Auslesen der Temperatur (Sensor 6)

  Sensor = analogRead(A7);                                      // Lichtsensor für Displaybeleuchtung
  Fuellstandswert = digitalRead(Fuellstand_empty);              // Merker für Füllstand der Sprühanage
  Fuellstandswert1 = digitalRead(Fuellstand_low);

  Temp1 = t1;
  Temp3 = t3;
  Temp5 = t5;
}

void Heizung_1() {
  switch(STD) {
    case 8 ... 17:
      digitalWrite(Heizung1, LOW);    
  }
}

void Heizung_2() {
  switch(STD) {
    case 8 ... 17:
      digitalWrite(Heizung2, LOW);    
  }
}

void Heizung_3() {
  switch(STD) {
    case 8 ... 17:
      digitalWrite(Heizung3, LOW);    
  }
}

void Display() {
  // Platzhalter für Lichtlevelanzeige im Display
    
    if (Sensor <=99) {
    lcd.setCursor(17,3);
    lcd.print(" ");
    lcd.setCursor(18,3);
    lcd.print(Sensor);
    }
    else {
    lcd.setCursor(17,3);
    lcd.print(Sensor);  
    }

  // Platzhalterstriche

    lcd.setCursor(17, 2);
    lcd.print("---");

  // Anzeige der Temperatur und Luftfeuchtigkeit

    // Sensor1
    lcd.setCursor(0, 0);                                          // 1. Zeichen, 1. Zeile
    lcd.print(t1);                                                // Temperaturwert anzeigen
    lcd.setCursor(4, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(0, 1);                                          // 1. Zeichen, 2. Zeile
    lcd.print(h1);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(4, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

    // Sensor2
    lcd.setCursor(0, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t2);                                                // Temperaturwert anzeigen
    lcd.setCursor(4, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(0, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h2);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(4, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

    //Sensor3
    lcd.setCursor(6, 0);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t3);                                                // Temperaturwert anzeigen
    lcd.setCursor(10, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(6, 1);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h3);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(10, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

    //Sensor4
    lcd.setCursor(6, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t4);                                                // Temperaturwert anzeigen
    lcd.setCursor(10, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(6, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h4);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(10, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

    //Sensor5
    lcd.setCursor(12, 0);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t5);                                                // Temperaturwert anzeigen
    lcd.setCursor(16, 0);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(12, 1);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h5);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(16, 1);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

    //Sensor6
    lcd.setCursor(12, 2);                                          // 7. Zeichen, 1. Zeile
    lcd.print(t6);                                                // Temperaturwert anzeigen
    lcd.setCursor(16, 2);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet
    lcd.setCursor(12, 3);                                          // 7. Zeichen, 2. Zeile
    lcd.print(h6);                                             // Feuchtigkeitswert anzeigen
    lcd.setCursor(16, 3);
    lcd.print(" ");                                               // Leerzeichen, damit die letzte 0 im Wert verschwindet

  // Aktuelle Uhrzeit im Display anzeigen

    if (STD <= 9)                                               // Uhrzeit verschieben (STD)
  {
    lcd.setCursor(18, 0);
    lcd.print("0");
    lcd.setCursor(19, 0);
    lcd.print(STD, DEC);
  }
  else
  {
    lcd.setCursor(18, 0);
    lcd.print(STD, DEC);
  }

  if (MIN <= 9)                                                // Uhrzeit verschieben (MIN)
  {
    lcd.setCursor(18, 1);                                      // Zeichen, Spalte
    lcd.print("0");
    lcd.setCursor(19, 1);
    lcd.print(MIN, DEC);
  }
  else
  {
    lcd.setCursor(18, 1);
    lcd.print(MIN, DEC);
  }

  // Anzeige-LEDs für geringen Füllstand
  
    if (Fuellstandswert == LOW) {
    digitalWrite(LED_empty, HIGH);
    }
    else {
    digitalWrite(LED_empty, LOW);
    }

    if (Fuellstandswert1 == LOW) {
    digitalWrite(LED_low, HIGH);
    }
    else {
    digitalWrite(LED_low, LOW);
    }
}

My idea now was to make this State Machine dependent on the time of the RTC. For example between hour 8 and 17 (german for 8am to 5:59pm) it should check if the temperatures are right and act accordingly. Another switch case would be dependent on the minutes, every 15/30 minutes to spray some water. I hope you understand where this is going.

But my question: Is this even a good way to write it like that? Can I use the delay() with this kind of setup? Or should I try to go with millis() instead (which I find way more difficult)? Right now all I'm doing is turning the heater on though. Where would I implement the code for turning it off again after reaching the temperature?

And worst of all, nothing really works right now :sweat_smile: ... The code compiles and I get no errors, but neither the display shows anything, nor does the heating work. All that the Arduino is doing right now is switching pin13 (Heizung1) on for a split second and switching it off again.

Maybe you see the faults in my early code? What could I change for it to run at least for a bit?
Today I ordered another Arduino Mega for this project. My other one is soldered into another project of mine :roll_eyes:

Thank you all for your time that you are spending with me on my project. I really appreciate it!

That sounds like the system is resetting. I suggest that you remove whatever you have from pins zero and one and add some serial prints to see what's going on.

Millis is a useful tool when you need the system to respond to button presses or other human input. Since you don't (yet) using delay is fine for now.

1 Like

Hi,
Are you aware you can use some of the Nano analog input pins as digital I/O.
That would free the pin0 and pin1 conflict.

Can you please post a schematic of your project?
Include component names and pin labels as well as power supplies.

Did you write your code in stages?
If so you should have code the JUST controls ONE terrarium.
If you run the single code with ONLY the one terrarium components fitted to your circuit does your problem still appear?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

1 Like

This is key. Although you haven't written the whole thing, you do have rather too much code there for something that doesn't work. Start small and test.

Hey Tom,

thank you for your help. I actually wrote the code myself and with the help of google. It is however a beefier version of the original code I still use in my other two terraria. And yes, I wrote it in in stages, although as soon as I get to the 'main' part with all the if-statements, the program refuses to work. I did not try to just controll one terrarium though.

For the schematics:

I made a custom PCB for this project. For easier access (well, I don't like the mini USB) I added a micro USB port to get power from. It (and everything related) is powered from a 5v 2A charger.
Pin A6 is just a dummy and not used atm. I just thought I'll add it to the PCB when I might need it.

And my wild guess is that it has to do something with either my poor writing (/understanding) of the code or with the way I implemented everything on the board. I just did what I was doing on my other terraria.

Greetings from your german pal

I think I've found the culprit... It seems the library for my DS3231 was somehow faulty. I updated it before I compiled the code.
I tested it with my new Arduino Mega and it gave me quite a headache... After removing almost everything from my code except for the time and sensor readings, I realised that something with my time seemed odd.
Long story short, I replaced the library (RTClib) with another library (uRTCLib) and it just works now. Even with my crappy code from the beginning.

Nonetheless I'd love to improve on my coding. But I'm not quite sure how to write that state machine (or at least how to start).

Thank you for your help my friends.

State machines are trivially easy to write, very powerful and well suited to the problem you're trying to solve. That's the good news. The bad news is that almost everyone finds it really hard to get their head around the concept.

You will need to look at tutorials and many many examples - the more the better. Once you get into the right way of thinking, it's simple. But the journey there is bizarrely difficult.

1 Like

I thought so :smiley:
But I'll keep learning! Thank you all for your help and time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.