Sunday, May 30, 2021

Building a Tweeting Weather Station

 

Almost Live Weather

I seem to be a bit of a sucker for weather stations. 

A couple of months ago I mentioned that I started subscribing to a crate service called CreationCrate, which sent you a monthly box stuffed with electronic goodies that typically included an Arduino Uno and plans to build a project of the month. 

This month when the crate arrived in my mailbox, I was absolutely stunned to see that the project of the month was a weather station kit complete with sensors to measure temperature, humidity, and barometric pressure. 

In particular, the sensors were DHT11 which detects the humidity and temperature, and a BMP180, which is capable of detecting barometric pressure, altitude, and temperature. 

BMP180

DHT11

These are pretty common and robust sensors and are pretty easy to use since they use only one wire to send information to the device that's reading the sensor. 

In the case of this project, we would use the DHT for humidity data and the BMP to collect the temperature and barometric pressure.  We could also use the DHT for temperature, but I've been told that the BMP sensor is the more accurate of the 2. 

The idea for the kit was to hook up the sensors to an Arduino, and after entering some screen input, have the data from the sensors print out on the Arduino's serial monitor.

Based on the instructions of the kit, wiring is very straightforward, though we did need to be careful in connecting the power since the sensors have to have  3.3 volts to work. Hooking them up to the Arduino's 5-volt sockets will cook them. 

Aside from the power connections, the DHT data signal was connected to the Arduino's #2 PWM pin, BMP's SCL pin to the Arduino's A5, and the SDA pin to the Arduino's A4 port. 

Wiring Diagram
Courtesy of CreationCrate

The code for the kit was pretty straightforward and made you enter in some parameters for the display values (such as metric or imperial values) on the serial monitor after which then the Arduino started to display weather data every 2 seconds. 

It was pretty fun putting the kit together, but after watching the values scroll by on the Arduino's monitor, I started having some thoughts...

  • Wouldn't it be nice if I could somehow collect that data into a file, instead of just watching it scroll by on my monitor
  • If I can collect it in a file, That means that I can do something useful with it - like tweet it to the world! 
The first challenge was to somehow capture the data that was happily scrolling by the screen. However, with the program firing out displays every 2 seconds, it will make for a very full file very quickly, plus I don't think Twitter would want me tweeting every 2 seconds.

Also, I didn't want the Arduino sitting around waiting for me to input parameters, I wanted it to immediately start monitoring the sensors as soon as it was powered on. 

Plus, since it was Twitter, I wanted to also attach some hashtags to my tweets. 

Based on that, I modified the original Creation Create code to display Temperature, Humidity, Heat Index, and Barometric Pressure every 6 hours. All output lines would have the hashtags #NorthPerth, #Listowel, and #weather since that is the town near where I live. 

Full code is here:

// Step 1: Include all necessary libraries
#include<DHT.h>
#include<Wire.h>
#include<Adafruit_BMP085.h>

// Step 2: Define pins and initialize global variables
#define DHTPIN 2
#define DHTTYPE DHT11

float temperature = 0;
float humidity = 0;
float pressure = 0;
float heatIndex= 0;
float altitude = 0;
float seaLevelPressure = 0;
int units = 'a';
bool DHT_OK = true;
bool BMP_OK = true;

// Constant variable (the value cannot be changed).
const float m_to_ft = 3.28084;

// Declare instances of classes.
Adafruit_BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);

// Step 3: Create setup loop
void setup() {
  Serial.begin (9600);
// Check if BMP180 is connected properly.
  if (!bmp.begin()) {
    Serial.println("\nCould does not find a valid BMP180 sensor, check to the wire! Continuing without BMP180...");
        BMP_OK = false;
  }

// Initiate the DHT sensor and check its connection.
  dht.begin();
// nan means ‘not a number’.
  if (isnan(dht.readHumidity()) || 
isnan(dht.readTemperature())) {
    Serial.println("Could not find a valid DHT11 sensor, check wiring!");
    DHT_OK = false;
  }

// If both sensors are bad, loop forever and display a message to a user.
  if (!BMP_OK && !DHT_OK) {
    Serial.println("Could not find either BMP180 or DHT11 sensor! Check wiring...reset to try again.");
    while (1) {}
  }

  units = 'm';
   
  if (BMP_OK) {
       seaLevelPressure = 97;
      }
// Check to see if pressure entered is within reasonable bounds.
     
    }

 // END OF SETUP LOOP

// Step 4: Create main loop
void loop() {
//  6 hour delay
  delay(21600000);
//    delay(20000);
// Get and print data using this function.
  printWeatherData();

// Function that gets and prints data to serial monitor.
void printWeatherData() {
  if (DHT_OK) {
// Get data from sensors.
    humidity = dht.readHumidity();
  }

   if (BMP_OK) {
// Get temperature from BMP180 (The DHT11 can also detect temperature, but the BMP180 is more precise).
    temperature = dht.readTemperature();
// Get current pressure.
    pressure = bmp.readPressure();
// Get altitude in meters (seaLevelPressurekPa * 1000 Pa/kPa).
    altitude = bmp.readAltitude(seaLevelPressure * 1000);
  } 

  else if (DHT_OK) {
// Get temperature from DHT11 since the more accurate BMP180 sensor is not working.
    temperature = dht.readTemperature();
  }

// Calculate heat index by taking humidity into account.
  if (units == 'i') {
    temperature = dht.convertCtoF(temperature);
    heatIndex = dht.computeHeatIndex(temperature, humidity,true);
  } 
  
  else {
    heatIndex = dht.computeHeatIndex(temperature, humidity,false);
  }

// Print weather data.
  Serial.print("Temperature: ");
  Serial.print(temperature, 1);
  Serial.print((units == 'm') ?" *C":" *F");

  Serial.print("\t   Humidity: ");
  Serial.print(humidity, 1);
  Serial.print(" %\t");

  Serial.print("   Heat index: ");
  Serial.print(heatIndex, 1);
  Serial.print((units == 'm') ?" *C      ":" *F");
  
  Serial.print("   Pressure: ");
  Serial.print(pressure / 1000, 3);
  Serial.print(" kPa");
  Serial.print("\t");

  Serial.print(" #NorthPerth #Weather #Listowel");                                          
  Serial.println("   ");
}

Now that I had how I wanted my data to be presented in my future tweets, the next challenge was to somehow get the output of the Arduino into a text file that I can then use to feed a process to send the data to Twitter. 

The Arduino editor is an excellent development platform that encompasses a powerful editor, compiler, and debug tools. As part of the debug tool suite, the Serial Monitor monitors the output of the Arduino as it's running a program via the USB connection to my computer. 

While the monitor provides a very user-friendly way to see how my program is running, it doesn't really have a way to export output - basically, I can look, but can't touch.  

After some research, I found the answer via  Arduino's big brother - the Raspberry Pi.  

The Raspberry Pi is primarily based on the Linux OS platform and acts very much like any other Linux-based server. Often servers will operate "headless" where they are not directly connected to a monitor or keyboard. Instead, access is done by remotely accessing the server from another computer via a terminal emulator program. 

The most common emulator used for Linux is Putty, which is an open-source emulator app that is free to download. In my searching the internet, I had stumbled across info that Putty also could be used to access devices that are connected via a compter's COM port - basically the same way the Arduino's serial monitor does when communicating with a host computer. 

The other nice thing about Putty is that it also had the capability to log output to a text file.  

To set up Putty to read in the Arduino output I first determined which COM port the Arduino was using on my computer - which I found out by looking at what the Arduino Editor was using to communicate with the Arduino - in my case, it was COM4 port. 

Opening up Putty, I defined a new terminal session by setting the connection type to Serial and typing in COM4 as the Serial Line value. 

The connection speed was set to 9600 baud.

Once that was done I saved the session with the name "Weather" 

Setting up the connection

Next, I needed to set up the details that I needed to allow Putty to send the Arduino output to a text file. 

To do that I clicked on the "Logging" tab on the left-hand side of the Putty interface screen.

This opens up the session logging set up screen 

To enable logging, I set the session logging on by clicking on the Printable Output radio button. 

After that, I defined my log file as "weather.txt", clicked on the "Always append to the end of the file" radio button and I clicked on "Flush Log File Frequently" 

Set up logging

I then saved the session details one more time and I then activated the session. 

Immediately a session box opened up on my PC and after 6 hours, I got my first sign of life. 

Logging under way

After a day, I decided to take a peek at my log file and I was rewarded with a nice stream of weather data,  

Log file


I now have my Arduino's weather data in a text file which I can now easily manipulate. The next hurdle to overcome was to somehow tweet this data, 

To be continued next week 😉


No comments:

Post a Comment