Pages: 1 [2]   Go Down
Author Topic: water temp fan controller  (Read 2088 times)
0 Members and 1 Guest are viewing this topic.
Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 40
Posts: 5594
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

tkbyd:
Quote
In the Arduino, unless you start working with interrupts, flow charts and structure diagrams will help you get things DESIGNED right BEFORE you start writing the code.... which has to be RE-written many times, if the design wasn't good going in.

This is actually true regardless of whatever process is being created; from a piece of software to an assembly line to how to order pizza (ok, maybe not the last one, but try flowcharting the process of ordering a pizza sometime - its more complex than you think, if you really think about the steps).

If you want to really understand process, look into six sigma - oh, boy!

But really, flowcharting and other graphical diagrams, along with pseudo-code breakouts and such, to "simulate" a design before committing it to real code is the way to go for any complex piece of software.

Take good notes on all of this, deputyhiro, because while people's comments here may seem like nit-picking, I would hazard to guess that much of it is because of long and hard experience in both coding and circuit design. If you don't do this right, up front, and you decide in five years to change things (after not looking at them for all that time), you may find yourself either scratching your head for a long time trying to figure out what is doing what, or giving up altogether and re-writing the whole thing again!

Also, use better variable names - for instance, instead of "tstat", why not "thermostatState"? It makes the code easier to read (and has that "self-commenting" style that can help yourself and others figure out what is going on).

Final note: USE PLENTY OF CLEAR AND CONSISE COMMENTS IN YOUR CODE - your future self will thank you (you seem to have a good start on this, but I just wanted to say it again)!

Good luck...  smiley
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I totally reworked this sketch, and it seems to be a lot easier to follow. Paul, when you looked at my last sketch I had  "while (tstat ==HIGH)  digitalwrite(FAN, HIGH)" and you said logically it was not correct and the fan would stay on. You were right, that is what it did.  I was under the assumption that once the stat became low, that made the statement false, turning the fan off.  Now, in this new sketch, I have the function for HEAT. When the tstat closes, it goes into the heat function, and stays there even when the stat goes low. What am I doing wrong now?  oh, and I kinda got the map function figured out, just have to do some experimenting with the numbers and get it calibrated. Thanks Brian


Code:
#define TSTAT 12                               //OR.OR/W  (THERMOSTAT WIRE COLORS)
#define FAN 13                                 //BR.BR/W  (FAN RELAY WIRE COLORS)
#define TEMP 0                                 // BL.BL/W (COIL TEMP SENSOR WIRE COLORS)
#define PUMP 11                                //G.W      (PUMP CONTROL SSR WIRE COLORS)
#define LITE 10                                //WARNING LITE ON DURING "SHUTDOWN"
const long ONE_SECOND = 1000;                  //DEFINE 1 SECOND
const long ONE_MINUTE = 60 * ONE_SECOND;       //DEFINE 1 MINUTE
const long ONE_HOUR = 60 * ONE_MINUTE;         //DEFINE 1 HOUR
const long FIVE_MINUTES = 5 * ONE_MINUTE;      //DEFINE 5 MINUTES
int TS_STATE = LOW;                            //THERMOSTAT VARIABLE
int T = 0;                                     //RAW COIL TEMP VARIABLE
int temp = 0;

void setup()
{
  pinMode(TSTAT, INPUT);                       //THERMOSTAT STATE INPUT
  pinMode(FAN, OUTPUT);                        //FAN CONTROL RELAY OUTPUT
  pinMode(TEMP, INPUT);                        //COIL TEMP
  pinMode(PUMP, OUTPUT);                       //SSR PUMP CONTROL OUTPUT
  pinMode(LITE, OUTPUT);                       //WARNING LITE OUTPUT
  Serial.begin(9600);                          //OPEN SERIAL PORT (FOR DIAG. ONLY)
  
}

void loop()  
{
  temp = analogRead(TEMP);                         //READ TEMP SENSOR
  Serial.println(temp);                         //PRINT ACTUAL TEMP
  if (temp > 475)                               //IF COIL TEMP IS LESS THAN 125F
  {
   TEMP_CHECK();                                //GO TO: FUNCTION "TEMP CHECK"
  }
   else                                         //COIL TEMP GREATER THAN 125F
   {
  if ((temp < 475) && (TS_STATE == LOW))        //COIL TEMP GREATER THAN 125 AND THERMOSTAT NOT CALLING FOR HEAT
  {
    STAND_BY();                                 //GO TO: FUNCTION "STAND BY"
  }
  if ((temp < 475) && (TS_STATE == HIGH))       //COIL TEMP GREATER THAN 125F AND THERMOSTAT CALLING FOR HEAT
  {
    HEAT();                                     //GO TO: FUNCTION "HEAT"
  }
  if (temp > 475)                               //COIL TEMP LESS THAN 125F
  {
    SHUTDOWN();                                 //GO TO: FUNCTION "SHUTDOWN"
  }
   }
    
}
                                                //SHUTDOWN (COLD WATER)
                                      //-----------------------------------------
void SHUTDOWN()
{
  Serial.print("SHUTDOWN!!!");                 //PRINT "SHUTDOWN" TO SERIAL PORT FOR DIAG
  delay(ONE_SECOND);                           //DELAY 1 SECOND
  Serial.println(temp);                        //PRINT ACTUAL TEMP
  digitalWrite(PUMP, LOW);                     //TURN PUMP OFF
  digitalWrite(LITE, HIGH);                    //TURN WARNING LITE ON
  delay(ONE_HOUR);                             //DELAY 1 HOUR TO LET BOILER TEMP RISE ABOVE 125F
  return;                                      //RETURN TO LOOP
}

                                               // HEAT FUNCTION
                                     //-------------------------------------------
void HEAT()
{
  Serial.print("HEAT");                        // PRINT "HEAT"
  delay(ONE_SECOND);                           //DELAY 1 SECOND
  Serial.println(temp);                        //PRINT ACTUAL TEMP
  while (( TS_STATE == HIGH) && (temp < 475))  //IF THERMOSTAT CALLS FOR HEAT,
  {                                            //AND COIL IS HOT
    digitalWrite(FAN, HIGH);                   //TURN FAN ON
  }
  if ((TS_STATE == LOW) && ( temp < 475))      //IF NOT, TURN FAN OFF
  {
    digitalWrite(FAN, LOW);
    return;                                    //RETURN TO LOOP
  }

}
                                               //TEMP CHECK FUNCTION
                              //CHECK FOR HOT WATER (ON STARUP, AFTER SHUTDOWN)
                          //-------------------------------------------------------
                          
void TEMP_CHECK()
{
  Serial.print("TEMP CHECK");                 //SERIAL PRINT "TEMP CHECK" FOR DIAG
  delay(ONE_SECOND);                          //DELAY 1 SECOND
  Serial.println(temp);                       //PRINT ACTUAL TEMP
  digitalWrite(PUMP, HIGH);                   //TURN PUMP ON
  delay(FIVE_MINUTES);                        // WAIT FOR COIL TO GET HOT
  temp = analogRead(TEMP);                    //READ TEMP, HOT?
  if (temp < 475)                             //IF TEMP IS OVER 125F
  {
  return ;                                    //GO BACK TO LOOP
  }
  else                                        //IF NOT,
  {
    SHUTDOWN();                               //GO TO FUNCTION: SHUTDOWN
  }
}

                                             //STAND BY, WAIT FOR HEAT CALL
                                     //-------------------------------------------
                
 void STAND_BY()
 {
   digitalWrite(PUMP, HIGH);                 //TURN COOLANT PUMP ON
   Serial.print("STAND BY");                 //PRINT "STAND BY" FOR DIAG
   delay(ONE_SECOND);                        //DELAY 1 SECOND
   Serial.print(temp);                       //SERIAL PRINT MAPPED TEMP READING FOR DIAG
  TS_STATE = digitalRead(TSTAT);             //CHECK THERMOSTAT STATE
  temp = analogRead(TEMP);                   //READ TEMP
  if (TS_STATE == HIGH)                      // IF THERMOSTAT IS CALLING FOR HEAT
  {
    return;                                  //RETURN TO LOOP
  }
  if (temp > 475)                            //IF COIL TEMP IS LESS THAN 125F
  {
    SHUTDOWN();                              //GO TO FUNCTION: SHUTDOWN
  }
 }
 
« Last Edit: January 27, 2010, 06:46:20 pm by deputyhiro » Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 638
Posts: 50319
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In STAND_BY, you have this:
Code:
  Serial.print(temp);                       //SERIAL PRINT MAPPED TEMP READING FOR DIAG
  TS_STATE = digitalRead(TSTAT);             //CHECK THERMOSTAT STATE
  temp = analogRead(TEMP);                   //READ TEMP

Shouldn't the printing of temp come after the analogRead that values temp?

In loop, you have 4 if statements involving temp. I think that this could be simplified. You want to do something if temp is below 475, and something else if it isn't.

If temp is below 475, the action depends on the thermostat, so that requires another if test, in the else block.

If the thermostat is HIGH, you call HEAT, which seems a reasonable thing to do. In the HEAT function, you have blocks that depend on the value in TS_STATE, but in the HEAT function, the value of TS_STATE never changes, and HEAT is only called when TS_STATE is HIGH.

I would guess that you need to call digitalRead in this function, to see if the thermostat is saying "Enough already, it's roasting in here" (or something like that).



This is unrelated to your problem, but worth mentioning. Look at the paragraph above the one above this one. See anything strange? You can't tell, unless you are familiar with the code which capitalized words are function names and which are constants.

There is a convention that says that all capital letters are reserved for #define'd value (HIGH, LOW, INPUT, OUTPUT, etc.). Function names are generally all letters (no _), using either camelCase or PascalCase for naming. For instance, digitalRead or analogWrite are two word function names, while print and delay are one word names. Variable names are typically all lower case.

I'd encourage you to follow the convention, so parts of your code can be picked up quickly by other people.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got it, uploaded it, and i'll be damned.......it works. All functions work as designed. Thank you Paul and all who helped. I will post the final code with all mods.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the finished, (working) product.......at least so far. Thanks again to all who helped.


Code:
#define TSTAT 12                               //OR.OR/W  (THERMOSTAT WIRE COLORS)
#define FAN 13                                 //BR.BR/W  (FAN RELAY WIRE COLORS)
#define TEMP 0                                 // BL.BL/W (COIL TEMP SENSOR WIRE COLORS)
#define PUMP 11                                //G.W      (PUMP CONTROL SSR WIRE COLORS)
#define LITE 10                                //WARNING LITE ON DURING "SHUTDOWN"
const long ONE_SECOND = 1000;                  //DEFINE 1 SECOND
const long ONE_MINUTE = 60 * ONE_SECOND;       //DEFINE 1 MINUTE
const long ONE_HOUR = 60 * ONE_MINUTE;         //DEFINE 1 HOUR
const long FIVE_MINUTES = 5 * ONE_MINUTE;      //DEFINE 5 MINUTES
int tsstate = LOW;                            //THERMOSTAT VARIABLE
int T = 0;                                     //RAW COIL TEMP VARIABLE
int temp = 0;

void setup()
{
  pinMode(TSTAT, INPUT);                       //THERMOSTAT STATE INPUT
  pinMode(FAN, OUTPUT);                        //FAN CONTROL RELAY OUTPUT
  pinMode(TEMP, INPUT);                        //COIL TEMP
  pinMode(PUMP, OUTPUT);                       //SSR PUMP CONTROL OUTPUT
  pinMode(LITE, OUTPUT);                       //WARNING LITE OUTPUT
  Serial.begin(9600);                          //OPEN SERIAL PORT (FOR DIAG. ONLY)
  
}

void loop()  
{
  tsstate = digitalRead(TSTAT);                 //READ THERMOSTAT STATE
  temp = analogRead(TEMP);                      //READ TEMP SENSOR
  Serial.println(temp);                         //PRINT ACTUAL TEMP
  delay(250);                                   //WAIT 1/4 SECOND SO SERIAL INFO IS NOT CRAMMED TOGETHER
  if (temp > 475)                               //IF COIL TEMP IS LESS THAN 125F
  {
   tempCheck();                                 //GO TO: FUNCTION "TEMP CHECK"
  }
                                            
                                            
  if (tsstate == HIGH)                          //THERMOSTAT CALLING FOR HEAT
  {
    heat();                                     //GO TO: FUNCTION heat
  }
  else                                           //COIL TEMP GREATER THAN 125F AND THERMOSTAT CALLING FOR HEAT
  {
    standBy();                                     //GO TO: FUNCTION standBy
  }
   }

                                                //SHUTDOWN (COLD WATER)
                                      //-----------------------------------------
void shutdown()
{
  Serial.println("SHUTDOWN!!!");                 //PRINT "SHUTDOWN" TO SERIAL PORT FOR DIAG
  delay(250);                                  //WAIT 1/4 SECOND
  temp = analogRead(TEMP);                     //READ TEMP SENSOR
  Serial.println(temp);                        //PRINT ACTUAL TEMP
  delay(250);                                  //WAIT 1/4 SECOND
  digitalWrite(PUMP, LOW);                     //TURN PUMP OFF
  digitalWrite(FAN, LOW);                      //TURN FAN OFF
  digitalWrite(LITE, HIGH);                    //TURN WARNING LITE ON
  delay(ONE_HOUR);                             //DELAY 1 HOUR TO LET BOILER TEMP RISE ABOVE 125F
  return;                                      //RETURN TO LOOP
}

                                               // HEAT FUNCTION
                                     //-------------------------------------------
void heat()
{
  Serial.println("HEAT");                        // PRINT "HEAT"
  delay(250);                                  //WAIT 1/4 SECOND
  temp = analogRead(TEMP);                     //READ TEMP SENSOR
  Serial.println(temp);                        //PRINT ACTUAL TEMP
  delay(250);                                  //WAIT 1/4 SECOND
  tsstate = digitalRead(TSTAT);                //READ THERMOSTAT STATE
  if (( tsstate == HIGH) && (temp < 475))      //IF THERMOSTAT CALLS FOR HEAT,
  {                                            //AND COIL IS HOT
    digitalWrite(FAN, HIGH);                   //TURN FAN ON
  }
  if ((tsstate == LOW) && (temp > 475))        //IF NOT, TURN FAN OFF
  {
    digitalWrite(FAN, LOW);
    return;                                    //RETURN TO LOOP
  }
  if (temp > 475)
  {
    tempCheck();
  }
}
                                               //TEMP CHECK FUNCTION
                              //CHECK FOR HOT WATER (ON STARUP, AFTER SHUTDOWN)
                          //-------------------------------------------------------
                          
void tempCheck()
{
  Serial.println("TEMP CHECK");                 //SERIAL PRINT "TEMP CHECK" FOR DIAG
  delay(250);                                 //WAIT 1/4 SECOND
  temp = analogRead(TEMP);                    //READ TEMP SENSOR
  Serial.println(temp);                       //PRINT ACTUAL TEMP
  delay(250);                                 //WAIT 1/4 SECOND
  digitalWrite(PUMP, HIGH);                   //TURN PUMP ON
  delay(FIVE_MINUTES);                        // WAIT FOR COIL TO GET HOT
  temp = analogRead(TEMP);                    //READ TEMP, HOT?
  if (temp < 475)                             //IF TEMP IS OVER 125F
  {
  return ;                                    //GO BACK TO LOOP
  }
  else                                        //IF NOT,
  {
    shutdown();                               //GO TO FUNCTION: shutdown
  }
}

                                             //STAND BY, WAIT FOR HEAT CALL
                                     //-------------------------------------------
                
 void standBy()
 {
   digitalWrite(PUMP, HIGH);                 //TURN COOLANT PUMP ON
   Serial.println("STAND BY");                 //PRINT "STAND BY" FOR DIAG
   delay(250);                               //WAIT 1/4 SECOND
   temp = analogRead(TEMP);                  //READ TEMP
   Serial.println(temp);                       //SERIAL PRINT MAPPED TEMP READING FOR DIAG
   delay(250);                               //WAIT 1/4 SECOND
   digitalWrite(FAN, LOW);
  tsstate = digitalRead(TSTAT);             //CHECK THERMOSTAT STATE
  if (tsstate == HIGH)                      // IF THERMOSTAT IS CALLING FOR HEAT
  {
    return;                                  //RETURN TO LOOP
  }
  if (temp > 475)                            //IF COIL TEMP IS LESS THAN 125F
  {
    tempCheck();                              //GO TO FUNCTION: tempCheck
  }
 }
 
« Last Edit: January 30, 2010, 08:33:53 am by deputyhiro » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the close to fininshed alternative. Paul when we first talked, I was writing a program that only turned the pump on when it called for heat. this last finished product Im sure you noticed the pump is on all the time as long as the water is hot. That is all fine, until the outside temp gets up into the mid 20s and 30s. So then I want to turn the pump off so I dont overheat the house....It will get into 78-80 range just from natual convection when that coil is hot. So for now, I run the 2 programs and when it gets  hot outside, (more efficient with the pump off/on) I upload 1 and when it gets cold outside, (it works more efficiently with the pump constantly on, Ive found) i do the other. this is the first year with this home made boiler and i am still learning its behaviors. Youre all thinking thats alot of work to, why not add an outdoor temp sensor and program it to do that on its own. I know.... That is the next step. Here is the code for the "warm weather" controller.  This one does have the map function in it, I am still working on the numbers.

Code:
#define TSTAT 12                           //OR.OR/W  (WIRE COLOR THERMOSTAT WIRING)
#define FAN 13                             //BR.BR/W  (WIRE COLOR FAN CONTROL RELAY)
#define TEMP 0                             // BL.BL/W (WIRE COLOR COIL TEMP SENSOR)
#define PUMP 11                            //G.W      (WIRE COLOR PUMP SSR)
#define LITE 10                            //SHUTDOWN WARNING LITE
const long ONE_SECOND = 1000;              //DEFINE ONE SECOND
const long ONE_MINUTE = 60 * ONE_SECOND;   //DEFINE ONE MINUTE
const long ONE_HOUR = 60 * ONE_MINUTE;     //DEFINE ONE HOUR

int T = 0;                                 //ANALOG READ TEMP
int temp = 0;                              //ACTUAL TEMP
int tstat = LOW;                           //THERMOSTAT STATE VARIABLE
void setup(){
  pinMode(TSTAT, INPUT);                   // THERMOSTAT INPUT
  pinMode(FAN, OUTPUT);                    //FAN RELAY OUTPUT
  pinMode(TEMP, INPUT);                    //COIL TEMP SENSOR
  pinMode(PUMP, OUTPUT);                   //PUMP SSR OUTPUT
  pinMode(LITE, OUTPUT);                   //WARNING LITE OUTPUT
  Serial.begin(9600);                      //OPEN SERIAL PORT
}

void loop(){
  temp = map(T, 0, 1023, 284, 43);
  tstat = digitalRead(TSTAT);               //READ THERMOSTAT
  delay(250);                               //WAIT 1/4 SECOND
  Serial.println(tstat);                    //PRINT THERMOSTAT STATE FOR DIAG
  delay(250);                               //WAIT 1/4 SECOND
  if (tstat == LOW)
  {                                         //IF THERMOSTAT IS LOW, NOT CALLING FOR HEAT
      digitalWrite(PUMP, LOW);              //TURN PUMP OFF
  }
  
  else                                      //IF THERMOSTAT IS HIGH, CALLING FOR HEAT
  {
      coilWarmup;                           //GO TO FUNCTION coilWarmup
  }
   }

                                                  //FUNCTION: shutdown
                           //FUNCTION IS RUN AFTER DETECTING COLD WATER FROM BOILER, SHUTS DOWN FOR 1 HOUR TO LET BOILER CATCH UP
  
void shutdown()        
    {  
      Serial.println("SHUTDOWN!");           //PRINTS SHUTDOWN TO SERIAL PORT FOR DIAG    
      digitalWrite(FAN, LOW);               //TURN FAN OFF
      digitalWrite(PUMP, LOW);              //TURN PUMP OFF
      digitalWrite(LITE, HIGH);             //TURN WARNING LITE ON
      delay(ONE_HOUR);                      //WAIT 1 HOUR FOR BOILER TO CATCH UP
      return;                               //GO BACK TO LOOP
    }
    
                                    
                                           //FUNCTION: coilWarmup
                            //RUNS PUMP FOR 5 MINUTES AND CHECKS FOR HOT WATER
void coilWarmup()    
   {
     digitalWrite(PUMP, HIGH);                            //TURN PUMP ON
     unsigned long T = millis();                          //RECORD TIME
     temp = analogRead(TEMP);                             //READ TEMP
   if (( millis() - T < 5 * ONE_MINUTE) && ( temp < 475)) //IF MORE THAN 5 MINUTES HAVE ELAPSED AND TEMP HAS REACHED 125, GO TO heat
   {
     heat;
   }
    else                                                  //IF COIL DOES NOT WARM UP IN 5 MINUTES, GO TO shutdown
    {
      shutdown;
    }
   }
  
  
                                            //FUNCTION: heat
void heat()
   {
     temp = analogRead(TEMP);             //READ TEMP
     Serial.println(temp);                //PRINT TEMP FOR DIAG
     delay(250);                          //WAIT 1/4 SECOND
     tstat = digitalRead(TSTAT);          //READ THERMOSTAT STATE
     if (tstat == HIGH)                   // IF THERMOSTAT CALLS FOR HEAT
     {
       digitalWrite(FAN, HIGH);           //TURN FAN ON
     }
     else                                 //IF THERMOSTAT DOESNT CALL FOR HEAT
     {
       digitalWrite(FAN, LOW);            //TURN FAN OFF
       digitalWrite(PUMP, LOW);
       return;
     }
     if  (temp > 475)                     //IF COIL TEMP DROPS BELOW 125 WHILE IN HEAT MODE, GO TO FUNCTION coilWarmup
     {
       coilWarmup;
     }
   }
    
  
« Last Edit: January 30, 2010, 09:04:32 am by deputyhiro » Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 638
Posts: 50319
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Until you get the outdoor temp sensor, you could just use a switch. If the switch is in the "it's cold out there" position, do the cold thing. If the switch is in the "Oh, what a beautiful day!" position, do the warm thing.

That way, you only need one sketch.

With modular code like you have now, it's much easier to implement these kind of changes.

When you get the outdoor temp sensor, it's easy to change the digitalRead to analogRead. The if test to determine mode will be of the form:

Code:
if(outdoorTemp >= someValue)

instead of

Code:
if(coldOutside == HIGH)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if have noticed that a good way to decide if you are in summer or winter is to record the temperature over a period of say 2 weeks, and if the temperature is above 20 degrees for 1 week in those 2 weeks, then declare the system to be in summer.

But to do this you need state stored somewhere, and you only need to do this check once day.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey All,

I am about to install fFCU ( Fan coil Units).
I am using these:
http://www.flaktwoods.eu/products/air-terminal-devices-and-ducts/fan-coils-chilled-water-cassette-perimeter-wall/satellite-qzsc

These have a 3 step Fan, and a 3 way valve for controlling water throughput.

SO, can anyone point me to the hardware aspects of doing this, rather than the software ??

gedw99 AT GMAIL dot COM
Logged

Pages: 1 [2]   Go Up
Jump to: