Another Greenhouse project code almalgamation

Hello All,

The project is using the DH11 humidity/ temperature sensor to measure and display via 16x2 lcd. Separately measure soil mosture and turn on the relay for 12v pump.

This has all been tested and is working fine via two separate arduinos on a 12v power supply driven by a solar panel and charge controller.

Please help. Im trying to almalgamate two working sets of code which work fine on thier own onto one arduino. I do not wish to use two Arduinos in this project.

Code one for the temperature/ humity is as follows :

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
#include  <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
  dht.begin();// initialize the sensor
 lcd.backlight();// turn on lcd backlight
  lcd.init();// initialize lcd
}
void loop() {
 lcd.clear();
   lcd.setCursor(0,0);//  set the cursor on the first row and column
   lcd.print("H=");
   lcd.print((float)dht.readHumidity());//print  the humidity
   lcd.print("%");
   lcd.setCursor(0,1);//set the cursor on  the second row and first column
   lcd.print("T=");
   lcd.print((float)dht.readTemperature());//print  the temperature
   lcd.print("c");
   delay(2000);
   lcd.clear();
         }

The second set of code for the soil sensor/ relay combo :

int waterPump = 3;
void setup() {
  Serial.begin(9600);
  pinMode(waterPump, OUTPUT);
}

void loop() {
  int humidityRaw = analogRead(A0);
  int humidityReal = map(humidityRaw, 1023, 0, 0, 100);
  Serial.println(humidityReal);
  delay(100);
  if (humidityReal > 20)
{
  digitalWrite(waterPump, HIGH);
}else{
  digitalWrite(waterPump, LOW);
}
}

My attempt at combination :

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
#define sensorPin A0
#define RELAY_PIN 13
DHT dht(DHTPIN, DHTTYPE);
#include  <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
  dht.begin();// initialize the sensor
 lcd.backlight();// turn on lcd backlight
  lcd.init();// initialize lcd
    pinMode(RELAY_PIN, OUTPUT);
}
void loop() {
 lcd.clear();
   lcd.setCursor(0,0);//  set the cursor on the first row and column
   lcd.print("H=");
   lcd.print((float)dht.readHumidity());//print  the humidity
   lcd.print("%");
   lcd.setCursor(0,1);//set the cursor on  the second row and first column
   lcd.print("T=");
   lcd.print((float)dht.readTemperature());//print  the temperature
   lcd.print("c");
 
    int value = analogRead(sensorPin);
     if(value > 20){
      digitalWrite(RELAY_PIN, HIGH);
      }else{
        digitalWrite(RELAY_PIN, LOW);
      }
        delay(1000);
   lcd.clear();

Apologies in advance if I have broken any rules here Ive tried my best. Any help is greatly appreciated.

Thanks
Jim

Jim, Thanks for posting your attempt to combine them. Many beginners post only the 2 original codes and say "I tried to combine them but it didn't work" and expect the forum to do the work for them.

What you forgot was to explain what the problem(s) is with your combined code. What happens when it runs and what did you want/expect to happen.

However, it would be useful if you could click Tools->Auto Format on the combined code and post it again.

There is some code missing at the end of your combined code. Maybe it's only a }. Or maybe there is a whole page of code missing?

I don't see this line, or any equivalent, in your combined code?

Maybe you tested the soil sensor/relay code "on the bench" but this code won't work well in practice. It will probably flood the greenhouse!

Water takes time to soak into the soil, so it's important to run the pump only for a short time, like maybe a minute, then wait for 10 minutes before taking a reading from the sensor and potentially running the pump again.

What type of sensor are you using? Resistive sensors will soon corrode and fail if they are powered full time, so it's best to use another Arduino pin to allow power to the sensor only at the moment the reading is being taken.

Thanks PaulRB, yes I dont understand the "tell me the answer" attitude as you dont really learn anything !. I think its important as we're all too often told to show your mistakes. Education is the key I think not just for me to get this running but anyone who might come up against the same issue.
I see what Ive done, the relay/ moisture code is the wrong one Ive posted, similar but ever so slightly different. Ill repost the whole thing reformated. thanks.

PaulRB,

I tested/used it in the "real" environment and Ive used the v1.2 capacitive sensor before just not in this combined way or on sort of 3 - 4 times the scale. I was aware of the corosive issues of the resitive sensors.
I agree about the pump times; Ive never had an issue at a smaller scale however this is a scalable project with future plans and Im not sure of my hose/ plant layout yet to match so once Ive got this part up and running Ill tackle scale.
That said im open to suggested and improvements where your obvious experience is evident.

Thanks
Jim

If your first sketch was complete, it is very easy to put that into you second sketch, no matter what.

This

   delay(2000);

is the only thing "wrong" with it. It serves to make the loop run slow, so its entire function is done but once every two seconds.

This kills the loop, which wants to run free, and which anything else you put in there should be able to depend on.

There's a code pattern called "blink without delay". You can find it in the IDE examlkes, and googling "arduino blink without delay" will turn up many many explanations, be they articles or videos or whatever.

Basically here you'd want to blink (perform sketch one) every two seconds.

First, rename the first sketch loop() as loopLCD(). That makes it into a function we can call in order to perform all the steps in its body.

Then write, in the other sketch's loop

  static unsigned long lastLCDTime;

          // if it is time
  if (millis() - lastLCDTime > 2000) {

          // perform all the steps of sketch one (call that function)
    loopLCD();

          // and remember when you did it
    lastLCDTime = millis();
  }

I'll trust you to do a bit of learning on the blink without delay; you will see the exact same steps:

has the timer expired? (last time is more in the past than the interval)
if so
  do the periodic task (print the temp and humidity, or whatever)
  and reset the timer (make it equal to now, so we can measure elapsed time since)

A timer in this context is just an unsigned long integer storing the value of the system clock which is millis(), the number of milliseconds since the sketch started.

HTH

a7

Thanks for this a7,

My thoughts were also with "delay()" as all advice is to try not to use if possible. When I removed it completely from the joined code the display only showed part of the reading from the sensor. Im assuming because the data was being (re)read to quickly to display.

Also thanks for pointing me in the right direction the first search took me to a page on this site explaining exactly what Im trying to do all be it with a rather crude example with led(s).

Jim.

Hi PaulRB, finally found the original code I plagerised for the soil moisture sensor :

#define sensorPin A0
#define RELAY_PIN 10

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(RELAY_PIN, OUTPUT);
}


void loop() {
   // Read the Analog Input
   // 625 IS AIR = 0%
   // 280-290 = WATER = 100%
  int value = analogRead(sensorPin);
  
  // Print the value to the serial monitor
  Serial.println("Analog output: ");
  Serial.println(value);
  
  // Wait for 1 second before the next reading
  delay(3000);

  if(value > 400){
    Serial.println("The soil moisture is DRY => activate pump");
    digitalWrite(RELAY_PIN, HIGH);
    delay(2000);
  }else{
    Serial.println("The soil moisture is WET => deactivate the pump");
    digitalWrite(RELAY_PIN, LOW);
    delay(2000);
  }

  delay(1000);
}

My thought was to use this to display on the LCD in the combined code but definately beyond me at the moment so I kept it simple and just went for function.

And the formated combined code :

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
#define sensorPin A0
#define RELAY_PIN 13
DHT dht(DHTPIN, DHTTYPE);
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
  dht.begin();      // initialize the sensor
  lcd.backlight();  // turn on lcd backlight
  lcd.init();       // initialize lcd
  pinMode(RELAY_PIN, OUTPUT);
}
void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);  //  set the cursor on the first row and column
  lcd.print("H=");
  lcd.print((float)dht.readHumidity());  //print  the humidity
  lcd.print("%");
  lcd.setCursor(0, 1);  //set the cursor on  the second row and first column
  lcd.print("T=");
  lcd.print((float)dht.readTemperature());  //print  the temperature
  lcd.print("c");

  int value = analogRead(sensorPin);
  if (value > 20) {
    digitalWrite(RELAY_PIN, HIGH);
  } else {
    digitalWrite(RELAY_PIN, LOW);
  }
  delay(1000);
  lcd.clear();

Thanks

Thanks.

I think I edited post #2 and added a comment that you may have missed. Sorry about that.

Also please re-read my posts #3 and #4.

The variations on the pattern almost always amount to the same steps. Check a timer, do something if it is time and remember that you did.

And you can start to think like a programmer - if you can turn on an LED once a second, you can at that exact same place in the sketch insert code lines that will also be execute once a second.

So where the LED in "blink without delay" is turned on, you could have all the lines that do you LCD stuff, essentially the entire loop() of your first sketch.

This will work. I only suggested making all those lines into a function so the top level code would be less cluttered, and easier to read, because all the steps and pesky details are elsewhere, and need be looked at only to fix or modify.

There is perhaps an Aha! moment in your near future. This small but key concept (BWOD) is very useful, and no one would say it isn't hard until it is easy.

Here's a thread that shows some of what it makes easier:

It's not the main problem but if you read past that you will see.

a7

Hi PaulRB,
I missed the "}" when copy and pasting, the combined code works largely just not the soil moisture sensor and pump section.
As a7 suggested I think in that code it is the delay() that is making the code fail.

Jim

I can't help if you're not willing to answer simple questions about what the symptoms of the problem are.

You are clutching at straws, not attempting to logically diagnose the problem. You have not even described the symptoms of the problem, despite more than one request.

tl;dr: Why is the threshold 20 in your code, but 400 in the code you found?

Its not clear that eliminating delay() will ever be important, but if you had each sketch working before combining them, it is not important now, and is not causing any problem other than possibly annoying you.

This is what and all you took from from the soil sensor code, except the setup()

  int value = analogRead(sensorPin);
  if (value > 20) {
    digitalWrite(RELAY_PIN, HIGH);
  } else {
    digitalWrite(RELAY_PIN, LOW);
  }

You eliminated the serial printing, which deprives you of useful feedback. There is no harm in leaving it in the code, even if the final deployment doesn't use the serial monitor. It will just talk and not even know no one is listening.

Beyond that, you changed the threshold value for turning on and off the pump. I assume this was on the basis of your careful experiments with your sensor, your pimp and your soil.

Your code also has delay() strewn about. I collected those, and offer this combined structure for you sketch. It still needs to do the delay differently as I have outlined, but shoukd function until you figure out how to call a function at a regular rate. You will need two LEDs that are blinking at rates that you want the two functions to get a chance to do their thing. Later. Or when you change how the sensor informs the pump as @PaulRB is suggesting.

// pins and stuff, OK
// setup, yeah yeah

void loop() {
  loopLCD();
  delay(2000);   // moved out of the loopLCD function
  loopSoil();
  delay(6000);  // moved out of the loopSoil function
}

// sketch one
void loopLCD() {
  // the other thing. all the lines of the LCD sketch loop
}

// sketch two
void loopSoil()
{
  int value = analogRead(sensorPin);
  Serial.println("Analog output: "); Serial.println(value);

  if (value > 400) {
    Serial.println("The soil moisture is DRY, activating pump");
    digitalWrite(RELAY_PIN, HIGH);
  }
  else {
    Serial.println("The soil moisture is WET, deactivating the pump");
    digitalWrite(RELAY_PIN, LOW);
  }

//  delay(6000);  // moved to loop. same same.
}

Pro tip: Life is short. Both sketches have long pointless delays making testing annoying. On the bench or wherever you are trying to get this to work, turn the delays way down, or if/when you have implemented the BWOD timing, temporarily reduce the interval between function calls.

You are correct that zero delay in the LCD code makes a mess, as it affords no time to see the later part of the screen. Also, the two calls to the clear() method are logically two steps in sequence, only one is necessary, and some mildly clever programming within your grasp woukd mean never having to clear the display at all. That LCD stuff is just minimal and lazy, gets the job done for now kinda code.

HTH

a7

a7, Thats great stuff. Theres loads to go on there. Thank you. Apologies for the delay in replying to your brilliant quick guidance/ support Ive been drafted into some DIY recently.

Firstly yes the threshold in the original code was not triggering so I had to change that. It seems the capacitive sensors are more sensitive that the resistive sensors which for I think that code may have been written.

The reason I removed the serial monitor was as I thought through my journey of "here" education and self education in the future Id display the out put via the actual lcd or make it selectable on a push button LCD ive got around rather than the serial monitor. "Pump on" Pump off" sort of thing and even add and override button. Im starting to find that simplification of the code might not be best practice.

Hopefully Ill get a chance to implement those improvements and do some testing in the next few days and report back better educated.

Thanks.

Hi a7 and all interested.
I eventually got this code to work after some major DIY and exhausted late night tinkering. I cant say my understanding of functions is any better but hopefully will be rectified with a few arduino programming books Ive ordered. (just the way i learn better).
There is plenty of scope for education, experimentation, expansion and improvement on my part largly thanks to the forums guidance so many thanks to those who contributed.
Jim