IoT: Collecting Weather Data

Collecting data from temperature, humidity and barometric sensors with an
Arduino is compelling when observing the weather. The idea is to create an outdoor sensor module. This outdoor module sends the measured data via WiFi to a server which stores the measurement data in a local database.

Components used

ESP-ADC DIL 18 with ESP8266 module
BMP085 Barometric Pressure & Temp Sensor
DHT22 Temperature and Humidity Sensor
220 uF 16V capacitor
Single color LED
220; 4,7k, 10k resistors
wires, switches, breadboard, breadboard power supply, 3,3 V FTDI programmer

Make it happen

Wiring

wiring of esp8266, dht22, bmp085

 

ESP8266 Parts Notes
GND GND DHT22 / GND BMP085 / GND ESP-ADC / LED – via 220 resistor
VCC 3,3 V VCC DHT22 / VCC BMP085 / VCC ESP8266
Reset switch 1 / GPIO_16 Connection to GPIO_16 required for deep sleep mode of ESP8266
GPIO_0 switch 2
GPIO_4 SDA BMP085 On ESP8266 I2C is implemented in software, could be soft-wired to any other GPIO, default for I2C clock is GPIO_4
GPIO_5 SDL BMP085 On ESP8266 I2C is implemented in software, could be soft-wired to any other GPIO, default for I2C data is GPIO_5
GPIO_7 Pin 2 DHT22, pull to 3,3 V VCC via 4,7 k resistor
GPIO_13 LED +
GPIO_16 RST ESP8266
CHPD 3,3 V VCC via 10k resistor

The capacitor is used to stabilize the electric power supply for the two sensors and the ESP8266. This is especially useful when the ESP8266 sets up a WiFi connection and its power consumption increases.

Uploading an Arduino Sketch to the ESP8266

Wiring

  • Adjust the FTDI programmer for 3,3 V logic
  • Connect the FTDI programmer’s RX and TX lines to the ESP8266.
  • Connect the FTDI programmer’s GND line to GND of the breadboard power supply.

Arduino IDE settings

Adjust the upload settings in the Arduino IDE:

Arduino IDE upload settings

Uploading

To upload an Arduino sketch to the ESP8266 module push the two buttons. Release the switch connected to Reset approx. a second before the switch connected to GPIO_0 and trigger the upload in the Arduino IDE. The timing is relevant. It may happen that this procedure has to be repeated several times until the upload succeeds.

After the successful upload of the sketch the output in the Arduino IDE looks similar to this:

...
upload message on success:
setting serial port timeouts to 1000 ms
 espcomm_send_command: receiving 2 bytes of data
 writing flash
............................................................................................................................................................................................................................
starting app without reboot
 espcomm_send_command: sending command header
 espcomm_send_command: sending command payload
 espcomm_send_command: receiving 2 bytes of data
closing bootloader
 flush start
 setting serial port timeouts to 1 ms
 setting serial port timeouts to 1000 ms
 flush complete

Sketch

Installing Adafruit Libraries

The Arduino sketch based on the examples for the unified BMP085 and DHT libraries.
The required libraries for Adafruid BMP085 Unified, Sensor and DHT Unified can be installed for the Arduino IDE via Sketch > Libraries > Manage Libraries… .

Some Code

#include <ESP8266WiFi.h> // http://esp8266.github.io/Arduino/versions/2.0.0/doc/libraries.html
#include <WiFiClient.h>

#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h> // https://github.com/adafruit/Adafruit_BMP085_Unified

#include <DHT.h>
#include <DHT_U.h> // https://github.com/adafruit/Adafruit_DHT_Unified
#define DHTTYPE DHT22
#define DHTPIN 7

// WiFi network credentials
const char* ssid = "<SSID>";
const char* password = "<PASSWD>";

// IP / port weather station server
#define IPWS "192.168.145.244"
#define PORT 20016

// times for deep sleep mode
unsigned long MIN_1 = 60000000;
unsigned long MIN_15 = 900000000;
unsigned long MIN_30 = 1800000000;
unsigned long S_30 = 30000000;
unsigned long DEEP_SLEEP = MIN_30;
RFMode MODE = WAKE_RF_DEFAULT;

// Initialize DHT sensor 
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold. It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value. The default for a 16mhz AVR is a value of 6. For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01 
DHT_Unified dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266

Adafruit_BMP085_Unified bmp;

#define STATUSLED 13

boolean debugging = false; // enable / disable debug output

String float2String(float value) {
  char v[10];
  dtostrf(value,4,1,v);
  return String(v);
}

String readSensors() {
  if( debugging ) Serial.println("Read sensor data...");
  String str = "";
  String str2Send = "wData;";

  if( debugging ) Serial.println("DHT22");
  sensors_event_t event;
  float temperature = 0.0;
  dht.temperature().getEvent(&event);
  temperature = event.temperature;
  if( isnan(temperature) ) {
    if( debugging ) Serial.println("Error reading temperature!");
  } else {
    if( debugging ) {
      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println(" *C");
    }
 }
 // Get humidity event and print its value.
 dht.humidity().getEvent(&event);
 float humidity = 0.0;
 humidity = event.relative_humidity;
 if( isnan(humidity) ) {
   if( debugging ) Serial.println("Error reading humidity!");
 } else {
   if( debugging ) {
     Serial.print("Humidity: ");
     Serial.print(humidity);
     Serial.println("%");
   }
 }

 float temperature2 = 0.0;
 bmp.getTemperature(&temperature2);
 str = "Temperature: " + float2String(temperature2) + " *C\n";
 str += "Humidity: " + float2String(humidity) +" %\n";

 float pressure = 0.0;
 bmp.getPressure(&pressure);
 pressure = pressure/100.0;
 if( debugging ) {
   Serial.print("Pressure: ");
   Serial.print(pressure);
   Serial.println(" hPa");
 }
 str += "Pressure: " + float2String(pressure) + " hPa\n";

 if( debugging ) {
   Serial.print("Collected sensor data: ");
   Serial.println(str);
 } 
 str2Send += temperature;
 str2Send += ";";
 str2Send += humidity;
 str2Send += ";";
 str2Send += pressure;
 str2Send += "\0";

 if( debugging ) {
   Serial.print("Sensor data for sending to server: ");
   Serial.println(str2Send);
 }
 return str2Send;
}

// expected string: e.g. weatherdata;14.3;60.7;1018.0
void sendSensorData(String str2Send) {
 WiFiClient client;
 client.connect(IPWS, PORT);
 if( debugging ) {
   Serial.print("Sending: ");
   Serial.println(str2Send);
 }
 client.write(str2Send.c_str(), str2Send.length());
 if( client.connected() ) {
   client.stop();
 }
}

void setup(void) {
 // You can open the Arduino IDE Serial Monitor window to see what the code is doing
 Serial.begin(115200); // Serial connection from ESP-01 via 3.3v console cable

 dht.begin(); // initialize temperature sensor

 if (!bmp.begin()) {
   if( debugging ) Serial.println("Could not find a valid BMP085 sensor, check wiring!");
   while (1) {}
 }
 
 // set as station
 WiFi.mode(WIFI_STA);
 
 // connect to WiFi network
 WiFi.begin(ssid, password);
 if( debugging ) Serial.print("\n\r \n\rWorking to connect");

 // wait for connection
 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   if( debugging ) Serial.print(".");
 }

 pinMode(STATUSLED, OUTPUT);
 digitalWrite(STATUSLED, LOW);
} // setup()

void loop(void) {

 // read data from sensors
 String str = readSensors();

 if( debugging ) {
   Serial.print("Sending sensor data to server: ");
   Serial.println(str);
 }
 sendSensorData(str);

 // indicate data acquisition and sending
 digitalWrite(STATUSLED, HIGH);
 delay(1000);

 // enter deep sleep mode for x minutes
 // GPIO16 needs to be tied to RST to wake ESP8266 from deep sleep mode
 // http://russ.russmathis.com/esp8266-power-modes/
 //ESP.deepSleep(DEEP_SLEEP, MODE);
 // 30000000 ms = 30 s
 ESP.deepSleep(MIN_30, WAKE_RF_DEFAULT);
} 

Output

In debug mode the output on the serial console is similar to this:

Working to connect….
Read sensor data…
DHT22
Temperature: 22.10 *C
Humidity: 53.60%
BMP085
Temperature: 22.10 *C
Pressure: 1009.2 hPa
Collected sensor data:
Temperature: 22.10 *C
Humidity: 53.60%
Pressure: 1009.2 hPa
Sending sensor data to server: …

Notes

After measurement the ESP8266 establishes a WiFi connection. The collected data is sent as a string to a dedicated server of the desired IP within the local network.
Another possibility would be to send the data to thingspeak.com for quick visualization.

Deep sleep – saving power

After having sent the measurement data the ESP8266 enters „deep sleep“ mode until it is woken up again after the desired time. For this feature GPIO_16 has to be wired with Reset on the ESP8266.

Configuration

The ESP8266 module should be configured as a a station, not as an accesspoint (WIFI_AP). In this setup the module is used for sending data only.

Barometric sensor

Usually the barometric pressure is the ‚raw‘ value. It is calculated to match the barometric pressure at sea level. Depending on the actual level the measured value differs from the barometric values close to the location. In this case the measured barometric pressure needs to be adapted.

Temperature sensor data

Small deviations of the measured temperature are possible between the two sensors. The causes for such deviations are usually production tolerances of the sensor’s chips or even a close local heat source.

Advertisements

3 Gedanken zu “IoT: Collecting Weather Data

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s