Introduction: The Super Simple Arduino Weather Web Server

Picture of The Super Simple Arduino Weather Web Server

From the minds at http://arduinotronics.blogspot.com/

Updates:
Added Heat Index & Dew Point calculations
Added Barometric Pressure Sensor

Wind Speed Monitoring

See the new BME280 combination Temperature, Humidity, AND Barometric Pressure Sensor all in one!

6/2/2015 See the new WiFi Version! - http://arduinotronics.blogspot.com/2015/06/wifi-we...

I wanted to set up a home web server that could monitor indoor and outdoor temperature, humidity levels, and even monitor for indoor freezing or flooding conditions (and other security, appliance or environmental alerts). The approach I took consists of a Arduino and a Ethernet shield, running a tiny web server sketch, and for this example, I'm using the popular DHT-11 Temperature / Humidity module. You can interface this to smoke / heat sensors, CO and other gas sensors, and a whole lot more.


For this example you will need:

Arduino
Ethernet Shield (this could be done with wifi as well with some code changes)
DHT-11 Temp/Humidity Module
10k Ohm Resistor

Optional: BMP-085 Barometric Pressure Sensor

A internet router and home internet access

Step 1: The DHT-11 Temperature / Humidity Sensor

Picture of The DHT-11 Temperature / Humidity Sensor

This little 4 pin sensor (only 3 are used) is an inexpensive and common sensor. It's easy to use and connect. Pin 1 connects to +5v, Pin 2 to an Arduino Input (we are using D2 on the Arduino), and pin 4 to Arduino Gnd. Since the Ethernet shield will stack on top of the Arduino, plug the DHT-11 into the same pins on the Ethernet shield.

The ethernet shield uses pins A0, A1, D4, and D10-D13
The DHT-11 is using D2, but can be changed.
The BMP180 uses A4 & A5.

Step 2: The Ethernet Shield

Picture of The Ethernet Shield

This shield from Arduino (the company) gives your Arduino (the board) the ability to communicate over the network, and internet. Write down the MAC address on the back, then plug the shield in, on top of your arduino, and connect a Ethernet cable to your router. 

Step 3: The Code

Picture of The Code

I've adapted the sample Web Server app included with the Arduino, by merging the DHTxx code and library from Lady Ada. This basically changes Serial.print statements to client.print, and I've massaged the html a bit to make it display nicer. You can download the code at 

http://arduinotronics.blogspot.com/2013/09/arduino-temp-humidity-web-server.html


#include <DHT.h>

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x00, 0x23, 0x36 }; //MAC address found on the back of your ethernet shield.
IPAddress ip(192,168,254,177); // IP address dependent upon your network addresses.

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  dht.begin();

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
 
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *C");
  }
 
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
   client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
        
          // output the value of the DHT-11
         client.println("<H2>");
            client.print("Humidity: ");
            client.println("</H2>");
            client.println("<p />");
            client.println("<H1>");
            client.print(h);
            client.print(" %\t");
            client.println("</H1>");
            client.println("<p />"); 
            client.println("<H2>");
            client.print("Temperature: ");
            client.println("</H2>");
            client.println("<H1>");
            client.print(t*1.8+32);
            client.println(" &#176;");
            client.println("F");
            client.println("</H1>");
           
                
         
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}



Step 4: Barometric Pressure

Picture of Barometric Pressure

We have added the BMP-085 / BMP180 Barometric Pressure Sensor, and the calculations for Heat Index and Dew point. The Barometric Pressure Sensor has 4 connections, SDA (A4), SCL (A5), Gnd, and VIN (5vdc). See http://arduinotronics.blogspot.com/2014/02/sensing-barometric-pressure.html for details.

The Adafruit BMP-180 is shown below, but have also tested with the ICStation BMP-085. No changes to code or circuit. See http://arduinotronics.blogspot.com/2014/02/icstation-5v-bmp-085-pressure.html

Here is the code with all the additions:

#include <Wire.h>
#include <Adafruit_BMP085.h>

float Tc=0;
float Tf=0;
float Pa=0;
float InHg=0;
float Am=0;
float Af=0;

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

float tF;
float dP;
float dPF;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x00, 0x23, 0x36 };
IPAddress ip(192,168,254,177);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);


Adafruit_BMP085 bmp;

void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(9600);
 
  if (!bmp.begin()) {
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
while (1) {}
  }
 
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  dht.begin();

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
 
  Serial.print("Temperature = ");
    //Serial.print(bmp.readTemperature());
    Tc=bmp.readTemperature();
    Tf=((Tc*9)/5)+32;
    Serial.print(Tf);
    Serial.println(" *F");
   
    Serial.print("Pressure = ");
    //Serial.print(bmp.readPressure());
    Pa=bmp.readPressure();
    InHg=Pa*0.000295333727;
    Serial.print(InHg);
    Serial.println(" In Hg");
   
    // Calculate altitude assuming 'standard' barometric
    // pressure of 1013.25 millibar = 101325 Pascal
    Serial.print("Altitude = ");
    //Serial.print(bmp.readAltitude());
    Am=bmp.readAltitude(101550); //adjusted for local altitude
    Af=Am*3.28084;
    Serial.print(Af);
    Serial.println(" feet");

  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
  //  Serial.print("Real altitude = ");
  //  Serial.print(bmp.readAltitude(101500));
  //  Serial.println(" meters");
   
    Serial.println();
 
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    tF=((t*9)/5)+32;
    Serial.println(" *C");
  }
 
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
   client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
        
        client.println("<TABLE>");
        client.println("<TR>");
        client.println("<TD>");
          // output the value of the DHT-11
      
            client.print("Humidity: ");
        client.println("</TD>");
        client.println("<TD>");
            client.print(h);
            client.print(" %\t");
        client.println("</TD>");
        client.println("</TR>");
        client.println("<TR>");
        client.println("<TD>");   
            client.print("Temperature: ");

        client.println("</TD>");
        client.println("<TD>");
            client.print(t*1.8+32);
            client.println(" &#176;");
            client.println("F");

client.println("</TD>");
client.println("</TR>");
client.println("<TR>");
client.println("<TD>");
            client.print("Barometric Pressure: ");

client.println("</TD>");
client.println("<TD>");
            client.print(InHg);
            //client.println(" &#176;");
            client.println(" In.");
client.println("</TD>");
client.println("</TR>");

client.println("<TR>");
client.println("<TD>");

client.println("Dew Point: ");

client.println("</TD>");
client.println("<TD>");
  dP=(dewPointFast(t, h));
  dPF=((dP*9)/5)+32;
client.println(dPF);
client.println(" &#176;");
client.println("F");

client.println("</TD>");
client.println("</TR>");
client.println("<TR>");
client.println("<TD>");

client.println("Heat Index: ");
client.println("</TD>");
client.println("<TD>");

client.println(heatIndex(tF,h));
client.println(" &#176;");
client.println("F");
client.println("</TD>");
client.println("</TR>");

client.println("</TABLE>");
           
                
         
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

// delta max = 0.6544 wrt dewPoint()
// 6.9 x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double dewPointFast(double celsius, double humidity)
{
double a = 17.271;
double b = 237.7;
double temp = (a * celsius) / (b + celsius) + log(humidity*0.01);
double Td = (b * temp) / (a - temp);
return Td;
}

double heatIndex(double tempF, double humidity)
{
  double c1 = -42.38, c2 = 2.049, c3 = 10.14, c4 = -0.2248, c5= -6.838e-3, c6=-5.482e-2, c7=1.228e-3, c8=8.528e-4, c9=-1.99e-6  ;
  double T = tempF;
  double R = humidity;

  double A = (( c5 * T) + c2) * T + c1;
  double B = ((c7 * T) + c4) * T + c3;
  double C = ((c9 * T) + c8) * T + c6;

  double rv = (C * R + B) * R + A;
  return rv;
}

Step 5: Accessing From the Outside World

Picture of Accessing From the Outside World

Modifying the setup on your home router to allow access from the outside world is a bit beyond the focus of this instructable, but there are many tutorials on the web. What you need to do is set up Network Address Translation (NAT), so someone accessing your public IP address gets forwarded (and translated) to the private IP on your Arduino. The other step is configuring Dynamic DNS (DDNS) so that when your ISP flips your IP address, the world can still access your Arduino by name, instead of a set of changing numbers. Here is a tutorial on the subject:

http://www.noip.com/support/knowledgebase/using-no-ip-with-a-cabledsl-router/


 

Comments

TariqA37 (author)2017-01-02

can any of you guys write a code for me :((((
using ds18b20 onewire
arduino uno

ESP8266

LCD+I2C

PLEAAAASSSSE , I HAVE TRIED A LOT.

CodfishCatfish (author)2016-12-24

Thought I would add my 2 pennies worth.

If you want to view the

external temp you need to change these lines.

// (port 80 is default for HTTP):
EthernetServer server(7050); //This is your forwarded port no longer port 80!!

In my case I forwarded port 7050... yours will be anything between 0 and 65535 but not 21 or 8080 etc.

Modify this for temperature in Celsius..

client.print("Temperature: ");
client.println("</H2>");
client.println("<H1>");
client.print(t);
client.println(" °");
client.println("C");

I am also working on a bunch of other mods but this is already a great project. Loving it every time I turn it on.

Regards de Spence M0STO

CodfishCatfish (author)2016-12-24

great little project, works a treat. I would say though that this line needs fixing.

Ethernet.begin(mac, ip); //broken in my setup

;Ethernet.begin(mac, ip); //works now.

And would love to see the output in Celsius (Metric UK here sorry).

Did you ever add the 4 wire output to a 16x2 LCD? A very nice project little buggy but easily fixed. 10/10 though all the way

sspence (author)CodfishCatfish2016-12-24

The project works as is in my setup, not buggy at all. Celsius is already in the code, just remove the conversion to F. I use the serial lcd at http://arduinotronics.blogspot.com/2014/02/sainsmart-i2c-lcd.html

BernalN (author)2015-10-25

What modification to the sketch would be required if one wanted to add an additional DHT11 to the weather web server? Thank you in advance for any info you could supply.

sspence (author)BernalN2015-10-25

just need to connect the data pins to separate inputs,and call the dht set up and reads separately. Here is instructions for using 2 or more DHT devices. http://forum.arduino.cc/index.php?topic=201122.0

BernalN (author)sspence2015-10-25

Thank you, most helpful.

win89 (author)2015-03-10

Good project. I'm still confuse how to acess my arduino server with no-IP. I use home network for this situation,but i want acess the arduino from anywhere outside my home network. Anyone know ho to do it?

Placing the IP the router assigns (usually 192.168.1.X) into the DMZ does the trick. The NO-IP acts as a re-direct so your home IP (as assigned by your ISP) is not revealed if you want other to see your webpage.

sspence (author)win892015-04-01

Here is a good article for the linksys models, but it's dependent on your router config.

http://www.wikihow.com/Adjust-Nat-Settings-on-Linksys-Router

Benjamink1 (author)2015-08-13

help me plz! how to put date and time? which rtc is better?

sspence (author)Benjamink12015-08-13

I use a DS1307 - See http://arduinotronics.blogspot.com/2014/03/the-arduino-lcd-clock.html

Benjamink1 (author)sspence2015-08-13

my output is not LCD and then I already buy DS1302

I try that coding but it is error :(

I want to show output "Date and time Temp Hum Pressure" every 30sec

#include <DS1302.h>

DS1302 rtc(2, 3, 4);

void setup()

{

rtc.halt(false);

rtc.writeProtect(false);

Serial.begin(9600);

tc.setDOW(FRIDAY);

rtc.setTime(12, 0, 0);

rtc.setDate(6, 8, 2010);

}

void loop()

{

Serial.print(rtc.getDOWStr());

Serial.print(" ");

Serial.print(rtc.getDateStr());

Serial.print(" -- ");

Serial.println(rtc.getTimeStr());

delay (1000);

}

jim.trapnell (author)2015-04-11

I wonder if I can trouble you with a request?
I'd like to add a 4 wire LCD like I've seen you use on other projects and so far I'm failing at the code for it. I only want to show the temp and humidity on the LCD.
Is this something you think you could add to the code whenever you get a chance?

sspence (author)jim.trapnell2015-04-11

Sure, I can do that.

jim.trapnell (author)sspence2015-07-08

Does the new WiFi version mean this one has been abandoned? I'd still really like to get a 4 wire LCD hooked up to this. Thank you for any help.

sspence (author)jim.trapnell2015-07-08

email me at greentrust@gmail.com to remind me, will try to get the lcd code done for you this week.

sspence (author)2015-06-04

email me your sketch at greentrust@gmail.com

I'll test it.

RuzainiM (author)2015-06-02

hi sir...why when i enter the adress "Connection refused: 192.168.1.31:80" will go out??what its problem sir??

sspence (author)RuzainiM2015-06-02

I assume 192.168.1.31 is the ip address of the ethernet shield? do you have the shield connected to the same hub/switch as the pc you are trying to browse with?

RuzainiM (author)sspence2015-06-04

sir...i still cnnot get the web...the website is no available..is my ethernet shield damaged??

RuzainiM (author)sspence2015-06-02

no..i just use the ethernet shield...dont have other shield connccted to the same switch...

RuzainiM (author)2015-05-28

hi sir...its ok if i dont want use the protoshield???and can u show me the schematic diagram??pleasee sir..

sspence (author)RuzainiM2015-05-28

schematic is in step one. protoshield is totally optional.

RuzainiM (author)sspence2015-05-31

how about the BMP180 sir??if dont use the portoboard...how to connect??

sspence (author)RuzainiM2015-05-31

Per http://arduinotronics.blogspot.com/2015/03/ic-stat...

// Connect VCC of the sensor to 5.0V

// Connect GND to Ground
// Connect SCL to Analog 5
// Connect SDA to Analog 4

RuzainiM (author)sspence2015-05-29

owhhh...tq sspence for the info..

muhhammad.zahiruddin (author)2015-04-12

Hi sir, your project is almost same with me, the different my with your is:
your:
1-DHT-11 Temp/Humidity Module
2-Arduino
3-Ethernet Shield
5-Display output to webserve

My:
1- Fingerprint Sensor
2-Arduino
3-DFRduino Ethenet Shield
5-Display output ID from fingerprint to webserve

The problem is i don know how to send that output id from fingerprint to webserve. Can u help me pls.

I think I found the Fingerprint sensor u have. It should be connected to an UART (say 'Serial port') and read from there at 9600 baud

Muhhammed, as you havent received an answer yet, I will give it a go. The two projects are as much the same as in having an arduino that has a sensor connected to it :-)
The DHT11 has a library that reads out the humidity and temperature, I figure your fingerprint sensor is a bit different. What is the output from that? is it just a logical yes or no (doubt it) or some sort of number?
Anyway, if instead of the value for temperature or humidity, you just substitute that number?

StephenB8 (author)2015-02-02

I'm trying to do something similar with an Arduino server and a MATLAB based user interface, but I'm stuck on getting the Arduino server to accept incoming name/value pairs for receiving information from the MATLAB interface. Does anybody here know how/if I can do that?

GuilhermeB1 (author)2015-01-06

Thank you so much. Worked fine for me, I just followed all intructions step by step.

Thank you again

diy_bloke (author)2014-11-23

eduman, with all due respect, if the program states "dht" library and you just install a library with a different name (DHT11) ofcourse the program is not working.
As you say you do not know the DHT library the proper way would be to ask about that first, people will always be willing to help.
Sadly though you install a clearly wrong library and then blame the author.
Just for argument sake.... I downloaded the program and it compiles.
Not everybody is an Arduino expert here, that is why we share our knowledge in these ibbkles,but you will find many more people willing to help if you just stay friendly instead of playing the blame game and start making demands.
"would you know where I can find the correct library" will get you more people willing to do that then "So you send correct library Your program is wrong"

BrentW1 (author)2014-11-21

Doesn't work in IDE 1.06.

sspence (author)BrentW12014-11-21

Have not had a chance to test any of my instructables in version 1.0.6, as it just came out. Am downloading and will post what changes need to be made.

sspence (author)sspence2014-11-21

Ok, just tried it in 1.0.6, and it seems to be workign fine. What failed for you, BrentW1?

eduman (author)2014-11-20

It's work now. :) The problem is my "import library". I'm so sorry sspence. I'm so sorry.

Thank you very much :)

sspence (author)eduman2014-11-20

Glad it's now working for you. Could you please delete the negative comments?

sspence (author)2014-11-19

Library is available in step 3. Maybe they changed their library since this project was built. I will download their latest and retry.

sspence (author)sspence2014-11-19

I just downloaded their latest library and installed it in the libraries folder. the code in this instructable compiles, uploads, and runs fine. This instructable has always been, and continues to be 100% correct.

sspence (author)2014-11-19

The library link is listed in step 3.

sspence (author)2014-11-19

My program is not wrong. It works fine on my hardware, and with the code I posted.

eduman (author)2014-11-18

Where is the your download link for DHT lib.?

sspence (author)eduman2014-11-19

Step 3, Lady Ada.

eduman (author)2014-11-18

I'm using 1.0.5

sspence (author)2014-11-18

Looks like yo forgot to install the DHT library, or are using the older IDE. This works fine with 1.0.5

eduman (author)2014-11-18

Very very bad project... it's not working !

sspence (author)eduman2014-11-18

Not a bad project, just maybe poor execution. Did you download the correct library? What version of the IDE are you using? Are your connections correct? Everything is tested well before uploading, and as you can see, the screenshots prove the project works.

diy_bloke (author)2013-11-17

great project, but are you sure you provided the correct library? I get the "DHT11 was not declared in this scope" error message, together with a hoist of other error messages

sspence (author)diy_bloke2013-11-17

Works ok for me. I'm using 1.0.5

About This Instructable

158,154views

193favorites

License:

Bio: Professionally, I'm an IT Engineer (Executive Level) and Electronics Tech. I'm a Amateur Radio Operator (KK4HFJ). I lived off grid, with Solar (PV ... More »
More by sspence:DIY I2C LCD Display with InputsRaspberry Pi & the Neo 6M GPSEarthquake / Vibration Sensor
Add instructable to: