Pages: 1 [2] 3 4   Go Down
Author Topic: Arduino Webserver with Temperature Monitor / Control  (Read 35081 times)
0 Members and 1 Guest are viewing this topic.
Belgium
Offline Offline
Full Member
***
Karma: 0
Posts: 143
Just Do it (with Arduino of course)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ;-)

* TempControllerWebServer.ino (11.7 KB - downloaded 126 times.)
Logged

Belgium
Offline Offline
Full Member
***
Karma: 0
Posts: 143
Just Do it (with Arduino of course)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@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 ?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I don't understand this
    "Temperature: <b>"
    "<br />"
    "<font size=""7"">"
    "$D.$D &deg;C</font></b>"   
and this
    "Target Temperature: <b>"
    "$D.0 &deg;C</b>"

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,
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
#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>"
  "<br />"
  "<font size=""5"">"
  "$D &deg;F</font></b>"   
  "<br />"
  "Current Target Temperature: <b>"
  "$D &deg;F</b>"
  "<br />"
  "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 (6.78 KB, 282x350 - viewed 294 times.)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

« Last Edit: February 04, 2013, 01:17:40 pm by AlexTroy » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Please read there:
http://www.homebrewtalk.com/f51/arduino-networked-temperature-monitor-340294/index2.html#post4286666
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
https://github.com/jcw/ethercard/issues/65
http://forum.jeelabs.net/comment/9920#comment-9920
« Last Edit: February 14, 2013, 05:31:50 am by alvydas001 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You really need a more powerful Arduino with more RAM (mega2560) or can try http://ksduino.org, http://open.sen.se/, https://www.thingspeak.com/ http://exosite.com/products/portals cloud. Ksduino and http://www.pushingbox.com/ support ENC28J60.
« Last Edit: February 15, 2013, 02:29:15 am by alvydas001 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You really need a more powerful Arduino with more RAM (mega2560) or can try ksduino.org, http://open.sen.se/, https://www.thingspeak.com/ http://exosite.com/products/portals cloud. Ksduino and http://www.pushingbox.com/ support ENC28J60.

Duemilanove + ethernetshield enc28j60 should be a great setup?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The full terms of reference in the scene!
Otherwise, there is nothing you will not respond.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The full terms of reference in the scene!
Otherwise, there is nothing you will not respond.



Sry for my bad english... I don't understand....   :<
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My English is very bad, too :-)
have to say what you wish to do so, must complete the task conditions, it is difficult to advise otherwise.
Logged

Pages: 1 [2] 3 4   Go Up
Jump to: