/*
* Halfluck Temperature Controller Webserver
* An open-source Temperature Controller for Arduino.
* v1.4 23/7/2012
* Hosted at http://www.halfluck.com/source/webserver/TempControllerWebServer.ino
* Described in http://www.halfluck.com/source/webserver/TempControllerWebServer.ino
*
* TempControllerWebServer.ino
*
* (cc) by Rob Hart
*
* http://www.halfluck.com
* http://creativecommons.org/license/cc-gpl
*targettemp
* Compiled & Tested in Arduino 1.0.1
* using OneWire Library v2.1 http://www.arduino.cc/playground/Learning/OneWire
* using Ethercard Library https://github.com/jcw/ethercard/
*
*/
#include <EtherCard.h>
#include <OneWire.h>
#include <EEPROM.h>
char TargetTemperarureTextbox[10]; // Data in text box
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = {
0x10,0x4a,0x7d,0x90,0xd3,0xa0 };
static byte myip[] = {
192,168,0,111 }; //used for static IP
byte Ethernet::buffer[1000]; // if you increase the size of the HTML
// code you may need to increase the buffer size
// (or it will stop working) //TODO
BufferFiller bfill;
const byte PinTemp = 4; // Dallas Ds1820 Temperature Sensors
const byte PinSSR1 = 5; // Pin for SSR 1
const byte PinSSR2 = 6; // Pin for SSR 2
byte sensor1[8] = {
0x28, 0x61, 0x24, 0xC5, 0x03, 0x00, 0x00, 0x51};
// User Defined Temperature Sensor Address 1
int currenttemp1 = 0; // curent temperature (1/16th degrees) sensor1
int lasttemp1 = 0; // previous temperature sensor 1
byte negativetemp1 = 0; // if negative temp display that
byte fractlessthan10 = 0; // if less than 10 then add a zero first
int SignBit, Whole, Fract, Tc_100;
byte TargetTemp = 0; // this is the placeholder for the target temperature
byte currenttemp1byte = 0;
OneWire ds(PinTemp);
byte Mode = 0; // 0 is Manual, 1 is Auto
byte SSR1on = 0; // 0 is Off, 1 is On
byte SSR2on = 0; // 0 is Off, 1 is On
void setup () {
if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0);
//Add alternative begin with 3rd parameter to specify CS pin to use.
// Only 8, 9 and 10 are usable. Default without 3rd parameter is pin 8.
ether.staticSetup(myip);
pinMode(PinTemp, INPUT); // sets the digital pin as input
pinMode(PinSSR1, OUTPUT); // sets the digital pin as input
pinMode(PinSSR2, OUTPUT); // sets the digital pin as input
TargetTemp = EEPROM.read(0);
Mode = EEPROM.read(1);
// //Stuff for DHCP
// Serial.begin(57600);
// Serial.println("\nDHCP]");
//
// if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
// Serial.println( "Failed to access Ethernet controller");
//
// Serial.println("Setting up DHCP");
// if (!ether.dhcpSetup())
// Serial.println( "DHCP failed");
//
// ether.printIp("My IP: ", ether.myip);
// ether.printIp("Netmask: ", ether.mymask);
// ether.printIp("GW IP: ", ether.gwip);
// ether.printIp("DNS IP: ", ether.dnsip);
}
int tempread(byte sensoraddr[])
// error codes:
// -1 no sensors found
// -2 invalid CRC
// -3 not a DS1820
{
byte i;
byte present = 0;
byte data[12];
byte addr[8];
//int HighByte, LowByte, TReading, SignBit, Tc_100, Tf_100, Whole, Fract;
int Temp;
if ( !ds.search(addr)) {
ds.reset_search();
return -1;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
return -2;
}
if ( addr[0] != 0x28) {
return -3;
}
for ( i = 0; i < 8; i++) {
addr[i]=sensoraddr[i];
}
ds.reset(); // pulse the pins and wait for a response to reset the DS1820
ds.select(addr); // 0x55 (MATCH_ROM) followed by the address of the 1820 to talk to.
// ds.write(0x44,1); // start conversion, with parasite power on at the end
ds.write(0x44,0); //PARASITE POWER OFF
//delay(800);
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
Temp=(data[1]<<8)+data[0]; //take the two bytes response holding temperature
SignBit = Temp & 0x8000; // test most sig bit
if (SignBit) // negative
{
Temp = (Temp ^ 0xffff) + 1; // 2's comp
}
return Temp;
}
const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n";
const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";
const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>401 Unauthorized</h1>";
static word homePage() {
// bfill = ether.tcpOffset();
//$D = word data type
//$L = long data type
//$S = c string
//$F = progmem string
//$E = byte from the eeprom.
//Uptime Stuff
long days=0;
long hours=0;
long mins=0;
long secs=0;
secs = millis()/1000; //convect milliseconds to seconds
mins=secs/60; //convert seconds to minutes
hours=mins/60; //convert minutes to hours
days=hours/24; //convert hours to days
secs=secs-(mins*60); //subtract the coverted seconds to minutes in order to display 59 secs max
mins=mins-(hours*60); //subtract the coverted minutes to hours in order to display 59 minutes max
hours=hours-(days*24); //subtract the coverted hours to days in order to display 23 hours max
char* SSR1stat;
if ( digitalRead(PinSSR1) == HIGH ) {
SSR1stat = "On" ;
}
else {
SSR1stat = "Off";
}
char* SSR2stat;
if ( digitalRead(PinSSR2) == HIGH ) {
SSR2stat = "On" ;
}
else {
SSR2stat = "Off";
}
if (Mode == 0) //If Manual
{
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
"\r\n"
"<!DOCTYPE html>"
"<html><head>"
"<meta http-equiv='refresh' content='5'/>"
"<title>Adria Webserver</title>"
"<body bgcolor=""#99CCFF"">"
"<center>"
"<hr />"
"<br />"
"<font size=""5"">"
"Martin`s campingvogn <b>"
"<br />"
"Temperatur i vognen: <b>"
"<br />"
"<br />"
"<font size=""7"">"
"$D.$D °C</font></b>"
"<br />"
"<br />"
"<font size=""5"">"
"Varme er <b>$S</b> "
"<form><input type=""button"" value=""Skift"" "
"onClick=""document.location.href='/?SSR1toggle';""></form>"
"<br />"
"Gulvvarme er <b>$S</b> "
"<form><input type=""button"" value=""Skift"" "
"onClick=""document.location.href='/?SSR2toggle';""></form>"
"<br />"
"<br />"
"<form><input type=""button"" value=""Skift til "
"Auto"" onClick=""document.location.href='/?modeauto';""></form>"
"<hr />"
"Uptime: $L Days $L Hours $L Mins $L Secs"
"</center></body></html>"),
Whole , Fract , SSR1stat, SSR2stat, days, hours, mins, secs );
return bfill.position();
}
else //its AutoMode display Target Temp
// and Textbox for adjusting Temperature
{
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
"\r\n"
"<!DOCTYPE html>"
"<html><head>"
"<meta http-equiv='refresh' content='5'/>"
"<title>Adria Webserver</title>"
"<body bgcolor=""#99CCFF"">"
"<center>"
"<hr />"
"<br />"
"<font size=""5"">"
"Martin`s campingvogn <b>"
"<br />"
"Temperatur i vognen: <b>"
"<br />"
"<br />"
"<font size=""7"">"
"$D.$D °C</font></b>"
"<br />"
"<br />"
"<font size=""5"">"
"Auto Temperatur: <b>"
"$D.0 °C</b>"
"<br />"
"<br />"
"Varme er <b>$S</b> "
"<br />"
"<br />"
// "Pump is <b>$S</b> "
// "<br />"
// "<form>"
// "<select id=""setit"" name=""select"">"
// "<option value=""/?modemanual"">Switch to Manual</option>"
// "</select>"
// "<input type=""button"" value=""Ok"" "
// "onclick=""window.open((setit.options[setit.selectedIndex].value)"
// ",'_self')""></form>"
"Skift Auto Temp"
"<form><input type=text name=targettemp size=10>"
"<input type=submit value=Ok> </form>"
"<br />"
"<form><input type=""button"" value=""Skift til Manuel"" "
"onClick=""document.location.href='/?modemanual';""></form>"
"<hr />"
"Uptime: $L Days $L Hours $L Mins $L Secs"
"</center></body></html>"),
//Whole , Fract , TargetTemp, SSR1stat, SSR2stat, days, hours, mins, secs );
Whole , Fract , TargetTemp, SSR1stat, days, hours, mins, secs );
return bfill.position();
}
}
void loop () {
if (Mode == 1) //if auto mode
{
if ((currenttemp1byte<TargetTemp) &&
(currenttemp1byte>0)) // below low range
{
digitalWrite(PinSSR1, HIGH); // turn SSR1oning on
SSR1on = 1;
}
else if ((currenttemp1byte>=TargetTemp) &&
(currenttemp1byte>0)) //ideal range
{
digitalWrite(PinSSR1, LOW); // turn SSR1oning off
SSR1on = 0;
}
}
currenttemp1 = tempread(sensor1);
if (currenttemp1>0)
{
currenttemp1byte = (byte)(currenttemp1>>4);
}
else {
currenttemp1byte = 0;
}
if ((currenttemp1 != lasttemp1) && (currenttemp1>0))
{
Tc_100 = (6 * currenttemp1) + currenttemp1 / 4;
// multiply by (100 * 0.0625) or 6.25
// Tf_100 = ((1.8)*Tc_100) + (32*100); // Farenheit
Whole = Tc_100 / 100; // separate off whole and fractional portions
Fract = Tc_100 % 100;
if (SignBit) // If its negative //TODO
{
negativetemp1 = 1;
}
else
{
negativetemp1 = 0;
}
if (Fract < 10) //TODO
{
fractlessthan10 = 1;
}
else
{
fractlessthan10 = 0;
}
lasttemp1 = currenttemp1;
}
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if (pos) {
// write to LED digital output
delay(1); // necessary for my system //TODO
bfill = ether.tcpOffset();
char *data = (char *) Ethernet::buffer + pos;
if (strncmp("GET /", data, 5) != 0) {
// Unsupported HTTP request
// 304 or 501 response would be more appropriate
bfill.emit_p(http_Unauthorized);
}
else {
data += 5;
if (data[0] == ' ') {
// Return home page
homePage();
}
else if (strncmp( "?modeauto" , data, 9 ) == 0)
{
Mode = 1;
EEPROM.write(1, Mode);
digitalWrite(PinSSR1, LOW); // turn SSR1 off
SSR1on = 0; // switch SSR off
digitalWrite(PinSSR2, LOW); // turn SSR1 off
bfill.emit_p(http_Found);
}
else if (strncmp( "?modemanual" , data, 11 ) == 0)
{
Mode = 0;
SSR1on = 0; // switch SSR off
EEPROM.write(1, Mode);
digitalWrite(PinSSR1, LOW); // turn SSR1 off
digitalWrite(PinSSR2, LOW); // turn SSR1 off
bfill.emit_p(http_Found);
}
else if (strncmp( "?SSR1toggle" , data, 11 ) == 0)
{
if (SSR1on == 0)
{
SSR1on = 1; // switch SSR off
digitalWrite(PinSSR1, HIGH); // turn SSR1 off
}
else
{
SSR1on = 0; // switch SSR off
digitalWrite(PinSSR1, LOW); // turn SSR1 off
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?SSR2toggle" , data, 11 ) == 0)
{
if (SSR2on == 0)
{
SSR2on = 1; // switch SSR off
digitalWrite(PinSSR2, HIGH); // turn SSR1 off
}
else
{
SSR2on = 0; // switch SSR off
digitalWrite(PinSSR2, LOW); // turn SSR1 off
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?targettemp=" , data , 12 ) == 0)
{
if (ether.findKeyVal(data+1, TargetTemperarureTextbox,
sizeof TargetTemperarureTextbox , "targettemp") > 0)
{
byte value = atoi(TargetTemperarureTextbox);
// command to convert a string to number
if ((value >=0) && (value <=25)) // temp within 0-25 range
{
TargetTemp = value;
EEPROM.write(0, value);
}
}
bfill.emit_p(http_Found);
}
ether.httpServerReply(bfill.position());
}
}
} //loop()