Web thermostat with Arduino
The Sketch
The sketch contains 3 .PDE files. This is the main program.
Download the Thermostat sketch
/* Thermostat with arduino
created 2011
by Boris Landoni
This example code is in the public domain.
https://oe2.open-electronics.org
http://www.futurashop.it
*/
#include <SPI.h>
#include <Ethernet.h>
#include <avr/pgmspace.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#define SHARE_FEED_ID 5102 // this is your Pachube feed ID that you want to share to
#define REMOTE_FEED_ID 256 // this is the ID of the remote Pachube feed that you want to connect to
#define REMOTE_FEED_DATASTREAMS 4 // make sure that remoteSensor array is big enough to fit all the remote data streams
#define UPDATE_INTERVAL 20000 // if the connection is good wait 10 seconds before updating again - should not be less than 5
#define RESET_INTERVAL 10000 // if connection fails/resets wait 10 seconds before trying again - should not be less than 5
#define PACHUBE_API_KEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // fill in your API key
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
int puls1 = 5; // pulsante per il cambio di modalità di funzionamento
int puls2 = 2; // pulsante per il cambio di modalità di funzionamento
int in = 3; // ingresso del termostato
prog_char string_0[] PROGMEM = "<html><head><title>Boris's Project</title><META HTTP-EQUIV=\"Refresh\" CONTENT=\"3600\"></head>";
prog_char string_1[] PROGMEM = "<body><center><br><form> <input type=button value=\"Refresh \" onClick=\"window.location.reload()\"> </form><br><br><h2>Remote Control Thermostat ";
prog_char string_2[] PROGMEM = " C</h2><form method=GET><font size= 5>Boiler ";
prog_char string_3[] PROGMEM = "</font><br><font size= 3>Input Thermostat ";
prog_char string_4[] PROGMEM = "</font><br><table><td><input type=\"radio\" name=\"statourl\" value=\"1\" onClick=\"this.form.submit()\" ";
prog_char string_5[] PROGMEM = "></td><td>Sensor</td><td><input type=\"radio\" name=\"statourl\" value=\"2\" onClick=\"this.form.submit()\" ";
prog_char string_6[] PROGMEM = "></td><td>Manual</td><td><input type=\"radio\" name=\"statourl\" value=\"3\" onClick=\"this.form.submit()\" ";
prog_char string_7[] PROGMEM = "></td><td>Thermostat</td><br></table> </form><form method=GET>";
prog_char string_8[] PROGMEM = "<table><tr><td><input type=submit name=b11 value=\"Boiler ON\"></td><td><input type=submit name=b10 value=\"Boiler OFF\"></td><td>";
prog_char string_9[] PROGMEM = "</td></tr></table></form><form method=GET>Temperature: <input type=\"text\" size=\"2\" name=temp value=#* MAXLENGTH=2>";
prog_char string_10[] PROGMEM = "<input type=\"submit\" value=\"Set temperature\"><br></form>";
prog_char string_11[] PROGMEM = "<br><OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"";
prog_char string_12[] PROGMEM = "codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab";
prog_char string_13[] PROGMEM = "#version=6,0,0,0\" WIDTH=\"200\" HEIGHT=\"100\" id=\"gauge\"><PARAM NAME=\"movie\"";
prog_char string_14[] PROGMEM = "VALUE=\"http://apps.pachube.com/scaredycat/gauge.swf?xml_source=";
prog_char string_15[] PROGMEM = "http%3A//apps.pachube.com/scaredycat/getData.php";
prog_char string_16[] PROGMEM = "%3Fm%3D0%26f%3D5102%26s%3D0%26u%3D30%26l%3D0%26n%3D5%26t%3D";
prog_char string_17[] PROGMEM = "Temperatura%26w%3Dfalse%26c1%3D33FF33%26c2%3DEFE415%26c3%3DEF8B15%26c4%3DFF3333%26";
prog_char string_18[] PROGMEM = "in%3Dtrue\" /><PARAM NAME=\"quality\" VALUE=\"high\" /><param name=\"wmode\" value=\"transparent\">";
prog_char string_19[] PROGMEM = "<param name=\"allowScriptAccess\" value=\"sameDomain\" /><EMBED src=\"";
prog_char string_20[] PROGMEM = "http://apps.pachube.com/scaredycat/gauge.swf?xml_source=";
prog_char string_21[] PROGMEM = "http%3A//apps.pachube.com/scaredycat/getData.php";
prog_char string_22[] PROGMEM = "%3Fm%3D0%26f%3D5102%26s%3D0%26u%3D30%26l%3D0%26n%3D5%26t%3D";
prog_char string_23[] PROGMEM = "Temperatura%26w%3Dtrue%26c1%3D33FF33%26c2%3DEFE415%26c3%3DEF8B15%26c4%3DFF3333%26in%3Dtrue\"";
prog_char string_24[] PROGMEM = "quality=\"high\" wmode=\"transparent\" WIDTH=\"200\" HEIGHT=\"100\"";
prog_char string_25[] PROGMEM = "NAME=\"gauge\" allowScriptAccess=\"sameDomain\" swLiveConnect=\"true\"";
prog_char string_26[] PROGMEM = "TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"";
prog_char string_27[] PROGMEM = "http://www.macromedia.com/go/getflashplayer\"></EMBED></OBJECT>";
prog_char string_28[] PROGMEM = "<br><br><script type=\"text/javascript\" src=\"http://www.google.com/jsapi\">";
prog_char string_29[] PROGMEM = "</script><script language=\"JavaScript\" src=\"http://apps.pachube.com/google_viz/viz_multi.js\">";
prog_char string_30[] PROGMEM = "</script><script language=\"JavaScript\">createViz([5102,5102],[0,1],800,400,[\"ff0000\",\"0000ff\"],0,40);</script>";
prog_char string_31[] PROGMEM = "";
prog_char string_32[] PROGMEM = "";
prog_char string_33[] PROGMEM = "<font size= 2>Powered by Open-Electronics.org - Boris Landoni</font>"; //please don't remove :-)
prog_char string_34[] PROGMEM = "";
prog_char string_35[] PROGMEM = "";
prog_char string_36[] PROGMEM = "";
prog_char string_37[] PROGMEM = "";
prog_char string_38[] PROGMEM = "";
prog_char string_39[] PROGMEM = "";
prog_char string_40[] PROGMEM = "<br></center></body></html>";
prog_char string_41[] PROGMEM = "<font color=\"red\">ON</font>";
prog_char string_42[] PROGMEM = "OFF";
prog_char string_43[] PROGMEM = "checked";
prog_char string_44[] PROGMEM = "on";
prog_char string_45[] PROGMEM = "off";
PROGMEM const char *string_table[] = // change "string_table" name to suit
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5,
string_6,
string_7,
string_8,
string_9,
string_10,
string_11,
string_12,
string_13,
string_14,
string_15,
string_16,
string_17,
string_18,
string_19,
string_20,
string_21,
string_22,
string_23,
string_24,
string_25,
string_26,
string_27,
string_28,
string_29,
string_30,
string_31,
string_32,
string_33,
string_34,
string_35,
string_36,
string_37,
string_38,
string_39,
string_40,
string_41,
string_42,
string_43,
string_44,
string_45
};
char buffer[150]; // make sure this is large enough for the largest string it must hold
byte mac[] = { 0xDE, 0xAD, 0xBA, 0xAF, 0xFA, 0xAD };
byte ip[] = { 192, 168, 0, 172 };
byte gateway[] = { 192, 168, 0, 1 };
byte subnet[] = { 255, 255, 255, 0 };
byte remoteServer[] = { 173,203,98,29 }; // pachube.com
float remoteSensor[REMOTE_FEED_DATASTREAMS]; // we know that feed 256 has floats - this might need changing for feeds without floats
String inString = String(35);
Server server(80);
const int led = 6;
const int rele = 7;
String temp="";
String statourl="";
int tam=0;
int st1=42,st2=42,st3=42,st4=42,st5=43,st6=44;
//float tempCold;
unsigned long pubblica;
unsigned long lampeggio;
int stato=1; // se 0 controllo con sensore temperatura integrato, se 1 controllo manuale, se 2 controllo con termostato esterno
float tempC=0;
void setup()
{
pinMode(puls1, INPUT);
pinMode(puls2, INPUT);
pinMode(in, INPUT);
pinMode(led, OUTPUT);
pinMode(rele, OUTPUT);
Serial.begin(9600);
Ethernet.begin(mac, ip,gateway,subnet);
server.begin();
Serial.println("Serial READY");
Serial.println("Ethernet READY");
Serial.println("Server READY");
sensors.begin();
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(insideThermometer, 9);
Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
void printWebPage(Client *client)
{
int tmp=0;
int temperatura=0;
// send a standard http response header
client->println("HTTP/1.1 200 OK");
client->println("Content-Type: text/html");
client->println();
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy.
client->println( buffer );
//Serial.println( buffer );
for (int i = 1; i < 41; i++)
{
if (i==9)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); //butto tutto nell'array buffer
for (tmp=0 ; tmp < sizeof(buffer); tmp++)
{
if (buffer[tmp]=='#')
{
//Serial.println( "trovato ##### " );
temperatura = EEPROM.read(0);
Serial.print("dato in mem : ");
Serial.println(temperatura);
buffer[tmp] = char ((temperatura/10)+48);
tmp++;
buffer[tmp] = char ((temperatura % 10)+48);
}
}
}
else
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
}
client->println( buffer );
switch(i){
case 1:
itoa (tempC, buffer, 10); client->print( buffer ); Serial.print( buffer ); client->print( "," ); Serial.print( "," ); itoa ((int(tempC * 100) % 100), buffer, 10); client->print( buffer ); Serial.print( buffer ); break;
case 2:
if(digitalRead(rele)) st4=41;
else st4=42;
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st4]))); client->println( buffer ); Serial.println( buffer ); break;
case 3:
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st6]))); client->println( buffer ); Serial.println( buffer ); break;
case 4:
if (stato==1){
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st5]))); client->println( buffer ); Serial.println( buffer ); break;
}
case 5:
if (stato==2){
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st5]))); client->println( buffer ); Serial.println( buffer ); break;
}
case 6:
if (stato==3){
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[st5]))); client->println( buffer ); Serial.println( buffer ); break;
}
}
delay(30);
}
}
void verificaingressi()
{
int temperatura = EEPROM.read(0);
if (!digitalRead(puls1))
{
stato=stato+1;
if (stato>3)
{
stato=1;
}
EEPROM.write(1, stato);
digitalWrite(led,HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
lampeggio=4000; //così lampeggia poi subito
}
if (stato==1)
{
if (tempC<temperatura )
{
digitalWrite(rele,HIGH);
//st4=41;
}
else
{
if (tempC>(temperatura+1))
{
digitalWrite(rele,LOW);
//st4=42;
}
}
}
if (!digitalRead(in))
{
if (stato==3) digitalWrite(rele,HIGH);
st6=44;
}
else
{
if (stato==3) digitalWrite(rele,LOW);
st6=45;
}
}
void loop()
{
stato = EEPROM.read(1);
verificaingressi();
sensors.requestTemperatures(); // Send the command to get temperatures
tempC = sensors.getTempC(insideThermometer);
if (millis() < pubblica) pubblica = millis();
if ((millis() - pubblica) > UPDATE_INTERVAL){
pubblica = millis();
Serial.println("Pubblico");
Serial.print("Temp C : ");
Serial.println(tempC);
if (tempC<50 && tempC>-20)
{
pachube_in_out(tempC);
}
}
if (millis() < lampeggio) lampeggio = millis();
if ((millis() - lampeggio) > 5000){ //ogni 5 sec faccio lampeggiare il led giallo
lampeggio = millis();
for (int i = 0; i < stato; i++)
{
//Serial.println("lamp");
digitalWrite(led,HIGH);
delay(250);
digitalWrite(led,LOW);
delay(250);
}
}
Client client = server.available();
int led=0;
int tmp=0;
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (inString.length() < 35) {
inString.concat(c);
}
if (c == '\n' && current_line_is_blank) {
if(inString.indexOf("b10")>=0){
digitalWrite(led,LOW);
stato=2;
}
if(inString.indexOf("b11")>=0){
digitalWrite(led,HIGH);
stato=2;
}
if(inString.indexOf("b40")>=0){
digitalWrite(led,LOW);
}
if(inString.indexOf("b41")>=0){
digitalWrite(led,HIGH);
}
if(digitalRead(rele)) st4=41;
else st4=42;
if (inString.indexOf("temp")>=0){
char tempArr[20];
temp=inString.substring(inString.indexOf('p')+2, inString.indexOf(" H"));
temp.toCharArray(tempArr, 5);
EEPROM.write(0, atoi(tempArr));
tmp = EEPROM.read(0);
stato=1;
}
if(inString.indexOf("statourl")>=0){
char statoArr[20];
statourl=inString.substring(inString.indexOf('l')+2, inString.indexOf(" H"));
statourl.toCharArray(statoArr, 5);
stato=(atoi(statoArr));
}
EEPROM.write(1, stato);
verificaingressi();
printWebPage( &client);
break;
}
if (c == '\n') {
// we're starting a new line
current_line_is_blank = true;
} else if (c != '\r') {
// we've gotten a character on the current line
current_line_is_blank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
inString = "";
client.stop();
}
}