Pages: [1]   Go Down
Author Topic: hot water system datalogger  (Read 3553 times)
0 Members and 1 Guest are viewing this topic.
North Carolina, USA
Offline Offline
Full Member
***
Karma: 1
Posts: 137
:O Arduino!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys, I just thought I'd post my largest sketch yet (11714 bytes smiley-grin) 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. smiley
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:
#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"
Logged

Pages: [1]   Go Up
Jump to: