Hi! I have a project where I want to turn a heater and a cooler on and off using both temperature and time.
I want the heating period to last for 1 hour. When reached the desired temperature, I want to keep it constant for the remaining time by turning the heater on and off. I am trying it out using LEDs and 40 second intervals instead of 1 hour. It seems like my code will not update within the millis interval, because when I change the temperature the LED will not turn off.
Any ideas on how to solve this problem?
#include <Adafruit_MAX31865.h>
int valve = 3; //green LED
int heater = 2; //red LED
int temp;
unsigned long startMillis;
unsigned long currentMillis;
unsigned long intervalprint = 2000;
unsigned long intervalcool = 40000;
unsigned long nocool = 40000;
unsigned long intervalheat = 40000;
unsigned long noheat = 40000;
unsigned long previouscool = 0;
unsigned long previousheat = 0;
unsigned long previousprint = 0;
Adafruit_MAX31865 max = Adafruit_MAX31865(10, 11, 12, 13);
#define RREF 430.0 //The value of the Rref resistor
#define RNOMINAL 100.0 //The 'nominal' 0-degrees-C resistance of the sensor
void setup() {
Serial.begin(115200);
pinMode(valve, OUTPUT);
pinMode(heater, OUTPUT);
startMillis = millis();
max.begin(MAX31865_3WIRE);
}
void loop() {
currentMillis = millis();
heat();
cool();
printinfo();
}
void heat() {
if (digitalRead(heater) == LOW) {
if (currentMillis - previousheat >= noheat)
//wait for no-heat interval to expire to turn the heater ON
{
if (temp < 20) {
digitalWrite(heater, HIGH);
}
if ( temp > 20) {
digitalWrite(heater, LOW);
}
}
previousheat += noheat;
}
else {
if (currentMillis - previousheat >= intervalheat) {
//wait for the heatinterval to expire to turn the heater OFF
{
digitalWrite(heater, LOW);
}
previousheat += intervalheat;
}
}
}
void cool() {
if ((digitalRead(valve) == LOW) && (currentMillis > 40000)) {
if (currentMillis - previouscool >= nocool) {
digitalWrite(valve, HIGH);
}
previouscool += intervalcool;
}
else {
if (currentMillis - previouscool >= intervalcool) {
{
digitalWrite(valve, LOW);
}
previouscool += intervalcool;
}
}
}
void printinfo() {
if (currentMillis - previousprint >= intervalprint) {
uint16_t rtd = max.readRTD();
//Serial.print("RTD value: "); Serial.println(rtd);
float ratio = rtd;
ratio /= 32768;
// Serial.print("Ratio = "); Serial.println(ratio, 8);
//Serial.print("Resistance = "); Serial.println(RREF * ratio, 8);
Serial.print("Temperature = "); Serial.println(max.temperature(RNOMINAL, RREF));
temp = max.temperature(RNOMINAL, RREF);
Serial.print("Time = "); Serial.println(currentMillis / 1000);
Serial.print("Red = "); Serial.println(digitalRead(2));
Serial.print("Green = "); Serial.println(digitalRead(3));
Serial.println(" ");
// Check and print any faults
uint8_t fault = max.readFault();
if (fault) {
Serial.print("Fault 0x"); Serial.println(fault, HEX);
if (fault & MAX31865_FAULT_HIGHTHRESH) {
Serial.println("RTD High Threshold");
}
if (fault & MAX31865_FAULT_LOWTHRESH) {
Serial.println("RTD Low Threshold");
}
if (fault & MAX31865_FAULT_REFINLOW) {
Serial.println("REFIN- > 0.85 x Bias");
}
if (fault & MAX31865_FAULT_REFINHIGH) {
Serial.println("REFIN- < 0.85 x Bias - FORCE- open");
}
if (fault & MAX31865_FAULT_RTDINLOW) {
Serial.println("RTDIN- < 0.85 x Bias - FORCE- open");
}
if (fault & MAX31865_FAULT_OVUV) {
Serial.println("Under/Over voltage");
}
max.clearFault();
}
previousprint = currentMillis;
}
}
currentMillis will only be less than 40,000 for the the first 40 seconds of program run time - is that what you want to test for?
if ((digitalRead(3) == LOW) && (currentMillis > 40000)) {
I'm not sure why you have all the different time tests. Why not have a single interval (for heating maybe 1 or 5 minutes would be appropriate) and do all the tests when the time is up, then stay quiet until the next interval.
It is also not a good idea to have "magic numbers" in code - such as digitalRead(3). Put the value 3 into a variable (or a constant) with a meaningful name.
What's the purpose of the no-heat and no-cool time periods? Why not just use temperature feedback with adequate hysteresis on both?
Also, how does the system differentiate between heat and cool modes? If the temperature is greater than '5' the cooling valve would open but the heating valve would be open if the temperature < 20. If the temperature is '10' do you want both on?
Also, can you clarify the temperature limits for heating and cooling? For heating, if the temperature is <20 the heat is on and if it's >20 heat is off. That makes sense if the temperature is, say, oC. But for cooling you've got a limit of 5; isn't that really cool already?
I intended to cool and heat in different durations, i.e. cooling for 45 minutes and heating for 1 hour. I also wanted a "wait" where nothing happened - therefore I defined noheat and nocool as intervals where the heater/cooler would be off. I had some trouble getting that to work, so as a simplification each period is now the same amount of time.
I do not want the cooling and heating to be on simultaneously. So if the temperature is 10 deg, the heater should be on if within intervalheat, and the valve should be open if within intervalcool.
Essentially I am just trying bring the temperature up to 90, but not higher, and keep it constant for a certain amount of time. And then bring the temperature down again. What is my main issue now is that I can't get the temperature to stay constant, as the heater stays on in the entire heatinterval.
You can have lots of different intervals but IF they all relate to the same thing (in this case the duration of heating or cooling) AND if the different intervals are mutually exclusive THEN there is only need for a single time check
if (currentMIllis - previousTimeCheckMillis >= currentIntervalMIllis) {
Depending on the mode you are in just change the value of currentIntervalMillis - very crudely ...
if (mode == 'H') {
currentIntervalMIllis = heatMillis;
}
else if (mode == 'C') {
currentIntervalMillis = coolMillis;
}
You can have as many different modes as you want.
You only need multiple time checks if you want to manage times for things that happen concurrently.
kajasol:
Essentially I am just trying bring the temperature up to 90, but not higher, and keep it constant for a certain amount of time. And then bring the temperature down again. What is my main issue now is that I can't get the temperature to stay constant, as the heater stays on in the entire heatinterval.
I hope that answered your comments...
Okay, can you define:
the upper limit of heating (90oC)
how long you want to hold it there
the lower limit of cooling (??oC)
how long you want to hold it there
Does the "machine" run continuously, heat-hold-cool-hold..., or does it need intervention?
Does the attached come close to what you want? I set the temperature limits to 90oC and 5oC; might be worth changing them down to 25 and 15 for testing...