My heating system is not working for my plants

Hello All!

So I have built a watering and heating system for my plants, I have chosen to use a relay to control all these systems, below is my code:


#define ntc_pin A2  // Pin, to which the voltage divider is connected
#define vd_power_pin 2            // 5V for the potential divider
#define temp_activate 4           // to activate the heater
#define nominal_resistance 10000  //Nominal resistance at 25⁰C
#define nominal_temeprature 25    // temperature for nominal resistance (almost always 25⁰ C)
#define samplingrate 10            // Number of samples
#define beta 3950                 // The beta coefficient or the B value of the thermistor (usually 3000-4000) check the datasheet for the accurate value.
#define Rref 10000                //Value of  resistor used for the voltage divider
int samples = 0;                  //array to store the samples
bool heater_on = false;
unsigned long heater_start_time = 0;

#define watering 7
const unsigned long day_since_watering = 1512000000L;
const unsigned long time_to_water = 100000L;
unsigned long startdate;
unsigned long currentdate;
unsigned long start_water_time;
unsigned long current_water_time;
bool pump_on = false;

void setup() {
  pinMode(vd_power_pin, OUTPUT);

  digitalWrite (watering, HIGH);
  digitalWrite(temp_activate, HIGH);

  pinMode(temp_activate, OUTPUT);
  pinMode(watering,OUTPUT);
  analogReference(EXTERNAL); 
  Serial.begin(9600);
  startdate = millis();
}
     
void loop() {
//-------------  boring calculation to find temp  -------------//
  uint8_t i;
  float average;
  samples = 0;
  // take voltage readings from the voltage divider
  digitalWrite(vd_power_pin, HIGH);
  for (i = 0; i < samplingrate; i++) {
    samples += analogRead(ntc_pin);
    delay(10);
  }
  digitalWrite(vd_power_pin, LOW);
  average = 0;
  average = samples / samplingrate;


  // Calculate NTC resistance
  average = 1023 / average - 1;
  average = Rref / average;


  float temperature;
  temperature = average / nominal_resistance;           // (R/Ro)
  temperature = log(temperature);                       // ln(R/Ro)
  temperature /= beta;                                  // 1/B * ln(R/Ro)
  temperature += 1.0 / (nominal_temeprature + 273.15);  // + (1/To)
  temperature = 1.0 / temperature;                      // Invert
  temperature -= 273.15;                                // convert absolute temp to C
  Serial.print("Temperature ");
  Serial.print(temperature);
  Serial.println(" ");
  delay(100);

 if (( temperature <= 10) && (heater_on == false))
// Temperature less than 10 and the heater is off
// so turn the heater on
{
	digitalWrite (temp_activate, LOW);
	heater_on = true;

	// Get the heater start time
	heater_start_time = millis();
}

// Check if the heater has been on for 3 hours
// If yes, then turn it off

unsigned long check_time = millis()- heater_start_time;
if (((heater_on == true) && (check_time >= 1800000L)) || ((heater_on == true) && (temperature >= 15)))
{
  digitalWrite (temp_activate, HIGH);
	heater_on = false;
}

currentdate = millis();
  if((currentdate - startdate >= day_since_watering) && (pump_on == false))
  {
    digitalWrite(watering, LOW);
    pump_on = true;
    startdate = currentdate;
    start_water_time = millis();
  }

  current_water_time = millis();
  if((current_water_time - start_water_time >= time_to_water) && (pump_on == true))
  {
    digitalWrite(watering, HIGH);
    pump_on = false; 
    start_water_time = current_water_time;
    startdate = millis();
  }

}

The relay's schematic is linked here:
image

I have pretty much followed this man on Youtube, everything should be the same except the IN1 and IN2 pins (those are 4 and 7 respectively) :

My pump and heater is connected to the NO (Normally open) and COM of the relay, the relay is working but I have noticed that every time I power it on, it is connected automatically, (as in the NO and COM are connected) unless I have reach the temperature of 10C and then bring it back up to 15C. This is rather annoying because that would mean I have to wait 2.5 weeks for my watering system to work. I am not sure how I would fix this. I have tested this code with LED lights and it works normally.

Too Long Didn't Read: Relay only start working properly when it has reach the code's variables/ limits?

Many thanks in advance !!

  • First things first, keep you assignments in agreement
    example:
    const unsigned long day_since_watering = 1512000000L;
    Should be:
    const unsigned long day_since_watering = 1512000000UL;

  • Always show us a good schematic of your proposed circuit.
    Show us a good image of your ‘actual’ wiring.
    Give links to components.

  • int samples = 0; //array to store the samples
    How is this an array ?

  • #define watering 7 maybe use better naming :thinking:
    #define watering 7
    #define wateringRelay 7

  • 1512000000L = a day ?
    let the compiler do your math…
    example:
    const unsigned long day_since_watering = 1512000000L;
    const unsigned long day_since_watering = 24UL * 60* 60 * 1000;

1 Like

What does the UL do?




I think my schematics are better than last time but still working on it.

I copied the code from a website :neutral_face: :

That is supposed to be 2.5 weeks, so it waters every 2.5 weeks

Do you mean LEDs connected to the relay COM and NO connections?

So I have tested the code without the relay, with normal led lights and it works so I don't think the code is the problem, but maybe it is and I just don't know better.

In your setup() you should do the digitalWrites after seting the pinMode

2 Likes
  • Correct the temperature circuit.

  • Why is D2 connected to AREF ? :scream:

  • The relays should be powered by an external 5v power supply, not the Arduino.
  • const unsigned long day_since_watering = 17UL * 24 * 60* 60 * 1000; //17 days

  • UL tells the compiler to use unsigned long math.

Before will work so you don’t have 4us where the relay tries to energize, but what the heck, what’s 4us amongst friends.

Place Serial prints in your code to prove variables are what you think they should be at different locations throughout your code.

So I have tried that and the relay would turn on very briefly before turning off again until I have warmed it up using my hand to 15C

Nevermind I am dumb it works now thank you so much!

Could you explain how putting the digitalWrite after the pinMode helps?

Try before and after.


  • Suggest you look at the way the code is written here and do similar in the future:

  • Suggest you use an RTC with battery (DS3231 ≈ $4.00)

  • Suggest you use DS18B20 temperature sensor (≈ $2.00)

Untested


#define ON                               HIGH
#define OFF                              LOW

#define wateringOFF                      HIGH
#define wateringON                       LOW

#define heatOFF                          HIGH
#define heatON                           LOW

#define ENABLED                          true
#define DISABLED                         false

#define nominal_resistance               10000 //Nominal resistance at 25⁰C
#define nominal_temeprature              25    //temperature for nominal resistance (almost always 25⁰ C)
#define samplingrate                     10    //Number of samples
#define beta                             3950  //The beta coefficient or the B value of the thermistor (usually 3000-4000) check the datasheet for the accurate value.
#define Rref                             10000 //Value of  resistor used for the voltage divider

const byte ntc_pin                     = A2;   // Pin, to which the voltage divider is connected
const byte vd_power_pin                = 2;    // 5V for the potential divider
const byte temp_activate               = 4;    // to activate the heater
const byte watering                    = 7;
const byte heartbeatLED                = 13;

bool heater_onFlag                     = DISABLED;
bool pump_onFlag                       = DISABLED;

byte samples                           = 0;    //array to store the samples

const unsigned long day_since_watering = 17UL * 24 * 60 * 60 * 1000;  //17 days
const unsigned long time_to_water      = 100UL * 1000;  //100 seconds

unsigned long heater_start_time;
unsigned long startdate;
unsigned long currentdate;
unsigned long start_water_time;
unsigned long current_water_time;
unsigned long heartbeatTime;

//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  analogReference(EXTERNAL);

  pinMode(heartbeatLED, OUTPUT);
  
  digitalWrite (vd_power_pin, OFF);
  pinMode(vd_power_pin, OUTPUT);
  digitalWrite (vd_power_pin, OFF);

  digitalWrite (watering, wateringOFF);
  pinMode(watering, OUTPUT);
  digitalWrite (watering, wateringOFF);
  
  digitalWrite(temp_activate, heatOFF);
  pinMode(temp_activate, OUTPUT);
  digitalWrite(temp_activate, heatOFF);

  startdate = millis();

} //END of   setup()


//********************************************^************************************************
void loop()
{
  //************************************************              T I M E R  heartbeatLED
  //is it time to toggle heartbeat LED ?
  if (millis() - heartbeatTime >= 500UL)
  {
    //restart this TIMER ?
    heartbeatTime = millis();

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //-------------  boring calculation to find temp  -------------//
  uint8_t i;
  float average;
  samples = 0;
  //take voltage readings from the voltage divider
  digitalWrite(vd_power_pin, ON);
  delay(10);

  //****************************************
  //read an average of the sensor reading
  for (i = 0; i < samplingrate; i++)
  {
    samples += analogRead(ntc_pin);
    delay(10);
  }

  digitalWrite(vd_power_pin, OFF);

  average = 0;
  average = samples / samplingrate;

  //Calculate NTC resistance
  average = 1023 / average - 1;
  average = Rref / average;

  float temperature;
  temperature = average / nominal_resistance;           // (R/Ro)
  temperature = log(temperature);                       // ln(R/Ro)
  temperature /= beta;                                  // 1/B * ln(R/Ro)
  temperature += 1.0 / (nominal_temeprature + 273.15);  // + (1/To)
  temperature = 1.0 / temperature;                      // Invert
  temperature -= 273.15;                                // convert absolute temp to C
  Serial.print("Temperature ");
  Serial.print(temperature);
  Serial.println(" ");

  delay(100);

  //****************************************
  //if temperature less than 10 and the heater is disabled
  //turn the heater on
  if ( heater_onFlag == DISABLED && temperature <= 10 )
  {
    heater_onFlag = ENABLED;
    digitalWrite (temp_activate, heatON);

    // Get the heater start time
    heater_start_time = millis();
  }

  //****************************************
  //Check if the heater has been on for 3 hours
  //If yes, then turn it off
  unsigned long check_time = millis() - heater_start_time;

  if ((heater_onFlag == ENABLED && check_time >= 1800000UL) || (heater_onFlag == ENABLED && temperature >= 15))
  {
    heater_onFlag = DISABLED;

    digitalWrite (temp_activate, heatOFF);
  }

  //****************************************
  //if we are not wtering, is it time to start watering
  if (pump_onFlag == DISABLED && millis() - startdate >= day_since_watering )
  {
    pump_onFlag = ENABLED;

    digitalWrite(watering, wateringON);

    start_water_time = millis();
  }

  //****************************************
  //if this TIMER is enabled, is it time to turn off the water
  if (pump_onFlag == ENABLED && millis() - start_water_time >= time_to_water )
  {
    digitalWrite(watering, wateringOFF);

    pump_onFlag = DISABLED;

    startdate = millis();
  }

} //END of   loop()


//********************************************^************************************************
q

If you set the pin mode to OUTPUT, then what happens when you use digitalWrite is clearly defined. A LOW will make the output LOW and HIGH will make the output HIGH.

If you don't first set the mode, then what happens when you do a digitalWrite will depend on which Arduino you are using. For the ATmega4809 I'm not sure what happens.

So it always best the set the pin mode first before you use a pin for output or input.

2 Likes

Okay, so this is a bit off topic, I have bought a soil sensor for my plant and I have decided to use that rather than counting how many days since it has been watered. I have copied the code off the internet and I know how it works (the tutorial is also linked below). The code on it's own works perfectly well but once it's implemented into my code it stops working. Below is all of my code:

#define ntc_pin A2  // Pin, to which the voltage divider is connected
#define vd_power_pin 2            // 5V for the potential divider
#define temp_activate 4           // to activate the heater
#define nominal_resistance 10000  //Nominal resistance at 25⁰C
#define nominal_temeprature 25    // temperature for nominal resistance (almost always 25⁰ C)
#define samplingrate 10            // Number of samples
#define beta 3950                 // The beta coefficient or the B value of the thermistor (usually 3000-4000) check the datasheet for the accurate value.
#define Rref 10000                //Value of  resistor used for the voltage divider
int samples = 0;                  //array to store the samples


bool heater_on = false;
unsigned long heater_start_time = 0;

#define wateringRelay 7
const unsigned long time_to_water = 10000UL;
unsigned long start_water_time;
unsigned long current_water_time;

#define sensorPower 8
#define sensorPin A0
const unsigned long pause_time = 10000UL;
unsigned long pause_current_time;
unsigned long pause_start_time;
bool pump_on = false;


void setup() {
  pinMode(vd_power_pin, OUTPUT);
  pinMode(temp_activate, OUTPUT);
  pinMode(wateringRelay,OUTPUT);
  pinMode(sensorPower, OUTPUT);
	
	// Initially keep the sensor OFF
	digitalWrite(sensorPower, LOW);
  digitalWrite (wateringRelay, HIGH);
  digitalWrite(temp_activate, HIGH);

  analogReference(EXTERNAL); 
  Serial.begin(9600);
  pause_start_time = millis();
}
     
//  This function returns the analog soil moisture measurement
int readSensor() {
	digitalWrite(sensorPower, HIGH);	// Turn the sensor ON
	delay(10);							// Allow power to settle
	int val = analogRead(sensorPin);	// Read the analog value form sensor
	digitalWrite(sensorPower, LOW);		// Turn the sensor OFF
	return val;							// Return analog moisture value
}

void loop() {
pause_current_time = millis();
  if((pause_current_time - pause_start_time >= pause_time))
    {
	    Serial.print("Analog output: ");
	    Serial.println(readSensor());
      pause_start_time = millis();
    }
    
    if((readSensor() >= 830) && (pump_on == false))
  {
    digitalWrite(wateringRelay, LOW);
    pump_on = true;
    start_water_time = millis();
  }

  current_water_time = millis();
  if((current_water_time - start_water_time >= time_to_water) && (pump_on == true))
  {
    digitalWrite(wateringRelay, HIGH);
    pump_on = false; 
    start_water_time = current_water_time;
  }

  uint8_t i;
  float average;
  samples = 0;
  // take voltage readings from the voltage divider
  digitalWrite(vd_power_pin, HIGH);
  for (i = 0; i < samplingrate; i++) {
    samples += analogRead(ntc_pin);
    delay(10);
  }
  digitalWrite(vd_power_pin, LOW);
  average = 0;
  average = samples / samplingrate;


  // Calculate NTC resistance
  average = 1023 / average - 1;
  average = Rref / average;


  float temperature;
  temperature = average / nominal_resistance;           // (R/Ro)
  temperature = log(temperature);                       // ln(R/Ro)
  temperature /= beta;                                  // 1/B * ln(R/Ro)
  temperature += 1.0 / (nominal_temeprature + 273.15);  // + (1/To)
  temperature = 1.0 / temperature;                      // Invert
  temperature -= 273.15;                                // convert absolute temp to C
  Serial.print("Temperature ");
  Serial.print(temperature);
  Serial.println(" ");
  delay(100);


 if (( temperature <= 10) && (heater_on == false))
// Temperature less than 10 and the heater is off
// so turn the heater on
{
	digitalWrite (temp_activate, LOW);
	heater_on = true;

	// Get the heater start time
	heater_start_time = millis();
}

// Check if the heater has been on for 3 hours
// If yes, then turn it off

unsigned long check_time = millis()- heater_start_time;
if (((heater_on == true) && (check_time >= 900000L)) || ((heater_on == true) && (temperature >= 15))) {
  digitalWrite (temp_activate, HIGH);
	heater_on = false;
}

}

Context, when the soil sensor reads anything above 800, the soil is dry and anything below 400 it is wet, this is the sensor that I bought:

So what I want to happen/ was thinking my code would do, is that it would take a reading every day (in this case it is 10 seconds because I wanted to check if the code is working or not) it see that the soil is greater or equal to 830, then the pump turns on for 10 seconds and then off and then it does the reading again in 24 hours.

What happened is that the led on my Module keeps flashing and the relay turns on for 10 seconds then off very briefly and then back on for 10 seconds.

I have been staring at this code for at least 3 hours now and I am getting nowhere.

Many thanks for your help

Are you actually watering the soil or just turning on the relay? Since you are “watering “ for ten seconds and testing the soil every ten seconds it will be difficult to determine which timer is doing what.

Try changing your day timer to 30 seconds. I suspect that this will change the brief time between waterings to 20 seconds. You will have to find a way to simulate a successful watering to test whether your code is working correctly.

When I have put it into 30 seconds it turns on for 30 seconds and then off for a very brief second before going back on for 30 seconds. The sensor reads it as 1023 (so it's constantly dry) and so it's on the whole time but when it's just this :

// Sensor pins
#define sensorPower 8
#define sensorPin A0
const unsigned long pause_time = 30000UL;
unsigned long pause_current_time;
unsigned long pause_start_time;

void setup() {
	pinMode(sensorPower, OUTPUT);
	
	// Initially keep the sensor OFF
	digitalWrite(sensorPower, LOW);
	  pause_start_time = millis();
	Serial.begin(9600);
}

void loop() {
	//get the reading from the function below and print it
    pause_current_time = millis();
    if((pause_current_time - pause_start_time >= pause_time))
    {
	    Serial.print("Analog output: ");
	    Serial.println(readSensor());
      pause_start_time = millis();
    }
}

//  This function returns the analog soil moisture measurement
int readSensor() {
	digitalWrite(sensorPower, HIGH);	// Turn the sensor ON
	delay(10);							// Allow power to settle
	int val = analogRead(sensorPin);	// Read the analog value form sensor
	digitalWrite(sensorPower, LOW);		// Turn the sensor OFF
	return val;							// Return analog moisture value
}

it works! So I am not sure what I did wrong

I don’t see where you are turning on the watering relay. It’s not even defined in your new sketch.

Exactly what is working? If the new sketch is turning on the watering relay then you have it connected to the wrong output.

this is missing in the sketch you say works??

good luck.. ~q

As @qubits-us pointed out, you need to remove the analogReference statement