Things used in this project

Hardware components:
Mfr 25frf52 10k sml
Resistor 10k ohm
Arbitrary value. Select based on photo resistor. Voltage divider resistance is entirely arbitrary, but select a reasonable resistance.
×3
386 00
DHT11 Temperature & Humidity Sensor
×1
Adafruit industries ada161 image 75px
Photo resistor
No specific photo resistor, match to resistor or vice versa
×1
Photon new
Particle Photon
×2
0.96" Yellow/Blue OLED 128x64 I2C
Various other displays would work, modify code as needed.
×1
12002 04
Breadboard (generic)
More permanent solutions are possible.
×2
11026 02
Jumper wires (generic)
×1
Waterproof enclosure
Various options available. A food storage container with latching lid was used. This is to protect the temperature and humidity photon, battery, and components from the elements. A clear enclosure was selected to allow light to the photo cell.
×1
LightMe Portable 15W 130lm Solar LED Light Bulb
This was used for its battery, solar panel, and charging circuit.
×1
One-Way Mirror
×1
Shadow Box
Match to the size of your one-way mirror.
×1
Software apps and online services:
Q8wtlimqnp04fzhtr9v5
IFTTT Maker service
Sends an email notification when tested battery voltage drops below 3.65 V (where the Photon may become unstable).
Hackster
ThingSpeak API
Graphs temperature, humidity, light levels, and battery voltage over time.
Hand tools and fabrication machines:
09507 01
Soldering iron (generic)

Schematics

Weather Station Schematic
Iot1 t2nxzbhkdn
Display Schematic
Photon2 qlam0kdbln

Code

OLED DisplayC/C++
This code is used to display weather data to an OLED on a Photon indoors.
/* 
                                      Power on USB
 *                                     +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *    To OLED Vcc           | [*] VIN           3V3 [ ] |
 *    To OLED Gnd           | [*] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [ ] |
 *                          | [ ] WKP            D7 [ ] |
 *                          | [ ] DAC +-------+  D6 [ ] |
 *                          | [ ] A5  |   *   |  D5 [ ] |                 
 *                          | [ ] A4  |Photon |  D4 [ ] |
 *                          | [ ] A3  |       |  D3 [ ] |
 *                          | [ ] A2  +-------+  D2 [ ] |                              
 *                          | [ ] A1             D1 [*] | To OLED SCL
 *                          | [ ] A0             D0 [*] | To OLED SDA
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */
 

#include "application.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

// OLED

//Use I2C with OLED RESET pin on D4
 #define OLED_RESET D4
  Adafruit_SSD1306 oled(OLED_RESET);
unsigned long previousMillis;
unsigned long interval = 30000;

// Define temperature, humidity, and light variables for later use

int temperature;
int humidity;
int light;
// bool lowVolts; // Low voltage display, not currently working

void setup() {
    
    //OLED
    // by default, we'll generate the high voltage from the 3.3v line internally.
    // initialize with the I2C addr 0x3D (for the 128x64)
  oled.begin();  
  //oled.display(); // uncomment to show Adafruit splashscreen on start.
  Time.zone(-4); // Set Eastern timezone.
 //  lowVolts=0; // set low volt initial state. Not currently working.
  
  
}

void loop() {
    
    // Data
    Particle.subscribe("t49megr3171temperature", Temp_Handler);
    Particle.subscribe("t49megr3171humidity", Humidity_Handler);
    Particle.subscribe("t49megr3171light", Light_Handler);
    // Particle.subscribe("t49megr3171LowVoltage", Low_Voltage); // Low voltage handler, not currently functional.
    
    //OLED Time
    oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Time");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(Time.format(Time.now(), "%I:%M%p"));;
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  // OLED Temp
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Temp.");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(String(temperature) + " F");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  // OLED Humidity
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Humidity");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(String(humidity) + "%");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
    // OLED Humidity
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Light");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(String(light) + "%");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  
  if((temperature==0)&&(humidity==0))
  {
  oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Error");
  oled.setCursor(0,24);
  oled.setTextSize(1);
  oled.print("Temp. = Humidity = 0");
  oled.setCursor(0,48);
  oled.setTextSize(1);
  oled.print("Check Sensor");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  }
  /* -- Low voltage display, not currently working
  if(lowVolts==1){
      oled.clearDisplay();
  delay(200);
  oled.setTextSize(3);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("CHECK");
  oled.setCursor(0,16);
  oled.setTextSize(3);
  oled.print("BATTERY");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print("VOLTS");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500); 
  }
  */ 
}

// Retrieve and convert the temperature data to an integer
void Temp_Handler(const char *event, const char *data){
  Serial.println(String(data) + "F");
  String k = data;
  temperature=k.toInt();
    
}
// Retrieve and convert the humidity data to an integer
void Humidity_Handler(const char *event, const char *data){
    Serial.println(String(data) + "%");
    String k = data;
    humidity=k.toInt();

}
// Retrieve and convert the light level data to an integer
void Light_Handler(const char *event, const char *data){
    Serial.println(String(data) + "%");
  String k = data;
  light=k.toInt();

}
// Low voltage handler - Not currently working.
/*
void Low_Voltage(const char *event, const char *data){
    if (strcmp(data,"Low Volts")==1){
    lowVolts=1; 
    }
   else if (strcmp(data,"Low Volts, Low Light")==1){
    lowVolts=1;
    }
   else{
   lowVolts=0;
    }
}
*/
Temperature/Humidity StationC/C++
This is the code for the Photon which is used to sense temperature and humidity data. It also self monitors voltage, and light level to help determine which sleep state to use.
/* This sketch experiments with battery & solar power for use with a temperature and humidity sensor. A photocell is
implemented to monitor light levels, and battery voltage is checked as well. A DHT11 digital temperature and humidity
is used; however, it would be equally feasible to use other sensors in the DHT family or a BME280 for greater accuracy
and additional features


The DHT data line goes to pin 5.
Currently setup for use with a DHT11
Light sensor voltage is taken from pin A0
Battery voltage is tested at pin A1
System power taken from a digital pin to prevent battery drain during sleep

 *                                     +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *                          | [ ] VIN           3V3 [ ] |
 *                          | [ ] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [*] |
 *                          | [ ] WKP            D7 [ ] |
 *                          | [ ] DAC +-------+  D6 [ ] |
 *                          | [ ] A5  |   *   |  D5 [*] |------ DHT Signal
 *                          | [ ] A4  |Photon |  D4 [ ] |
 *                          | [ ] A3  |       |  D3 [*] |------ Voltage Supply Pin (set high)
 *                          | [ ] A2  +-------+  D2 [*] |------ Voltage Test Ground
 * Battery Voltage Sense----| [*] A1             D1 [ ] |
 *    Light Sensor     -----| [*] A0             D0 [ ] |
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */
 
 /*  begin particle webhook code snippit to add to particle webhook interface on console
 // For thingspeak:
   {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "lat": "{{a}}",
        "long": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    }
}
*/

// Add the OLED and temp/humidity sensor libraries
#include "application.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include <Adafruit_DHT.h>

// DHT parameters
#define DHTPIN 5
#define DHTTYPE DHT11


// This is the code for the OLED if you want to use the temp/humidity station photon to simply display/publish indoor temperature data. 
// Uncomment if you want to use the OLED with this portion of the program. It could be useful to check sensors working without opening a browser.

// OLED
/*
//Use I2C with OLED RESET pin on D4
 #define OLED_RESET D4
  Adafruit_SSD1306 oled(OLED_RESET);
unsigned long previousMillis;
unsigned long interval = 30000;
*/

// Variables
int temperature;
int humidity;
int light;
float voltage;
int vsup = D3; // This will be used to supply voltage to the DHT11 and photoresistor
int sysdgnd = D2; // Inadequate voltage from the GPIO pin due to losses using this setup to power the DHT11. Can still ground photocell and voltage read.
int vbatt_pin = A1; // Pin A1 will test battery voltage
int light_sensor_pin = A0; // Assign light sensor pin
long sleeptime=1200; // Sleep for 15 minutes/900 seconds 10 minutes/1200s 30 minutes/1800s
const String key = "YOUR_API_KEY_HERE";

// Setup DHT sensor pin for use with libraries

DHT dht(DHTPIN, DHTTYPE);

// Begin the setup loop

void setup() {
    
    // Start DHT sensor
    dht.begin();
    Serial.begin(9600);
    pinMode(vsup, OUTPUT); // Setup voltage supply
   pinMode(sysdgnd, OUTPUT); // Setup system ground
    
    //OLED
    
    // oled.begin();  // initialize with the I2C addr 0x3D (for the 128x64)
     
    // oled.display(); // show splashscreen
    
  Time.zone(-4);
  
}

void loop() {
    
    // Turn on the system. Delay for sensors to stabilize.
    digitalWrite(vsup, HIGH);
    digitalWrite(sysdgnd, LOW);
    delay(1000);
    
    // Temperature measurement taken from sensor
    temperature = dht.getTempFarenheit();
    delay(500);
    // Humidity measurement taken from sensor
    humidity = dht.getHumidity();
    // Light level measurement. Note this is simply a voltage divider with an appropriate resistor & photocell.
    float light_measurement = analogRead(light_sensor_pin);
    light = (int)(light_measurement/4096*100);
   
    // Battery voltage measurement
    float volt_measurement = analogRead(vbatt_pin);
    // Serial.println(volt_measurement);
    Particle.publish("volt_measurement",String(volt_measurement));
    voltage = (float)(2*volt_measurement*3.3/4096*4.08/4.029);

    // Publish data to thingSpeak
    
    Particle.publish("thingSpeakWrite_All", "{ \"1\": \"" + String(temperature) + "\"," +
       "\"2\": \"" + String(humidity) + "\"," +
       "\"3\": \"" + String(light) + "\"," +
       "\"4\": \"" + String(voltage) + "\"," +
       // "\"5\": \"" + String(var5) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE);
     delay(1000);
 // Publish data for a buddy's photon, could pull from ThingSpeak if desired? (work in progress)
   bool pubtemp = Particle.publish("t49megr3171temperature", String(temperature));
    delay(1000);
   bool pubhum = Particle.publish("t49megr3171humidity", String(humidity));
    delay(1000);
   bool publit = Particle.publish("t49megr3171light", String(light));
    delay(1000);
  bool pubv = Particle.publish("t49megr3171voltage", String(voltage));
    delay(1000);
  // Extra sleep on low voltage. Even more on low light. Try to recover some voltage. Send notification to IFTTT maybe? Haven't gotten that far.
  if(voltage<3.65)
    {
        lowVoltageSleep();
    }
    
  if ((pubtemp==TRUE)&&(pubhum==TRUE)&&(publit==TRUE)&&(pubv==TRUE))
   {
    System.sleep(SLEEP_MODE_DEEP,sleeptime);
   }
   
 /* Uncomment to set up with OLED. Be sure to comment out sleep mode if you want to display to the OLED.   
    //OLED Time
    oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Time");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(Time.format(Time.now(), "%I:%M%p"));
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  // OLED Temp
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Temp.");
  oled.setCursor(0,32);
    oled.setTextSize(3);
  oled.print(String(temperature) + " F");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
  // OLED Humidity
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Humidity");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(String(humidity) + "%");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
    // OLED Humidity
   oled.clearDisplay();
  delay(200);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.print("Light");
  oled.setCursor(0,32);
  oled.setTextSize(3);
  oled.print(String(light) + "%");
  oled.setTextColor(BLACK, WHITE); // 'inverted' text
  oled.display();
  delay(2500);
 */
 
} // End of loop

// Low voltage, so sleep extra long. Hopefully recover some extra battery. Sleep even longer with low light.
void lowVoltageSleep(){
    
    if (light<45)
        lowLightSleep();
    else
        Particle.publish("t49megr3171LowVoltage",String("Low Volts"));
        System.sleep(SLEEP_MODE_DEEP,4*sleeptime);
    
}

void lowLightSleep(){
        Particle.publish("t49megr3171LowVoltage",String("Low Volts, Low Light"));
        System.sleep(SLEEP_MODE_DEEP,10*sleeptime);
}
ThingSpeak WebHookJSON
This is the JSON webhook for ThingSpeak integration
{
  "api_key": "{{k}}",
  "field1": "{{1}}",
  "field2": "{{2}}",
  "field3": "{{3}}",
  "field4": "{{4}}",
  "field5": "{{5}}",
  "field6": "{{6}}",
  "field7": "{{7}}",
  "field8": "{{8}}",
  "lat": "{{a}}",
  "long": "{{o}}",
  "elevation": "{{e}}",
  "status": "{{s}}"
}

Credits

Drewdrew 5f0ma1gn4l
Andrew Hillier

Mechanical Engineering Student at UNC Charlotte.

Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Other Clocks
Intermediate
  • 179
  • 3

Work in progress

A combination of 3 different clocks in one frame.

ConnectTheDots with Particle Azure IoT Hub Integration
Intermediate
  • 529
  • 6

Protip

This project will allow you to connect your Particle device into an Azure IoT Hub for viewing data in real-time through an ASP.NET web app!

Weather Aware Sprinkler Controller
Intermediate
  • 1,278
  • 16

Full instructions

6 station Photon controller uses the Weather Underground API to prevent watering when windy, rainy, or too cold.

Christmas Gift Box
Intermediate
  • 3,600
  • 595

Full instructions

Christmas Gift Box plays music and sends an email when it is opened.

Simple Environmental Monitoring
Intermediate
  • 1,495
  • 13

Full instructions

Particle Photon circuit allowing the display of environmental conditions (light, temperature, humidity, pressure) using the Blynk app.

Pool Buddy
Intermediate
  • 2,743
  • 22

Work in progress

Monitor and log water quality (pH & ORP) and temperature from everywhere.

ProjectsCommunitiesTopicsContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login