Rebecca NelsonAndrew Hillier
Published © GPL3+

Temperature Mirror

The Temperature Mirror incorporates a digital display to allow its user to readily view time, temperature, humidity, and light.

IntermediateFull instructions provided3 hours2,026
Temperature Mirror

Things used in this project

Hardware components

Resistor 10k ohm
Resistor 10k ohm
Arbitrary value. Select based on photo resistor. Voltage divider resistance is entirely arbitrary, but select a reasonable resistance.
×3
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
Photo resistor
Photo resistor
No specific photo resistor, match to resistor or vice versa
×1
Photon
Particle Photon
×2
0.96" Yellow/Blue OLED 128x64 I2C
Various other displays would work, modify code as needed.
×1
Breadboard (generic)
Breadboard (generic)
More permanent solutions are possible.
×2
Jumper wires (generic)
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

Maker service
IFTTT Maker service
Sends an email notification when tested battery voltage drops below 3.65 V (where the Photon may become unstable).
ThingSpeak API
ThingSpeak API
Graphs temperature, humidity, light levels, and battery voltage over time.

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Weather Station Schematic

Display Schematic

Code

OLED Display

C/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 Station

C/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 WebHook

JSON
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

Rebecca Nelson

Rebecca Nelson

1 project • 3 followers
Andrew Hillier

Andrew Hillier

1 project • 6 followers
Mechanical Engineering Student at UNC Charlotte.

Comments