Page 1 of 1

Weather station Wunderground

Posted: Tue Jan 28, 2014 9:34 pm
by fmbfla
Enjoy!

Code: Select all

/*
 This MODIFIED sketch connects to a website (http://www.rtupdate.wunderground.com)
 Using an Arduino Wiznet Ethernet shield To upload your weather conditions to wunderground.com,
 We make a standard HTTP GET request with the ID, PASSWORD and weather conditions as GET parameters.
 You must first create an account with wunderground for this to werk!
 Various notes throughout attempt to explain why i did what i did to make it werk.
 This sketch also incorporates an NTP RTC update code to make sure that the time is always correct and
 resets the RTC Soft or Hard to UTC ZULU Wunderground wants "UTC ZULU HOUR".
 Results for this can be monitored @ http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KFLFORTM67

Binary sketch size: 28,058 bytes (of a 32,256 byte maximum)
 
 Circuit:
 * Arduino UNO adafruit
 * Ethernet shield attached to pins 10, 11, 12, 13
 * DHT to pin A0 adafruit
 * Wind direction to pin A1(360 var resistor)
 * Anemometer to Digtal 2 (INT0) (reed)
 * Rain tip to Digital 3 (INT1) (hall effect)
 * BMP to I2C adafruit
 * RTC to I2C adafruit
 **
 Originaly created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe, based on work by Adrian McEwen
 **
 **
 Modified  To upload weather conditions to wunderground.com
 1,Jan 2014
 By the drunkin programer
 *
 */
 
 
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>	      // New from IDE 1.0
#include <Wire.h>
#include "DHT.h"
#include <Adafruit_BMP085.h>
#include "RTClib.h"
//Pins 
#define DHTPIN  A0                   // DHT 22  (AM2302)
#define vane A1
#define anemometer  2                // D2 Wind speed
#define rainTip  3                   // pin D3 Rain bucket
#define led  13                      // Notification of SENDING DATA
#define DHTTYPE DHT22                // DHT 22  (AM2302)
//IPAddress SERVER(38,102,137,157);  // numeric IP for wunderground.com
char SERVER[] = "rtupdate.wunderground.com";           // Realtime update server
//char SERVER [] = "weatherstation.wunderground.com";  //standard server
char WEBPAGE [] = "GET /weatherstation/updateweatherstation.php?";
char ID [] = "BANNED";
char PASSWORD [] = "BANNED";

// Pick one below
// byte timeServer[] = {192, 43, 244, 18}; // time.nist.gov NTP server
byte timeServer[] = {
  132, 163, 4, 101};    // ntp1.nl.net NTP server  
//byte timeServer[] = {132, 163, 4, 102}; // time-b.timefreq.bldrdoc.gov NTP server
// byte timeServer[] = (132, 163, 4, 103);
const int NTP_PACKET_SIZE= 48;        // NTP time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE];             // buffer to hold incoming and outgoing packets 
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//Hard config my mac
//IPAddress ip(192,168,1,109);//Hard config ip

EthernetClient client;
unsigned int localPort = 8888;

const float pi = 3.14159265; // pi, not apple, not pumpkin, not pizza, not even related to Raspberry Pi. http://www.raspberrypi.org/ This is the REAL PI for RPM/Wind speed calculations
// Radius from vertical anemometer axis to a cup center (mm)
const int radio = 60;
// (changing "Wait")changes the windspeed calculation "period" automaticly
const unsigned long Wait = 1250;  // Amount of Time to wait till Re-connecting, Changing this also 
const unsigned long period = Wait * 2; // Measurement period (miliseconds)
const unsigned long IDLE_TIMEOUT_MS = 1000;
unsigned int counter = 0;         // pulse count for wind sensor 
unsigned int RPM = 0;             // Revolutions per minute
unsigned int Sample = 0;          // Sample number
unsigned int TIME = 10;           // count down from 10 and reat the rtc
unsigned int connections = 0;     // number of connections
unsigned int winddir = 0.0;       // Wind direction
unsigned int rainin = 0;          // counter for Rain 
unsigned int rainSample = 0;      // counter for Rain Samples  
float windspeedmph = 0/ 0.445;    // Wind speed (m/s) 
float windgustmph = 0;            // Max wind speed
//---DEWPOINT CALC!-------------------------------
double dewPoint(double tempf, double humidity)
{
  double A0= 373.15/(273.15 + tempf);
  double SUM = -7.90298 * (A0-1);
  SUM += 5.02808 * log10(A0);
  SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
  SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
  SUM += log10(1013.246);
  double VP = pow(10, SUM-3) * humidity;
  double T = log(VP/0.61078);   
  return (241.88 * T) / (17.558-T);
}
//---DEWPOINT CALC!-------------------------------

EthernetUDP Udp;                  // UDP for the time server
DHT dht(DHTPIN, DHTTYPE);         // DHT 22  (AM2302)
Adafruit_BMP085 bmp;              // BMP Sensor
RTC_DS1307 rtc; // Hardware RTC time
//RTC_Millis rtc; // Software RTC time
void setup(void)  
{  
  attachInterrupt(1, addrain, RISING); // attachInterrupt 1 sp that it can count the rain constantly 
  // (it does'nt tip that often and we dont need to calcualate). 
  Serial.begin(38400);
  Wire.begin();    //Rtc
  rtc.begin();     //uncomment to use hardware rtc
  //uncomment below to reset the time !
  //rtc.adjust(DateTime(__DATE__, __TIME__));// leave uncommented if using software rtc
  bmp.begin();
  dht.begin();
  pinMode(anemometer, INPUT); //Anemometer input(spins like made when the wind blows).
  digitalWrite(anemometer, HIGH); // set this high so when it detects a change it records it via INT(0)
  pinMode(rainTip, INPUT);// rain tip input
  digitalWrite(rainTip, HIGH);     // set this high so when it detects a change it records it via INT(1)
  Serial.println(F("NTP2RTC / Ethernet shield to Wunderground Test!\n")); 
  Serial.print(F("\nInitializing..."));
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    //Ethernet.begin(mac, ip);
    // Serial.println(ip);
  }
  Serial.print("Local I.P: ");
  Serial.println(Ethernet.localIP());

  Serial.println("Ready!");
  Serial.println("End of the Setup Function");
}
void loop(void)
{
  // Lets see what time the RTC is set at! 
  DateTime now = rtc.now();
  Serial.println("+++++++++++++++++++++++++");
  Serial.println("RTC current TIME ");

   if(now.hour() < 10){            // Zero padding if value less than 10 ie."09" instead of "9"
    Serial.print(" ");
    Serial.print((now.hour() > 12) ? now.hour() - 12 : ((now.hour() == 0) ? 12 : now.hour()), DEC); // Conversion to AM/PM  
  }
  else{
    Serial.print((now.hour() > 12) ? now.hour() - 12 : ((now.hour() == 0) ? 12 : now.hour()), DEC); // Conversion to AM/PM
  } 
  Serial.print(':');
  if (now.minute() <= 10){
    Serial.print("0");
  }
  Serial.print(now.minute());
  Serial.print(':');
  if (now.second() <= 10){
    Serial.print("0");
  }
  Serial.println(now.second());
  //Clear the rainin, windgustmph and rainSample every 10 loops. 
  //if you let the results runn they will add up on wunderground and report constant additions to wing gust and rain fall
  //But you must report the readings for a rew posts for wunderground to realize it is a real reading and not a false one
  if (rainSample >=10){
    rainin = 0;//Clear the rainCount
    rainSample = 0;// Clear the rain samples
    windgustmph = 0;  //clear Max wind speed
  }
  Sample ++;    // add "loop's
  TIME--;       // Subtract Count doun from 10 to reset the RTC
  rainSample++; // add and when limmit reached clear the results
  windvelocity();
  RPMcalc();
  WindSpeed();
  Heading();
  float tempf = dht.readTemperature(); 
  float humidity = dht.readHumidity(); 
  float baromin = bmp.readPressure()* 0.0002953;// Calc for converting Pa to inHg (wunderground)
  float dewptf = (dewPoint(dht.readTemperature(), dht.readHumidity())); //Dew point calc(wunderground)
  // max wind speed holder(wunderground)
  if (windspeedmph > windgustmph) {
    windgustmph = windspeedmph;
  }

  Serial.print("Posting Sample # ");// tells us how many loops
  Serial.println(Sample);
  Serial.print("Posts till clock Reset ");// tells us when the clock will try a reset might fail every now and then but werks!
  Serial.println(TIME);
  Serial.println();
  Serial.println("-------------------------------------");
/*
// Debug, or you can sit up all night watching it.
  Serial.print("wind dir= ");
  Serial.print(winddir);
  Serial.println(" deg's");
  Serial.print("windspeed mph= ");
  Serial.println(windspeedmph);
  Serial.print("wind gust mph= ");
  Serial.println(windgustmph);
  Serial.print("temp= ");
  Serial.print(tempf);
  Serial.println(" *F");
  Serial.print("rain in= ");
  Serial.println(rainin / 2.0 / 100.0);
  Serial.print("baro= ");
  Serial.print(baromin);
  Serial.println(" inHg");
  Serial.print("dew point= ");
  Serial.println(dewptf);
  Serial.print("humidity= ");
  Serial.println(humidity);
  Serial.println();
  Serial.print("Waiting ");
  Serial.print(Wait*2/1000.0);
  Serial.println(" seconds.");*/
  if (TIME  <= 1) {// Hey, if the TIME reached 1 then contact the NTP site and try to set the RTC to UTC ZULU
    TIME = 10; // Make the countdown start from 10 again
    Udp.begin(localPort);// Call from this line.......PLEASE
    Serial.println("UpDating CLOCK");
    Serial.print("RTC before: ");
    PrintDateTime(rtc.now());// Show me the time
    Serial.println();
    int packetSize = Udp.parsePacket(); //<<<<<<<<<<<<NEW LINE HERE 
    // send an NTP packet to a time server
    sendNTPpacket(timeServer);// Ask the bum for the time... and say please!

    // wait to see if a reply is available
    delay(1000);

    if ( Udp.available() ) {
      // read the packet into the buffer
      Udp.read(pb, packetSize);      // New from IDE 1.0 <<<<<<<<<<<<<MODIFIED LINE

      unsigned long t1, t2, t3, t4;
      t1 = t2 = t3 = t4 = 0;
      for (int i=0; i< 4; i++)
      {
        t1 = t1 << 8 | pb[16+i];      
        t2 = t2 << 8 | pb[24+i];      
        t3 = t3 << 8 | pb[32+i];      
        t4 = t4 << 8 | pb[40+i];
      }

      float f1,f2,f3,f4;
      f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
      f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
      f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
      f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;

      const unsigned long seventyYears = 2208988800UL;
      t1 -= seventyYears;
      t2 -= seventyYears;
      t3 -= seventyYears;
      t4 -= seventyYears;

      PrintDateTime(DateTime(t4)); 
      Serial.println(f4,4);
      Serial.println();
//WUNDERGROUND  COMMENTS
      //Adjust your timezone ... in my case I substract 5 hours for West Florida Time 
      //**** YOU MUST Add "X" hours (in my case + 5) to the  client.print(now.hour() + 5); ****
      // to get back to UTC ZULU, or Wunderground wont show RAPID FIRE or display incorrect times for you observations
//WUNDERGROUND  COMMENTS      
      t4 -= (5 * 3600L);     // Notice the L for long calculations!!
      t4 += 1;               // adjust the delay(1000) at begin of loop!
      if (f4 > 0.4) t4++;    // adjust fractional part, see above
      rtc.adjust(DateTime(t4));

      Serial.print("RTC after : ");
      PrintDateTime(rtc.now());
      Serial.println();

      Serial.println("done ...");
      // endless loop 
      //while(1);
    }
    else
    {
      Serial.println("No UDP available ...");
      Serial.println("ARRRRRRRRRRRRrrr !!!");// wait 10 more loop's.
    }

  }
  Serial.println("+++++++++++++++++++++++++");
  Serial.println();

  
  if (client.connect(SERVER, 80)) { // Money Shot!
    Serial.println("Sending DATA ");
    client.print(WEBPAGE); 
    client.print("ID=");
    client.print(ID);
    client.print("&PASSWORD=");
    client.print(PASSWORD);
    client.print("&dateutc=");
    client.print(now.year());
    client.print("-");
    client.print(now.month());
    client.print("-");
    client.print(now.day());
    client.print("+");
    client.print(now.hour()+5);// YOU MUST Add 5 hours to get back to UTC or Wunderground wont show RAPID FIRE
    client.print("%3A");
    client.print(now.minute());
    client.print("%3A");
    client.print(now.second());
    client.print("&winddir=");
    client.print(winddir);
    client.print("&windspeedmph=");
    client.print(windspeedmph);
    client.print("&windgustmph=");
    client.print(windgustmph);
    client.print("&tempf=");
    client.print(tempf);
    client.print("&rainin=");
    client.print(rainin / 2.0 / 100.0);
    client.print("&baromin=");
    client.print(baromin);
    client.print("&dewptf=");
    client.print(dewptf);
    client.print("&humidity=");
    client.print(humidity);
    //client.print("&action=updateraw");//Standard update
    client.print("&softwaretype=Arduino%20UNO%20version1&action=updateraw&realtime=1&rtfreq=2.5");//Rapid Fire
    client.println();
    Serial.println("Upload complete");

  } 
  else {
    Serial.println(F("Connection failed"));    
    return;
  }
  Serial.println("-------------------------------------");
  Serial.println("Server Response!");
  unsigned long lastRead = millis();
  while (client.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
      lastRead = millis();
    }
  }
  client.stop();// Wipe it off and get ready to do it again
    delay(Wait);// 30sec +/-
  Serial.println();
  Serial.println("-------------------------------------");
}// end loop
//MISC--------------------------------------------------
void windvelocity(){
  windspeedmph = 0;
  counter = 0;
  attachInterrupt(0, addcount, RISING);//anemometer
  //attachInterrupt(1, addrain, RISING); // Read the Rain tips Hall Effect
  unsigned long millis();                     
  long startTime = millis();
  while(millis() < startTime + period) {
  }
  detachInterrupt(0);
  //detachInterrupt(1);

}
void RPMcalc(){
  RPM=((counter*4)*60)/(period/1000);  // Calculate revolutions per minute (RPM)
}
void WindSpeed(){
  windspeedmph = ((2 * pi * radio * RPM)/60) / 1000;
}
void addcount(){
  counter++;
}
void addrain(){
  rainin++;
}
void Heading(){
  float windDir =(analogRead(vane)* 5.00 / 1023.0);    // Wind direction                
  if ((windDir > 4.94)||(windDir < 0.01))
    (winddir = 0.0);// North
  if ((windDir >= 0.02)&&(windDir < 0.30))
    (winddir = 22.5);//NNE
  if ((windDir >= 0.31)&&(windDir < 0.72))
    (winddir = 45.0);//NE
  if ((windDir >= 0.72)&&(windDir < 0.99))
    (winddir= 67.5);//ENE
  if ((windDir >= 1.00)&&(windDir < 1.25))
    (winddir = 90.0);//E
  if ((windDir >= 1.26)&&(windDir < 1.52))
    (winddir= 112.5);//ESE
  if ((windDir >= 1.53)&&(windDir < 1.91))
    (winddir= 135.0);//SE
  if ((windDir >= 1.92)&&(windDir < 2.40))
    (winddir = 157.5);//SSE
  if ((windDir >= 2.41)&&(windDir < 2.73))
    (winddir = 180.0);//S
  if ((windDir >= 2.74)&&(windDir < 2.96))
    (winddir = 202.5);//SSW
  if ((windDir >= 2.97)&&(windDir < 3.37))
    (winddir = 225.0);//SW
  if ((windDir >= 3.38)&&(windDir < 3.55))
    (winddir = 247.5);//WSW
  if ((windDir >= 3.56)&&(windDir < 3.85))
    (winddir = 270.0);//W
  if ((windDir >= 4.13)&&(windDir < 4.06))
    (winddir = 292.5);//WNW
  if ((windDir >= 4.07)&&(windDir < 4.32))
    (winddir = 315.0);//NW
  if ((windDir >= 4.33)&&(windDir < 4.93))
    (winddir = 337.5);//NNW
}


///////////////////////////////////////////
//
// MISC
// 
void PrintDateTime(DateTime t)
{
  char datestr[24];
  sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
  Serial.print(datestr);  
}


// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49; 
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 
#if ARDUINO >= 100
  // IDE 1.0 compatible:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(pb,NTP_PACKET_SIZE);
  Udp.endPacket(); 
#else
  Udp.sendPacket( pb,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
#endif	  

}
///////////////////////////////////////////
//
// End of program
//











Re: Weather station Wunderground

Posted: Wed Jan 29, 2014 12:45 am
by Franklin97355
Sorry, this would not compile for me. I'll have to figure out why later. Gave me an error with printdatetime.

Re: Weather station Wunderground

Posted: Mon Feb 17, 2014 8:20 pm
by fmbfla
Hmm, Compiled fer me with IDE 1.0.5
Binary sketch size: 28,062 bytes (of a 32,256 byte maximum)
I think i have made some changes if you would like the newest
Binary sketch size: 28,854 bytes (of a 32,256 byte maximum)

Code: Select all

/*
 This MODIFIED sketch connects to a website (http://www.rtupdate.wunderground.com)
 Using an Arduino Wiznet Ethernet shield To upload your weather conditions to wunderground.com,
 We make a standard HTTP GET request with the ID, PASSWORD and weather conditions as GET parameters.
 You must first create an account with wunderground for this to werk!
 The anemometer/windvane are from ebay looke for a inexpensiveone and upgrade it or make your own
 Various notes throughout attempt to explain why i did what i did to make it werk.
 This sketch also incorporates an NTP RTC update code to make sure that the time is always correct and
 resets the RTC Soft or Hard to UTC ZULU Wunderground wants "UTC ZULU HOUR".
 Results for this can be monitored @ http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KFLFORTM67
 
 Information on the Upload Protocol for wunderground can be found at http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol
 
 Binary sketch size: 28,278 bytes (of a 32,256 byte maximum)
 
 
 Circuit:
 * Arduino UNO adafruit http://www.adafruit.com/products/50
 * Ethernet shield attached to pins 10, 11, 12, 13 http://www.adafruit.com/products/201
 * DHT to pin A0 adafruit http://www.adafruit.com/products/393
 * Wind direction to pin A1 this is a DAVIS instrument which incorperates the anemometer (or make a home made one using a 360 var resistor)
 * Anemometer to Digtal 2 (interrupt 0)this is a DAVIS instrument (reed switch) 
 * and it looks like this http://www.skygeek.com/davis-instrument-7890-anemometer-mast-mount.html?utm_source=googlebase&utm_medium=shoppingengine&utm_content=davis-instrument-7890-anemometer-mast-mount&utm_BANNED=froogle&gclid=CLLugIr107wCFbB9Ogodi14AiA
 * Rain tip to Digital 3 (interrupt 1) (hall effect sensor) http://www.adafruit.com/products/158
 * BMP to I2C adafruit https://www.adafruit.com/products/391
 * RTC to I2C adafruit https://www.adafruit.com/products/264
 **
 Originaly created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe, based on work by Adrian McEwen
 **
 **
 Modified  To upload weather conditions to wunderground.com
 1,Jan 2014
 By the drunkin programer
 *
 */


#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>	      // New from IDE 1.0
#include <Wire.h>
#include "DHT.h"
#include <Adafruit_BMP085.h>
#include "RTClib.h"
//Pins 
#define DHTPIN  A0                   // DHT 22  (AM2302)
#define vane A1
#define anemometer  2                // D2 Wind speed
#define rainTip  3                   // pin D3 Rain bucket
#define led  13                      // Notification of SENDING DATA
#define DHTTYPE DHT22                // DHT 22  (AM2302)
//IPAddress SERVER(38,102,137,157);  // numeric IP for wunderground.com
char SERVER[] = "rtupdate.wunderground.com";           // Realtime update server
//char SERVER [] = "weatherstation.wunderground.com";  //standard server
char WEBPAGE [] = "GET /weatherstation/updateweatherstation.php?";
char ID [] = "KFLFORTM67";
char PASSWORD [] = "BANNED";

// Pick one below
// byte timeServer[] = {192, 43, 244, 18}; // time.nist.gov NTP server
byte timeServer[] = {
  132, 163, 4, 101};    // ntp1.nl.net NTP server  
//byte timeServer[] = {132, 163, 4, 102}; // time-b.timefreq.bldrdoc.gov NTP server
// byte timeServer[] = (132, 163, 4, 103);
const int NTP_PACKET_SIZE= 48;        // NTP time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE];             // buffer to hold incoming and outgoing packets 
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//Hard config my mac
//IPAddress ip(192,168,1,109);//Hard config ip

EthernetClient client;
unsigned int localPort = 8888;

const float pi = 3.14159265; // pi, not apple, not pumpkin, not pizza, not even related to Raspberry Pi. http://www.raspberrypi.org/ This is the REAL PI for RPM/Wind speed calculations
// Radius from vertical anemometer axis to a cup center (mm)
const int radio = 60;
// (changing "Wait")changes the windspeed calculation "period" automaticly
//const unsigned long 10min = 600*100L;  // Amount of Time to wait till Re-connecting, Changing this also 
const unsigned long period = 2500; // Measurement period (miliseconds)
const unsigned long IDLE_TIMEOUT_MS = 1000;
unsigned int counter = 0;         // pulse count for wind sensor 
unsigned int RPM = 0;             // Revolutions per minute
unsigned int Sample = 0;          // Sample number
unsigned int TIME = 10;           // count down from 10 and reset the rtc
unsigned int winddir = 0.0;       // Wind direction
unsigned int rainin = 0;          // counter for Rain 
unsigned int dailyrainin = 0;     // 24 hour counter for Rain
unsigned int rainCount = 20;       // counter for Rain


float windspeedmph = 0/ 0.445;    // Wind speed (m/s) 
float windgustmph = 0;            // Max wind speed
//---DEWPOINT CALC!-------------------------------
double dewPoint(double tempf, double humidity)
{
  double A0= 373.15/(273.15 + tempf);
  double SUM = -7.90298 * (A0-1);
  SUM += 5.02808 * log10(A0);
  SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
  SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
  SUM += log10(1013.246);
  double VP = pow(10, SUM-3) * humidity;
  double T = log(VP/0.61078);   
  return (241.88 * T) / (17.558-T);
}
//---DEWPOINT CALC!-------------------------------

EthernetUDP Udp;                  // UDP for the time server
DHT dht(DHTPIN, DHTTYPE);         // DHT 22  (AM2302)
Adafruit_BMP085 bmp;              // BMP Sensor
RTC_DS1307 rtc; // Hardware RTC time
//RTC_Millis rtc; // Software RTC time
void setup(void)  
{  
  // (it does'nt tip that often and we dont need to calcualate). 
  Serial.begin(38400);
  Wire.begin();    //Rtc
  rtc.begin();     //uncomment to use hardware rtc
  //uncomment below to reset the time !
  //rtc.adjust(DateTime(__DATE__, __TIME__));// leave uncommented if using software rtc
  bmp.begin();
  dht.begin();
  pinMode(anemometer, INPUT); //Anemometer input(spins like made when the wind blows).
  digitalWrite(anemometer, HIGH); // set this high so when it detects a change it records it via INT(0)
  pinMode(rainTip, INPUT);// rain tip input
  digitalWrite(rainTip, HIGH);     // set this high so when it detects a change it records it via INT(1)
  Serial.println(F("NTP2RTC / Ethernet shield to Wunderground Test!\n")); 
  Serial.print(F("\nInitializing..."));
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    //Ethernet.begin(mac, ip);
    // Serial.println(ip);
  }
  Serial.print("Local I.P: ");
  Serial.println(Ethernet.localIP());
  rainin = 0;          // zero the counter for Rain on start up to cut noise
  dailyrainin = 0;       // zero the 24 hour counter for Rain on start up to cut noise
  Serial.println("Ready!");
  Serial.println("End of the Setup Function");
}
void loop(void)
{

  DateTime now = rtc.now();
  Serial.println("Current TIME ");

  if(now.hour() < 10){            // Zero padding if value less than 10 ie."09" instead of "9"
    Serial.print(" ");
    Serial.print((now.hour() > 12) ? now.hour() - 12 : ((now.hour() == 0) ? 12 : now.hour()), DEC); // Conversion to AM/PM  
  }
  else{
    Serial.print((now.hour() > 12) ? now.hour() - 12 : ((now.hour() == 0) ? 12 : now.hour()), DEC); // Conversion to AM/PM
  } 
  Serial.print(':');
  if (now.minute() <= 10){
    Serial.print("0");
  }
  Serial.print(now.minute());
  Serial.print(':');
  if (now.second() <= 10){
    Serial.print("0");
  }
  Serial.println(now.second());
  Serial.print("Posting Sample # ");// tells us how many loops
  Serial.println(Sample);
  Serial.print("Clock Reset in ");// tells us when the clock will try a reset might fail every now and then but werks!
  Serial.println(TIME);
  Serial.print("Rain Reset in ");
  Serial.println(rainCount);
  Serial.println();
  //Clear the rainCount [rain inches over the past hour)] -- the accumulated rainfall in the past 60 min
  if (rainCount == 0) {
    rainin = 0;
    windgustmph = 0;  //clear Max wind speed
    rainCount = 20;
  }
  //Clear the rainCount [rain inches over the past 24 hour3)] -- the accumulated rainfall in the past 24 hours
  if (now.hour()== 24){
    dailyrainin = 0;
  }
  rainCount--;
  Sample ++;    // add the loop's for debugging
  TIME--;       // Subtract - Count doun from 10 to reset the RTC
  windvelocity();
  RPMcalc();
  WindSpeed();
  Heading();
  countRain();
  float tempf = dht.readTemperature(); 
  float humidity = dht.readHumidity(); 
  float baromin = bmp.readPressure()* 0.0002953;// Calc for converting Pa to inHg (wunderground)
  float dewptf = (dewPoint(dht.readTemperature(), dht.readHumidity())); //Dew point calc(wunderground)
  // max wind speed holder(wunderground)
  if (windspeedmph > windgustmph) {
    windgustmph = windspeedmph;
  }

  // for Debug, or you can sit up all night watching it.
  Serial.print("wind dir= ");
  Serial.print(winddir);
  Serial.println(" deg's");
  Serial.print("windspeed mph= ");
  Serial.println(windspeedmph);
  Serial.print("wind gust mph= ");
  Serial.println(windgustmph);
  Serial.print("temp= ");
  Serial.print(tempf);
  Serial.println(" *F");
  Serial.print("rain 1 Hr==== ");Serial.println(rainin / 2.0 / 100.0);
  Serial.print("rain 24 Hr=== ");Serial.println(dailyrainin / 2.0 / 100.0 );
  Serial.print("baro= ");
  Serial.print(baromin);
  Serial.println(" inHg");
  Serial.print("dew point= ");
  Serial.println(dewptf);
  Serial.print("humidity= ");
  Serial.println(humidity);
  Serial.println();
  Serial.print("Updates every  ");
  Serial.print(period/1000.0);
  Serial.println(" seconds.");
  if (TIME  <= 1) {// Hey, if the TIME reached 1 then contact the NTP site and try to set the RTC to UTC ZULU
    TIME = 10; // Make the countdown start from 10 again
    Udp.begin(localPort);// Call from this line.......PLEASE
    Serial.println();
    int packetSize = Udp.parsePacket(); //<<<<<<<<<<<<NEW LINE HERE 
    // send an NTP packet to a time server
    sendNTPpacket(timeServer);// Ask the bum for the time... and say please!

    // wait to see if a reply is available
    delay(500);

    if ( Udp.available() ) {
      // read the packet into the buffer
      Udp.read(pb, packetSize);      // New from IDE 1.0 <<<<<<<<<<<<<MODIFIED LINE

      unsigned long t1, t2, t3, t4;
      t1 = t2 = t3 = t4 = 0;
      for (int i=0; i< 4; i++)
      {
        t1 = t1 << 8 | pb[16+i];      
        t2 = t2 << 8 | pb[24+i];      
        t3 = t3 << 8 | pb[32+i];      
        t4 = t4 << 8 | pb[40+i];
      }

      float f1,f2,f3,f4;
      f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
      f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
      f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
      f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;

      const unsigned long seventyYears = 2208988800UL;
      t1 -= seventyYears;
      t2 -= seventyYears;
      t3 -= seventyYears;
      t4 -= seventyYears;

      PrintDateTime(DateTime(t4)); 
      Serial.println(f4,4);
      Serial.println();
      //WUNDERGROUND  COMMENTS
      //Adjust your timezone ... in my case I substract 5 hours for West Florida Time 
      //**** YOU MUST Add "X" hours (in my case + 5) to the  client.print(now.hour() + 5); ****
      // to get back to UTC ZULU, or Wunderground wont show RAPID FIRE or display incorrect times for you observations
      //WUNDERGROUND  COMMENTS      
      t4 -= (5 * 3600L);     // Notice the L for long calculations!!
      t4 += 1;               // adjust the delay(1000) at begin of loop!
      if (f4 > 0.4) t4++;    // adjust fractional part, see above
      Serial.println("UpDating CLOCK");
    Serial.print("RTC before: ");
    PrintDateTime(rtc.now());// Show me the time
      rtc.adjust(DateTime(t4));
      Serial.println("Clock Successfully Reset");
      Serial.print("Updated Time : ");
      PrintDateTime(rtc.now());
      Serial.println();
      Serial.println("done ...");
    }
    else
    {
      Serial.println("ARRRRRRRRRRRRrrr !!!");// wait 10 more loop's.
      Serial.println("No UDP available ...");
    }
  }
  Serial.println();
  if (client.connect(SERVER, 80)) { 
  Serial.println("-------------------------------------");
    Serial.println("Sending DATA ");
    client.print(WEBPAGE); 
    client.print("ID=");
    client.print(ID);
    client.print("&PASSWORD=");
    client.print(PASSWORD);
    client.print("&dateutc=");
    client.print(now.year());
    client.print("-");
    client.print(now.month());
    client.print("-");
    client.print(now.day());
    client.print("+");
    client.print(now.hour()+5);// I MUST Add 5 hours (USA EST)to get back to UTC or Wunderground wont show RAPID FIRE
    client.print("%3A");
    client.print(now.minute());
    client.print("%3A");
    client.print(now.second());
    client.print("&winddir=");
    client.print(winddir);
    client.print("&windspeedmph=");
    client.print(windspeedmph);
    client.print("&windgustmph=");
    client.print(windgustmph);
    //client.print("&windgustmph_10m=");
    //client.print(windgustmph_10m);//[mph past 10 minutes wind gust mph ]
    client.print("&tempf=");
    client.print(tempf);
    client.print("&rainin=");
    client.print(rainin / 2.0 / 100.0);
    client.print("&dailyrainin=");
    client.print(dailyrainin / 2.0 / 100.0); 
    client.print("&baromin=");
    client.print(baromin);
    client.print("&dewptf=");
    client.print(dewptf);
    client.print("&humidity=");
    client.print(humidity);
    //client.print("&action=updateraw");//Standard update
    client.print("&softwaretype=Arduino%20UNO%20version1&action=updateraw&realtime=1&rtfreq=2.5");//Rapid Fire
    client.println();
  } 
  else {
    Serial.println(F("Connection failed"));    
    return;
  }
  Serial.println("Server Response!");
  unsigned long lastRead = millis();
  while (client.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
      lastRead = millis();
    }
  }
  client.stop();
  Serial.println("-------------------------------------");
  Serial.println();
}// end loop
//MISC--------------------------------------------------
void windvelocity(){
  windspeedmph = 0;
  counter = 0;
  attachInterrupt(0, addcount, RISING);//anemometer
  unsigned long millis();                     
  long startTime = millis();
  while(millis() < startTime + period) {
  }
  detachInterrupt(0);

}
void countRain(){
  attachInterrupt(1, addrain, RISING); // Read the Rain tips Hall Effect
  unsigned long millis();                     
  long startTime = millis();
  while(millis() < startTime + period) {
  }

  detachInterrupt(1);

}
void RPMcalc(){
  RPM=((counter*4)*60)/(period/1000);  // Calculate revolutions per minute (RPM)
}
void WindSpeed(){
  windspeedmph = ((2 * pi * radio * RPM)/60) / 1000;
}
void addcount(){
  counter++;
}
void addrain(){
  rainin++;
  dailyrainin++;
}
void Heading(){
  float windDir =(analogRead(vane)* 5.00 / 1023.0);    // Wind direction                
  if ((windDir > 4.94)||(windDir < 0.01))
    (winddir = 0.0);// North
  if ((windDir >= 0.02)&&(windDir < 0.30))
    (winddir = 22.5);//NNE
  if ((windDir >= 0.31)&&(windDir < 0.72))
    (winddir = 45.0);//NE
  if ((windDir >= 0.72)&&(windDir < 0.99))
    (winddir= 67.5);//ENE
  if ((windDir >= 1.00)&&(windDir < 1.25))
    (winddir = 90.0);//E
  if ((windDir >= 1.26)&&(windDir < 1.52))
    (winddir= 112.5);//ESE
  if ((windDir >= 1.53)&&(windDir < 1.91))
    (winddir= 135.0);//SE
  if ((windDir >= 1.92)&&(windDir < 2.40))
    (winddir = 157.5);//SSE
  if ((windDir >= 2.41)&&(windDir < 2.73))
    (winddir = 180.0);//S
  if ((windDir >= 2.74)&&(windDir < 2.96))
    (winddir = 202.5);//SSW
  if ((windDir >= 2.97)&&(windDir < 3.37))
    (winddir = 225.0);//SW
  if ((windDir >= 3.38)&&(windDir < 3.55))
    (winddir = 247.5);//WSW
  if ((windDir >= 3.56)&&(windDir < 3.85))
    (winddir = 270.0);//W
  if ((windDir >= 4.13)&&(windDir < 4.06))
    (winddir = 292.5);//WNW
  if ((windDir >= 4.07)&&(windDir < 4.32))
    (winddir = 315.0);//NW
  if ((windDir >= 4.33)&&(windDir < 4.93))
    (winddir = 337.5);//NNW
}


///////////////////////////////////////////
//
// MISC
// 
void PrintDateTime(DateTime t)
{
  char datestr[24];
  sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
  Serial.print(datestr);  
}


// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49; 
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 
#if ARDUINO >= 100
  // IDE 1.0 compatible:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(pb,NTP_PACKET_SIZE);
  Udp.endPacket(); 
#else
  Udp.sendPacket( pb,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
#endif	  

}
///////////////////////////////////////////
//
// End of program
//