Tortoise vivarium controller

would it be wise to just start from scratch? get the DHT's working well then add the LEDs and so on and so fourth?

Well I would have a test sketch for each subsystem, so get a just two sensors reads and prints the temps and humidities sketch working on the side.

But starting all over seems extreme. There are a few delays sprinkled around, none woukd be particularly hard to eliminate. I can't just now, but having a pump come on for some logical reason, then go off three seconds later, does not need to depend on delay().

When you turn on the pump, note the time, and that the pump is. Pumping.

if ( <whatever reason>) {
    pumpStartedTime = millis();
    pumpBePumping = true;

    digitalWrite… or whatever turns on the pump. 
}

Then anywhere else in you loop() function (outside any if statements or loops it might have) just plop down some code to turn off the pump when the time is arrived, viz:

  if (pumpBePuming && millis() - pumpStartedTime > 3000) {
    pumpBePumping = false;

    digitalWrite… or whatever turns ~~on~~ _off_ the pump. 
  }

Which snippets assume a few variables:

unsinged long pumpStartTime;
bool pumpBePumping = false;  // global would be false automatically, but let's be clear

HTH

a7

As @alto777 said, not necessarily. You just have to conceptualize this differently. Think about a video game with different game modes on the startup screen, something like Mario Bros (pick one)
You have all the same assets available on the cartridge, but options for One Player, Two Player, Vs and maybe Demo that select out the ones you don't need depending on what you choose.
In your case, since you want an automated vivarium (my new favorite word) "what you choose" isn't you pressing a button on a Nintendo controller (but it could be - super easy to use with Arduino due to some hard work others have posted on the internet, but I digress). "What you choose" in your case will be defined by sensor readings.
You will have (so far from your sketch), four conditions you need to monitor for your tortoise:

  • too warm
  • too cold
  • too wet
  • too dry

So you check these at the start of void loop(). What you need to do is make a state machine where all the possible conditions from those four vivarium conditions drive a single byte that you initialize in void setup() as zero, or the default condition

Then you drive the state variable in your globals, maybe

byte vivMode;

using numbers you assign in your checkThresholds(temp1, temp2, humidity1, humidity2);
function to every possible threshold combination you have, including when everything is just fine (which you set back to zero, just like it was initialized in setup()).
As you have it right now, it's really easy since it looks like your only outputs in any adverse condition are to turn an led and buzzer on or off.
But if you do the legwork on figuring out all the possible combinations of conditions in the vivarium, it becomes easy to plug in the different functions such as mister, lights, whatever, and add later on if you wish.
Consider the following sketch, which just checks millis() and increments though a few modes that do nothing except report the mode and increment to the next one.

byte mode; // you could have 0 - 255 modes if you wanted.
unsigned long currentTime;
unsigned long lastTimeAround;

void setup() {
  Serial.begin(9600);
  Serial.println(F("millisTimerStateMachine"));
  delay(500);
  Serial.println();
  mode = 0; // start at mode 0
  currentTime = 0;
  lastTimeAround = 0;
}

void loop() {
  // start free running timer
  currentTime = millis();
  // set conditional statement whose condition is to check clock and report every  seconds
  if (currentTime - lastTimeAround > 2000) {
    switch (mode) {
      case 0:
        zero();
        break;
      case 1:
        one();
        break;
      case 2:
        two();
        break;
      case 3:
        three();
        break;
      case 4:
        four();
        break;
    }
    // synch the time marker to the free running clock
    lastTimeAround = currentTime;
  }
}
void zero() {
  Serial.println("mode 0");
  mode += 1; // increment mode by one, to mode 1
}
void one() {
  Serial.println("mode 1");
  mode += 1; // exit to mode 2
}
void two() {
  Serial.println("mode 2");
  mode += 1;
}
void three() {
  Serial.println("mode 3");
  mode += 1;
}
void four() {
  Serial.println("mode 4");
  mode = 0; // reset to mode 0
}

Consider this alternate way of driving the state machine, just type in 0-4 in serial monitor. In your project, 0-4 wouldn't be driven by typing in the serial monitor; rather, by the possible conditions of the vivarium based on temp and humidity.

char vivMode; 

void setup() {
  Serial.begin(9600);
  Serial.println(F("charDrivenStateMachine"));
  delay(500);
  Serial.println();
  vivMode = '0'; // start at vivMode 0
}

void loop() {
  if (Serial.available() > 0) {
    vivMode = Serial.read();
    switch (vivMode) {
      case '0':
        vivModeZero();
        break;
      case '1':
        vivModeOne();
        break;
      case '2':
        vivModeTwo();
        break;
      case '3':
        vivModeThree();
        break;
      case '4':
        vivModeFour();
        break;
    }
  }
}

void vivModeZero() {
  Serial.println("vivMode 0");
  Serial.println("everything off function here");
  Serial.println("");
}
void vivModeOne() {
  Serial.println("vivMode 1");
  Serial.println("lights on, heater on, mister on function here");
  Serial.println("");
}
void vivModeTwo() {
  Serial.println("vivMode 2");
  Serial.println("lights on, heater on, mister off function here");
  Serial.println("");
}
void vivModeThree() {
  Serial.println("vivMode 3");
  Serial.println("lights on, heater off, mister off function here");
  Serial.println("");
}
void vivModeFour() {
  Serial.println("vivMode 4");
  Serial.println("lights on, heater off, mister on function here");
  Serial.println("");
}


Yes, that's how to start. I would sit down with a clean sheet of paper and a pencil with a large eraser. Start listing what you want to monitor and or control and what you want to happen when a parameter is above or below your limits. As pointed out if temperature > a preset point, do something. :slight_smile: Detail everything on the sheet of paper you start with.

I would take baby steps on your code. Start simple making sure at each step the code compiles and runs before moving along adding more code.

Ron

Okay. I've started over. So far I've got both DHT's sort of reading. They read temperature just fine, but the humidity is just a number? When I looked through the library files, the humidity line doesn't have a calculation. Not sure if that matters. Any idea how to get the humidity reading correctly?

/*
Godzilla monitor. Monitor temperature and humidity with 2x DHT22's. Temperature parameters are >75 <90*F. 
Humidity parameters are >40 <60%. Humidity is controlled by a submersible waterpump that activates when humidity falls 
below 40%, connected to an IoT relay, should only need 1 relay switch. A UVB light is also connected to an IoT and will 
cycle between 12hrs on / 12hrs off, should also need 1 relay switch here as well. Temperature and humidity will be 
displayed on a 16x2 LCD. A red LED will illuminate when temp or humidity is out of parameters. A blue LED will 
illuminate when the water pump is active. A green LED will illuminate when a relay is activated. 

-Eventually I want to connect it to the internet, possibly a different arduino board.
*/

#include <Bonezegei_DHT11.h>
#include <LiquidCrystal.h>



//DHT11 signal pin
Bonezegei_DHT11 dht_1(2);
Bonezegei_DHT11 dht_2(3);

//Type of DHT
//DHT dht_1(DHT_1_PIN_DATA);
//DHT dht_2(DHT_2_PIN_DATA);


//LCD signal pins
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 13, en = 12, d4 = 5, d5 = 6, d6 = 7, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  Serial.begin(9600);
  //starting various things
  dht_1.begin();
  dht_2.begin();
  lcd.begin(16, 1);
  // Print a message to the LCD.
  lcd.print("Godzilla's House");
  delay(3000);
  lcd.clear();
  //lcd.print("Species Acquired Apr30,2024");
  //delay(7000);
  //lcd.clear();
}

void loop() {
    // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(16, 1);
  

  if (dht_1.getData()) {                         // get All data from DHT11
    //float tempDeg = dht.getTemperature(false);      // return temperature in celsius
    float tempFar = dht_1.getTemperature(true);  // return temperature in fahrenheit if true celsius of false
    int hum = dht_1.getHumidity();               // return humidity
    String str  = "Temp: ";
        //   str += tempDeg;
        //   str += "°C  ";
           str += tempFar;
           str += "°F  Hum:";
           str += hum;
    Serial.println(str.c_str());
    //Serial.printf("Temperature: %0.1lf°C  %0.1lf°F Humidity:%d \n", tempDeg, tempFar, hum);
    lcd.println(str.c_str());
    delay(3000);  //delay atleast 2 seconds for DHT11 to read tha data
    lcd.clear();
    

 if (dht_2.getData()) {                         // get All data from DHT11
    //float tempDeg = dht.getTemperature(false);      // return temperature in celsius
    float tempFar = dht_2.getTemperature(true);  // return temperature in fahrenheit if true celsius of false
    int hum = dht_2.getHumidity();               // return humidity
    String str  = "Temp: ";
        //   str += tempDeg;
        //   str += "°C  ";
           str += tempFar;
           str += "°F  Hum:";
           str += hum;
    Serial.println(str.c_str());
    //Serial.print("Temperature: %0.1lf°C  %0.1lf°F Humidity:%d \n, tempDeg, tempFar, hum");
    lcd.println(str.c_str());
    delay(3000);  //delay atleast 2 seconds for DHT11 to read tha data
    lcd.clear();
  }
}
}
  

Screenshot 2024-05-09 at 4.27.58 PM
Here's how it displays

Throw in some debugging prints - try printing the value of hum right after it is read. If necessary, throw some into the library to see what the data bytes from the hardware actually are. Make sure to keep a clean copy of the library though :smiley:

I got the same thing from your code. The humidity is definitely not right.

With a different library and switching to the (as far as I know) totally compatible DHT22, meaningful humidity numbers appear.

Maybe switch libraries and try a similar small temp and humidity from one (and then two) sensors just printing to the serial monitor sketch.

a7

Okay, I've switched libraries but now I'm having issues with a redeclaration error. The temp, humidity, and heat index all work using the new adafruit DHT library but having errors when I try an implement it into my code. I'm still learning so please forgive me if I seem clueless in some areas.

/*
Godzilla monitor. Monitor temperature and humidity with 2x DHT22's. Temperature parameters are >75 <90*F. 
Humidity parameters are >40 <60%. Humidity is controlled by a submersible waterpump that activates when humidity falls 
below 40%, connected to an IoT relay, should only need 1 relay switch. A UVB light is also connected to an IoT and will 
cycle between 12hrs on / 12hrs off, should also need 1 relay switch here as well. Temperature and humidity will be 
displayed on a 16x2 LCD. A red LED will illuminate when temp or humidity is out of parameters. A blue LED will 
illuminate when the water pump is active. A green LED will illuminate when a relay is activated. 

-Eventually I want to connect it to the internet, possibly a different arduino board.
*/

#include <DHT.h>
#include <LiquidCrystal.h>




//DHT11 signal pin
#define DHT_1 dht_1(2);
#define DHT_2 dht_2(3);

//Type of DHT
DHT dht_1(2, DHT22);
DHT dht_2(3, DHT22);

//LED pins
//RED DHT1-32
//RED DHT2-33
//Yellow DHT1-34
//Yellow DHT2-35
//BLUE-36
//GREEN-31
//GREEN-30
//


//LCD signal pins
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 13, en = 12, d4 = 5, d5 = 6, d6 = 7, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  Serial.begin(9600);
  //starting various things
  dht_1.begin();
  dht_2.begin();
  lcd.begin(16, 1);
  // Print a message to the LCD.
  lcd.print("Godzilla's House");
  delay(3000);
  lcd.clear();
  //lcd.print("Species Acquired Apr30,2024");
  //delay(7000);
  //lcd.clear();
  //pinMode(LED_BUILTIN, 30);
}

void loop() {
    // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(16, 1);
  //This is DHT_1
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht_1.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht_1.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht_1.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht_1.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht_1.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  //Serial.print(hic);
  //Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));

 //delay(3000);
    
 //This is DHT_2
 // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht_2.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht_2.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht_2.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht_2.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht_2.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
 //If temp above 73 on DHT1/2 turn on Red LEDs   
    if (dht_1.readTemperature(true); tempFar > 73.00) digitalWrite(32, HIGH);
    if (dht_2.readTemperature(true); tempFar >73.00) digitalWrite(33, HIGH);
    delay(3000);
    //IF Humidity below 40% turn on Yellow LEDs
    if (dht_1.readHumidity(); hum <3) digitalWrite(34, HIGH);
    else digitalWrite(34, LOW);
    if (dht_2.readHumidity(); hum <3) digitalWrite(35, HIGH);
    else digitalWrite(35, LOW);

//Relay 1 for UVB light, 12hrs on, 12hrs off, 2 green LEDs show when active
//12hrs in milliseconds: 43200000 ms
    delay(3000);
    digitalWrite(30, HIGH);
    delay(4000);
    digitalWrite(30, LOW);

//Relay 2 
    digitalWrite(31, HIGH);
    delay(4000);
    digitalWrite(31, LOW);

//Waterpump operation
if (dht_1.readHumidity(); hum <3); digitalWrite(40, HIGH);
 }else digitalWrite(40, LOW);
if (dht_2.readHumidity(); hum <3); digitalWrite(40, HIGH);
 }else digitalWrite(40, LOW);
if (digitalWrite(40,HIGH), digitalWrite(36, HIGH);
 }else digitalWrite(36, LOW);

}
}}}

  

Below is the error I get:
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino: In function 'void loop()':
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:101:9: error: redeclaration of 'float h'
float h = dht_2.readHumidity();
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:67:9: note: 'float h' previously declared here
float h = dht_1.readHumidity();
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:103:9: error: redeclaration of 'float t'
float t = dht_2.readTemperature();
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:69:9: note: 'float t' previously declared here
float t = dht_1.readTemperature();
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:105:9: error: redeclaration of 'float f'
float f = dht_2.readTemperature(true);
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:71:9: note: 'float f' previously declared here
float f = dht_1.readTemperature(true);
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:114:9: error: redeclaration of 'float hif'
float hif = dht_2.computeHeatIndex(f, h);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:80:9: note: 'float hif' previously declared here
float hif = dht_1.computeHeatIndex(f, h);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:116:9: error: redeclaration of 'float hic'
float hic = dht_2.computeHeatIndex(t, h, false);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:82:9: note: 'float hic' previously declared here
float hic = dht_1.computeHeatIndex(t, h, false);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:130:38: error: 'tempFar' was not declared in this scope
if (dht_1.readTemperature(true); tempFar > 73.00) digitalWrite(32, HIGH);
^~~~~~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:130:38: note: suggested alternative: 'tmpnam'
if (dht_1.readTemperature(true); tempFar > 73.00) digitalWrite(32, HIGH);
^~~~~~~
tmpnam
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:131:38: error: 'tempFar' was not declared in this scope
if (dht_2.readTemperature(true); tempFar >73.00) digitalWrite(33, HIGH);
^~~~~~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:131:38: note: suggested alternative: 'tmpnam'
if (dht_2.readTemperature(true); tempFar >73.00) digitalWrite(33, HIGH);
^~~~~~~
tmpnam
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:134:31: error: 'hum' was not declared in this scope
if (dht_1.readHumidity(); hum <3) digitalWrite(34, HIGH);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:136:31: error: 'hum' was not declared in this scope
if (dht_2.readHumidity(); hum <3) digitalWrite(35, HIGH);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:152:27: error: 'hum' was not declared in this scope
if (dht_1.readHumidity(); hum <3); digitalWrite(40, HIGH);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino: At global scope:
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:153:3: error: expected unqualified-id before 'else'
}else digitalWrite(40, LOW);
^~~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:1: error: expected unqualified-id before 'if'
if (dht_2.readHumidity(); hum <3); digitalWrite(40, HIGH);
^~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:27: error: 'hum' does not name a type
if (dht_2.readHumidity(); hum <3); digitalWrite(40, HIGH);
^~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:48: error: expected constructor, destructor, or type conversion before '(' token
if (dht_2.readHumidity(); hum <3); digitalWrite(40, HIGH);
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:155:2: error: expected declaration before '}' token
}else digitalWrite(40, LOW);
^
Multiple libraries were found for "LiquidCrystal.h"
Used: /Users/j.rohrbachart/Documents/Arduino/libraries/LiquidCrystal
Not used: /Users/j.rohrbachart/Library/Arduino15/libraries/LiquidCrystal
exit status 1

Compilation error: redeclaration of 'float h'

You are pre-forgiven. We all start nowhere.

Here your mistake is spelled out in the error messages.

This

   float h = dht_1.readHumidity();

does two things. It makes new variable, and sets it to the value returned by the readHunidity() method.

This, later, would be how to just do the assignment, not attempt to create a new variable of the same name in the same scope.

   h = dht_1.readHumidity();

So you shoukd have only one "float" qualifier before any given variable, at the first place you need to tell your code you are using new variable.

For noobs and many ppl, the easiest is to use global variables, declared at the top of the code

float theHumidity;

and use theHumidity wherever you want, just without that "float" qualifier.

If you want to learn more, in general you could look into variable types, variable definitions, variable declarations and variable scope.

Maybe start here:

HTH

a7

aha! So I figured out in the time since I posted that I already declared t, h, and f so I added a 2 next to the second sensors t, h, and f to help delineate between the two sensors. But now I get a new error "expected unqualified-is before ___, there's multiple errors but going short hand for this part.

Might I say, you all are some awesome people and thank you for the help.

/*
Godzilla monitor. Monitor temperature and humidity with 2x DHT22's. Temperature parameters are >75 <90*F. 
Humidity parameters are >40 <60%. Humidity is controlled by a submersible waterpump that activates when humidity falls 
below 40%, connected to an IoT relay, should only need 1 relay switch. A UVB light is also connected to an IoT and will 
cycle between 12hrs on / 12hrs off, should also need 1 relay switch here as well. Temperature and humidity will be 
displayed on a 16x2 LCD. A red LED will illuminate when temp or humidity is out of parameters. A blue LED will 
illuminate when the water pump is active. A green LED will illuminate when a relay is activated. 

-Eventually I want to connect it to the internet, possibly a different arduino board.
*/

#include <DHT.h>
#include <LiquidCrystal.h>




//DHT11 signal pin
#define DHT_1 dht_1(2);
#define DHT_2 dht_2(3);

//Type of DHT
DHT dht_1(2, DHT22);
DHT dht_2(3, DHT22);

//LED pins
//RED DHT1-32
//RED DHT2-33
//Yellow DHT1-34
//Yellow DHT2-35
//BLUE-36
//GREEN-31
//GREEN-30
//


//LCD signal pins
// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 13, en = 12, d4 = 5, d5 = 6, d6 = 7, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


void setup() {
  Serial.begin(9600);
  //starting various things
  dht_1.begin();
  dht_2.begin();
  lcd.begin(16, 1);
  // Print a message to the LCD.
  lcd.print("Godzilla's House");
  delay(3000);
  lcd.clear();
  //lcd.print("Species Acquired Apr30,2024");
  //delay(7000);
  //lcd.clear();
  //pinMode(LED_BUILTIN, 30);
}

void loop() {
    // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(16, 1);
  //This is DHT_1
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht_1.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht_1.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht_1.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht_1.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht_1.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  //Serial.print(hic);
  //Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));

 //delay(3000);
    
 //This is DHT_2
 // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h2 = dht_2.readHumidity();
  // Read temperature as Celsius (the default)
  float t2 = dht_2.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f2 = dht_2.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif2 = dht_2.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic2 = dht_2.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
 //If temp above 73 on DHT1/2 turn on Red LEDs   
    if (dht_1.readTemperature(true); t > 73.00) digitalWrite(32, HIGH);
    if (dht_2.readTemperature(true); t2 >73.00) digitalWrite(33, HIGH);
    delay(3000);}
    //IF Humidity below 40% turn on Yellow LEDs
    {if (dht_1.readHumidity(); h <3) digitalWrite(34, HIGH);
    else digitalWrite(34, LOW);
    if (dht_2.readHumidity(); h2 <3) digitalWrite(35, HIGH);
    else digitalWrite(35, LOW);

//Relay 1 for UVB light, 12hrs on, 12hrs off, 2 green LEDs show when active
//12hrs in milliseconds: 43200000 ms
    delay(3000);
    digitalWrite(30, HIGH);
    delay(4000);
    digitalWrite(30, LOW);

//Relay 2 
    digitalWrite(31, HIGH);
    delay(4000);
    digitalWrite(31, LOW);

//Waterpump operation
if (dht_1.readHumidity(); h <3); digitalWrite(40, HIGH);
 }else digitalWrite(40, LOW);
if (dht_2.readHumidity(); h2 <3); digitalWrite(40, HIGH);
 }else digitalWrite(40, LOW);
if (digitalWrite(40,HIGH), digitalWrite(36, HIGH);
 }else digitalWrite(36, LOW);

}
}}}

  

The following is the error:/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:153:3: error: expected unqualified-id before 'else'
}else digitalWrite(40, LOW);
^~~~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:1: error: expected unqualified-id before 'if'
if (dht_2.readHumidity(); h2 <3); digitalWrite(40, HIGH);
^~
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:27: error: 'h2' does not name a type; did you mean 'A2'?
if (dht_2.readHumidity(); h2 <3); digitalWrite(40, HIGH);
^~
A2
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:154:47: error: expected constructor, destructor, or type conversion before '(' token
if (dht_2.readHumidity(); h2 <3); digitalWrite(40, HIGH);
^
/Users/j.rohrbachart/Documents/Arduino/GodzillaNew/GodzillaNew.ino:155:2: error: expected declaration before '}' token
}else digitalWrite(40, LOW);
^
Multiple libraries were found for "LiquidCrystal.h"
Used: /Users/j.rohrbachart/Documents/Arduino/libraries/LiquidCrystal
Not used: /Users/j.rohrbachart/Library/Arduino15/libraries/LiquidCrystal
exit status 1

Compilation error: expected unqualified-id before 'else'

It's probably something easy, but I have no idea. I think it has something to do with the curly brackets, but I'm not entirely sure what it is.

I just read your post. So I'll admit your post reads like gibberish to me. Not a programmer by trade. I'm and artist and a quality inspector :rofl: but I think what your saying is "float h = dht_1.readHumidity();" is creating a new variable and value. "h = dht_1.readHumidity();" means I'm naming h is dat_1.readHumidity so currently, I would use the letter "h" in the code to call the dht_1.readHumidity? I think but you go on to mention, "float theHumidity;" is used by us noobs :laughing:. So at the beginning of my code I could say humidity1 = dot_1.readHumidity and then anywhere I need that information pulled, I just type "humidity1" or whatever I decide to name it. correct?

Sorry, no, not. And I've placed dangerous new ideas in your brain I am afraid.

Just read the article I linked, then maybe read my confusing post again.

Another thing you could start making time for is read read reading code. These fora are very good usually, the code contributed by helpers is going to be better, of course.

Usually it will compile and be syntactically correct, and correct in general… not all valid syntax is what you mean!

Here

if (dht_1.readHumidity(); hum <3); digitalWrite(40, HIGH);

the 2nd semicolon ends the if statement, so that code is actually

 if (dht_1.readHumidity(); hum <3); 


 digitalWrite(40, HIGH);

And the first semicolon is completely out of place, so the first statement is an error maker, and the else you thought went with the if is… totally not connected, and thus appears where it should not do syntax-wise.

If you read code that works, you won't see things like that…

Pick topics of interest and seem to be about at your level and read read read the prose and the code.

HTH

a7

Thanks for the help on this. I do read as I go. I browse the libraries and the Arduino docs to help me understand but even then sometimes it’s hard. Actually doing it and seeing how the Arduino reacts has helped me a ton in understanding what’s happening.

Ok, so did you know if you click just to the right of any curly brace { or } in the IDE, it will automagically put a little rectangle around its partner?

Were you aware that the closing curly brace for your void loop() is on this line: delay(3000);}?

When you go to solve things like this, it can be helpful to make a second copy of the exact same sketch, take out ALL the comments and use this version just to catch such errors.

EDIT: just noticed it's two different sensors

The link I provided didn't go too much into detail, I hope you can google for some of the other words I used.

In the meantime, I am working on something that I will probably never publish, but I place it here in the condition it is with the hope that it doesn't hurt.


Including some lies for the moment, here is a synopsis of variable use C. And it applies to C++, therefore also to Arduino.

Before they are used, variables must be brought to the attention of the compiler. Each variable needs one definition. Any extra definition is an error. One definition.

Variable definitions can appear in two places. Then they are known to the compiler, and are either global or local depending on which of the two places you put the definition.

Global: Outside any functions, at the start of the program. Not inside { braces } , the ones that embrace a function statements, or the ones used inside functions.

A definition is of the form

<variable type> <name>;

like this

int buildingNumber;

defines storage and an identifier (name) for one variable, here an integer.

Global variables can be used anywhere in the entire program. All references to a global variable will be to the same exact variable.

Local: Inside a function, after the function's open brace.

Thjs

void loop() {
  int buildingNumber;

// rest of the function

}

defines storage and an identifier for one variable, here an integer.

Local variables can be used anywhere within the function they are defined in. Within the { opening and closing } braces. No matter there are global variables with the same name, or local variables with the same name in other functions, referring to a local variable will always be to the one defined in the function.

Note: you can confuse yourself and others by using the same name for different variables all over the place. Don't do that.

All variables must be initialized before they are used. A good place to initialize global variables is in the setup() function.

Like this

int wifeWeight;

void setup() {
   wifeWeight = 62;

// rest of the function

}

Local variables can be initialized as the first executable statements in a function. Here's two local variables and initialization for them in function myFunction():

void myFunction() {
   int celerySize;
   int celeryCount;

  celerySize = 42;
  celeryCount = 0;

// rest of the function

}

Note: variables don't have any predictable value, including zero, until you make that initial assignment.

A good habit is to define variables such that only the code that needs them can even see them. Make variables local to a function if they only need to be used within that function. Make global variables for those that are to be used in multiple functions in your program. This is referred to generally as variable scope.

Variables have a type, this is what the int is for in the definition. There are a number of variable types. Any variable you define will have its type right there.

One other variable type worth knowing about right away is float, this is used for real numbers as opposed to integers.

float wifeWeight;
int wifeAge;

void setup() {
   wifeWeight = 61.6;
   wifeAge = 73;

// rest of the function

}

A good habit is to use int when an integer will do, and float only when real numbers are necessary.

Some advanced code exploits integers in such a way as to eliminate the need for using real numbers. Using real numbers takes more storage and is slower. And occasionally less accurate. Often this will not be important. Sometimes it will be critical.

For writing code using simple variables, that is close to the least you need to know.


When reading code, you will find there is more to the story. There is always more to the story, that's why reading code is a good thing - you'll see things that you haven't, and learn more about programming. Read code carefully, and pay attention to the syntax of any new things. Ask questions here; google is you friend.

Lies…

So… variables can be defined in a number of other places. Some variables do get an initial value automatically . There are a handful of additional qualifiers that might appear in a variable definition along with the type.

Don't panic if you see

volatile int wifeWeight = 62;

or

void myFunction() {
   static int celeryCount = 1000;
// rest of the function

}

Just know those are simply more detailed definitions, and the variables defined will be used like any variables. Ask question or google about the part you did not understand

static in variable definition C++

would probably google you up some help.

One thing you will see for sure is initialization in the same line of code that defines a variable. I slipped one in above, here's a global variable with an initial value added:

int wifeWeight = 62;

Lastly, no assignment to a variable establishes any kind of permanent or "magical" connection to anything. An assignment only puts the value calculated on the right hand side of the = into the variable on the left hand side at the time the assignment is made.

int edgeLength = 10;
int perimeter = edgeLength * 4;

creates two variables, with values 10 and 40 respectively. It does not make perimeter track with edgeLength.

If edgeLength is assigned a new value, perimeter will not be adjusted. If you want perimeter to change, you must make an assignment it.

int edgeLength = 10;
int perimeter = edgeLength * 4;

void loop() {

//

  edgeLength += 15;   // longer edge means
  perimeter = edgeLength * 4;  // a different perimeter

}

a7

Here's a version that won't work as you intend (since I don't have all that gear in front of me to test it out, nor do I know the purpose of all the delays - so I took them out - nor do I understand why you need to separate what you do for each temp or humidity sensor - so I checked them together and just turned on or off all the equipment related to those (I think)...but anyway)

#include <DHT.h>
#include <LiquidCrystal.h>
#define DHT_1 dht_1(2);
#define DHT_2 dht_2(3);
DHT dht_1(2, DHT22);
DHT dht_2(3, DHT22);
float h;
float h2;
float t;
float t2;
float f;
float f2;
float hic;
float hic2;
float hif;
float hif2;

const int rs = 13, en = 12, d4 = 5, d5 = 6, d6 = 7, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  Serial.begin(9600);
  dht_1.begin();
  dht_2.begin();
  lcd.begin(16, 1);
  lcd.print("Godzilla's House");
  delay(3000);
  lcd.clear();
  h = 0.0;
  h2 = 0.0;
  t = 0.0;
  t2 = 0.0;
  f = 0.0;
  f2 = 0.0;
  hic = 0.0;
  hic2 = 0.0;
  hif = 0.0;
  hif2 = 0.0;
}

void loop() {
  lcd.setCursor(16, 1);
  h = dht_1.readHumidity();
  t = dht_1.readTemperature();
  f = dht_1.readTemperature(true);
  h2 = dht_2.readHumidity();
  t2 = dht_2.readTemperature();
  f2 = dht_2.readTemperature(true);
  hif = dht_1.computeHeatIndex(f, h);
  hic = dht_1.computeHeatIndex(t, h, false);
  hif2 = dht_2.computeHeatIndex(f, h);
  hic2 = dht_2.computeHeatIndex(t, h, false);

  if ((t > 73.00) || (t2 > 73.00)) {
    digitalWrite(32, HIGH);
    digitalWrite(33, HIGH);
  }
  else if ((t <= 73.00) || (t2 <= 73.00)) {
    digitalWrite(32, LOW);
    digitalWrite(33, LOW);
  }
  if ((h < 3) || (h2 < 3)) {
    digitalWrite(30, HIGH);
    digitalWrite(31, HIGH);
    digitalWrite(34, HIGH);
    digitalWrite(35, HIGH);
    digitalWrite(36, HIGH);
    digitalWrite(40, HIGH);
  }
  else if ((h >= 3) || (h2 >= 3)) {
    digitalWrite(30, LOW);
    digitalWrite(31, LOW);
    digitalWrite(34, LOW);
    digitalWrite(35, LOW);
    digitalWrite(36, LOW);
    digitalWrite(40, LOW);
  }
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }
  printHandT();
}

void printHandT() {
  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

So note: the purpose of the above code is not to get your project working as you intend. The purpose of the above code is to (a) get you something that will compile at least and (b), show you something closer to what your code should and/or might look like once it's done.

Notice I created a separate function for your Serial printing. That's just to reduce lines in void loop, less to scroll through as you go through it.

Also, I made your variables global and initialized them in void setup() as suggested by @alto777 (who is a way better programmer than I am).

In short, this is just a rough version to help you look at your code in a different way.

@alto777 blushes.

We all start nowhere, we all got a long road ahead of stuff to learn.

Sometimes I think I am going in the wrong direction, sliding back down the learning curve…

Which is one reason I spend time here. I always learn something, or at least get exposed to things. Remembering is a bit more of a challenge at times.

a7

I did not know this about finding its partner. This is very helpful as I nearly went insane looking for curly brackets last night.

I’ll make a copy of my code when I get home tonight and look at it stripped down with no comments and such.

Holy smokes this looks wayyyy cleaner than my mess. But I guess we all start somewhere. I have found the more I learn the more I clean up my current sketch. Since you make the serial print its own function, would that allow the loop function to run faster? Just curious here. Also does the serial print function need to be at the end? Let’s say I’ve got a bunch of calculations in the loop function, another function to monitor xyz, the serial would come after all that correct? Or would I need to give each function its own serial print function?

You guys are a massive help and infinitely better than I at this. I’ve learned probably more in the last week between you all and just fiddling around with it then I ever have before when attempting this. I had another project for testing camera shutter speeds on retro cameras but gave up on it because it was baffling to my brain.

As for the amount of delays, I was using LEDs in the circuit as the water pump and relays just to see if what I was doing was working. Eventually the actual parts, I.e. relays and water pump will be placed in the build.