Greenhouse Project - Relay triggers

Good day,

I have been slogging along trying to cobble together both the electronics and code necessary to make this project work, this is my first adventure into arduino. I had hoped to just find someone else’s project that I could copy but I was unable to find exactly what I was looking for and instead had to start from scratch, writing each line of code and verifying that it would work before progressing to the next.

I have the following bits:

Arduino Uno;
LCD 16 x 2;
DHT 12;
Photosensor - connected via a 220 ohm resistor;
2 x 10kOhm potentiometers (1 for contrast, 1 for backlight);
Soil moisture;
2 channel relay board.

My intentions are to have the arduino control the output to the relays for exhaust fans for the greenhouse. I have picked the values that work for me to have the fans turn on or off. However, I can get to sensors to change value but, there is no change in state for the relays?

Specifically:
High temp = relays ON / Low Temp = relays OFF;
High Humidity = relays ON / Low Humidity = relay OFF;
Low Light = Relays OFF / High Light = Relay ON

Thanks for the assistance.

Please find the below code:

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

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
#define DHTPIN A1
#define DHTTYPE DHT12
DHT dht(DHTPIN, DHTTYPE);

int fan1 = 8;
int fan2 = 9;
int soil1 = A2;
int light = A0; // select the input pin for LDR
int LUX = 0; // variable to store the value coming from the sensor
int h = 0;
int t = 0;
int soil = 0;

void setup() {
 dht.begin();
 lcd.begin(16, 2);
 pinMode(light, INPUT);
 pinMode(soil1, INPUT);
 pinMode(fan1, OUTPUT);
 pinMode(fan2, OUTPUT);
 //pinMode(water1, OUTPUT);
 digitalWrite(fan1, HIGH);
 digitalWrite(fan2, HIGH);
}
void loop() {
 sensorcheck();
 humidcontrol();
 tempcontrol();
 soilcondition();
 lcdprint();
}
void sensorcheck() {
 h = dht.readHumidity();
 t = dht.readTemperature();
 soil1 = analogRead(A2);
 LUX = analogRead(A0);
}
void humidcontrol() {
 if (h >= 60) {
   digitalWrite(fan1, HIGH);
   digitalWrite(fan2, HIGH);
 }
 else if (h <= 55) {
   digitalWrite(fan1, LOW);
   digitalWrite(fan2, LOW);
 }
}
void tempcontrol() {
 if (t >= 35) {
   digitalWrite(fan1, HIGH);
   digitalWrite(fan2, HIGH);
 }
 else if (t <= 30) {
   digitalWrite(fan1, LOW);
   digitalWrite(fan2, LOW);
 }
}
void lightcheck() {
 if (LUX >= 55) {
   digitalWrite(fan1, HIGH);
   digitalWrite(fan2, HIGH);
 }
 else if (LUX <= 50) {
   digitalWrite(fan1, LOW);
   digitalWrite(fan2, LOW);
 }
}
void soilcondition() {
 soil = analogRead(A2);
 soil = map(soil, 1020, 230 , 0, 100);
}

void lcdprint() {
 lcd.setCursor(0, 0);
 lcd.print("Temp:");
 lcd.print(t);
 lcd.print("C ");
 lcd.print("Hum:");
 lcd.print(h);
 lcd.print ("%");
 lcd.setCursor(0, 1);
 lcd.print("Lux:");
 lcd.print(analogRead(A0));
 lcd.print(" ");
 lcd.print("Soil:");
 lcd.print(soil);
 lcd.print("%");
 lcd.print(" ");
}

The fans will always just be the state of the last if() test, ignoring all previous tests.

Calculate all three values (as already done) and create three boolean results by comparing to your thresholds by replacing the fans in each routine with named boolean type variables. Then, using the truth table you’re already created (the hard part for most newbies), check for the fans to be on or off with one test. In pseudo code:

If high temp or high humidity or high light then fans on else fans off.

In actual code, the test would look something like this:

  if ( hTemp|| hHumidly || hLight ) {
    digitalWrite( fan, HIGH );
    }
  else {
    digitalWrite( fan, LOW );
    }

Does that get you pointed in the correct direction?

AWESOME!!

Thank you for the quick reply. I had hoped that I wouldn't have to try and build everything, but it has been pretty invaluable in understanding programming process. So, for the sample code that you provided, I assume I need to define "hTemp | hHumid | hLight" and then where should I put the code chunk including them? Like do I get rid of all the command line in each of my sensor reading scripts?

Thank you again

Sorry, If I had read your message with my eyes open :o I might have actually gleaned what I needed... I am rewriting now and should be able to make it work.

Okay,

So I have again fumbled my way around and discovered the “char” variable, I have been unable to figure out how to have the code chunk suggested integrate into my original. Because I needed to define the new terms, but I don’t know how to have the sensor output end up with the “h sensor” or “l sensor” so that the final script will then work? As it stands the sensors are reading, and displaying on the LCD (Good), but changing their values does not get me anywhere and the relays are “ON”…

I apologize, however, none of the tutorials really address this situation, and the examples from the arduino reference page don’t really explain the various variables.

modified code is attached

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

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
#define DHTPIN A1
#define DHTTYPE DHT12
DHT dht(DHTPIN, DHTTYPE);

int fan1 = 8;
int fan2 = 9;
int soil1 = A2;
int light = A0; // select the input pin for LDR
int LUX = 0; // variable to store the value coming from the sensor
int h = 0;
int t = 0;
int soil = 0;
char (hTemp);
char (lTemp);
char (hHumid);
char (lHumid);
char (hLight);
char (lLight);


void setup() {
  dht.begin();
  lcd.begin(16, 2);
  pinMode(light, INPUT);
  pinMode(soil1, INPUT);
  pinMode(fan1, OUTPUT);
  pinMode(fan2, OUTPUT);
  //pinMode(water1, OUTPUT);
}
void loop() {
  sensorcheck();
  humidcontrol();
  tempcontrol();
  soilcondition();
  fanstate();
  lcdprint();
}
void sensorcheck() {
  h = dht.readHumidity();
  t = dht.readTemperature();
  soil1 = analogRead(A2);
  LUX = analogRead(A0);
}
void humidcontrol() {
  if (h >= 60) {
   (hHumid);
  }
  else if (h <= 55) {
    (lHumid);
  }
}
void tempcontrol() {
  if (t >= 35) {
    (hTemp);
  }
  else if (t <= 30) {
    (lTemp);
  }
}
void lightcheck() {
  if (LUX >= 105) {
    (hLight);
   }
  else if (LUX <= 100) {
    (lLight);
  }
}
void soilcondition() {
  soil = analogRead(A2);
  soil = map(soil, 1020, 230 , 0, 100);
}
void fanstate() {
  if ( hTemp || hHumid || hLight ) {
    digitalWrite( fan1, HIGH );
    digitalWrite( fan2, HIGH );
  }
  else if ( lTemp || lHumid || lLight){
    digitalWrite( fan1, LOW );
    digitalWrite( fan2, LOW );
  }
}
  void lcdprint() {
    lcd.setCursor(0, 0);
    lcd.print("Temp:");
    lcd.print(t);
    lcd.print("C ");
    lcd.print("Hum:");
    lcd.print(h);
    lcd.print ("%");
    lcd.setCursor(0, 1);
    lcd.print("Lux:");
    lcd.print(analogRead(A0));
    lcd.print(" ");
    lcd.print("Soil:");
    lcd.print(soil);
    lcd.print("%");
    lcd.print(" ");
  }

The suggestion was to use three boolean variables: hTemp, hHumidly and hLight. If any one of them is true, run the fans, which is indeed what your fan state function is trying to do, albeit with char variables instead.

The piece you're missing is that those booleans need to be set appropriately, so for example, your humidcontrol function needs to be more like this:

void humidcontrol()
{
  if (h >= 60)
  {
    hHumid=true;
  }
  else
  {
    hHumid=false;
  }
}

This may cause you trouble when the temperature is near 60 where you'll get rapid on & off, but it should get you started.

Super, thank you very much!

I was unsure about what to do with the boolean logic statements, I understood what was trying to be achieved, but not how to implement it. I will have to play around with the variables once I have everything in place in the greenhouse, but they were a starting point.

Okay,

I have written and rewritten, changed variables and values, researched and reviewed and I am now frustrated because I think that I have everything in the correct place, but I am not getting the functionality that I desire.

I am looking to have 2 relays (digital pins 8, 9) trigger to turn on exhaust fans in the greenhouse.

The triggers are (High temp or high humidity and/or high light) Light trigger is somewhat important as the power will be automotive batteries connected to a solar cell and I don’t want the fans to be running when there is no charging going on. I have been able to get the baseline functional, so the relays turn on when the humidity passes threshold value, and when temperature does as well, but the light trigger is a no go. I have used the light as a trigger for relays or for backlight, but once added to the larger code it stops working as it should. The sensor is still reading data but I can’t do anything with it.

I apologize for seeming needy, but this has now gone beyond my reasoning and I have been unable to decipher the correct arrangement by searching through other’s projects.

So, this is where I am at:

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

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
#define DHTPIN A1
#define DHTTYPE DHT12
DHT dht(DHTPIN, DHTTYPE);

int fan1 = 8;
int fan2 = 9;
int soil1 = A2;
int light = A0; // select the input pin for LDR
int LUX = 0; // variable to store the value coming from the sensor
int h = 0;
int t = 0;
int soil = 0;
char hTemp;
//char lTemp;
char hHumid;
//char lHumid;
char hLight;
//char lLight;


void setup() {
  dht.begin();
  lcd.begin(16, 2);
  pinMode(light, INPUT);
  pinMode(soil1, INPUT);
  pinMode(fan1, OUTPUT);
  pinMode(fan2, OUTPUT);
  //pinMode(water1, OUTPUT);
}
void loop() {
  sensorcheck();
  humidcontrol();
  tempcontrol();
  soilcondition();
  fanstate();
  lcdprint();
}
void sensorcheck() {
  h = dht.readHumidity();
  t = dht.readTemperature();
  soil1 = analogRead(A2);
  LUX = analogRead(A0);
}
void humidcontrol() {
  if (h >= 60) {
    hHumid = true;
  }
  else if (h <= 55) {
    hHumid = false;
  }
}
void tempcontrol() {
  if (t >= 35) {
    hTemp = true;
  }
  else if (t <= 30) {
    hTemp = false;
  }
}
void lightcheck() {
  if (LUX >= 105) {
    hLight = true;
  }
  else if (LUX <= 100) {
    hLight = false;
  }
}
void soilcondition() {
  soil = analogRead(A2);
  soil = map(soil, 1020, 230 , 0, 100);
}
void fanstate() {
  if ( hTemp || hHumid || hLight ) {
    digitalWrite( fan1, LOW );
    digitalWrite( fan2, LOW );
  }
  else {
    digitalWrite( fan1, HIGH );
    digitalWrite( fan2, HIGH );
  }
}
void lcdprint() {
  lcd.setCursor(0, 0);
  lcd.print("Temp:");
  lcd.print(t);
  lcd.print("C ");
  lcd.print("Hum:");
  lcd.print(h);
  lcd.print ("%");
  lcd.setCursor(0, 1);
  lcd.print("Lux:");
  lcd.print(analogRead(A0));
  lcd.print(" ");
  lcd.print("Soil:");
  lcd.print(soil);
  lcd.print("%");
  lcd.print(" ");
}

Thank you in advance

wildbill:
The piece you're missing is that those booleans need to be set appropriately

char hLight; // “char” is not a a Boolean...

You state:

lkettlewell:
The triggers are (High temp or high humidity and/or high light)

but the code says if ( hTemp || hHumid || hLight ). No AND included here so any of the arguments true will put the fan outputs LOW.

In the world of logic, "and/or" has no meaning. "And" means both, "or" means at least one, so "and" is just one of the 3 cases (for 2 variables) where the "or" output is true:

input1   input2  (input1 OR input2)
0          0          0
0          1          1
1          0          1
1          1          1  (this is the AND case)

"or" means an "inclusive or" where 1 OR 1 is 1, as opposed the "exclusive or, XOR" where the AND case is false, 1 XOR 1 is 0.

"and/or" is a phrase we tend to use in colloquial English, but "and" is subsumed by "or" so it's redundant and sometimes confusing.

For total clarity, you could draw up a 4-column truth table with your 3 inputs listed in 8 rows from 000 to 111 and then show the output as 0 or 1 for each of those cases.

dougp:
You state:

but the code says if ( hTemp || hHumid || hLight ). No AND included here so any of the arguments true will put the fan outputs LOW.

Good point!

This is a problem with having more than one working copy as I am trying to get things to work the way I wanted and in frustration / exhaustion I must have either switched it back or copied the wrong tab...

So if I change to

 { if ( hTemp || hHumid && hLight );
    digitalWrite( fan1, LOW );
    digitalWrite( fan2, LOW );
  }
  else {
    digitalWrite( fan1, HIGH );
    digitalWrite( fan2, HIGH );
  }
}

then this is what I was actually meaning to post.

My question is now, what and where do I establish that this is was I want the programming to do? The online help sections cover the " IF, OR, IF ELSE, ELSE...." part of the boolean logic, but I don't know / understand what the primer is? I used "char" only because I was trying to figure out how I could use the suggested logic table with the keywords that weren't set anywhere else.

I have seen an example, but it only shows the one variable, so "bool running = false;" works, but with the multiples how do I start? Or, do I put "bool fanstate = false/true", depending on if I want the fans on or not?

I have reached a point tonight where I can't logic anymore, and the uploader has decided that it will not compile for Arduino / uno anymore and I don't want to fight anymore.... To be continued!

lkettlewell:
I can't logic anymore,

Draw up a truth table then, as I suggested. That will should help to keep things clear.

lkettlewell:
This is a problem with having more than one working copy as I am trying to get things to work the way I wanted and in frustration / exhaustion I must have either switched it back or copied the wrong tab...

The different versions must necessarily have different file names. If you add the line Serial.println(FILE); the path and filename will display on the serial monitor every time the sketch starts up. Might help to keep things straight.