#include <Wire.h>
#include "RTClib.h"
#include <LCD4Bit_mod.h>
#include <stdio.h>
#include <stdlib.h>
#include <VirtualWire.h>
LCD4Bit_mod lcd = LCD4Bit_mod(2);
#define tture1 2 // data line of DS18B20 sensor connected to D2
#define tture2 3
#define tture3 10
RTC_DS1307 RTC;
char Sensor1CharMsg[4];
int Sensor1Data, pumpon, solon, ct, tt, bt, x, h, m, w, d, adc_key_in; //initiate intergers,
//for pump state, ct temp and bt temp, and data from sensors, pushbuttons, and timing constants.
//int tankmax = 95; // set maximin temp of top tank sensor
int diff = 12; // initial differential, temp above bt temp that pump turns on
int pumpoffdelay = 20;
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Ttemp, Fract, at;
const int pump = A1; //define pin for pump relay
const int pumpLED = A2; // define pin for LED output
const int sol = A3; // define pin for overtemp water release solenoid
const int tmax = 75; //max top tank temp set point for water solenoid to dump excess hot water
void setup() {
Wire.begin();
RTC.begin();
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
pinMode (pump, OUTPUT); //set pins to output pump relay
pinMode (pumpLED, OUTPUT); // sets LED pin to show pump is on
pinMode (sol, OUTPUT); // sets pin to output solenoid
lcd.init(); //initiate display and setup standing display elements
setupscreen();
//For each tture sensor: Do a pinMode and a digitalWrite
pinMode(tture1, INPUT);
pinMode(tture2, INPUT);
pinMode(tture3, INPUT);
digitalWrite(tture1, LOW);//Disable internal pull-up.
digitalWrite(tture2, LOW);
digitalWrite(tture3, LOW);
Serial.begin(9600);
delay(100);
// VirtualWire setup
vw_setup(1000); // Bits per sec
}
void loop(){
adc_key_in = analogRead(0);
int hundreds = (tt*100); //round off top tank temperature into a whole int and send it to first two digits of the four digit string
Sensor1Data = (hundreds+ct); //combine together to make four digit string
itoa(Sensor1Data,Sensor1CharMsg,10); // send four digit string containing both temps
w = w +1;
//Serial.println(adc_key_in); //was used for setting up buttons
if (adc_key_in < 150) { //if "UP" button is pressed, increment diff value up one.
diff = diff + 1;
delay(50);
}
if ((adc_key_in > 300) && (adc_key_in < 350)) { //if "DOWN" button is pressed, increment diff value down one.
if (diff > 3) { // diff value can not go below 3 (coz that'd be daft).
diff = diff - 1;
delay(50);
}
}
if (diff < 10) // this is just to keep the display neat if the diff is reduced back below 10
{
lcd.cursorTo(1, 15);
lcd.printIn(" ");
}
delay(200);
readTture(tture1);//N.B.: Values passed back in globals
Serial.print("ct");
ct = Whole; // ct is collector temperature, used for pump operation calculations
lcd.cursorTo(1, 2); //top line cursor position 3
printTture();//
Serial.print(" ");
delay(200);
lcd.cursorTo(1, 9);
Serial.print("tt");
readTture(tture2);//Now read and report 2nd tture.
tt = Whole; // store this temperature value as current top tank temp
printTture();
delay(200);//
Serial.print(" bt");//Start new line
lcd.cursorTo(2, 2); //line=2, x=0
readTture(tture3);//N.B.: Values passed back in globals
bt = Whole; //bt is bottom tank temperature used for pump operation calculations
printTture();//N.B.: Takes values from globals. Also...
Serial.print(" ");
if (pumpon == true) {
Serial.print("PUMP ON");
}
else {
Serial.print("PUMP OFF");
}
if (solon == true) {
Serial.print(" SOL ON");
}
else {
Serial.print(" SOL OFF");
}
Serial.print(" pump off delay is ");
Serial.print(pumpoffdelay);
Serial.print(" diff ");
Serial.print(diff);
//Serial.print(" "Ttemp);
Serial.print("\n");
// DEBUG radio
//Serial.print("Sensor1 Integer: ");
//Serial.print(Sensor1Data);
//Serial.print(" Sensor1 CharMsg: ");
//Serial.print(Sensor1CharMsg);
//Serial.println(" ");
//Serial.print(hundreds);
//Serial.print(" ");
delay(100);// Delay... must not be too short.
x = x +1;
if (x == 40) {
vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg)); //send string to radio
vw_wait_tx(); // Wait until the whole message is gone
//at = (tt+bt)/2; //calculates at average temperature average temp of the whole tank
// Ttemp = map(tt, 40, 80, 17, 10);
// diff = constrain(Ttemp, 10, 17); //these two steps change the diff value so it is wide for a cool tank, narrow for hot tank, thereby
// helping to maintain the tank around 65 degrees if the system gets too much sun
DateTime now = RTC.now();
Serial.print(now.hour(), DEC);
Serial.print(':');
if ( now.minute() < 10) {
Serial.print("0");
}
Serial.print(now.minute(), DEC);
Serial.print(':');
if (now.second() < 10) {
Serial.print("0");
}
Serial.print(now.second(), DEC);
h = (now.hour());
m = (now.minute());
Serial.println();
char timehour [33];
char timemin [33];
itoa (h,timehour,10);
itoa (m,timemin,10);
lcd.clear();
lcd.cursorTo(1, 5);
if (h < 10) {
lcd.printIn(" ");
}
lcd.printIn(timehour);
lcd.printIn(":");
if (m < 10) {
lcd.printIn("0");
}
lcd.printIn(timemin);
if (tt >= tmax) { //turns on heat dump solenoid if temp of tank is above tmax deg c
solon = true;
}
else {
solon = false;
}
delay(1000);
setupscreen();
x = 0;
}
if (ct > (tt + diff)) {
pumpon = true;
w = 0;
}
else {
if (w == pumpoffdelay) { // this ensures that if the pump turns on, it STAYS on for 20 cycles (seconds)
pumpon = false;
w = 0;
}
}
if (w == 101) {
w = 0;
}
if (pumpon == false) {
lcd.cursorTo(2, 13);
lcd.printIn("OFF");
digitalWrite (pump, LOW);
digitalWrite (pumpLED, LOW);
}
if (pumpon == true) {
lcd.cursorTo(2, 13);
lcd.printIn("ON ");
digitalWrite (pump, HIGH);
digitalWrite (pumpLED, HIGH);
}
if (solon == true) {
digitalWrite (sol, HIGH);
}
if (solon == false) {
digitalWrite (sol, LOW);
}
}
void OneWireReset(int Pin) // reset. Should improve to act as a presence pulse
{
digitalWrite(Pin, LOW);
pinMode(Pin, OUTPUT); // bring low for 500 us
delayMicroseconds(400);
pinMode(Pin, INPUT);
delayMicroseconds(400);
}//end OneWireReset
void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
byte n;
for(n=8; n!=0; n--)
{
if ((d & 0x01) == 1) // test least sig bit
{
digitalWrite(Pin, LOW);
pinMode(Pin, OUTPUT);
delayMicroseconds(5);
pinMode(Pin, INPUT);
delayMicroseconds(60);
}
else
{
digitalWrite(Pin, LOW);
pinMode(Pin, OUTPUT);
delayMicroseconds(60);
pinMode(Pin, INPUT);
}
d=d>>1; // now the next bit is in the least sig bit position.
}
}//end OneWireOutByte
byte OneWireInByte(int Pin) // read byte, least sig byte first
{
byte d, n, b;
for (n=0; n<8; n++)
{
digitalWrite(Pin, LOW);
pinMode(Pin, OUTPUT);
delayMicroseconds(5);
pinMode(Pin, INPUT);
delayMicroseconds(5);
b = digitalRead(Pin);
delayMicroseconds(50);
d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
}
return(d);
}//end OneWireInByte
void readTture(byte Pin){
//Pass WHICH pin you want to read in "Pin"
//Returns values in... (See global declarations)
OneWireReset(Pin);
OneWireOutByte(Pin, 0xcc);
OneWireOutByte(Pin, 0x44);
OneWireReset(Pin);
OneWireOutByte(Pin, 0xcc);
OneWireOutByte(Pin, 0xbe);
LowByte = OneWireInByte(Pin);
HighByte = OneWireInByte(Pin);
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
};//end readTture
void printTture(){
//N.B.: No new line inside printTture
if (SignBit) // If it's negative
{
Serial.print("-");
};
Serial.print(Whole);
Serial.print(".");
if (Fract < 10)
{
Serial.print("0");
};
Serial.print(Fract);
char temp [33];
char D [33];
char Dec [10];
itoa (Whole,temp,10);
itoa (diff,D,10);
d = floor (Fract/10);
itoa (d,Dec,10);
lcd.printIn(temp);
lcd.printIn(".");
lcd.printIn(Dec);
lcd.cursorTo(1, 14);
if (diff<10) {
lcd.printIn("0");
}
lcd.printIn(D);
}
void setupscreen(){
lcd.clear(); // clears display
lcd.printIn("CT c");
lcd.cursorTo(2, 0);
lcd.printIn("BT c");
lcd.cursorTo(1, 7);
lcd.printIn("TT c");
lcd.cursorTo(2, 8);
lcd.printIn("Pump");
};