0

Ardino weather/webcam/webserver up and running.
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Ardino weather/webcam/webserver up and running.

by EVRE on Sat Aug 31, 2013 12:23 pm

I built a webserver based on the Arduino Mega, it does the following:
-Take sensor readings and picture every 10 min and store on SD card.
-Barometric pressure
-outside humidity
-inside humidity
-outside temperature
-inside temperature
-outside ambient light level (needs better sensor, like the one available on Adafruit)

Server main page.jpg
Server main page.jpg (139.21 KiB) Viewed 1464 times

The server has its quirks and downfalls.
When there are over ~1800 images stored on the SD card, it becomes /more/ unstable. I have to remember to copy off the images once a month. At ~1800 images, the ethernet crashes, but it still logs data, over ~2200 images, the entire board periodically crashes and no data is logged.

All fixed now. works like a champ for months!

It goes offline during the sensor readings and picture capturing for about 30 seconds.

If you want to visit it, please visit 1 min after the 10's of the hr. (1:01pm, 10:51, etc.)
http://ptr3.no-ip.biz:8081


*edit* the crawlers are DDoS my Arduino, manually enter the addy to browser...................... grr...
Last edited by EVRE on Thu Feb 19, 2015 5:10 pm, edited 3 times in total.
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by adafruit_support_bill on Sat Aug 31, 2013 12:39 pm

Nice project! Thanks for posting.

adafruit_support_bill
 
Posts: 73190
Joined: Sat Feb 07, 2009 10:11 am

Re: Ardino weather/webcam/webserver up and running.

by EVRE on Sat Aug 31, 2013 8:57 pm

The ethernet crashed =/ guess it didnt like the attention of www.
Good news was it didnt miss a beat logging data.

I cant wait for Adafruit to finish the coding for their wifi CC3000. I'm hoping it will bring better stability to serving the www with an Arduino.

My impression of the Arduino Ethernet is, that if it gets too many requests for connections, it just gives up and hangs...?
My project, generally has a pretty good uptime. :?
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by EVRE on Sat Aug 31, 2013 11:26 pm

Lesson learned.. Arduino's ethernet is finiky enough, dont put it online where the search crawlers can find it!
They are like a DDoS (Denial of service attack) to the arduino. :evil:

I was happy to see a few forum members viewed it between crashes this afternoon.
With just myself and a few friends I have had it stay running for at least a week.

..Again hoping for a more robust Ethernet implementation!
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by wlbryce on Tue Sep 03, 2013 11:19 pm

Can you post your code and build info for this project? Would like to duplicate it at my site.
Thanks!

wlbryce
 
Posts: 9
Joined: Sat Nov 01, 2008 6:50 pm

Re: Ardino weather/webcam/webserver up and running.

by EVRE on Wed Feb 18, 2015 11:02 pm

Revisited this recently.
Its been running for a few year with very few hiccups.

I wasnt happy with the readings of the temperature sensor so close to the house so I built a remote station using an uno, DHT22, BMP180 and an NRF24 module to send the data back.
The NRF24 module will not play nice with my Mega so I used an Uno to handle the wireless communication and it connects to the Mega's serial3.

The remote station in this case is being ran by solar.. not because I need to, but because I can!
Solar Weather station.jpg
Solar Weather station.jpg (134.94 KiB) Viewed 792 times


Here is my terribly commented.... sloppy code. I'm sure a veteran will be shaking their head.. I'm open to suggestions on cleaning it up.

Code: Select all | TOGGLE FULL SIZE
/*
Written by Tevis Cox =^;~;^=
Version 4.2
2/18/15
*/
  #include <avr/pgmspace.h>
  #include <Adafruit_VC0706.h>
  #include <Adafruit_BMP085.h>
  #include <SdFat.h>
  #include <SdFatUtil.h>
  #include <SPI.h>
  #include <Wire.h>
  #include <RTClib.h>
  #include <SoftwareSerial.h>   
  #include <Ethernet.h>
  #include <EthernetUdp.h>
  #include <DHT.h>
  #include <EEPROM.h>
  #include<stdlib.h>

  //#include <OneWire.h>
 
  #define BUFSIZ 100
  #define DHTPIN 2
  #define DHTTYPE DHT11
  //#define BADTEMP -1000
    char p_buffer[80];
  #define P(str) (strcpy_P(p_buffer, PSTR(str)), p_buffer)
 
 
  //Ethernet Variables
  uint8_t bufindex;
  const uint8_t maxbyte=255;
  uint8_t buf[maxbyte];
  byte mac[] = {0x90,0x42,0xDA,0x00,0x37,0xFF};
  byte ip[] = {192,168,3,251};
  byte gateway[] = { 192,168,3,1 };
  // the subnet:
  byte subnet[] = { 255, 255, 255, 0 };
 
  char rootFileName[] = ("index.htm");
  EthernetServer server(8081);
 
  EthernetUDP Udp;
  char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
  char  ReplyBuffer[16];

 
  SdFat sd;
  SdFile imgFile;
  Sd2Card card;
  SdVolume volume;
  SdFile root;
  SdFile file;
  SdFile Log;
 
  //Hardware initializers
  Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);
  DHT dht(DHTPIN, DHT22);
  DHT dht2(44, DHT22);
  RTC_DS1307 RTC;
  Adafruit_BMP085 bmp;
   SoftwareSerial lcd = SoftwareSerial(0,7); //set tx to digital pin 7 LCD
 
  //Variables
  DateTime now;
  int Hour, Hour24, Minute, sec, Month, Day, Year;

  String TimeStamp, LastUpDate, TheTime;
  String strLastUpdateTime;
  unsigned long NextUpdateTime, LastUpdateTime, OnSince;
  unsigned long currentMillis, currentMillis2;
  bool DLST = false;
  bool up;
 
  String LastPicName;
  float DHThumidity,BMPpressure, DHThumidityOS, DHTtemperatureOS;
  float DSInsidetemp, DSOutsidetemp, DHTtemperature,BMPtemperature;
  float DewPoint, inHg;
  float prvBMP = 100;
  int hiT = -100;
  int lowT = 200;
 
  long previousMillis = 0;
 
  int tempmin, intUpdateMinute;
  int Hits;
 
  // Variables used for remote station
   
 String DHTOStemp;
 String BMP;
 String BMPtemp;
 String Humidity;
 String Brightness;
 String BattVolts;
 String SolarVolts;
 String ChargeAmps;
 
int msg[1];

const uint64_t pipe = 0xE8E8F0F0E1LL;
int lastmsg = 1;
String theMessage = "";
 
  //end of those variables
 
  //Display Custom Characters
    byte uparrow[8] = {
    0b00100,
    0b01110,
    0b10101,
    0b00100,
    0b00100,
    0b00000,
    0b00000,
    0b00000
  };
 
  byte dwnarrow[8] = {
    0b00000,
    0b00000,
    0b00000,
    0b00100,
    0b00100,
    0b10101,
    0b01110,
    0b00100
  };
 
  byte hi[8] = {
    0b11011,
    0b11010,
    0b00011,
    0b00010,
    0b10101,
    0b11100,
    0b10101,
    0b10101
  };
 
  byte lo[8] = {
    0b11011,
    0b11010,
    0b00011,
    0b00010,
    0b10000,
    0b10010,
    0b10101,
    0b11010
  };
 
  byte degsym[8] = {
    0b11100,
    0b10100,
    0b11100,
    0b00000,
    0b00111,
    0b00100,
    0b00110,
    0b00100
  };
 
  byte coln0sym[8] ={
    0b00000,
    0b00000,
    0b00100,
    0b00000,
    0b00000,
    0b00100,
    0b00000,
    0b00000
  };
 
  byte coln1sym[8] ={
    0b00000,
    0b01110,
    0b01010,
    0b01110,
    0b01110,
    0b01010,
    0b01110,
    0b00000
  };
 
  byte prcntsym[8]= {
    0b10010,
    0b00100,
    0b01000,
    0b10010,
    0b00000,
    0b00000,
    0b00000,
    0b00000
  };
 
 
 
  #define error(s) error_P(PSTR(s))
  void error_P(const char* str) {
    PgmPrint("error: ");
    SerialPrintln_P(str);
    if (card.errorCode()) {
      PgmPrint("SD error: ");
      Serial.print(card.errorCode(), HEX);
      Serial.print(',');
      Serial.println(card.errorData(), HEX);
    }
    while(1);
  }
  //█████████████████████████████████████
  //Void Setup()
  //█████████████████████████████████████
  void setup() {
           Serial.begin(9600);
           Serial2.begin(9600);
           
           //Wire.begin(); //Start Wire 
           RTC.begin(); //Start the RTC
           lcd.begin(9600);
           dht.begin(); //Start DHT
             if (!bmp.begin()) {
             Serial.println(P("Could not find a valid BMP085 sensor, check wiring!"));
             while (1) {}
            }
           
            dht2.begin(); //Start DHT
             if (!bmp.begin()) {
             Serial.println(P("Could not find a valid BMP085 sensor, check wiring!"));
             while (1) {}
            }
           
           pinMode(10, OUTPUT);
           digitalWrite(10, HIGH);
           
             // see if the card is present and can be initialized:
            if (!sd.begin(4, SPI_FULL_SPEED)) sd.initErrorHalt();
            if (!card.init(SPI_FULL_SPEED, 4)) error("card.init failed!");
            if (!volume.init(&card)) error("vol.init failed!");
          //Webserver init
            Serial.println(volume.fatType(),DEC);
            Serial.println();
            if (!root.openRoot(&volume)) error("openRoot failed");
          //  PgmPrintln("Files found in root:");
          //  root.ls(LS_DATE | LS_SIZE);
          //  Serial.println();
          //  PgmPrintln("Files found in all dirs:");
          //  root.ls(LS_R);
          //  Serial.println();
            PgmPrintln("Done");
            Ethernet.begin(mac, ip, gateway, subnet);
            server.begin();
            Udp.begin(8081);
             // Try to locate the camera
            if (cam.begin()) {
              Serial.println(P("Camera Found:"));
            } else {
              Serial.println(P("No camera found?"));
              return;
            }
             cam.setImageSize(VC0706_640x480);        // biggest
           
            LCDsetContrast(40); // contrast 1-50
            LCDsetBrightness(2); // brightness 1-8
            LCDcreateChar(1, degsym);
            LCDcreateChar(2, coln0sym);
            LCDcreateChar(3, coln1sym);
            LCDcreateChar(4, prcntsym);
            LCDcreateChar(5, uparrow);
            LCDcreateChar(6, dwnarrow);
            LCDcreateChar(7, hi);
            LCDcreateChar(8, lo);
           
             PgmPrint("Free RAM: ");
            Serial.println(FreeRam());
         
            BootUpdate();
  }
 
  //█████████████████████████████████████
  //Void Loop()
  //█████████████████████████████████████

  void loop(){
    currentMillis = millis();
    // to run once a second
    if(currentMillis - previousMillis > 1000) {
         previousMillis = currentMillis;
         SetTime();
         LCDdisplay();
         tempmin = Minute;
             
             //to run once a minute
             if(tempmin != intUpdateMinute){
              intUpdateMinute = tempmin;
             
              HiLowT();
              GenTimeStamp();
              UpdateSensors();
              LCDclear();
              LCDdisplay();
                //to run once every 10 min
                if(tempmin %10 ==0){
               
                  Update();
                  BMPpoll();
                  CaptureCameraFrame();
                  BMPchange();
                  LogFileWrite();//Last thing to do!             
                }
             }
       }
   
       WebServer();
    while (Serial2.available()) {
    delay(3); 
    char c = Serial2.read();
    theMessage += c;
  }   
       theMessage.trim();
       ParseOut();
       theMessage= "";
       
      }
   
 
 


  //█████████████████████████████████████
  //LCD Display
  //█████████████████████████████████████
 
void LCDdisplay(){
         
       
          String AMPM = P("am");
          TheTime ="";
         

          if(Hour >=12){
           AMPM = P("pm");
          }
         
          if(Hour >=13){
           Hour = Hour -12;
          }
          if(Hour == 0){
           Hour = 12;
          }
         
          LCDsetCursor(1,1);
       
          if(Hour < 10){
           lcd.print(" ");
          }
          lcd.print(Hour);
          TheTime += Hour;
          TheTime += P(":");
          if(sec %2 == 0){
           LCDsetCursor(1,3);
           lcd.write(2);
          }
          if(sec %2 != 0){
          LCDsetCursor(1,3);
          lcd.write(3);
          }
          if(Minute < 10){
           lcd.print(P("0"));
          TheTime+=  P("0");
          }
          lcd.print(Minute);
          lcd.print(AMPM);
          TheTime += Minute;
          TheTime += AMPM;
         
          LCDsetCursor(1,11);
          lcd.print(Month);
          lcd.print(P("/"));
          lcd.print(Day);
          lcd.print(P("/"));
          lcd.print(Year);
         
          LCDsetCursor(2,1);
          lcd.print(P("In     Out   bmp in"));
          LCDsetCursor(3,1);
          lcd.print(DHTtemperature,1);
          lcd.write(1);
          LCDsetCursor(3,8);
          lcd.print(DHTOStemp.toFloat(),1);
          lcd.write(1);
          LCDsetCursor(3,14);
          lcd.print(inHg,3);
          if(up == true){
           lcd.write(5);
          }
          else{
           lcd.write(6);
          }
          LCDsetCursor(4,1);
          lcd.print(DHThumidity,1);
          lcd.write(4);
          LCDsetCursor(4,8);
          lcd.print(DHThumidityOS,1);
          lcd.write(4);
         
          // High Low T
          LCDsetCursor(4,14);
          lcd.print(hiT);
          lcd.write(7);
          LCDsetCursor(4,18);
          lcd.print(lowT);
          lcd.write(8);
         
         
  }
 
  //█████████████████████████████████████
  //Time Management
  //█████████████████████████████████████
 
    void SetTime(){
             
      now = RTC.now();
       
         if(DLST == false){
         Hour = now.hour();
         Hour24 = Hour;
         Minute = now.minute();
         sec = now.second();
         Month = now.month();
         Day = now.day();
         Year = now.year();
         }
         
         if(DLST == true){
         DateTime future (now.unixtime()+3600);
         Hour = future.hour();
         Hour24 = Hour;
         Minute = future.minute();
         sec = future.second();
         Month = future.month();
         Day = future.day();
         Year = future.year();
         }
  }
 
  String UpTime(){
          unsigned long secs, days, hours, minutes;

          String Time;
            secs = (millis() /1000);
                     
            minutes = secs/60;
            hours = minutes/60;
            days = hours/24;
            secs = secs-(minutes*60);
            minutes = minutes-(hours*60);
            hours = hours-(days*24);
           
            if(days != 0){
            Time += days;
            Time += (P(" Days ")); 
            }
            if(hours !=0){
            Time += hours;
            Time += (P(" Hours ")); 
            }
            if(minutes != 0){
            Time += minutes;
            Time += (P(" Minutes ")); 
            }
            Time += secs;
            Time += (P(" Seconds"));
           
       
            return Time;
  }
 
  void UpdateSensors(){
        DHTpoll();
        //BMPpoll(); 
  }
 
  void Update(){
     
        LastUpdateTime = now.unixtime();
        strLastUpdateTime = TimeStamp;
        NextUpdateTime = LastUpdateTime + 600;
        LastUpDate = P("");
        LastUpDate += Month;
        LastUpDate +=P(("/"));
        LastUpDate += Day;
        LastUpDate +=P(("/"));
        LastUpDate += Year;


       
       
       
       
  }
 
  int TimeToNextUpdate(){
         
         unsigned long time2 =  now.unixtime();
         unsigned long time;
         
         time = NextUpdateTime - time2;
         
         Serial.print(P("UnixTime "));
         Serial.println(time2);
         Serial.print(P("NextUpdateTime "));
         Serial.println(NextUpdateTime);
         Serial.print(P("Time TO Next Update "));
         Serial.println(time);
         
           return time;
  }
 
  void GenTimeStamp(){
         
          TimeStamp = P("");
          if(Month < 10){
            TimeStamp += P("0");
            TimeStamp += Month;
          }else {
            TimeStamp += Month;
          }
            if(Day < 10){
            TimeStamp += P("0");
            TimeStamp += Day;
          }else {
            TimeStamp += Day;
          }
            if(Hour24 < 10){
            TimeStamp += P("0");
            TimeStamp += Hour24;
          }else {
            TimeStamp += Hour24;
          }
            if(Minute < 10){
            TimeStamp += P("0");
            TimeStamp += Minute;
          }else {
            TimeStamp += Minute;
          }
           // if(now.second() < 10){
           // TimeStamp += "0";
           // TimeStamp += now.second();
          //}else {
          //  TimeStamp += now.second();
         // }
          Serial.print(P("TimeStamp "));
          Serial.println(TimeStamp);
   
  }
 
  //█████████████████████████████████████
  //Simple Functions
  //█████████████████████████████████████

 
char* ToAscii(double temp)
{
  char ascii[32];
  int frac;
  frac=(unsigned int)(temp*1000)%1000;  //get three numbers to the right of the deciaml point

  itoa((int)temp,ascii,10);
  strcat(ascii,".");
  itoa(frac,&ascii[strlen(ascii)],10); //put the frac after the deciaml
 Serial.println(ascii);
  return ascii;
}
 
void BootUpdate(){
    SetTime();
    Update();
    DHTpoll();
    BMPpoll();
   GenTimeStamp();
   prvBMP = BMPpressure;
   CaptureCameraFrame();
  }
 
  float ConvertCtoF(float temp){
   temp = temp / 5 * 9 +32;
  return temp;
  }
 
void EEPROMWriteInt(int p_address, int p_value)
     {
     byte lowByte = ((p_value >> 0) & 0xFF);
     byte highByte = ((p_value >> 8) & 0xFF);
 
     EEPROM.write(p_address, lowByte);
     EEPROM.write(p_address + 1, highByte);
     }
 
  //This function will read a 2 byte integer from the eeprom at the specified address and address + 1
  unsigned int EEPROMReadInt(int p_address)
     {
     byte lowByte = EEPROM.read(p_address);
     byte highByte = EEPROM.read(p_address + 1);
 
       return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
     }
 
  //incriment the hitcounter +1 when called.
void hitcounter(){
   
    Hits = EEPROMReadInt(0);
    Hits +=1;
    EEPROMWriteInt(0, Hits);
   
  }
 
 
  //█████████████████████████████████████
  //Log File
  //█████████████████████████████████████
void LogFileWrite(){
            sd.chdir(P("/DATALOG"));
            if (!Log.open(P("LOG.csv"), O_CREAT | O_APPEND | O_RDWR)) {
              sd.errorHalt(P("opening file for write failed"));
            }
 
            Log.print(Month);
            Log.print(P("/"));
            Log.print(Day);
            Log.print(P("/"));
            Log.print(Year);
            Log.print(P("  "));
             if(Hour24 <10){
              Log.print(P("0"));
            }
            Log.print(Hour24);
            Log.print(P(":"));
              if(Minute <10){
              Log.print(P("0"));
            }
            Log.print(Minute);
            Log.print(P(", "));
            Log.print(strLastUpdateTime);
            Log.print(P(", "));
            Log.print(BMPpressure,3);
            Log.print(P(", "));
            Log.print(BMPtemperature);
            Log.print(P(", "));
            Log.print(DHThumidity);
            Log.print(P(", "));
            Log.print(DHTtemperature);
            Log.print(P(", "));
            Log.print(DHThumidityOS);
            Log.print(P(", "));
            Log.print(DHTtemperatureOS);
            Log.print(P(", "));
            Log.print(DewPoint);
            Log.print(P(", "));
            Log.print(analogRead(A0));
            Log.print(P(", "));
            Log.print(DHTOStemp);
            Log.print(P(", "));
            Log.print(Humidity);
            Log.print(P(", "));
            Log.print(BMP);
            Log.print(P(", "));
            Log.print(BMPtemp);
            Log.print(P(", "));
            Log.print(Brightness);
            Log.print(P(", "));
            Log.print(BattVolts);
            Log.print(P(", "));
            Log.print(SolarVolts);
            Log.print(P(", "));
            Log.println(ChargeAmps);
            Log.close();
            sd.chdir();
           
            Serial.println(P("wrote to log"));
  }
 
 
  //█████████████████████████████████████
  //Start Sensors Code, weather
  //█████████████████████████████████████
 
  void BMPchange(){
    if(BMPpressure > prvBMP){
     up = true;
    }
    else{
     up = false;
    }
  prvBMP = BMPpressure;
  }
 
  int HLday = -1;
  void HiLowT(){ // used to reset high/low temp (Bug: works for 1 mo, quits 1st day next mo.
    if(HLday != Day){
     hiT = -100;
    lowT = 200;
     HLday = Day;
    }
   
    if(DHTOStemp.toFloat() > hiT){
     hiT = DHTOStemp.toFloat();
    }
    if(DHTOStemp.toFloat() < lowT){
     lowT = DHTOStemp.toFloat();
    }
   
    }
 
 
  void DHTpoll(){
          double temptemp;
          DHThumidity = dht.readHumidity();
          DHTtemperature = ConvertCtoF(dht.readTemperature());
          DHThumidityOS = dht2.readHumidity();
          temptemp = dht2.readTemperature();
          DHTtemperatureOS = ConvertCtoF(temptemp);
          DewPoint = ConvertCtoF(dewPoint(temptemp, DHThumidityOS));
         
    }
 

void BMPpoll(){
         double tempBMP = 0;
         int i;
         for(i=0; i<10;i++){
           tempBMP += bmp.readPressure();
          delay(500);
         }
         tempBMP = tempBMP*.1;
         inHg = (0.2952998751 * tempBMP)*.001;
         BMPtemperature =  ConvertCtoF(bmp.readTemperature());
         BMPpressure = tempBMP *.001; //read in kPa
  }
 
double dewPoint(double celsius, double humidity)
  {
          double RATIO = 373.15 / (273.15 + celsius);  // RATIO was originally named A0, possibly confusing in Arduino context
          double SUM = -7.90298 * (RATIO - 1);
          SUM += 5.02808 * log10(RATIO);
          SUM += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ;
          SUM += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
          SUM += log10(1013.246);
          double VP = pow(10, SUM - 3) * humidity;
          double T = log(VP/0.61078);   // temp var
          return (241.88 * T) / (17.558 - T);
  }
 
  //█████████████████████████████████████
  //Start Web Server Code
  //█████████████████████████████████████
void WebServer()
  {
        char clientline[BUFSIZ];
        char *filename;
        int index = 0;
        int image = 0;
        EthernetClient client = server.available();
        if (client) {
          boolean current_line_is_blank = true;
          index = 0;
          while (client.connected()) {
            if (client.available()) {
              char c = client.read();
              if (c != '\n' && c != '\r') {
                clientline[index] = c;
                index++;
                if (index >= BUFSIZ)
                  index = BUFSIZ -1;
                continue;
              }
              clientline[index] = 0;
              filename = 0;
              Serial.println(clientline);
              if (strstr(clientline, (P("GET / "))) != 0) {
                //filename = rootFileName;
                INDEX();
                delay(1);
                client.stop();
                break;
              }
              if (strstr(clientline, (P("GET /"))) != 0) {
                if (!filename) filename = clientline + 5;
                (strstr(clientline, (P(" HTTP"))))[0] = 0;
                Serial.println(filename);
                if(filename == P("data")){
                  datahtm();
                  delay(1);
                  client.stop();
                  break;
                }
                if (! file.open(&root, filename, O_READ)) {
                  //client.println(P("HTTP/1.1 404 Not Found"));
                  //client.println(P("Content-Type: text/html"));
                  //client.println();
                  //file.open(&root,(P("404error.htm")),O_READ);  //Opens the file 404error.htm from the root directory.  This is if the file doesn't exist
                  //int16_t c;
                  //while((c=file.read())>=0){  //sends file (yes it is the slow way, but if you don't have a picture, thats ok
                    //client.write((char)c);
                  //}
                  //file.close();
                  datahtm();
                  break;
                }
                Serial.println(P("Opened!"));
                client.println(P("HTTP/1.1 200 OK"));
                if (strstr(filename, P(".htm")) != 0)
                  client.println(P("Content-Type: text/html"));
                else if (strstr(filename, P(".css")) != 0)
                  client.println(P("Content-Type: text/css"));
                else if (strstr(filename, P(".png")) != 0)
                  client.println(P("Content-Type: image/png"));
                else if (strstr(filename, P(".jpg")) != 0)
                  client.println(P("Content-Type: image/jpeg"));
                else if (strstr(filename, P(".gif")) != 0)
                  client.println(P("Content-Type: image/gif"));
                else if (strstr(filename, P(".3gp")) != 0)
                  client.println(P("Content-Type: video/mpeg"));
                else if (strstr(filename, P(".pdf")) != 0)
                  client.println(P("Content-Type: application/pdf"));
                else if (strstr(filename, P(".js")) != 0)
                  client.println(P("Content-Type: application/x-javascript"));
                else if (strstr(filename, P(".xml")) != 0)
                  client.println(P("Content-Type: application/xml"));
                else
                  client.println(P("Content-Type: text"));
                client.println();
                int16_t c;
                bufindex=0;
                while ((c = file.read()) >= 0) {
                  buf[bufindex++]=((char)c);
                  if(bufindex==maxbyte)
                  {
                    client.write(buf, maxbyte);
                    bufindex=0;
                  }
                }
                file.close();
                if(bufindex>0)
                {
                  client.write(buf, bufindex);
                }
                bufindex=0;
              }
              else {
                client.println(P("HTTP/1.1 404 Not Found"));
                client.println(P("Content-Type: text/html"));
                client.println();
                file.open(&root,P("404error.htm"),O_READ);  //this is if the "GET /" fails to retrieve data
                int16_t c;
                while((c=file.read())>=0)  //sends file.  still not fast.
                  client.write((char)c);
                }
                file.close();
              }
              break;
            }
          }
          delay(1);
          client.stop();
    }
 
  //█████████████████████████████████████
  //Start Camera Code
  //█████████████████████████████████████
void CaptureCameraFrame(){
              // Open the file for writing
            char filename[13];
          String TempFileName;
          GenTimeStamp();
          TempFileName = TimeStamp;
         
          TempFileName += P(".JPG");
          TempFileName.toCharArray(filename,13);
          //Serial.println(filename);
            sd.chdir();
          sd.chdir(P("/IMGLOG"));
              if (sd.exists(filename)) {
                  sd.chdir();
                return;
              }
             if (! cam.takePicture()){
             
              Serial.println(P("Failed to snap!"));
              return;
            }
            else
              Serial.print(P("Picture taken!"));
              Serial.println(filename);
           
         
            if (!imgFile.open(filename, O_CREAT | O_TRUNC | O_RDWR)) {
              sd.errorHalt(P("opening file for write failed"));
            }
            // Get the size of the image (frame) taken 
            uint16_t jpglen = cam.frameLength();
            Serial.print(jpglen, DEC);
            Serial.println(P(" byte image"));
         
            int32_t time = millis();
            pinMode(8, OUTPUT);
            // Read all the data up to # bytes!
            byte wCount = 0; // For counting # of writes
            while (jpglen > 0) {
              // read 32 bytes at a time;
              uint8_t *buffer;
              uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
              buffer = cam.readPicture(bytesToRead);
              imgFile.write(buffer, bytesToRead);
              if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
                Serial.print('.');
                wCount = 0;
              }
              //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
              jpglen -= bytesToRead;
            }
            imgFile.close();
            LastPicName = filename;
            sd.chdir();
            cam.resumeVideo();
            Serial.println(P("Done!"));
  }
 
  //█████████████████████████████████████
  //Start Remote weather recieve code
  //█████████████████████████████████████
 
  void ParseOut(){
  int spaces[10];
  int spacestemp =0;
  if(theMessage[0] == 's'){
    Serial.println(theMessage.length());
    DHTOStemp = "";
    BMP = "";
    BMPtemp = "";
    Humidity = "";
    Brightness = "";
    BattVolts = "";
    SolarVolts = "";
    ChargeAmps = "";
   
    for(int i =0; i< theMessage.length(); i++){
     if(theMessage[i] == ' '){
      spaces[spacestemp] = i;
      spacestemp +=1;
      Serial.print(i);
      Serial.print(" ");
     }
     
    }
    Serial.println();
    //Read DHTOStemp out of string
    for(int i =(spaces[0])+1; i< spaces[1]; i++){
     DHTOStemp += theMessage[i];
    }
   
    for(int i =(spaces[1])+1; i<spaces[2]; i++){
     Humidity += theMessage[i];
    }
   
    for(int i =(spaces[2])+1; i<spaces[3]; i++){
     BMP += theMessage[i];
    }
   
    for(int i =(spaces[3])+1 ; i<spaces[4]; i++){
     BMPtemp += theMessage[i];
    }   
   
    for(int i =(spaces[4])+1; i<spaces[5]; i++){
     Brightness += theMessage[i];
    }
   
    for(int i =(spaces[5])+1; i<spaces[6]; i++){
     BattVolts += theMessage[i];
    }
   
    for(int i =(spaces[6])+1; i<spaces[7]; i++){
     SolarVolts += theMessage[i];
    }
   
    for(int i =(spaces[7])+1; i<spaces[8]; i++){
     ChargeAmps += theMessage[i];
    }
    Serial.println(DHTOStemp);
    Serial.println(Humidity);
    Serial.println(BMP);
    Serial.println(BMPtemp);
    Serial.println(Brightness);
    Serial.println(BattVolts);
    Serial.println(SolarVolts);
    Serial.println(ChargeAmps);   
   
   
  }

 
}
 
  //█████████████████████████████████████
  //ROOT - Index webpage code
  //█████████████████████████████████████
 

 
void INDEX(){
            // listen for incoming clients
          EthernetClient client = server.available();
          if (client) {
            Serial.println(P("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(P("HTTP/1.1 200 OK"));
                  client.println(P("Content-Type: text/html"));
                  client.println(P("Connection: close"));
                  client.println();
                  client.println(P("<!DOCTYPE HTML>"));
                  client.println(P("<html>"));
                  client.println(P("<head> "));
                  client.println(P("<link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\"> "));
                  client.println(P("<link rel=\"icon\" href=\"/favicon.ico\" type=\"image/x-icon\"> "));
                  client.println(P("<title>PTR Weather Station</title> "));
                  // add a meta refresh tag
                  client.println(P("<meta http-equiv=\"refresh\" content=\""));
                  client.print(float(TimeToNextUpdate() +60));
                  client.println(P("\">"));
 
                  client.println(P(""));
                  client.println(P("<style> "));
                  client.println(P("img{"));
                  client.println(P("max-width: 100%;"));
                  client.println(P("height: auto;"));
                  client.println(P("width: auto\0;"));
                  client.println(P("}"));
                  client.println(P("a:link    {color:green;} "));
                  client.println(P("a:visited {color:green;} "));
                  client.println(P("body {color:white;} "));
                  client.println(P("body { background-color:#000000;} "));
                  client.println(P("h1 { background-color:#d5edb3;color:green;} "));
                  client.println(P("h2 { background-color:#d5edb3;} "));
                  client.println(P("</style></head><body> "));
                  client.println(P(" <h1> PTR Weather Camera <img src=\"BOT.gif\" align=\"right\"  /></h1> "));
                  client.println(P("<div>"));
       
                  client.println(P("<br><br><Center>"));
 
                  client.print(P("<div style=\"max-width:640px;\"> <img src=\"IMGLOG/"));
                    client.print(LastPicName);
                    //client.print("11170640.JPG");
                    client.print(P("/\"></div> <br> "));
                  client.print(P("Next update in: "));
                  client.print(TimeToNextUpdate()/60);
                  client.println(P(" minutes"));
                  client.print(P("</Center><br><br>"));
                  client.print(P("Remote Station<br>"));
                  client.print(DHTOStemp);
                  client.print(P("&deg;F Outside Temperature <br>"));
                  client.print(Humidity);
                  client.print(P("% Relative Humidity<br>"));
                  client.print(BMP);
                  client.print(P(" kPa <br>"));
                  client.print(BattVolts);
                  client.print(P("v Battery Volts. 6.4-8.2v <br>"));
                  client.print(SolarVolts);
                  client.print(P("v Solar<br><br>"));
                  client.print(P("Conditions as of : "));
                  client.println(TheTime);
                  client.print(P(" "));
                  client.println(LastUpDate);
                  client.print(P(" <br>&nbsp &nbsp &nbsp &nbsp &nbsp  Outside Temperature : "));
                  client.print((DHTtemperatureOS));
                  client.println(P("&degF <br>"));
                  client.print(P("&nbsp &nbsp &nbsp &nbsp &nbsp  Low/Hi Temperature : "));
                  client.print((lowT));
                  client.println(P("/"));
                  client.println(hiT);
                  client.println(P("&deg;F <br>"));
                 
                  client.print(P("&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp  &nbsp Relative Humidity : "));
                  client.print(DHThumidityOS);
                  client.println(P("%<br>"));
                  client.print(P("&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp  &nbsp &nbsp &nbsp  &nbsp &nbsp &nbsp Dew Point : "));
                  client.print(DewPoint);
                  client.println(P("&deg;F <br>"));
                  client.print(P("Barometric pressure in kPa : "));
                  client.println(BMPpressure,3);
                  client.println(P("<br>"));
                  client.print(P("Barometric pressure in inHg: "));
                  client.println(inHg,4);
                  client.print(P("<br> Barometric pressure trending: "));
                  if(up == true){
                   client.print(P("&uarr;"));
                  }
                  else{
                    client.print(P("&darr;"));
                  }
                  client.println(P("<br> <br>&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp  &nbsp &nbsp &nbsp   Inside Temp : "));
                  client.print(DHTtemperature);
                  client.print(P("&degF  <br> &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp Inside Humidity : "));
                  client.print(DHThumidity);
                  client.println(P("% <br><br><a href=\"DATALOG/LOG.CSV\"> Download LOG.csv</a> "));
                  client.println(P("<br><br>"));
                  hitcounter();
                  client.println(P("Hits &nbsp <font color=\"green\"><b>"));
                  client.print(Hits);
                  client.println(P("</font></b><br>Up Time: "));
                  client.println(UpTime());
                  client.println(P("<br><br><div id=\"footer\">Copyright &copy; 2012 Tevis Cox</div>"));
                  client.println(P("This web page is hosted on an Arduino Mega 1280.<br>"));
                  client.println(P("16mhz, 8kb of ram."));
                  client.print(P("Free Ram: "));
                  client.println(FreeRam());
                  client.println(P(" Bytes <br>"));
                   
                  client.println(P("</html>"));
                    delay(1);
                     client.stop();
                         Serial.println(P("client disconnected"));
                  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
     
            // close the connection:
       
 
    }
  }
 
 
void  datahtm(){
               // listen for incoming clients
          EthernetClient client = server.available();
          if (client) {
            Serial.println(P("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(P("HTTP/1.1 200 OK"));
//                  client.println(P("Content-Type: text/html"));
//                  client.println(P("Connection: close"));
//                  client.println(P("<!DOCTYPE HTML>"));
//                  client.println(P("<html>"));
                  client.println((DHTtemperatureOS));
                  client.println(DHThumidityOS);
                  client.println(BMPpressure,3);
                  client.println(DHTtemperature);
                  client.println(DHThumidity);
                  client.println(P("Error 404 I looked for the page, I promise.. "));
                                 
                    delay(1);
                     client.stop();
                         Serial.println(P("client disconnected"));
                  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
     
            // close the connection:
       
 
    }
  }
  //█████████████████████████████████████
  //Start NTP Code
  //█████████████████████████████████████
 
  //█████████████████████████████████████ 
  //▼ LCD Command Code
  //█████████████████████████████████████
   
  void LCDinitialize(){
    lcd.write(0xFE);
    lcd.write(0x41);
    lcd.write(0xFE);
    lcd.write(0x51);
  }
 
  void LCDsetContrast(int contrast){
    if(contrast >51){
     return;
    }
    lcd.write(0xFE);
    lcd.write(0x52);
    lcd.write(contrast);
  }
 
  void LCDsetBrightness(int level){
    if(level > 8){
     return;
    }
     lcd.write(0xFE);
    lcd.write(0x53);
    lcd.write(level);
  }
 
  void LCDclear(){
    lcd.write(0xFE);
    lcd.write(0x51);
  }
 
  void LCDon(){
    lcd.write(0xFE);
    lcd.write(0x41);
  }
 
  void LCDoff(){
    lcd.write(0xFE);
    lcd.write(0x42);
  }
 
  void LCDsetCursor(int line_num, int x){
    int g_index[4] = { 0x00, 0x40, 0x14, 0x54 };
    lcd.write(0xFE);
    lcd.write(0x45);
    lcd.write(g_index[line_num-1] + x - 1);
  }
 
  void LCDcursorLeft(){
    lcd.write(0xFE);
    lcd.write(0x49);
  }
 
  void LCDcursorRight(){
    lcd.write(0xFE);
    lcd.write(0x4A);
  }
 
  void LCDcursorBlinkOn(){
    lcd.write(0xFE);
    lcd.write(0x4B);
  }
  void LCDcursorBlinkOff(){
    lcd.write(0xFE);
    lcd.write(0x4C);
  }
 
  void LCDcursorBackspace(){
    lcd.write(0xFE);
    lcd.write(0x4E);
  }
 
  void LCDShiftLeft(){
    lcd.write(0xFE);
    lcd.write(0x55);
  }
 
  void LCDShiftRight(){
    lcd.write(0xFE);
    lcd.write(0x56);
  }
 
  void LCDcreateChar(unsigned char char_num, unsigned char *rows){
    lcd.write(0xFE);
    lcd.write(0x54);
    lcd.write(char_num);
    lcd.write(rows, 8);
  }
 
  void LCDchangeBaudRate(unsigned char baud){
    lcd.write(0xFE);
    lcd.write(0x61);
    lcd.write(baud);
   }
   
   void LCDdisplayBaudRate(){
    lcd.write(0xFE);
    lcd.write(0x71);
   }
   
   void LCDdisplayI2CAddress(){
    lcd.write(0xFE);
    lcd.write(0x72);
   }
   
   void LCDchangeI2CAddress(unsigned char addr){
    lcd.write(0xFE);
    lcd.write(0x62);
    lcd.write(addr);
   }
   
   void LCDdisplayVersion(){
    lcd.write(0xFE);
    lcd.write(0x70);
   }
   //█████████████████████████████████████
 


The code for the TX station. Sleeping not yet working, should help battery life quite a bit.
Code: Select all | TOGGLE FULL SIZE
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include "DHT.h"
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

volatile int f_wdt=1;

#define DHTPIN 2 //pin the didgital humidity temp sensor is on
#define DHTTYPE DHT22 // is its a DHT22
#define DHTPower 3 // pin to write HIGH or LOW to power up/down the sensor

Adafruit_BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);

float OStemp = 0;
float BMP = 0;
float BMPtemp =0;
float Humidity = 0;
float Brightness = 0;
float BattVolts = 0;
float SolarVolts = 0;
float ChargeAmps = 0;

unsigned long currentMillis, previousMillis;
ISR(WDT_vect)
{
  if(f_wdt == 0)
  {
    f_wdt=1;
  }
  else
  {
    Serial.println("WDT Overrun!!!");
  }
}


 
int msg[1]; //variable used in creation of char/string for tx with NRF module

String theMessage; // string used to put all sensor data into for transmittal

RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup(void){
 
 
 
 
 
 
  Serial.begin(9600);
 
  pinMode(DHTPower,OUTPUT);
  pinMode(8,OUTPUT);
 
  digitalWrite(DHTPower,HIGH);
  delay(100);
  dht.begin();

  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {}
  }


  radio.begin();
  radio.openWritingPipe(pipe);
 
   /*** Setup the WDT ***/
  /* Clear the reset flag. */
  MCUSR &= ~(1<<WDRF);
   /* In order to change WDE or the prescaler, we need to
   * set WDCE (This will allow updates for 4 clock cycles).
   */
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  /* set new watchdog timeout prescaler value */
  WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
  /* Enable the WD interrupt (note no reset). */
  WDTCSR |= _BV(WDIE);
 
 
 delay(3000);

}


void loop(void){
    currentMillis = millis();
    // to run once a second
    if(currentMillis - previousMillis > 30000) { 
      previousMillis = currentMillis;
PollSensors(); 
createString();
TXdata();
ToCharge();
radio.powerDown();
SleepyDuino();
delay(1000);
radio.powerUp();
    }


}

void ToCharge(){
  digitalWrite(8,HIGH);
 if(SolarVolts > BattVolts){
   if(BattVolts < 8.30){ //protect battery from over charging
  digitalWrite(8,LOW);
   }
 }
 if(SolarVolts < BattVolts){
  digitalWrite(8,HIGH);
 }
}

float ConvertCtoF(float temp){
   temp = temp / 5 * 9 +32;
  return temp;
  }

void PollSensors(){
 OStemp =  ConvertCtoF(dht.readTemperature());
 Humidity = dht.readHumidity();
 BMP = (bmp.readPressure())*.001;
 BMPtemp = ConvertCtoF(bmp.readTemperature());
 BattVolts = (analogRead(A1)*1.005) * (20.0/1023.0);
 SolarVolts = (analogRead(A0)*1.03175) * (25.0/1023.0);
 
}

void TXdata(){
   
  int messageSize = theMessage.length();
  for (int i = 0; i < messageSize; i++) {
    int charToSend[1];
    charToSend[0] = theMessage.charAt(i);
    radio.write(charToSend,1);
  } 
//send the 'terminate string' value... 
  msg[0] = 2;
  radio.write(msg,1);

  radio.powerDown();
  delay(1000);
  radio.powerUp();
 
}

void createString(){
  char temp[6];
  theMessage = "";
  theMessage += "s";
  theMessage += " ";
  theMessage += OStemp;
  theMessage += " ";
  theMessage += Humidity;
  theMessage += " "; 
  theMessage += dtostrf(BMP, 3,3,temp);
  theMessage += " ";
  theMessage += BMPtemp;
  theMessage += " ";
  theMessage += Brightness;
  theMessage += " "; 
  theMessage += BattVolts;
  theMessage += " ";
  theMessage += SolarVolts;
  theMessage += " "; 
  theMessage += ChargeAmps;
  theMessage += " ";
  theMessage += "e";

 Serial.println(theMessage); 
}

void SleepyDuino(){
    if(f_wdt == 1)
  {
   
    /* Don't forget to clear the flag. */
    f_wdt = 0;
   
    /* Re-enter sleep mode. */
    enterSleep();
  }
  else
  {
    /* Do nothing. */
  }
 
}

void enterSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();
 
  /* Now enter sleep mode. */
  sleep_mode();
 
  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */
 
  /* Re-enable the peripherals. */
  power_all_enable();
}


The code for the RX station
Code: Select all | TOGGLE FULL SIZE
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>
 
 
 String DHTOStemp;
 String BMP;
 String BMPtemp;
 String Humidity;
 String Brightness;
 String BattVolts;
 String SolarVolts;
 String ChargeAmps;
 
int msg[1];
RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL;
int lastmsg = 1;
String theMessage = "";
void setup(void){
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}
void loop(void){
  if (radio.available()){
    bool done = false; 
      done = radio.read(msg, 1);
      char theChar = msg[0];
      if (msg[0] != 2){
        theMessage.concat(theChar);
        }
      else {
        theMessage.trim();
       Serial.println(theMessage);
       //ParseOut();
       theMessage= "";
      }
   }

}


void ParseOut(){
  int spaces[10];
  int spacestemp =0;
  if(theMessage[0] == 's'){
    //Serial.println(theMessage.length());
    DHTOStemp = "";
    BMP = "";
    BMPtemp = "";
    Humidity = "";
    Brightness = "";
    BattVolts = "";
    SolarVolts = "";
    ChargeAmps = "";
   
    for(int i =0; i< theMessage.length(); i++){
     if(theMessage[i] == ' '){
      spaces[spacestemp] = i;
      spacestemp +=1;
     // Serial.print(i);
     // Serial.print(" ");
     }
     
    }
    //Serial.println();
    //Read DHTOStemp out of string
    for(int i =(spaces[0])+1; i< spaces[1]; i++){
     DHTOStemp += theMessage[i];
    }
   
    for(int i =(spaces[1])+1; i<spaces[2]; i++){
     Humidity += theMessage[i];
    }
   
    for(int i =(spaces[2])+1; i<spaces[3]; i++){
     BMP += theMessage[i];
    }
   
    for(int i =(spaces[3])+1 ; i<spaces[4]; i++){
     BMPtemp += theMessage[i];
    }   
   
    for(int i =(spaces[4])+1; i<spaces[5]; i++){
     Brightness += theMessage[i];
    }
   
    for(int i =(spaces[5])+1; i<spaces[6]; i++){
     BattVolts += theMessage[i];
    }
   
    for(int i =(spaces[6])+1; i<spaces[7]; i++){
     SolarVolts += theMessage[i];
    }
   
    for(int i =(spaces[7])+1; i<spaces[8]; i++){
     ChargeAmps += theMessage[i];
    }
   // Serial.println(DHTOStemp);
   // Serial.println(Humidity);
    //Serial.println(BMP);
    //Serial.println(BMPtemp);
   // Serial.println(Brightness);
   // Serial.println(BattVolts);
   // Serial.println(SolarVolts);
  //  Serial.println(ChargeAmps);   
   
   
  }

 
}
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by adafruit_support_bill on Thu Feb 19, 2015 8:23 am

Awesome! Thanks for posting.

adafruit_support_bill
 
Posts: 73190
Joined: Sat Feb 07, 2009 10:11 am

Re: Ardino weather/webcam/webserver up and running.

by EVRE on Thu Feb 19, 2015 5:20 pm

Adafruit hardware list:
Camera https://www.adafruit.com/products/397
Barometric pressure BMP180 https://www.adafruit.com/products/1603
Digital humidity temp sensor DHT22 https://www.adafruit.com/products/385
Ethernet Shield https://www.adafruit.com/products/201
Real time clock (you want an accurate clock) https://www.adafruit.com/products/255
A mega of your choice.
An LED can serve as a light sensor, just not as well as some of Adafruits choices.

One thing I'm confused on, the camera lists that its not compatible with a MEGA, but I'm using one right now.
change in hardware? I want to buy another, but don't want it to not work now.

Ideas on how to measure rainfall.
Build a cone to funnel water into a digital scale. The container will have a electric solenoid that can drain the container and reset. For snowfall, heat all the components up to melt the snow, then measure.

Idea to measure wind speed, but not direction. A short poll with a strain gauge... could determine direction using 3 strain gauges.. then use an anemometer to calibrate the readings or do the hefty math.
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by adafruit_support_bill on Thu Feb 19, 2015 5:41 pm

Not sure of the Mega limitation. That qualification may be outdated. I'll look into it.

For rainfall measurement, we have the eTape sensors; https://www.adafruit.com/product/463
For wind speed, you may want to check out the Modern Device sensor: http://moderndevice.com/product/wind-sensor/

adafruit_support_bill
 
Posts: 73190
Joined: Sat Feb 07, 2009 10:11 am

Re: Ardino weather/webcam/webserver up and running.

by EVRE on Thu Feb 19, 2015 6:18 pm

Thanks Bill! :)
The eTape and wind meter are both excellent ideas for this project.


Here is some more code that I use with this.
Set the time using an Ethernet shield and NTP.
I upload this from time to time to get the clock back to being accurate... it can drift about a minute per month!
Thats why I mentioned that an accurate clock is nice, only need to do this.. once a year?

Code: Select all | TOGGLE FULL SIZE
/*
RTC Programmer NTP
Configure a DS1307 RTC using the time collected from an NTP server. Netowkring configured using DHCP

Requires
Arduino Ethernet Shield
DS1307 RTC
Pinout: +5V Vcc
GND GND
A4 SCL
A5 SQW
*/

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Wire.h>
#include <RTClib.h>

//RTC Encapsulation
RTC_DS1307 RTC;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//MAC Address for Ethernet Shield

unsigned int localPort = 8888; //Local port to listen for UDP Packets

IPAddress timeServer(132, 163, 4, 101);//NTP Server IP (time.nist.gov)

const int NTP_PACKET_SIZE= 48; //NTP Time stamp is in the firth 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //Buffer to hold incomming and outgoing packets

EthernetUDP Udp; //UDP Instance to let us send and recieve packets

unsigned long epoch; //Unix Epoch time (NTP or RTC depending on state)

void setup() {
  Serial.begin(9600); //Start the serial interface

  Wire.begin(); //Start Wire
 
  RTC.begin(); //Start the RTC

  delay(1000);
  //check to see if the RTC is already configured
  //if( !RTC.isrunning() ) {
    Serial.println("RTC Not Configured");
    Serial.println("Starting Ethernet"); //configure Ethernet
    if(Ethernet.begin(mac) == 0) {
      Serial.println("Fatal Error: Unable to obtain DHCP address");
      for(;;) //do nothing forever!
        ; //TODO Change this to retry a few times
    }
   
    Serial.println("Ethernet Configured");
    Udp.begin(localPort);

    //get the NTP timestamp
    epoch = getNTP();
   
    //set the RTC
    RTC.adjust(epoch - 28800);//Time zone offset of 8 hrs.
   
    //display what we did!
    Serial.println("RTC Configured:");
   
    //show Unix Epoch
    Serial.print("Unix Epoch: ");
    Serial.println(epoch);
   
    //show UTC
    Serial.print("UTC: ");
    showUTC(epoch);
  //} else {
   // Serial.println("RTC Already Configured");
 // }
}

void loop() {
  //repeatedly show the current date and time, taken from the RTC
  DateTime now = RTC.now();

  Serial.print(now.unixtime());
  Serial.print(" - ");
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" - ");

  showUTC(now.unixtime());
 
  delay(5000);
}

void showUTC(unsigned long epoch) {
  Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
  Serial.print(':');
  if ( ((epoch % 3600) / 60) < 10 ) {
    // In the first 10 minutes of each hour, we'll want a leading '0'
    Serial.print('0');
  }
  Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
  Serial.print(':');
  if ( (epoch % 60) < 10 ) {
    // In the first 10 seconds of each minute, we'll want a leading '0'
    Serial.print('0');
  }
  Serial.println(epoch %60); // print the second
}

unsigned long getNTP() {
  sendNTPpacket(timeServer); // send an NTP packet to a time server

  // wait to see if a reply is available
  delay(1000);
  if ( Udp.parsePacket() ) {
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = " );
    Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
   
    return epoch;
  }
}

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

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}
EVRE
 
Posts: 59
Joined: Sat Feb 18, 2012 11:21 pm

Re: Ardino weather/webcam/webserver up and running.

by adafruit2 on Fri Feb 20, 2015 2:00 pm

It can work with a Mega but we haven't done up the tutorial to match so its not supported

adafruit2
Site Admin
 
Posts: 18423
Joined: Fri Mar 11, 2005 7:36 pm

Please be positive and constructive with your questions and comments.