Phoenix, Arizona USA
Offline
Faraday Member
Karma: 30
Posts: 5123
Where's the beer?
|
 |
« Reply #15 on: January 26, 2010, 11:29:46 pm » |
tkbyd: 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... 
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 22
Arduino rocks
|
 |
« Reply #16 on: January 27, 2010, 06:44:50 pm » |
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 #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
Offline
Brattain Member
Karma: 336
Posts: 36476
Seattle, WA USA
|
 |
« Reply #17 on: January 27, 2010, 07:17:28 pm » |
In STAND_BY, you have this: 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
Newbie
Karma: 0
Posts: 22
Arduino rocks
|
 |
« Reply #18 on: January 29, 2010, 06:20:18 pm » |
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
Newbie
Karma: 0
Posts: 22
Arduino rocks
|
 |
« Reply #19 on: January 30, 2010, 08:32:35 am » |
Here is the finished, (working) product.......at least so far. Thanks again to all who helped. #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
Newbie
Karma: 0
Posts: 22
Arduino rocks
|
 |
« Reply #20 on: January 30, 2010, 09:02:38 am » |
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. #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
Offline
Brattain Member
Karma: 336
Posts: 36476
Seattle, WA USA
|
 |
« Reply #21 on: January 30, 2010, 09:16:40 am » |
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: if(outdoorTemp >= someValue) instead of if(coldOutside == HIGH)
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 5
Arduino rocks
|
 |
« Reply #22 on: April 15, 2010, 03:40:35 pm » |
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
|
|
|
|
|
|
|
|