Go Down

Topic: hot water system datalogger (Read 3715 times) previous topic - next topic

kevinsa5

Hey guys, I just thought I'd post my largest sketch yet (11714 bytes :D) that I've written that both compiles and does what I want. you know, probably. I haven't tested it in the field yet, but initial reports come back good! I put it into all different tabs, so I guess I'll paste one below the other? ah well.

Also, I'll let you know that I commented the code for the first time especially for this, I wouldn't have otherwise. :)
As I commented it, I noticed some stuff that could be better (bottom/top factoring etc) so I changed it, so no promises that it'll work.

Anyway, the purpose of this is to monitor my house's hot water system. We have some solar collectors up on the roof that heat our water with a backup regular heating element if it's cloudy for a couple days or something. I (my dad) thought it would be fun to monitor the system, see when stuff is on & off, see what temperature it is, and it would be so easy to do w/ arduino right? anyway, a year and a bit later, here's the finished code, fingers crossed. What it does is connects to a flash drive with a VDIP1 module and logs the times when two heat pumps and a heating element turn on and off and also logs the temperatures of two water pipes every five minutes. The heat pumps are both at 24VAC so I threw a diode in line with each (I might make a full wave rectifier if I feel like being productive) and voltage dividers to step it down. I'll probably end up changing it from a digitalRead to an analogRead because it'll pick up the AC better. The heating element is 240VAC so I just stuck a cell charger in there that brings it down to 5v and I'm reading that. I'm using two LM35s for the temperatures with the same setup as I wrote in a playground page a while back... http://www.arduino.cc/playground/Main/LM35HigherResolution , basically just using internal analog reference.

I found that working with Strings with the VDIP1 generally saved my some headaches, so that's why they're all over the place in the code. I dunno if they actually make it better, but it gave me better results. Also, let me say something about the VDIP1. I HATE IT. IT'S THE WORST. I picked up electronics about a year and a half ago and the VDIP1 has definitely been the most infuriating part of it. If you're going to go with datalogging, I'd go with an SD card or something, just because the VDIP1 is so darn picky in my experience.

Code: [Select]

#include <Time.h>
#include <NewSoftSerial.h>

NewSoftSerial mySerial(3, 4); // serial w/ the VDIP1 module

boolean state = LOW; //State of heating element
boolean state1 = LOW; // state of heat pump 1
boolean state2 = LOW; // state of heat pump 2
boolean stateElem = LOW; //pretty sure this one is the previous state of the heating element
int previous = 0; // previous logtime, it goes every five minutes for the temperatures
boolean LED_STATE = LOW; //not used anymore I don't think but left in anyway

int pPin1 = 11; //heat pump 1
int pPin2 = 12; // heat pump 2
int tPin1 = 0; // temp 1
int tPin2 = 1; // temp 2
int elementPin = 10; //you can guess this one

//int RTSpin = 9;
// RTS may be implemented later when it screws up for lack of handshaking :)

void setup()
{
 pinMode(pPin1, INPUT); //you can guess these
 pinMode(pPin2, INPUT);
 pinMode(elementPin, INPUT);  
 pinMode(13, OUTPUT); //LED pin if I want it
 
 Serial.begin(9600); //for debugging/monitoring
 
 mySerial.begin(9600); //connection to the VDIP1 module
 mySerial.print("IPA"); //tell it I want to work in ASCII
 mySerial.print(13, BYTE);
 Serial.println("Setupdone"); //the standard feedback line
 analogReference(INTERNAL); // I use the internal for higher resolution w/ the LM35s, see my playground page
}

void loop()
{
 int incoming = 0;
 if (Serial.available()) {incoming = Serial.read();} // receive incoming data from the computer
 
 if (incoming =='1')
 {
   mySerial.print("DIR"); //tell the VDIP1 to spit out everything on the usb disk
   mySerial.print(13, BYTE);
   incoming = '0';
 }  

if(incoming == '2') // print out all the states of the pins
{

 Serial.print(digitalRead(pPin1));
 Serial.print(",");
 Serial.print(digitalRead(pPin2));
 Serial.print(",");
 Serial.print(digitalRead(elementPin));
 Serial.print(",");
 Serial.print(analogRead(tPin1));
 Serial.print(",");
 Serial.print(analogRead(tPin2));
 Serial.print("   ");
 Serial.println(getTime());
 incoming = '0';
 
}


 while (mySerial.available()) { // spits back responses from VDIP1 to computer.
   char letter = (char)mySerial.read();
   if(letter == '>')
   Serial.println(letter);
   else
   Serial.print(letter);
 }
 
 temps();
 element();
 heatPumps();
 
//  digitalWrite(13, LED_STATE);

}

String getTemp(int pin)
{
 int reading;
 for(int i = 0;i<10;i++) // average the readings to get rid of noise
 {
   reading += analogRead(pin);
 }
 reading = (float)reading / 93.1;
 String temp = String(reading, DEC);
 return temp;
}

String getTime() // Strings FTW
{
 String time = String(month());
 time = time.concat("/");
 time = time.concat(day());
 time = time.concat("/");
 time = time.concat(year());
 time = time.concat(" ");
 time = time.concat(hour());
 time = time.concat(":");
 if(minute() < 10)
 {
   time = time.concat("0"); // for format like 9:05 instead of 9:5
 }
 time = time.concat(minute());
 return time;
}

void timeStamp(String time) // used for timestamping data sent to VDIP1
{
 mySerial.print("WRF ");
 mySerial.print(time.length() + 2);
 mySerial.print(13, BYTE);
 mySerial.print(" ");
 mySerial.print(time);
 mySerial.print(13, BYTE);
}
boolean readAC(int pin) // I have to see if a half-rectified AC wave is present
{
 for(int i = 0;i< 20;i++)
 {
   if(digitalRead(pin) == HIGH)
   {
     return HIGH;
   }
   else
   {
     delay(1);
   }
 }
 return LOW;
}

String dToS(double x) // changing a double to a string
{
 int y = ((int)x)*10000; // I probably could have used % here but I didn't know it then
 int z = (10000*x) - y;
 String foo = String(y/10000);
 foo = foo.concat(".");
 foo = foo.concat(z);
 return foo;
}

boolean readDigital(int pin) // make sure it's not noise
{
 boolean vals[10]; // I did this because it would register when I touched the arduino for some reason.
 for(int i = 0; i < 10; i++)
 {
   vals[i] = digitalRead(pin);
   delay(100);
 }
 for(int i = 0;i < 10; i++)
 {
   if(vals[i] == LOW)
   {
     return LOW;
   }
 }
 return HIGH; // only return high if all of the readings over a second are high
}

void element()
{
 state = readDigital(elementPin);
 if(state != stateElem) // if the state changed from before
 {
   // LED_STATE = !LED_STATE;
   mySerial.print("OPW ELEMENT.TXT"); //logging data
   mySerial.print(13, BYTE);
   if(state == HIGH)
   {
     mySerial.print("WRF 5");
     mySerial.print("On at");
     timeStamp(getTime());
     stateElem = true;
    }
 
   if(state == LOW)
   {
     mySerial.print("WRF 6");
     mySerial.print("Off at");
     timeStamp(getTime());
     stateElem = false;
    }
    mySerial.print("CLF ELEMENT.TXT");
    mySerial.print(13, BYTE);
    Serial.print("element!   ");
    Serial.println(minute());
 }
}


void heatPumps()
{
 
 state = readAC(pPin1);
 
 if(state != state1)
 {
//   LED_STATE = !LED_STATE;
 mySerial.print("OPW HEATPUMP1.TXT");
 mySerial.print(13, BYTE);
 
 if(state == HIGH)
 {
   mySerial.print("WRF 5");
   mySerial.print("On at");
   timeStamp(getTime());
   state1 = true;
 }

 if(state == LOW)
 {
   mySerial.print("WRF 6");
   mySerial.print("Off at");
   timeStamp(getTime());
   state1 = false;
  }
 
  mySerial.print("CLF HEATPUMP1.TXT");
  mySerial.print(13, BYTE);
 
  Serial.print("heatpumps!   ");
  Serial.println(minute());

 }
 
 state = readAC(pPin2);

 if(state != state2)
 {
 //  LED_STATE = !LED_STATE;
   mySerial.print("OPW HEATPUMP2.TXT");
   mySerial.print(13, BYTE);
   
   if(state == HIGH)
   {
     mySerial.print("WRF 5");
     mySerial.print("On at");
     timeStamp(getTime());
     state2 = true;
   }
   if(state == LOW)
   {
    mySerial.print("WRF 6");
    mySerial.print("Off at");
    timeStamp(getTime());
    state2 = false;
    }
    mySerial.print("CLF HEATPUMP2.TXT");
    mySerial.print(13, BYTE);
   
    Serial.print("heatpumps!   ");
    Serial.println(minute());
 }
}

void temps()
{
 if(minute() - previous >=5)
 {
  String temp1= dToS(analogRead(tPin1) / 9.31); // convert voltage to temperature
  String temp2= dToS(analogRead(tPin2) / 9.31); // see my playground page

  mySerial.print("OPW TEMPS.TXT");
  mySerial.print(13, BYTE);
  mySerial.print("WRF ");
  mySerial.print(temp1.length()+temp2.length()+1);
  mySerial.print(13, BYTE);
  mySerial.print(temp1);
  mySerial.print(",");
  mySerial.print(temp2);
  previous = minute();
  timeStamp(getTime());
  mySerial.print("CLF TEMPS.TXT");
  mySerial.print(13, BYTE);
  Serial.print("temps!   ");
  Serial.println(String(minute()));
 }
}



phew! Comments, questions, feedback, etc? After all this work, I'd like some sort of validation from people who know more than zip about programming, from my fam it's just "oh that's nice all those little brackets and stuff"

Go Up