Introduction: Solar Powered NodeMCU Weather Station

About: A bit of a dabbler by nature with a bent towards working with wood for fun and with technology in the day job, I like to try and make things that allow me to explore the best of both worlds. I write abou…

In recent years, there has been a lot of buzz going on about having what used to be very mundane everyday household items become "smart" by being able to be connected to the internet and communicate with you or with other smart devices.

This concept - more commonly referred to as the "Internet of Things" (or IOT) - has unleashed an avalanche of smart thermostats, front door locks and refrigerators - all with the ability to let you know whether you need milk or that you've left the back door open and now the cat has escaped and is terrorizing the neighborhood.

Being someone who has made a career in the Information Technology field, I was starting to feel a wee bit out of the loop about these things - not a good place to be for any self-respecting IT guy.

I could have just simply read up on IOT devices, but why waste a perfectly good excuse for a bit of puttering in the shop...

You can literally build anything with a little electronic "LEGO". A quick search of the internet showed me many examples of people building their own IOT devices in such a way.

One common thing that I found with these projects was that a lot of them used a small Arduino compatible device based on the ESP8266 board.

The really nice thing about these boards is that they are:

  • fairly small (maybe 3 inches long and about an inch wide)
  • have Wi-Fi capability
  • easily programmable with a number of computer languages
  • extremely cheap (around $4 on e-bay)

As a starting project, I wanted to do something fairly simple and fairly useful.

I was always a bit of a weather nut, so I decided that I wanted to build a wireless thermometer that would let me see what the temperature was while I was away from home. I figured that this would be a good first project.

Step 1: Parts to Build the Weather Station

To create the weather station I first needed to collect the following items:

Materials

  • A NodeMCU ESP8622 Board
  • DHT22 temperature/humidity module
  • A small perf board
  • A 5 Volt Solar cell
  • A Yellow LED
  • A 1 amp Solar Charger Controller
  • Three AA 3.7 Volt Lithium-Ion rechargeable batteries
  • Three AA Battery holders
  • A 0.9-5 Volt to 5 Volt Step Up Booster Module
  • Various bits of wire
  • various pieces of 1/2 inch birch
  • 1 inch hinge and screws
  • white paint
  • wood glue
  • drawer knob

Tools

  • Soldering Iron
  • Table Saw
  • Miter Saw
  • Drill Press with:
  • 1 inch drill bit
  • 1/8 inch drill bit
  • 5 mm drill bit
  • Nail gun
  • Hot glue gun
  • Screwdriver

Step 2: Getting an Operational Weather Station Going

After some more searching on the internet, I found a really good tutorial at Losant.com on how to build such a device with the ESP8266 and a DHT22 temperature/humidity module. (You can pick up a DHT22 for a couple of dollars on e-Bay)

After some research, I settled on using the NodeMCU ESP8266 board

Once I gathered all the various pieces together I followed the instructions in the tutorial on how to wire up the NodeMCU to the DHT22. I then plugged in the supplied program code, hooked my NodeMCU to a power source and watched it spring to life.

Buoyed by my success I wanted to make a few minor alterations to the program that Losant provided:

I wanted to add a little heartbeat LED to let me know that the board was working. I also wanted to reduce the data send rate to 10 seconds (the original program was set to 2 seconds) in order to conserve power if I wanted to run the board from a battery. I occasionally found that the NodeMCU board would "freeze" after a few hours since I was finding that the WiFi connection was dropping every once in a while, so I wanted the board to reboot itself every hour or so as a "refresh" mechanism. Taking the original code that Losant developed, I modified it to this:

/**
 * Example for sending temperature and humidity
 * to the cloud using the DHT22 and ESP8266
 *
 * Copyright (c) 2016 Losant IoT. All rights reserved.
 * Modifications by Small Workshop Chronicles
 * <a href="https://www.losant.com"> <a href="https://www.losant.com"> https://www.losant.com</a>  
</a>
 */
#include "DHT.h"
#include 
#include 
#include 
#include 
#define DHTPIN 4     // what digital pin the DHT22 is conected to
#define DHTTYPE DHT22   // There are multiple kinds of DHT sensors
DHT dht(DHTPIN, DHTTYPE);
// WiFi credentials.
const char* WIFI_SSID = "";
const char* WIFI_PASS = "";
// Losant credentials.
const char* LOSANT_DEVICE_ID = "";
const char* LOSANT_ACCESS_KEY = "";
const char* LOSANT_ACCESS_SECRET = "";
WiFiClientSecure wifiClient;
LosantDevice device(LOSANT_DEVICE_ID);
void connect() {
  // Connect to Wifi.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  // WiFi fix: <a href="https://github.com/esp8266/Arduino/issues/2186"> <a href="https://github.com/esp8266/Arduino/issues/2186"> https://github.com/esp8266/Arduino/issues/2186
</a>
</a>
  WiFi.persistent(false);
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  unsigned long wifiConnectStart = millis();
  while (WiFi.status() != WL_CONNECTED) {
    // Check to see if
    if (WiFi.status() == WL_CONNECT_FAILED) {
      Serial.println("Failed to connect to WIFI. Please verify credentials: ");
      Serial.println();
      Serial.print("SSID: ");
      Serial.println(WIFI_SSID);
      Serial.print("Password: ");
      Serial.println(WIFI_PASS);
      Serial.println();
    }
    delay(500);
    Serial.println("...");
    // Only try for 5 seconds.
    if(millis() - wifiConnectStart > 5000) {
      Serial.println("Failed to connect to WiFi");
      Serial.println("Please attempt to send updated configuration parameters.");
      return;
    }
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.print("Authenticating Device...");
  HTTPClient http;
  http.begin("http://api.losant.com/auth/device");
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Accept", "application/json");
  /* Create JSON payload to sent to Losant
   *
   *   {
   *     "deviceId": "575ecf887ae143cd83dc4aa2",
   *     "key": "this_would_be_the_key",
   *     "secret": "this_would_be_the_secret"
   *   }
   *
   */
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["deviceId"] = LOSANT_DEVICE_ID;
  root["key"] = LOSANT_ACCESS_KEY;
  root["secret"] = LOSANT_ACCESS_SECRET;
  String buffer;
  root.printTo(buffer);
  int httpCode = http.POST(buffer);
  if(httpCode > 0) {
      if(httpCode == HTTP_CODE_OK) {
          Serial.println("This device is authorized!");
      } else {
        Serial.println("Failed to authorize device to Losant.");
        if(httpCode == 400) {
          Serial.println("Validation error: The device ID, access key, or access secret is not in the proper format.");
        } else if(httpCode == 401) {
          Serial.println("Invalid credentials to Losant: Please double-check the device ID, access key, and access secret.");
        } else {
           Serial.println("Unknown response from API");
        }
      }
    } else {
        Serial.println("Failed to connect to Losant API.");
   }
  http.end();
  // Connect to Losant.
  Serial.println();
  Serial.print("Connecting to Losant...");
  device.connectSecure(wifiClient, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);
  while(!device.connected()) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected!");
  Serial.println();
  Serial.println("This device is now ready for use!");
}
void setup() {
  Serial.begin(9600);
  Serial.setTimeout(2000);
  pinMode(BUILTIN_LED, OUTPUT);
  // Wait for serial to initialize.
  while(!Serial) { }
  Serial.println("Device Started");
  Serial.println("-------------------------------------");
  Serial.println("Running DHT!");
  Serial.println("-------------------------------------");
  connect();
}
void report(double humidity, double tempC, double heatIndexC) 
{
  StaticJsonBuffer<400> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["humidity"] = humidity;
  root["tempC"] = tempC;
  root["heatIndexC"] = heatIndexC;
  device.sendState(root);
  Serial.println("Reported!");
}
int timeSinceLastRead = 0;
int timeTotal = 0;
void loop() {
   bool toReconnect = false;
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Disconnected from WiFi");
    toReconnect = true;
  }
  if (!device.connected()) {
    Serial.println("Disconnected from MQTT");
    Serial.println(device.mqttClient.state());
    toReconnect = true;
  }
  if (toReconnect) {
    connect();
  }
  device.loop();
  // Reboot roughly every hour.
  if (timeTotal > 30000) {
    Serial.println("Reboot");
    ESP.restart();
  }
  // Report every 10 seconds.
  if(timeSinceLastRead > 10000) {
    digitalWrite(BUILTIN_LED, HIGH);
    Serial.println(timeTotal);
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("Failed to read from DHT sensor!");
      timeSinceLastRead = 0;
      return;
    }
    // Compute heat index in Fahrenheit (the default)
    float hif = dht.computeHeatIndex(f, h);
    // Compute heat index in Celsius (isFahreheit = false)
    float hic = dht.computeHeatIndex(t, h, false);
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t");
    Serial.print("Heat index: ");
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(hif);
    Serial.println(" *F");
    report(h, t, hic);
    timeSinceLastRead = 0;
  }
  delay(100);
  timeSinceLastRead += 100;
  timeTotal += 1;
  digitalWrite(BUILTIN_LED, LOW);
  }

The key items to note with this code:

  • I added a counter called timeTotal that incremented by one during each loop cycle. When the count reached 30000, a system restart was initiated.
  • The LED flashes every time data is sent over the WiFi via the digitalWrite command.
  • I changed the timeSinceLastRead value check in the loop to send data at 10000 milliseconds versus the default of 2000 milliseconds(or 10 seconds versus 2 seconds)

Once I got the code compiled and loaded into my NodeMCU, I then attached a white LED to the D1 port of the board and hooked everything back up to a power source.

Watching the LED blinking every 10 seconds was a very good sign.

Now that the board was alive, I needed it to talk to the internet. One of the main services that Losant provides is a cloud hosting of data from IOT devices. They provide a series of very easy to set up dashboard widgets that you could use with your device.

Referring back to their tutorial I set up a Losant account, set up a device id and key (which I had to plug into my program code and recompile back into the NodeMCU) and created a few dashboard widgets on the temperature data that I was sending.

The nice thing was that it was also pretty easy to embed these dashboard widgets into any website.

Oh, by the way, is anyone curious about the temperature outside my door?

And with that, I built my first Internet of Things device.

At the moment it was just a couple of electronic bits sitting on a breadboard, relying on an external power source, but my ultimate goal is to have this in a more proper home for my new creation that is better suited for living outside in the elements, nowhere near any place that it could plug into for juice.

Step 3: Taking the Weather Station of the Grid

While I was happy in how things turned out, in order to power up the station I still needed to have it connected to a USB power source. Since I wanted to have the weather station to be located outside, I needed to find a way to keep it powered up without the need for it to be plugged into a wall socket.

Since the NodeMCU only requires 5 volts to run, it does make it a perfect candidate to run off a battery. If it can be run off a battery, then that also means that the battery itself can be charged with a solar cell.

With that in mind I went to my box of electronic LEGO and pulled out the following items:

  • A 5 Volt Solar cell
  • A 1 Amp Solar Charger Controller
  • Three AA 3.7 Volt Lithium Ion rechargeable batteries
  • Three AA Battery holders
  • A 0.9-5 Volt to 5 Volt Step Up Booster Module
  • Various bits of wire

With this collection of parts, I can easily put together a circuit that can charge a 3.7 Volt lithium battery via a solar cell. While the battery is being charged, the solar cell also provides power to the NodeMCU. When the sun is not out, the battery powers the NodeMCU via the 5 Volt converter module.

I started by attaching wires to the negative and positive terminals of the solar cell, followed by soldering the other ends of the wires to the input terminals of the solar charger controller.

Luckily the input connections were marked on the charger's circuit board.

Once the solar cell was connected to the controller I then connected the battery holders to the battery terminals on the controller board.

While I suspect that one 3.7 volt battery probably would have sufficed, I had decided to wire three battery holders together in parallel in order to have as much storage capacity available for the NodeMCU -in case there are any extended periods of time where full sunlight is not available. Additionally, this would also add some redundancy to the system in case one of the batteries failed.

I had confirmed beforehand that the solar charger was quite happy charging 3 batteries. before I wired everything permanently together.

With the batteries and solar cell hooked up, the final step was to connect the 5-volt converter to the charge controller. Again this was done by attaching wires to the negative and positive terminals of the converter, followed by soldering the other ends of the wires to the load output terminals of the charger controller.

With that, the solar power source for the NodeMCU was built.

To make sure that everything was working before I hooked up the NodeMCU, I first installed the batteries and placed the whole contraption out into the sunlight.

If everything was hooked up correctly, I should have seen a red status LED on the controller light up - which indicated that the batteries were charging. After a few hours, the LED then changed to green, indicating that the batteries were fully charged.

Likewise, the 5-volt converter was also showing a red LED, indicating that it was working.

Luckily for me, everything lit up like it was supposed to on the first try!

Flushed with success, I then plugged in the NodeMCU and let it start logging the weather outside - secure in the knowledge that the device will be continuously powered thanks to the sun.

But, once the sun went down, the batteries only lasted about 6 hours, and I wasn't able to get them recharged enough the next day to keep the NodeMCU going.

Upon some additional research, I discovered that the NodeMCU is a bit of a power hog when it's running, even when it's not doing any actual work.

Apparently, this is a common issue with these devices. but they do happen to have what is called a deep sleep mode which allows you to effectively power the NodeMCU down for a set period of time, have it wake up to do a task and then go back to sleep again.

This deep sleep mode is accomplished via a combination of programming code to invoke the sleep mode and a hardware configuration of connecting the Reset pin to the D0 pin on the NodeMCU.

The Reset pin is used to send a signal to the D0 pin to trigger the wake-up command.

This did pose a bit of a problem however in that I had already allocated the D0 pin in my code to blink the LED that I was using to indicate that the system was working. To solve that I was able to allocate the D4 pin as the blink pin for my LED,

I then stripped out the delay code that I had in my program and in its place, I implemented a command to put the NodeMCU into a deep sleep state every 30 mins.

So basically what the program will now do is:

  • Log onto the Losant site
  • Send a burst of data to it for about 1 minute
  • Go to sleep for 30 minutes
  • Wake up and do it all over again.

Going back to my original program I changed it to this (changes that indicate the LED going to pin D0 and the invoking of the sleep more are highlighted with the comment of "New Code"):

/**
 * Example for sending temperature and humidity
 * to the cloud using the DHT22 and ESP8266
 *
 * Copyright (c) 2016 Losant IoT. All rights reserved.
 * Modifications by Small Workshop Chronicles
 *  https://www.losant.com

 */
#include "DHT.h"
#include <esp8266wifi.h>
#include <esp8266httpclient.h>
#include <losant.h>
#define DHTPIN 4     // what digital pin the DHT22 is conected to
#define DHTTYPE DHT22   // There are multiple kinds of DHT sensors
DHT dht(DHTPIN, DHTTYPE);
// WiFi credentials.
const char* WIFI_SSID = "<my wifi="" id="">";
const char* WIFI_PASS = "<my password="">";</my></my>
// Losant credentials.
const char* LOSANT_DEVICE_ID = "<my device="" id="">";
const char* LOSANT_ACCESS_KEY = "<my access="" key="">";
const char* LOSANT_ACCESS_SECRET = "<my access="" code="">";
WiFiClientSecure wifiClient;
LosantDevice device(LOSANT_DEVICE_ID);
void connect() {
  // Connect to Wifi.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WIFI_SSID);
  // WiFi fix:  https://github.com/esp8266/Arduino/issues/2186

  WiFi.persistent(false);
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  unsigned long wifiConnectStart = millis();
  while (WiFi.status() != WL_CONNECTED) {
    // Check to see if
    if (WiFi.status() == WL_CONNECT_FAILED) {
      Serial.println("Failed to connect to WIFI. Please verify credentials: ");
      Serial.println();
      Serial.print("SSID: ");
      Serial.println(WIFI_SSID);
      Serial.print("Password: ");
      Serial.println(WIFI_PASS);
      Serial.println();
    }
    delay(500);
    Serial.println("...");
    // Only try for 5 seconds.
    if(millis() - wifiConnectStart > 5000) {
      Serial.println("Failed to connect to WiFi");
      Serial.println("Please attempt to send updated configuration parameters.");
      return;
    }
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  Serial.print("Authenticating Device...");
  HTTPClient http;
  http.begin("http://api.losant.com/auth/device");
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Accept", "application/json");
  /* Create JSON payload to sent to Losant
   *
   *   {
   *     "deviceId": "575ecf887ae143cd83dc4aa2",
   *     "key": "this_would_be_the_key",
   *     "secret": "this_would_be_the_secret"
   *   }
   *
   */
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["deviceId"] = LOSANT_DEVICE_ID;
  root["key"] = LOSANT_ACCESS_KEY;
  root["secret"] = LOSANT_ACCESS_SECRET;
  String buffer;
  root.printTo(buffer);
  int httpCode = http.POST(buffer);
  if(httpCode > 0) {
      if(httpCode == HTTP_CODE_OK) {
          Serial.println("This device is authorized!");
      } else {
        Serial.println("Failed to authorize device to Losant.");
        if(httpCode == 400) {
          Serial.println("Validation error: The device ID, access key, or access secret is not in the proper format.");
        } else if(httpCode == 401) {
          Serial.println("Invalid credentials to Losant: Please double-check the device ID, access key, and access secret.");
        } else {
           Serial.println("Unknown response from API");
        }
      }
    } else {
        Serial.println("Failed to connect to Losant API.");
   }
  http.end();
  // Connect to Losant.
  Serial.println();
  Serial.print("Connecting to Losant...");
  device.connectSecure(wifiClient, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);
  
  while(!device.connected()) {
    delay(500);
    Serial.print(".");
    Serial.println("Reboot");
    ESP.restart();
    
  }
  Serial.println("Connected!");
  Serial.println();
  Serial.println("This device is now ready for use!");
}
void setup() {
  Serial.begin(9600);
  Serial.setTimeout(2000);
  pinMode(D4, OUTPUT);                                            // New Code - ressigned for LED
  // Wait for serial to initialize.
  while(!Serial) { }
  Serial.println("Device Started");
  Serial.println("-------------------------------------");
  Serial.println("Running DHT!");
  Serial.println("-------------------------------------");
  connect();
}
void report(double humidity, double tempC, double heatIndexC) 
{
  StaticJsonBuffer<400> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["humidity"] = humidity;
  root["tempC"] = tempC;
  root["heatIndexC"] = heatIndexC;
  device.sendState(root);
  Serial.println("Reported!");
  delay(1000);
}
void callback() {
  Serial.flush();
}
int timeSinceLastRead = 0;
int timeTotal = 0;
void loop() {
   bool toReconnect = false;
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Disconnected from WiFi");
    toReconnect = true;
  }
  if (!device.connected()) {
    Serial.println("Disconnected from MQTT");
    Serial.println(device.mqttClient.state());
    toReconnect = true;
  }
  if (toReconnect) {
    connect();
  }
  device.loop();
  // Sleep for 30 mins.                                //New Code  - Logic for deep sleep 
  if (timeTotal > 1000) {                             //New Code    mode. This logic will 
    Serial.println("Sleep");                          // New Code   make the module sleep for
    ESP.deepSleep(30*60*1000000);                     // New Code   30 minutes
    Serial.println("Awake");                          // New Code
  }
  // Report every 10 seconds.
  if(timeSinceLastRead > 10000) {
    digitalWrite(D4, HIGH);                          //New Code - triggers LED
    
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("Failed to read from DHT sensor!");
      timeSinceLastRead = 0;
      return;
    }
    // Compute heat index in Fahrenheit (the default)
    float hif = dht.computeHeatIndex(f, h);
    // Compute heat index in Celsius (isFahreheit = false)
    float hic = dht.computeHeatIndex(t, h, false);
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t");
    Serial.print("Heat index: ");
    Serial.print(hic);
    Serial.print(" *C ");
    Serial.print(hif);
    Serial.println(" *F");
    report(h, t, hic);
      
    digitalWrite(D4, LOW);                                           // New code - turns off LED
    
    timeSinceLastRead = 0;
  }
  
  timeSinceLastRead += 100;
  timeTotal += 1;
  
  }

I also changed the LED connection from the D0 pin to the D4 pin on the NodeMCU.

I then connected the Reset pin to the D0 pin.

In the end, the connections to the NodeMCU looked like the circuit diagram pictured above.

Once I made the necessary wiring changes and uploaded the new code up to the NodeMCU, I plugged the NodeMCU back into the solar charger circuit.

This proved to be much more successful.

With the sleep mode implemented, the NodeMCU is only truly on for 2 minutes per hour, Which gives the solar charger ample time to charge the batteries during the sleep cycles and has minimized the power draw during the night so that the NodeMCU is easily able to operate for the entire night,

Now that I have the electronics of my weather station sorted out, I now needed to figure out a suitable enclosure for my weather station so that it could survive the elements.

Step 4: Building a Stevenson Screen for the IOT Weather Station

Now that I had the electronic solution worked out, the next step was to house everything in a weather resistant enclosure that still allowed the station access to the outside air in order to ensure accurate readings.

Basically what I needed to construct was a Stevenson Screen.

A Stevenson Screen, to quote Wikipedia, is:

"... A Stevenson screen or instrument shelter is a shelter or an enclosure to protect meteorological instruments against precipitation and direct heat radiation from outside sources, while still allowing air to circulate freely around them.[1] It forms part of a standard weather station. The Stevenson screen holds instruments that may include thermometers (ordinary, maximum/minimum), a hygrometer, a psychrometer, a dewcell, a barometer, and a thermograph. Stevenson screens may also be known as a cotton region shelter, an instrument shelter, a thermometer shelter, a thermoscreen or a thermometer screen. Its purpose is to provide a standardized environment in which to measure temperature, humidity, dewpoint, and atmospheric pressure...."

In short, it's a box that has holes or slots in it that allows air to come in but keeps the rain out.

While I was doing research on how the Stevenson screens are built, I found out that these screens were typically simple boxes that had double louvered sides. The plan for my screen was to build it as simple as possible while maintaining the necessary protection from the elements.

Eventually, I happened across the Weather for Schools web site where I found plans for a simple weather box.

After reviewing the instructions, I realized that, with some minor modifications, this would work nicely for what I wanted to do.

To start the build I first cut out the basic shape of the box by cutting out the pieces as I have identified in the cutting diagram above using some 1/2 inch scrap birch that I had laying around.

When I cut out the side pieces, I also cut a 15-degree angle along one end.

Once the parts of the screen were cut out I then took my measuring tape and marked a spot every 2 inches in the middle of the sides and the door pieces.

I then drilled a 1-inch hole at every spot that I marked,

These holes will act as the ventilation holes in order to allow air flow to the weather station sensors.

Next, I attached the sides of the Stevenson screen to the back piece with some brad nails and wood glue.

I then drilled a 1/8 inch hole at the top of the back piece to act as a mounting point for hanging screen when it's ready to be installed.

With the sides and back attached I then attached the bottom of the Stevenson screen to the sides and back, but first I needed to drill a small 5mm hole in the center of the bottom.

The reason for the hole is to give me some way to visually indicate when the weather station was transmitting data. As you may recall, I programmed the NodeMCU to flash an LED when it was sending data,

My plan was to install the LED into the bottom of the Stevenson screen so that I can visually tell when a transmission is occurring.

I drilled the hole in the center of the bottom by marking 2 diagonal lines between the corners of the bottom piece and drilling the hole where the 2 lines intersected in the middle.

Once the hole was drilled, the bottom was then attached to the screen with some glue and brad nails.

Finally, I attached the top of the Stevenson screen in pretty much the same manner that I did with the bottom in that I needed to first drill a hole into the center of the top in order to allow the wires from the solar cellto pass through.

Once the hole was drilled, the top was attached to the sides and back of the Stevenson screen with some glue and brad nails.

Now that the body of the screen was pretty much built, I then took the time to give the screen a coat of white paint. White is recommended so that the sun's rays can be reflected off the Stevenson screen and not directly affect the interior temperature of the box.

The next thing I focussed on was the door. I wanted to have the ability to open the door so that I can easily check on the condition of the weather station or to do any maintenance like change the batteries.

In order to make the door easy to open, I decided to install a small wooden drawer pull that I happen to have sitting in my junk box.

To install the door pull, I marked a spot in the center of the top of the door and drilled a 1/8 inch hole at that location.

I then installed the door pull in the drilled hole.

I then installed the door by attaching a hinge to the bottom of the Stevenson screen with some screws.

Once one half of the hinge was attached to the bottom, I then attached the other half of the hinge to the bottom edge of the door.

Once I installed the hinge, I then tested the door to make sure that I could open and close the door fairly easily.

And with that, the Stevenson screen was basically complete.

Step 5: Putting It All Together

The last step in the process is to install the electronics of the weather station into the Stevenson Screen itself.

First I started by collecting all the various bits of electronic LEGO that I used when I was building the solar battery charging circuit for the weather station.

I started the install by first soldering hook up wires to the positive and negative terminals of the solar panel.

Once the solder had cooled I then applied a small dab of hot glue to the solder joints in order to provide some weather protection to the joints.

I then applied some hot glue to the top of the Stevenson screen, routed the wires attached to the solar panel through the top of the screen and attached the solar panel to the top of the screen.

With the solar panel installed, the next step was to wire up the solar charger controller board. As I mentioned earlier, connecting the controller board is a simple matter of wiring the positive and negative wires from the solar cell to the input terminals on the controller, soldering the battery holders to the battery terminals and finally soldering the 5 volt converter to the output terminals of the controller.

With the electronics all wired up, they are then installed into the Stevenson screen by securing them to the back of the screen with some hot glue.

When I installed the components, I made sure to leave enough room at the bottom of the Stevenson Screen to allow for the installation of the NodeMCU and sensor.

Before installing the NodeMCU, I first installed the LED into the bottom of the screen and secured it in place with some hot glue.

Finally, I applied some hot glue to the back of the NodeMCU and sensor module and installed it into the back of the Stevenson Screen.

I soldered the LED to the NodeMCU board, plugged the NodeMCU into the 5-volt converter and installed the lithium batteries.

With any luck at all, the weather station should power right up.

Before wrapping things up I then applied a coating of hot glue on top of all the exposed electronic surfaces to serve as weatherproofing.

And with that - the Weather Station was installed and the Stevenson Screen was ready to go.

To install the Stevenson Screen, I selected a spot that would get a fair bit of air movement while at the same time provide enough direct sunlight during the day to keep the batteries charged.

So far the weather station is working quite well and has been staying powered up continuously since I installed it about 6 months ago.

In the end, the whole station cost me about 15 dollars to build - considering what it would cost to buy a similar weather station with wireless internet connectivity from a store, it's quite the bargain and I ended up learning a bit about how IOT devices worked to boot!

Thanks for checking out my Instructable!

If you find this intriguing, please check out my site to see what other things I'm tinkering with!

IoT Challenge

Runner Up in the
IoT Challenge