Arduino Webserver with Temperature Monitor / Control

Great job!

warunasanjaya11,

Yes the Nano is USB. The one on the website you listed is the same as the one I got.

I just grabbed the Nano ($15 inc post) and Ethernet Controller ($5 inc post) from dealextreme, but ebay had similar prices.

Amazing how cheap all this stuff has gotten over the last couple of years.

Cheers Rob.

Hi

I really like your project, it has finally got me to understanding some of the programming involved in completing this.

You have changed your sketch from version one, do you have any plans to post the new sketch?

I'd like to compare the two new vs old.

Thanks you have been a great help.

Rich

Hey Rich,

Thanks much appreciated.

When I changed the sketch to the Ethercard library I updated it on the link too. So that is latest version.

Still waiting on the Custom PCB to arrive to finish the project.....

Cheers Rob.

Hi looks good - I have a question on the PCB?

Did you order just one? or a few?

What was the cost? including shippping?

And who did it?

I want to get some board made but still not sure of where to get it done. I am in New Zealand.

Also what did you use for the board design?

Cheers

Chris

Hi looks good - I have a question on the PCB?

Hello Chris

Did you order just one? or a few?

I ordered 3 (the minimal)

What was the cost? including shippping?

$5 per square inch for three copies of your design and postage was $5, so If you can fit it on a square inch works out to be ~$3.30 a board

Pricing is here OSH Park Docs ~ Services ~ Fabrication Services

And who did it?

These guys http://oshpark.com/
Great site and very easy to use and deal with.

I want to get some board made but still not sure of where to get it done. I am in New Zealand.

I am in Australia so not to far :slight_smile:

Also what did you use for the board design?

I used Eagle free version

http://www.cadsoftusa.com/eagle-pcb-design-software/?language=en

easy enough to use and there is heaps of guides on youtube, instructables etc.

Rob.

Thanks Rob

Appreciate the quick response

chris

Im having trouble with this ethernet module. What pinout did you use with the jeelabs library.
thanks Michael

Looks great! Well done!

michaelelcano:
Im having trouble with this ethernet module. What pinout did you use with the jeelabs library.
thanks Michael

Hey Michael,

I used :

Arduino ==> Ethernet Controller

2 ==> INT
10 ==> CS
11 ==> SI
12 ==> SO
13 ==> SCK
Reset ==> RST

and +3.3v, Ground

also make sure that you are calling pin 10 at the start of the sketch like os

if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)

Lemme know if you get stuck...

I got the PCB's on friday, soldered it up, put it inside an enclosure and gave it a good run in on the weekend and it works perfectly, very happy, bit of a tight fit inside the enclosure tho!

Cheers Rob.

Thanks Rob for sharing this app. I'm in your tracks (but way behind) on a DINo, with Cosm publishing.

If that helps, I reformatted your sketch (mainly strings and comments) so that it prints correctly. Attached.
Apparently Arduino doesn't word wrap, and fails to print if you lower the margins.

I checked it still compiles, but can't check if it still works OK :wink:

TempControllerWebServer.ino (11.7 KB)

@Rob,

I tried to integrate part of your sketch in mine, and it failed to compile because I didn't include BufferFiller. Strange, as my sketch already included some web page(s?) using the Stash, and I don't see you using it. Any idea on the inner working that could help me understand ?

Thanks for the source code.

I'm new to arduino and html code as well and for my first big project I want to make a web controlled thermostat. I have both an uno and a mega and I am also using a wiznet 5100 ethernet shield. Plan is to wire a set of contacts from my relay module parallel with the thermostat on the wall. In the end I'd like to have a temperature schedule set up on the web page where I can set a different temperature every 3 hours for all 7 days. But for now I'd just like to be able to set the target temperature through the web page.

I was happy when I saw your code cause I needed an example to go off of. Problem is I am using the wiznet 5100 ethernet chip.

Anyways do you know what needs to be changed to get your code to work with the wiznet chip?

I am also using an analog temperature sensor so I edited out all the code for the dallas sensor and added in code for the analog sensor.

Thanks

can someone please explain how the current temperature and the target temperature get displayed on the web page.

I don't understand this
"Temperature: "
"
"
"<font size=""7"">"
"$D.$D °C
"
and this
"Target Temperature: "
"$D.0 °C
"

what is SD.SD and SD.0 are those somehow bound to currenttemp and targettemp?

I'd like to edit the original code to display a couple other values besides the current and target temperatures.

Thanks,

Finally realized how the ethercard code works and was able to edit your original code. Added 3 more text input boxes to the web page. My code has day and night temperature set points as well as day and night start times. I added a real time clock so it will automatically change the target temp based on the times i set on the web page. Thanks again for the source code, I didn't know what I was getting into when I got the Enc28J60 module.

#include <EtherCard.h>
#include <EEPROM.h>
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

char DayTempTextbox[4];               // Data in text box
char NightTempTextbox[4];             // Data in text box
char DayTimeTextbox[4];               // Data in text box
char NightTimeTextbox[4];             // Data in text box

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA };
static byte myip[] = { 192,168,1,102 }; //used for static IP

byte Ethernet::buffer[1000];
BufferFiller bfill;

byte TargetTemp = 65;                     
byte DayTempSP = 70;
byte NightTempSP = 68;
byte DayStartTime = 7;
byte NightStartTime = 20;
byte value;

byte TempSensor = A3;
byte HeatONRelay1 = 3;
byte HeatONRelay2 = 4;

const int numReadings = 15;
byte TempReading[numReadings];
byte TempIndex = 0;
int TempTotal = 0;

byte RoomTemperature = 0;
byte TempDBMax = 71;
byte TempDBMin = 69;
byte TempDeadBandSP = 1;

byte Hour = 12;
byte Minute = 24;
byte Second = 36;
byte Month = 11;
byte Day = 23;
int Year = 2012;

//====================================================================================================
void setup () {
//====================================================================================================
  if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0);
  ether.staticSetup(myip);
  Wire.begin();
  RTC.begin();
  pinMode(HeatONRelay1, OUTPUT);          // sets the digital pin as input
  pinMode(HeatONRelay2, OUTPUT);          // sets the digital pin as input
  
  analogReference(INTERNAL);  
  
  DayTempSP = EEPROM.read(0);
  NightTempSP = EEPROM.read(1);
  DayStartTime = EEPROM.read(2);
  NightStartTime = EEPROM.read(3);
   
}

//====================================================================================================

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() {
//====================================================================================================

//$D = word data type
//$L = long data type
//$S = c string
//$F = progmem string
//$E = byte from the eeprom. 

  char* Heatstat;
  if ( digitalRead(HeatONRelay1) == HIGH ) {
    Heatstat = "On" ; }
  else {
    Heatstat = "Off"; }
    
  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='10'/>"
  "<title>ArduStat</title>"
  "<body bgcolor=""#99CCFF"">"
  "<center>"
  "<hr />"
  "Temperature: <b>"
  "
"
  "<font size=""5"">"
  "$D &deg;F</font></b>"   
  "
"
  "Current Target Temperature: <b>"
  "$D &deg;F</b>"
  "
"
  "Heat is <b>$S</b> "
  "<hr />"
  "Current Temperature Setpoint: <b><font size=""4"">$D &deg;F</font></b>" 
  "<form><input type=text name=daytemp size=4> <input type=submit value=Ok> </form>" 
  "Current Start Time: <b><font size=""4"">$D</font></b>"     
  "<form><input type=text name=daytime size=4> <input type=submit value=Ok> </form>" 
  "Current Temperature Setpoint: <b><font size=""4"">$D &deg;F</font></b>" 
  "<form><input type=text name=nighttemp size=4> <input type=submit value=Ok> </form>"  
  "Current Start Time: <b><font size=""4"">$D</font></b>" 
  "<form><input type=text name=nighttime size=4> <input type=submit value=Ok> </form>"
  "<hr />"
  "Date: $D/$D/$D Time: $D:$D:$D "     
  "</center></body></html>"),
  RoomTemperature, TargetTemp, Heatstat, DayTempSP, DayStartTime, NightTempSP, NightStartTime, Month, Day, Year, Hour, Minute, Second );
  return bfill.position();
         
}
//====================================================================================================
void loop () {
//====================================================================================================

  DateTime now = RTC.now();
  Month = now.month();
  Day = now.day();
  Year = now.year();
  Hour = now.hour();
  Minute = now.minute();
  Second = now.second();
  
  TempTotal = TempTotal - TempReading[TempIndex];
  TempReading[TempIndex] = ((analogRead(TempSensor)/9.31)-3);
  TempTotal = TempTotal + TempReading[TempIndex];
  TempIndex = TempIndex + 1;
  if (TempIndex >= numReadings) {
    TempIndex = 0; }
  RoomTemperature = TempTotal / numReadings;
  
  if ((Hour >= DayStartTime) & (Hour < NightStartTime)) {
    TargetTemp = DayTempSP; }
      
  if ((Hour >= NightStartTime) | (Hour < DayStartTime)) {
    TargetTemp = NightTempSP; }
  
  TempDBMin = (TargetTemp - TempDeadBandSP);
  TempDBMax = (TargetTemp + TempDeadBandSP);  
  
  if (RoomTemperature < TempDBMin) {
    digitalWrite(HeatONRelay1, HIGH);
    digitalWrite(HeatONRelay2, HIGH); }
  if (RoomTemperature > TempDBMax) {
    digitalWrite(HeatONRelay1, LOW);
    digitalWrite(HeatONRelay2, LOW); }
  
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  if (pos) {
    delay(1);   // necessary for my system //TODO
    bfill = ether.tcpOffset();
    char *data = (char *) Ethernet::buffer + pos;
    if (strncmp("GET /", data, 5) != 0) {
      bfill.emit_p(http_Unauthorized); }
    else {
      data += 5;
      if (data[0] == ' ') {
        homePage(); }
      else if (strncmp( "?daytemp=" , data , 8 ) == 0) {
        if (ether.findKeyVal(data + 1, DayTempTextbox , sizeof DayTempTextbox , "daytemp") > 0) { 
          value = atoi(DayTempTextbox);   // command to convert a string to number
          if ((value >= 55) & (value <= 80)) {
            DayTempSP = value;
            EEPROM.write(0, value); }
        }
        bfill.emit_p(http_Found);
      }
      else if (strncmp( "?daytime=" , data , 8 ) == 0) {
        if (ether.findKeyVal(data + 1, DayTimeTextbox , sizeof DayTimeTextbox , "daytime") > 0) { 
          value = atoi(DayTimeTextbox);   // command to convert a string to number
          if ((value > 0) & (value <= 24)) {
            DayStartTime = value;
            EEPROM.write(2, value); }
        }
        bfill.emit_p(http_Found);
      }
      else if (strncmp( "?nighttemp=" , data , 10 ) == 0) {
        if (ether.findKeyVal(data + 1, NightTempTextbox , sizeof NightTempTextbox , "nighttemp") > 0) { 
          value = atoi(NightTempTextbox);   // command to convert a string to number
          if ((value >= 55) & (value <= 80)) {
             NightTempSP = value;
            EEPROM.write(1, value); }
        }
        bfill.emit_p(http_Found);
      }  
      else if (strncmp( "?nighttime=" , data , 10 ) == 0) {
        if (ether.findKeyVal(data + 1, NightTimeTextbox , sizeof NightTimeTextbox , "nighttime") > 0) { 
          value = atoi(NightTimeTextbox);   // command to convert a string to number
          if ((value > 0) & (value <= 24)) {
            NightStartTime = value;
            EEPROM.write(3, value); }
        }
        bfill.emit_p(http_Found);
      }
      ether.httpServerReply(bfill.position()); 
    }
  }
}

webpage:

Arduino Thermostat 2.png

Hello!
Very interesting thermostat you get. Have a question. As I understand it 18b20 address must be specified manually in the sketch, how to connect the sensor to a different address, without flashing?

Please read there:

Is this code source work if I only copy/pastre to my enc28j60 ethenet shield?

Does this thermostat can send email if the temperature range is below or under the value I preset?

Im very interrested to reproduce this thing, it's awsome! thanks for sharing and let me know!

It could be cool to share an HOW TO for beginners like me :slight_smile:

I think that e-mail can send only arduino mega 2560, arduino uno insufficient memory, if you want to supplement the program

http://www.lucadentella.it/en/2012/12/16/enc28j60-e-arduino-12/, https://raw.github.com/lucadentella/enc28j60_tutorial/master/_12_SkebbySMS/_12_SkebbySMS.ino
SMTP protocol problems · Issue #65 · njh/EtherCard · GitHub
http://forum.jeelabs.net/comment/9920#comment-9920

Okay i think that would help.

I'm realy bad in programming, My project is to take the entire web temperature fo enc28j60 code and modify it to send email when the value is under or over the preset.

Thanks for help and shared links!