This is my first every post here so please bare with me while I learn my ways around here! I recently got my hands on an Arduino Uno Wifi rev2 and I wanted to make a little watering/heating system for my plant while I'm away at uni.
The basic concept is that I have a thermistor (I don't know if I should use a thermistor or a temperature and humidity sensor, is one better than another?????) which measures the temp of a green house I've made for my plant. If it gets below 10 degrees C then it will warm up for 3 hours and then stop and then it takes another reading in 3 hours and so on
As for the watering system I have 3D printed a peristaltic gear pump and plan on using that. I want the board to keep track of time, so that every 7 days it would activate the pump.
The problems that I have encountered:
Implementing the "activate for 3 hours" has been tricky and I'm not sure how to do it, my initial thought was to add a delay but then it would stop literally everything else to stop running so that was a no no. I have tried to implement a "Blink without delay" sort of vibe thingy to my program and that doesn't work. Here is my code:
#define ntc_pin A0 // Pin, to which the voltage divider is connected
#define vd_power_pin 2 // 5V for the voltage divider
#define temp_activate 4
#define nominal_resistance 10000 //Nominal resistance at 25⁰C
#define nominal_temeprature 25 // temperature for nominal resistance (almost always 25⁰ C)
#define samplingrate 5 // 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
void setup() {
pinMode(vd_power_pin, OUTPUT);
pinMode(temp_activate, OUTPUT);
Serial.begin(9600); //initialize serial communication at a baud rate of 9600
}
void loop() {
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;
Serial.print("ADC readings ");
Serial.println(average);
// Calculate NTC resistance
average = 1023 / average - 1;
average = Rref / average;
Serial.print("Thermistor resistance ");
Serial.println(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(" *C");
delay(100);
if (temperature >= 30.00) {
digitalWrite(temp_activate, HIGH);
}
int intervalTemp = 12000;
unsigned long previousTemp = 0;
int TempState = LOW;
unsigned long currentMillis = millis();
if (currentMillis - previousTemp >= intervalTemp) {
previousTemp = currentMillis;
digitalWrite(temp_activate, LOW);
}
}
(I have used 30C because I wanted to test the code out with my body temp. temp_activate is the name I have assigned to a pin)
(My train of thought was it reads the temp, if too cold it activates and starts the timer and then wait for 3 hours, if still too cold, keep on, if above 10C, turn off)
Second problem is I do not know how to implement a timer for my watering system, as mentioned before I have a UNO wifi, so am I able to connect to wifi and get access to a timer?? or would I have to buy module for it?
IN SUMMARY: I DONT KNOW HOW TO DO A 7 DAYS TIMER FOR MY WATERING SYSTEM AND I DONT KNOW HOW TO DO A 3 HOURS TIMER FOR MY HEATING SYSTEM. I ALSO DONT KNOW IF A THERMISTOR IS GOOD ENOUGH FOR MY PLANT
As mentioned above, I was hoping that if it gets too cold, the pin activates and then starts counting till 3 hours (it says 12000 milliseconds now because I wanted to test the code out) and it keeps comparing with previousTemp to see if it has reached the 3 hour mark. If it has then it would deactivate the pin. I followed the "Blink without delay" tutorial from the Arduino website.
However currently, when I heat the thermistor up to 30C the pin does activate, I put in an LED to see if it's working or not, and it keeps blinking and I'm not sure why.
What I wish for it to happen is, when it reach 30C, it stays on for 3 hours (or 12000 milliseconds because that's what my code said) and then stop and check the temp again
Using obscure (at least to me) abbreviations only makes people take time away from providing help to look up the meaning. You could have just said: “In summery:” if someone doesn’t take the time to read the whole thing they are unlikely to take the Time help you.
I haven’t looked at your code thoroughly but I intend to. The first thing that makes me wonder is the 30 minutes of heating time before you read the temperature again. Normally a temperature controller will have a high and a low limit. In your case turn on the heat when the temperature drops to 30 degrees. Then turn off the heat when the temperature rises to the high limit.
Your temperature averaging routine consumes about a minute. That seems to me to be a good amount of time to wait and then decide to keep the heat on or turn it off.
A thermistor should be adequate for your purposes. If I was doing this I would calculate the actual voltage levels that your divider will provide for the two temperatures mentioned above and place those in two defined variables at the top of your code rather than do the complex calculations that you are doing in your.
If you keep the calculation in your code, put it in a separate function that is called by the main loop. Pass your raw measurement to the function and have it return the temperature.
This will turn the heater on once the temperature reaches 30 degrees. I believe the comparison you want is “<=“.
I am not sure where you got the 30 minutes from, or maybe I didn't fully understand what you mean?
As for the "temperature controller" I am planning to use a heating mat (the ones you would get for your pet lizard or something) and have a motor that switches a switch and turn the mat on(I know it seems like a very stupid way of doing it but I don't know how to connect the heating mat to the Arduino and doing it like this is is the easiest for my current skill level)
In my case, the code that I have here, I have set the limit as if it gets over 30C, an LED light will turn on, so I will use my body temperature to check if the code is working. I can easily change the limits later on when I know that the code is working.
What I think the code is doing is, when temp is 30C, light up the LED, and keep lighting it for 3 hours. After 3 hours have past, check temp again. If temp is below 30C, turn off LED.
(So if I change the signs and the limits around for my actual project it would be if temp is 10C or lower, heat on for 3 hours and then check temp again after the 3 hours has pass. If temp is higher than 10C, heat off)
[quote="carsonwc, post:5, topic:1145017"]
As for the "temperature controller" I am planning to use a heating mat (the ones you would get for your pet lizard or something) and have a motor that switches a switch and turn the mat on(I know it seems like a very stupid way of doing it but I don't know how to connect the heating mat to the Arduino and doing it like this is is the easiest for my current skill level)
[/quote
Your Arduino is the temperature controller in this case. The thirty minutes is my mistake. You have stated three hours. Even worse!
Questions:
What exactly are you trying to control the temperature of, the air around the plant, the bottom of the pot, she plant soil, etc.?
How hot and how cold can the above get? In other words what is the desired temperature range?
If you are wanting to control the air temperature and the pot is sitting on the lizard warmer, the soil in the pot might get too warm before the air reaches the desired temperature.
From what I know about the plant, the temperature around the air should not drop below 10 degrees C. So the air around the plant should be equal or higher than 10C.
As for how hot, there really isn't a limit, obviously I don't want to waste electricity just by turning the heating mat on the whole time, so maybe 10-15 C? Given that it is such a low temp and for such a long time, I think that the heat would just spread out evenly across the whole "Greenhouse" (By green house I mean I am keeping the plant in a plastic container)
Furthermore, I am able to set the temp of the heating mat ahead of time so it doesn't go beyond 15C, turning the mat on isn't the problem, the problem is reading the temp after the mat has been on for a set amount of time and then turning it off if it's above 10C
The reason why I have set it for 3 hours is because I don't want to switch the mat on and off too often since it is a mechanical part and I know it's very very unlikely to break but if the thermistor is too sensitive and reading it too fast that might overload the motor??? I don't know if that made any sense.
Although I could try and connect the heat mat to the Arduino but that would probably require some soldering (And I don't have a soldering iron) and something to step up the voltage / amp, something which I have no idea how to do.
Your solution using the motor to switch the heater on and off seems reasonable. Be aware that an Arduino cannot power a motor directly from an output so you will need to use some additional components to run it. Since you will need something more to run the motor anyway you might want to consider using a relay module to turn the heater on and off directly.
The above would be if your overall objective is to learn to use the Arduino. If you only want to control the temperature this will be the easiest.
I have used these and they work well. I have not looked for any other voltages in case you don’t have the 120 volt, 60 Hz flavor of electricity. They may have them in other flavors.
Thank you so much for the relay! I haven't gotten to that part yet but I probably will soon! I also have a Arduino brand Motor shield so I think I will be okay in that sense
But currently, I am still stuck with the timing problem of activating it for 3 hours and then stop to measure the temp, if it 's too warm it would turn off. Would it be worth it to just buy a real time clock module? Or is there another fancy way I can do it via code?
As for the code, am I coding something wrong? Or am I misunderstanding what millis() does?
The code that I wanted to do is:
The temperature sensor sense that the temperature is too low (below 10C) and it activates the pin and then it starts counting till 3 hours and keep comparing with previousTemp, after 3 hours have pass, it turns off and starts recounting again.
I have redone my code a little:
#define ntc_pin A0 // Pin, to which the voltage divider is connected
#define vd_power_pin 2
#define temp_activate 4 // 5V for the voltage divider
#define nominal_resistance 10000 //Nominal resistance at 25⁰C
#define nominal_temeprature 25 // temperature for nominal resistance (almost always 25⁰ C)
#define samplingrate 5 // 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
void setup() {
pinMode(vd_power_pin, OUTPUT);
pinMode(temp_activate, OUTPUT);
Serial.begin(9600); //initialize serial communication at a baud rate of 9600
}
void loop() {
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;
Serial.print("ADC readings ");
Serial.println(average);
// Calculate NTC resistance
average = 1023 / average - 1;
average = Rref / average;
Serial.print("Thermistor resistance ");
Serial.println(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(" *C");
delay(100);
if (temperature >= 30.00) {
digitalWrite(temp_activate, HIGH);
int intervalTemp = 30000;
unsigned long previousTemp = 0;
int TempState = LOW;
unsigned long currentMillis = millis();
if (currentMillis - previousTemp >= intervalTemp) {
previousTemp = currentMillis;
digitalWrite(temp_activate, LOW);
}
}
}
Notably I have changed the intervalTemp to 30 seconds rather than 12 seconds, and also I have put the counting if loop within the "temperature >= 30.00".
Currently. the LED is no longer flashing and is turning on, but it doesn't turn off when 30 seconds have passed. So I'm not sure what I have done wrong? Maybe the order of the code is wrong? Maybe I should separate the loops?
Althought all the variables on the code is different because I wanted to test that the code is working before I do anything else and th easiest way for me to check it is to use my body temperature. I think I know how to do step 1 and 2, but I am stuck on step 3. Step 1 and 2 is just:
(I should also probably write an error code in the case that the temp is lower than 10C and the mat is on)
the part I do not understand is whether I should include the counting (i.e the millis() ) within the if statement or not since I only want it to start counting till 3 hours when the temp is less than or equal to 10C and then to turn off the heating mat I would just do :
Another thing which I am not so sure about are the "int" and the "unsigned long", everytime we run the if statement again, do these value goes back to the default values? (for example we are counting till 3 hours and constantly comparing to intervalTemp, once that loop has been completed and it goes back to "if (temp <= 10)" does the currentMillis store the previous value from the previous loop or does it start at 0 again?)
// This goes above setup()
//---
bool heater_on = false;
unsigned long heater_start_time = 0;
//---
// This goes inside loop()
if (( temperature <= 10) && (heater_on == false))
// Temperature less than 10 and the heater is off
// so turn the heater on
{
digitalWrite (Heater, HIGH); // ON
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 >= 30000L))
{
heater_on = false
digitalWrite (Heater, LOW); // OFF
}
unsigned long check_time = millis()- heater_start_time;
what exactly is happening here? wouldn't both of them be the same since you've started recording the time in the if statement before and assigning the value to heater_start_time so wouldn't check_time be 0 the whole time?
are true and false the same as high and low? If so why do you sometime use true and false and other time you use high and low?
I saw that you used 30000L so that it doesn't overflow, would this also work for my watering system since it has to have a timer for 7 days (it water the plant every 7 days)?
I have not check the code yet but I will when I get home!
1 what exactly is happening here? wouldn't both of them be the same since you've started recording the time in the if statement before and assigning the value to heater_start_time so wouldn't check_time be 0 the whole time?
Don't forget that all that code is in loop() which runs forever. They may both be the same during the first pass of the loop but millis() will increment some the second time around.
2 are true and false the same as high and low? If so why do you sometime use true and false and other time you use high and low?
High/Low 1/0, true/false, all the same. Which is less ambiguous, Heater_on = true, 1, High? Does High mean it is on or off?
3 I saw that you used 30000L so that it doesn't overflow, would this also work for my watering system since it has to have a timer for 7 days (it water the plant every 7 days)?
The L indicates that the constant is a long, otherwise it might be interpreted as an integer.