Instructables

Need help programming an Adruino to function as a solar differential controller

Hi I need help to write a program for an Arduino to allow it to function as a Solar Differential Controller (SDC). An SDC simultaneously reads the temperature of two different elements,1) the water inside the thermal storage tank and 2) the inside of the solar collector. When the sun rises in the morning it begins to heat up the inside of the collector. When the SDC senses that the collector is a few degrees warmer than the storage tank it signals a circulation pump to turn on to circulate water from the tank, through the collectors and back to the tank. When the sun starts to set in the evening and the collector cools to within a few degrees of the storage tank, it signals the pump to shut off.

So basicly I need the Arduino mega 2560 to read the temperature from two DS18B20 digital temperature probes. When one of the probes shows a reading 5oC higher than the other, the Arduino changes an output to high. When the higher probe's reading drops to within 5oC of the lower one, the Arduino changes the output back to low.

I don't even know where to start really, this programming is way over my head. Any help would be appreciated. This program is for a large project I'm working on for this site and any help you give me will be credited to you. Thanks.

maewert1 year ago
The program shouldn't be too difficult.  Any standard Arduino should be up for the task, you should not require an ArduinoMega as an Arduino UNO or lesser will be more than adequate.  The DS18B20s are 'one wire' devices which you should connect to two separate pins, say D10 and D11.  The Arduino one wire library can return the 9 byte words from the devices.  The first two bytes are the temperatre readings in degrees C. 

The output from the Arduino which turns on the pump will of course have to take the 5 volt signals from the Arduino and control the pump.  A single bit from the arduino should suffice, you just need to build the control electronics to drive whatever type of pump you are using.

You might also want to include a display so the arduino reads out the temperatures so you can monitor it and tell if it is working.

The Arduino code has two main parts, the Setup and the Loop.  Within the Setup you would initialize all of your variables.  In the loop portion you would read the temperature from the tank, read the temperature from the collector, adn turn on the pump when the temp difference is over your threshold.  Maybe you also want to stop the pump if the temperature of the tank is 'too high'.  I believe the DS18B20's go up to 85 degrees C and water from the collector can be shoot past this value!  I've heard that running the system without water circulating can even unsweat the pipes if you are not careful.  A complete system might want to include an alarm if the temperatures get too high, etc. 

If you provide more system details I am sure I or others can help you write this bit of code.

Best Wishes
EcoMotive (author)  maewert1 year ago
Thanks for your reply. I already have the Arduino mega so thats why I'd like to use that. The pump runs on 120VAC. If the Arduino gives me a 5v output I can take care of the rest getting the pump to come on.
An LCD display and alarm would be great but waaaay out of my league right now.
What other system details do you think I should provide?
Again, thanks for your answer.
no problem.  Lets start small and work your way up.
Connect the temperature sensor as shown in the following tutorial:  http://bildr.org/2011/07/ds18b20-arduino/

It includes code to start you out.  Get the code to work first then we can add the second temperature sensor.  then we'll add the output relay and you'll be done!

Let me know when the tutorial is working and we'll get you going on the next step!

Mark
EcoMotive (author)  maewert1 year ago
Hey, I can't get the code to work. When I try to complie it and send it to the Arduino almost a dozen error messages come up. I don't know what any of them mean.
I did get the temperature probe working before using the code from this page http://sheepdogguides.com/arduino/ar3ne1tt.htm
It says that you can add more sensors by adding more define, read and report answer lines but I couldnt figure out how to. Even if I could add another sensor, I dont know how to get it to change an output or display the temp on an LCD. WHat do you think?
Thanks for your help so far.
You probably had an error with the library. We can use the code that worked though (even though it uses global variables which is poor programming, but, hey, it works.) I modified the example to compare the two values and serial print ON or OFF:

Give this a try. If it works then we can set an output pin instead of the serial prints and you can use it to drive a relay.


/*ReadDS18B20two
ver: 18 Jly 2010
Started end of term eve WG/TA/LE/EW/JGB

Reading two DS18B20s

See...

http://sheepdogguides.com/arduino/ar3ne1tt2.htm

... for explanation of this code.

Code adapted from code from nuelectronics.com demo*/

#define tture1 14//no ; here
#define tture2 15//no ; here

/*Forward declarations. Only the last two need concern the user
Remmed out, as they seem unnecessary
void OneWireReset(int Pin);//Called by readTture
void OneWireOutByte(int Pin, byte d);//Called by readTture
byte OneWireInByte(int Pin);//Called by readTture

void readTture(byte Pin);//Of use to users
void printTture();//Of use to users
*/

//Following globals used to communicate results back
//from readTture(Pin), and to send data to printTture...
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void setup() {
//For each tture sensor: Do a pinMode and a digitalWrite
pinMode(tture1, INPUT);
pinMode(tture2, INPUT);

digitalWrite(tture1, LOW);//Disable internal pull-up.
digitalWrite(tture2, LOW);

Serial.begin(9600);
delay(300);//Wait for newly restarted system to stabilize
Serial.print("Temperature measurement, two sensors:\n\n");
}

void loop(){
int t1, t2;

t1 = readTture(tture1);//N.B.: Values passed back in globals
//printTture();//N.B.: Takes values from globals. Also...
//no newline part of pritTture;
//Serial.print(" ");
delay(120);// Delay... must not be too short.
t2 = readTture(tture2);//Now read and report 2nd tture.
//printTture();
delay(200);// Delay... must not be too short.
//Serial.print("\n");//Start new line

if (t1 > t2 + 6)
{
Serial.println ("ON");
}
else
{
Serial.println ("OFF");
}
}


//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
// directly. Others are subordinate to those.
//These routine access the following global variables...
// int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
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(500);
pinMode(Pin, INPUT);
delayMicroseconds(500);
}//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

int 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); // perform temperature conversion, strong pullup for one sec

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;
return (Whole);
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//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);
};
//end printTture
EcoMotive (author)  maewert1 year ago
Dude you are a freakin godsend! I managed to get that code working with the serial monitor changing it's output. I managed to adjust the temperature difference needed to trigger the "on" signal so I'm glad I can tweak the thing when it's finally hooked up to the solar collector system.
As you can see from the picture below, I'm ready to get a 5v output into a useable 120vac signal using the equipment from my greenhouse. This is all a temporary setup until I get a new enclosure dedicated to the solar system. Thanks a million for your help so far.
DSCN2074.JPG
Any time I can help I'm happy  :-)
Looks like you have a bank of 16 blue relays plus others, plus some other things I could not identify.  How are you driving the relays?  As others have noted inductive loads like relay coils can produce a back EMF when you turn them on/off so you need to  have a diode across the coil to absorb the  energy so it doesn't hurt the arduino.  You probably have it covered but just wanted to mention it :-)

You probably can add an alarm easily if the temperatures are too
high, etc.  I could also assist if you wanted an LCD display of the temps, etc.  Just let me know.

Best Wishes,

Mark.
EcoMotive (author)  maewert1 year ago
Alright, the blue relay board accepts the 5v from the arduino directly through a bank of male pins on the far right side of the board. Hopefully you can see it in the pic. There are also connections there for an external 12v supply (black and red wires above the male pins). All you have to do is apply 5v to the appropriate pin to switch the relay so I'm assuming that the 12v relay coil is not directly driven by the arduino and a diode is not necessary (or already built into the board).
The blue relays on the board are supposed to be rated 10A at 250VAC but they're not CSA certified so I won't use them to switch any more than 24v. Instead the blue relays are used to switch the 12v coil of the larger relays on the bottom right of the picture. Those larger relays ARE CSA certified for 10A at 120VAC. There is also a motor contactor that is rated for 1 HP in single phase. That will be used for the highly inductive pump motor in the greenhouse that the general purpose relays cant handle.

So thanks again for your help and please help me get the serial print turned to a 5v output. An LCD screen would be wonderful but one necessity I have it to be able to run the system without a computer hooked up.
DSCN2077.JPG


Try this:

/*ReadDS18B20two
ver: 18 Jly 2010
Started end of term eve WG/TA/LE/EW/JGB

Reading two DS18B20s

See...

http://sheepdogguides.com/arduino/ar3ne1tt2.htm

... for explanation of this code.

Code adapted from code from nuelectronics.com demo*/

#define tture1 14//no ; here
#define tture2 15//no ; here

/*Forward declarations. Only the last two need concern the user
Remmed out, as they seem unnecessary
void OneWireReset(int Pin);//Called by readTture
void OneWireOutByte(int Pin, byte d);//Called by readTture
byte OneWireInByte(int Pin);//Called by readTture

void readTture(byte Pin);//Of use to users
void printTture();//Of use to users
*/

//Following globals used to communicate results back
//from readTture(Pin), and to send data to printTture...
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

int Relay = 10;  // Relay on Pin 10

void setup() {
  //For each tture sensor: Do a pinMode and a digitalWrite
  pinMode(tture1, INPUT);
  pinMode(tture2, INPUT);
  pinMode(Relay, OUTPUT);

  digitalWrite(tture1, LOW);//Disable internal pull-up.
  digitalWrite(tture2, LOW);

  Serial.begin(9600);
  delay(300);//Wait for newly restarted system to stabilize
  Serial.print("Temperature measurement, two sensors:\n\n");
}

void loop(){
  int t1, t2;

  t1 = readTture(tture1);//N.B.: Values passed back in globals
  delay(120);// Delay... must not be too short.
  t2 = readTture(tture2);//Now read and report 2nd tture.
  delay(200);// Delay... must not be too short.

  if (t1 > t2 + 6)
  {
    Serial.println ("ON");
    digitalWrite(Relay,HIGH);
  }
  else
  {
    Serial.println ("OFF");
    digitalWrite(Relay,LOW);
  }
}


//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
// directly. Others are subordinate to those.
//These routine access the following global variables...
// int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
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(500);
pinMode(Pin, INPUT);
delayMicroseconds(500);
}//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

int 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); // perform temperature conversion, strong pullup for one sec

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;
return (Whole);
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//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);
};
//end printTture
EcoMotive (author)  maewert1 year ago
ok I got that working, the relays are switching as necessary. The only thing it that the relays cycle on and off like mad for a few seconds when the "collector temperature" gets higher than the "tank temperature" I suppose this can be fixed by setting the thing to only take a reading every three seconds or so.
The program works without the computer connected which is good, but the serial monitor glitches everything out and a total cold reset of the arduino is required. When I open the serial monitor with the relays connected to the arduino, it works fine until an "on" signal is made. All of a sudden the computer can't find the Arduino on COM3 and everything goes haywire.
So is it easy or hard to get the arduino to display the temps on and LCD? The one I have is a 2004 and I'm pretty sure it's serial since it only has 4 pins; SDA, SCL, GND, VCC. Thanks again for your help I really appreciate it.
OK, to get rid of the relay cycling lets add a little hysteresis of maybe 2 degrees:

/*ReadDS18B20two
ver: 18 Jly 2010
Started end of term eve WG/TA/LE/EW/JGB

Reading two DS18B20s

See...

http://sheepdogguides.com/arduino/ar3ne1tt2.htm

... for explanation of this code.

Code adapted from code from nuelectronics.com demo*/

#define tture1 14//no ; here
#define tture2 15//no ; here

/*Forward declarations. Only the last two need concern the user
Remmed out, as they seem unnecessary
void OneWireReset(int Pin);//Called by readTture
void OneWireOutByte(int Pin, byte d);//Called by readTture
byte OneWireInByte(int Pin);//Called by readTture

void readTture(byte Pin);//Of use to users
void printTture();//Of use to users
*/

//Following globals used to communicate results back
//from readTture(Pin), and to send data to printTture...
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

int Relay = 10;  // Relay on Pin 10
int hysteresis = 2; // a 2 degree hysteresis
boolean prior_state;
int switch_point = 6;

void setup() {
  //For each tture sensor: Do a pinMode and a digitalWrite
  pinMode(tture1, INPUT);
  pinMode(tture2, INPUT);
  pinMode(Relay, OUTPUT);

  prior_state = false;  // lets start with relay off
  digitalWrite(Relay,LOW);

  digitalWrite(tture1, LOW);//Disable internal pull-up.
  digitalWrite(tture2, LOW);

  Serial.begin(9600);
  delay(300);//Wait for newly restarted system to stabilize
  Serial.print("Temperature measurement, two sensors:\n\n");
}

void loop(){
  int t1, t2;

  t1 = readTture(tture1);//N.B.: Values passed back in globals
  delay(120);// Delay... must not be too short.
  t2 = readTture(tture2);//Now read and report 2nd tture.
  delay(200);// Delay... must not be too short.

  if  ((prior_state == false) && (t1 > t2 + switch_point + hysteresis))
  {
    Serial.println ("ON");
    digitalWrite(Relay,HIGH);
    prior_state = true;
  }
  else
  {
    if  ((prior_state == true) && (t1 <= t2 + switch_point - hysteresis))
    {   
      Serial.println ("OFF");
      digitalWrite(Relay,LOW);
      prior_state = false;
    }
    else
    {
//   Here we don't really need to do anything.
//  This is what we do if we check the sensors and don't change.
//   remove the /* and the */ if you want the serial prints
/*
      if (prior_state)
        Serial.println("Still on");
      else
        Serial.println("Still off");
*/
    }
  }
}


//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
// directly. Others are subordinate to those.
//These routine access the following global variables...
// int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
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(500);
pinMode(Pin, INPUT);
delayMicroseconds(500);
}//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

int 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); // perform temperature conversion, strong pullup for one sec

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;
return (Whole);
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//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);
};
//end printTture
EcoMotive (author)  maewert1 year ago
Alright the relays seem to be switching more smoothly now. We're almost there just need to get the temperature displayed on that QY-2004A. Thanks again.
Here is another program with your latest VALVE functions:
/*ReadDS18B20two
ver: 18 Jly 2010
Started end of term eve WG/TA/LE/EW/JGB

Reading two DS18B20s

See...

http://sheepdogguides.com/arduino/ar3ne1tt2.htm

... for explanation of this code.

Code adapted from code from nuelectronics.com demo*/

#define tture1 14//no ; here
#define tture2 15//no ; here

/*Forward declarations. Only the last two need concern the user
Remmed out, as they seem unnecessary
void OneWireReset(int Pin);//Called by readTture
void OneWireOutByte(int Pin, byte d);//Called by readTture
byte OneWireInByte(int Pin);//Called by readTture

void readTture(byte Pin);//Of use to users
void printTture();//Of use to users
*/

//Following globals used to communicate results back
//from readTture(Pin), and to send data to printTture...
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

int Relay = 10;  // Relay on Pin 10
int valve = 9;   // value pin set to pin 9
int hysteresis = 2; // a 2 degree hysteresis
boolean prior_state;
int switch_point = 6;

void setup() {
  //For each tture sensor: Do a pinMode and a digitalWrite
  pinMode(tture1, INPUT);
  pinMode(tture2, INPUT);
  pinMode(Relay, OUTPUT);
  pinMode(valve, OUTPUT);

  prior_state = false;  // lets start with relay and value off
  digitalWrite(Relay,LOW);
  digitalWrite(valve,LOW);

  digitalWrite(tture1, LOW);//Disable internal pull-up.
  digitalWrite(tture2, LOW);

  Serial.begin(9600);
  delay(300);//Wait for newly restarted system to stabilize
  Serial.print("Temperature measurement, two sensors:\n\n");
}

void loop(){
  int t1, t2;

  t1 = readTture(tture1);//N.B.: Values passed back in globals
  delay(120);// Delay... must not be too short.
  t2 = readTture(tture2);//Now read and report 2nd tture.
  delay(200);// Delay... must not be too short.

  if  ((prior_state == false) && (t1 > t2 + switch_point + hysteresis))
  {
    Serial.println ("ON");
    digitalWrite(Relay,HIGH);
    prior_state = true;
  }
  else
  {
    if  ((prior_state == true) && (t1 <= t2 + switch_point - hysteresis))
    {  
      Serial.println ("OFF");
      digitalWrite(Relay,LOW);
      delay(30000);             // wait 30 seconds
      digitalWrite(valve,HIGH); // Set valve pin to HIGH
      delay(5000);              // wait 5 seconds
      digitalWrite(valve,LOW);  // Set valve pin to LOW
      prior_state = false;
    }
    else
    {
//   Here we don't really need to do anything.
//  This is what we do if we check the sensors and don't change.
//   remove the /* and the */ if you want the serial prints
/*
      if (prior_state)
        Serial.println("Still on");
      else
        Serial.println("Still off");
*/
    }
  }
}


//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
// directly. Others are subordinate to those.
//These routine access the following global variables...
// int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
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(500);
  pinMode(Pin, INPUT);
  delayMicroseconds(500);
}//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

int 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); // perform temperature conversion, strong pullup for one sec
 
  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;
  return (Whole);
};//end readTture

void printTture(){//Uses values from global variables.
  //See global declarations.
  //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);
};
//end printTture
Glad to hear it.  You can always play with the parameters to fine tune it.

I'm not too sure about the LCD.  From what I've read there are various ones out there both with parallel interface and I2C. 

Here is some sample code for the I2C interface.  You will need the libraries and install them into the appropriate location according to the instructions.  Try it out and see if you can get the thing to respond.  If so then we can glue the two codes together.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2); //set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("b2cqshop");
    lcd.setCursor(0, 1);
    lcd.print("Voltage: ");
    lcd.setCursor(13, 1);
    lcd.print("V");
}
void loop()
{
    int val;
    float temp;
    val=analogRead(0);
    temp=val/4.092;
    val=(int)temp;//
    lcd.setCursor(9, 1);
    lcd.print(0x30+val/100,BYTE);
    lcd.print(0x30+(val%100)/10,BYTE);
    lcd.print('.');
    lcd.print(0x30+val%10,BYTE);
    delay(100);
}
EcoMotive (author)  maewert1 year ago
Alright so according to this code, where should I hook up the SDA and SCL pins? The other two are VCC and GND but I think I can figure out where they go. Thanks again.
I do not have these displays myself so I can only be marginally helpful, namely googling the device and giving you the link:
http://arduino-info.wikispaces.com/LCD-Blue-I2C.

I can help also later after you get the LCD to work to then glue the two program together if you need.

Best Wishes
Mark
EcoMotive (author)  maewert1 year ago
I've been working on getting that LCD working for a while now but all of the code I've found is useless. I used the sketch>import library>liquid crystal in my sketch. All it does is add one line of code to the top of the sketch and still nothing works.
Do you have an LCD that you have personally had sucess with? If so, could you give me the model number and a link to the sample code to that I can try to get that to work? Thanks again for all of your help.
Last we talked you were getting compiler errors.  Are you still getting those?  I have other LCDs but I'm afraid that unless you get the libraries installed correctly no LCD is going to work for you!
EcoMotive (author)  maewert1 year ago
Alright I figured out how to connect the LCD to the Arduino but when I try to upload the code it highlights the line

LiquidCrystal_I2C lcd(0x27,16,2); //set the LCD address to 0x27 for a 16 chars and 2 line display

and says

'LiquidCrystal_I2C' does not name a type
As of arduino 1.0 the 'BYTE' keyword is no longer supported. Please use Serial.write() instead.

I see that the code defines the LCD as a 1602 display when the one I`m using is a 2004. Does that make much of a difference. Thanks again for everything so far.

I think you have not selected SKETCH->Import Library -> LiquidCrystal
in your sketch.

Also you may want to use the second example on the http://arduino-info.wikispaces.com/LCD-Blue-I2C page which says it is for the 4x20 LCD instead of the 16x2 line LCD.

Best Wishes
EcoMotive (author)  maewert1 year ago
I also forgot to mention that I tried several other examples of I2C code I found on the internet including some from the place that I bought the LCD. Some other sources said the code was specificly for a 2004 display. All of them had the same error message.
Relay cycling should be fixed with the hysteresis code included in the other message.  The updated code does not blast data to the serial monitor (it does if you uncomment out the block in the code...).  The code update only serial prints on a relay change.

As for glitches, your relays may be drawing more power than the Arduino can supply.  You can add a capacitor across the power supply on the arduino... it might help.  You may need to put a 1K resistor on the output of the arduino which connects to the base of say an NPN transistor.  Lots of examples can be found here. 

The LCD shouldn't be too difficult to add :-).  I'd have to do a little investigation on the specific LCD to glue the std LCD library to your existing code.  Let me know if you have the LCD part number, etc.

Best Wishes.
EcoMotive (author)  maewert1 year ago
Thanks all I know about it is the part number is QY-2004A
Make sure you have a protection diode on your relay.

Have an indicator light on the outputs so you can tell if it triggers. Then you can test it quickly with your body heat.

You can get I2C or SPI LCD screens that have built in controllers, and arduino libraries so you only need to hook up the wires, and a lcd.begin() in your setup, and a lcd.print() in your loop.
iceng1 year ago
You do know that an Op-amp and two reverse biased diodes as temp
sensors can do this function as well ?
You may want to look into an LM35 temp sensor. I believe it's cheaper then the one your looking at. Another plus is there are a lot of Arduino projects and examples out there that use this sensor.

You already have the basic logic of the program so one you find a good example of how to wire up the sensor and read it then you can easily put together the final sketch for you project.
EcoMotive (author)  mpilchfamily1 year ago
Thanks but I already have the DS18B20's installed in the collector
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!