Part 3 of Weather Station with Arduino

In Part 3 of our project – home weather station with Arduino board, comes the most interesting part, at least for me – connecting the sensors and data extraction.

To see working and reporting stations made with setup similar to mine, check out Chris’ and Alan’s pages.

Ok. Lets continue:

The first step is to plug the Ethernet shield in to the main board – gently insert the board on top of the Arduino – nothing special.

* Note – if the station is going to be in a box, put the sensor cable as far away from the board as possible. The main chip of Ethernet shield can get quite hot 42-43 degrees at 22 degrees ambient temperature, which can seriously affect the data.

Once we have the basic modules connected:

  • Connect BMP180 pressure and temperature sensor:
    • SCL to analog pin 5
    • SDA to analog pin 4
    • VDD pin to 5 volts
    • GND to ground
  • Connect the SHT75 temp and humidity:
    • Clock (Pin1) digital pin 2
    • Data (Pin4) digital pin 3
    • Vcc (Pin2) to pins with 5V
    • GND (Pin3) to ground.
    • For DHT11 sensor linking use the same order
  • Connect the rain sensor:
    • A1 analog pin 1
    • Vcc pins to 5 volts
    • GND to ground.

Sorry I didn’t took any photos when I made the project, but my test version of the staton looked similar to this one:

Arduino board

Once we connect all the sensors the only thing that is remaining is to write the code. Some sensors require a library, for example BMP180 requires one, which can be downloaded from HERE.

Below is code that I wrote with comments about it.

What the code does, is printing the results of the sensors on the serial monitor (Tools > Serial Monitor), as well as displaying the data trough a Web server to local IP address, on minimalist look web page, so that you can style it later.

#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <Sensirion.h>
     
/*    
   Connections [BMP180]
   ===========
   Connect SCL to analog 5
   Connect SDA to analog 4
   Connect VDD to 5V DC
   Connect GROUND to common ground

   Connections [SHT75]
   ===========
   Connect Clock(Pin1 - White) to 2 (digital)
   Connect Data(Pin4 - Yellow) to 3 (digital)
   Connect Vcc (Pin2 - Red) to 5V DC
   Connect GND (Pin3 - Black) to common ground
*/
/*Sensirion SHT75 Constants*/
const uint8_t dataPin =  3;              // SHT serial data
const uint8_t sclkPin =  2;              // SHT serial clock
const uint32_t TRHSTEP   = 5000UL;       // Sensor query period
const int rainMin = 0;     // rain sensor minimum
const int rainMax = 1024;  // rain sensor maximum

Sensirion sht = Sensirion(dataPin, sclkPin);
 
uint16_t rawData;
float temperature;
float humidity;
float humidex;
float dewpoint;
 
byte measActive = false;
byte measType = TEMP;
 
unsigned long trhMillis = 0;             // Time interval tracking

/*Sensirion SHT75 Constants END*/

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); //BMP180 code
/*OneWire  ds(7);  // on pin 2 (a 4.7K resistor is necessary)*/
float celsius = 0; // global temperature variable
float pressurekPa = 0; //global pressure variable

//Ethernet setup >
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 200);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(80);

void setup(void) 
{
  Serial.begin(9600);
  /*SHT75 SETUP:*/
  delay(15);                             // Wait >= 11 ms before first cmd
// Demonstrate blocking calls
  sht.measTemp(&rawData);                // sht.meas(TEMP, &rawData, BLOCK)
  temperature = sht.calcTemp(rawData);
  sht.measHumi(&rawData);                // sht.meas(HUMI, &rawData, BLOCK)
  humidity = sht.calcHumi(rawData, temperature);
  dewpoint = sht.calcDewpoint(humidity, temperature);
  logData();
  /*SHT75 SETUP END*/
  
  /* Ethernet config */
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  
  /* Initialise the BMP180 sensor */
  if(!bmp.begin())
  {
    /* There was a problem detecting the BMP180 ... check your connections */
    Serial.print("Ooops, no BMP180 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }

}

void loop(void) 
{
    /* Temp readings: */
    /*SHT75 loop: */
      unsigned long curMillis = millis();          // Get current time
     
      // Demonstrate non-blocking calls
      if (curMillis - trhMillis >= TRHSTEP) {      // Time for new measurements?
        measActive = true;
        measType = TEMP;
        sht.meas(TEMP, &rawData, NONBLOCK);        // Start temp measurement
       
        BMP180();                                  // Pressure measurement
        
        trhMillis = curMillis;
      }
      if (measActive && sht.measRdy()) {           // Note: no error checking
        if (measType == TEMP) {                    // Process temp or humi?
          measType = HUMI;
          temperature = sht.calcTemp(rawData);     // Convert raw sensor data
          sht.meas(HUMI, &rawData, NONBLOCK);      // Start humidity measurement
        } else {
          measActive = false;
          humidity = sht.calcHumi(rawData, temperature); // Convert raw sensor data
          dewpoint = sht.calcDewpoint(humidity, temperature);
          
          //humidex code:
          float h,e; //humidex and other
          e = 6.11 * exp(5417.7530 * ((1/273.16) - (1/(dewpoint + 273.15)))); 
          h = (0.5555)*(e - 10.0);
          humidex = temperature + h;
          logData();
        }
      }
    /*SHT75 loop end*/
    
    
  /* Web server: */
    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"); // 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 data
            client.print(temperature);
            client.print(" ");
            client.print(humidity);
            client.print(" ");
            client.print(pressurekPa);
            client.print(" ");
            client.print(dewpoint);
            client.print(" ");
            client.print(humidex);
            client.print(" ");
            client.print(analogRead(A1));
            //client.println("<br />");
          
          //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 disconnected");
  }
}



void BMP180() {
  delay(1500);
  /* Get a new sensor event */ 
  sensors_event_t event;
  bmp.getEvent(&event);
 
  /* Display the results (barometric pressure is measure in kPa) */
  if (event.pressure)
  {
    /* Display atmospheric pressue in kPa */
    Serial.print("[BMP180]Pressure:    ");
    Serial.print(event.pressure / 10);
    pressurekPa = event.pressure / 10;
    Serial.println(" kPa");
         
    /* First we get the current temperature from the BMP085 */
    float temperature;
    bmp.getTemperature(&temperature);
    Serial.print("[BMP180]Temperature: ");
    Serial.print(temperature);
    Serial.println(" C");

    /* Then convert the atmospheric pressure, and SLP to altitude         */
    /* Update this next line with the current SLP for better results      */
    float seaLevelPressure = 1022 /*SENSORS_PRESSURE_SEALEVELHPA*/;
    Serial.print("[BMP180]Altitude:    "); 
    Serial.print(bmp.pressureToAltitude(seaLevelPressure,
                                        event.pressure)); 
    Serial.println(" m");
    Serial.println("");
  }
  else
  {
    Serial.println("Sensor error");
  }
}

    void logData() {
      Serial.print("[SHT75]Temperature = ");   Serial.print(temperature);
      Serial.print(" C, Humidity = ");  Serial.print(humidity);
      Serial.print(" %, Dewpoint = ");  Serial.print(dewpoint);
      Serial.println(" C");
      Serial.print("Humidex: ");
      Serial.println(humidex);
      Serial.print("Water Level: ");
      Serial.println(analogRead(A1));
    }

The above code will make a Web server on 192.168.1.200, where on a single line you will see the data from all sensors.

These data can now be taken in order to generate graphics or store it inside a file or whatever you are most comfortable with. I personally use Linux machine that draws graphics using munin software (based on rrdtool). There are thousands of solutions for drawing graphics; you just have to look at the options.

And that’s it.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>