Hi all
Sorry for the wait. I have only had an hour today, so I did not get to make it very nice or anything, but this should work. Tell me what you want in addition to this. If you do understand a little programming, then making changes to the switch/case thing in the loop function at the bottom should be quite easy. The pump relays could of course also be used to control fans for a water to air or air to air system. No de-icing implemented though. I would add an extra state (or case in the main switch/case part) that has a 5 minute delay and turns off everything except an external deicing heater during this period. Easily done if someone wants it.
This is what you need to do for temperature sensors:
For X number of sensors you need:
2 1N914 diodes
X LM35
X 18kOhm resistors
And some whire. Standard twisted pair or a coaxial cable or whatever you like. If the cable is very long ( > 10 meters ), I would add a small capacitor across the sensor and between output signal and ground all the way out by the sensor, as well as one between ground and signal at the arduino, just to remove any noise that is picked up along the way.
LM35 - Precision Centigrade Temperature Sensor
There are loads of differenty types of temperature sensors, but this one is very easy to use. Also, it gives you a quite accurate temperature range of -55C to +150C. Unfortunately the resolution is not very good, but it is more than good enough for our use.
For the output relays, you need to do like this:
http://www.arduino.cc/playground/upl...ing/relays.pdf
You can use any digital output except 1,2 and 13. I use 13 as a status diode thingy. You will see in the code comments. It is on for either 1, 2, 3 or 4 seconds in a 5 second period to indicate which state it is in.
If you wonder why A0 is connected to the two diodes, that is to get an input reference, as this temperature sensor gives an output signal that is 0V compared to ground at 0C, and 10mV up or down is one C. Analog input 0 will be reference voltage for the temperature sensors. You also get these with Farenheit I believe, in that case, some of the numbers must be changed. Get the Celcius, it is the logical way of measuring temperature anyway
The text at the start should explain most of it. I did leave out a few settings, and I don't utilize the indoor and outdoor temperature. I just left the readings in there so that you could add the probes and get a reading on the serial interface.
WARNING: NOT TESTED IN REAL LIFE!
I did do some simple testing here with a breadboard, but that is the complete extent of it.
Allright, here is the code:
Code:
/* First some legal mumbo jumbo:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
* This is a crude implementation for a state for controlling a
* ground souce heat pump machine.
*
* Written by Morgan Tørvolt <morgan@torvolt.com>.
*
* Analog inputs:
*
* T1 - indoor temperature, connects to A1
* T2 - outdoor temperature, connects to A2
* T3 - accumulator tank temperature, connects to A3
* T4 - ground loop temperature out, connects to A4
*
* Digital outputs:
*
* D3 - Relay for ground loop water pump
* D4 - Relay for warm side water loop to accumulator tank
* D5 - Relay for starting the heat pump
*
* Defined settings for temperatures and such. Set those below this comment section
*
* TEMP_TYPE : CELCIUS or FARENHEIT
* TEMP_START : T3 temperature for when the HP should start
* TEMP_STOP : T3 temperature for when the HP should stop
* TEMP_SHUTOFF : T4 temperature that is critically
* cold (freezing) and the HP should stop
* DELAY_BOOT : Time to wait when powering up in seconds
* DELAY_START : How long to run the water pumps before turning
* on the HP in seconds
*
* State 0: All off
* Wait 2 minutes before doing anything. Blink diode 1 second on and 1 second off
* Go to state 1 after two minutes
* State 1:
* If T3 < TEMP_START, go to state 2
* Blink diode on 2 sek, off 1 sek
* State 2:
* Turn on D3 and D4 (start water pumps), leave D5 off (HP)
* Wait for 2 minutes, then go to state 3
* State 3:
* If T4 > TEMP_SHUTOFF and T3 < TEMP_STOP, leave HP and water pumps running using D3, D4 and D5
* If T4 < TEMP_SHUTOFF or T3 > TEMP_STOP, jump to state 1
*
*/
enum { CELCIUS, FARENHEIT };
#define TEMP_TYPE CELCIUS
#define TEMP_START 40
#define TEMP_STOP 50
#define TEMP_SHUTOFF 1
#define DELAY_BOOT 120
#define DELAY_START 120
// General program code. Go further down
// if you don't want to know what is going on
// in the background
void blinkDiode( int on, int period )
{
if( ( ( millis() / 1000 ) % period ) < on )
{
digitalWrite( 13, HIGH );
}
else
{
digitalWrite( 13, LOW );
}
}
float getTemperature( int input )
{
int raw = static_cast< int >( analogRead( input ) ) - static_cast< int >( analogRead( A0 ) );
switch( TEMP_TYPE )
{
case CELCIUS:
// 1024 states across 5V gives 4.8828 mV per step. For celcius, 10 mV = 1C, so we multiply by 0.48828 to get celcius
return raw * 0.48828;
case FARENHEIT:
// °F = (°C × 9/5) + 32
return ( raw * 0.8789 ) + 32;
}
// This should never happen
return 0;
}
void setOutputs( int output_3, int output_4, int output_5 )
{
digitalWrite( 3, output_3 );
digitalWrite( 4, output_4 );
digitalWrite( 5, output_5 );
}
void setup()
{
// declare all digital pins as output pins:
for( int i = 2; i <= 13; ++i )
{
pinMode( i, OUTPUT );
digitalWrite( i, LOW );
}
Serial.begin( 9600 );
}
int state = 0; // We start in state 0
unsigned long waitUntil = 0;
bool diodeState = 0;
void loop()
{
delay( 50 ); // No need to rush things, and also make sure we don't overflow the serial interface
Serial.print( "State: " );
Serial.print( state );
Serial.print( " Temps: " );
Serial.print( getTemperature( A1 ) );
Serial.print( " " );
Serial.print( getTemperature( A2 ) );
Serial.print( " " );
Serial.print( getTemperature( A3 ) );
Serial.print( " " );
Serial.println( getTemperature( A4 ) );
switch( state )
{
case 0:
setOutputs( LOW, LOW, LOW );
if( millis() > DELAY_BOOT*1000 )
{
state = 1;
}
blinkDiode( 1, 5 ); // on 1 of 5 seconds
break;
case 1:
setOutputs( LOW, LOW, LOW );
if( getTemperature( A3 ) < TEMP_START )
{
waitUntil = millis() + DELAY_START * 1000;
state = 2;
}
blinkDiode( 2, 5 ); // on 2 of 5 seconds
break;
case 2:
setOutputs( HIGH, HIGH, LOW );
if( millis() > waitUntil && millis() - waitUntil < 20000 ) // Just making sure that things does not get screwed up when the unsigned long overflows.
{
state = 3;
}
blinkDiode( 3, 5 ); // on 3 of 5 seconds
break;
case 3:
setOutputs( HIGH, HIGH, HIGH );
if( getTemperature( A3 ) > TEMP_STOP || getTemperature( A4 ) < TEMP_SHUTOFF )
{
state = 1;
}
blinkDiode( 4, 5 ); // on 4 of 5 seconds
break;
}
}