Project tutorial
Wireless weather station (Arduino + ESP8266 + Thingspeak)

Wireless weather station (Arduino + ESP8266 + Thingspeak) © GPL3+

Ever wondered how much CO level is in your city air? How about the temperature and humidity around you? If so, welcome to this project page!

  • 9,901 views
  • 2 comments
  • 16 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
Hy gluegun
Hot glue gun (generic)
Electric file
Multimeter

Apps and online services

About this project

Intro:

This project started off as a final assessment homework for an university course I've followed this year, but proved out to be a really fun and practical way of learning new and interesting things about wireless communication and microcontrollers in general.

The main idea:

The core of this project is an Arduino Uno developing board which gathers data from two sensors:

  • DHT 11 - which is used for measuring temperature and humidity levels
  • MQ-7 - which is used for measuring the CO level in the air (ppm)

The data received from the sensors is then sent to www.thingspeak.com by using an ESP8266 12-E Wireless Module.

The components and their role:

M1201 step down buck converter (#2)

This component is needed to step down the voltage from 5V to 1.4V. The 1.4V are then used to power up the MQ-7 gas sensor for a period of 90s, the so called "reading period". (check MQ-7 datasheet for more info on the operation principle)

Note: The one that I had couldn't go down to 1.4V (although it should have) so I've used 2 more diodes to lower the voltage (check the schematics)

Mini-360 step down buck converter (#3)

This component is needed to step down the voltage from 5V to 3.3V. You can as well see it as the main 3.3V power supply in the system. The 3.3V are used to power up the ESP8266 12-E Wi-Fi module, as well as the low side of the logic level shifter.

  • The ESP8266 12-E is a Wi-Fi module which is powered at 3.3V, NOT 5V. Powering it at 5V will permanently damage the module!
  • The ESP8266 draws more than 200mA of current while operating and sending values to the web server. Powering it from Arduino's 3.3V power pin would be a big mistake as Arduino cannot provide that much current, thus making the Wi-Fi module unstable.

SRD-05VDC-SL-C 5V 1 Channel Relay Module(#8)

This relay is directly connected on the powering line of the MQ-7 CO gas sensor and has the role of cycling between 1.4V for 90S and 5V for 60s. Why so? Well according to the MQ-7 datasheet you have to heat up the sensor for 90s@5V. Only after the heating cycle you can read the sensor values for the next 60s@1.4V.

Note: See the MQ-7 datasheet for mor info on this

Logic level shifter 5V - 3.3V (#7)

Since the Arduino Uno runs at 5V and the ESP8266 12-E runs at 3.3V the logic levels are quite different between the two components. Thus, when trying to "speak" with the ESP8266 by using the RX,TX (serial communication) ports on the Arduino Uno we need a logic level shifter to do so. This component does exactly what we need: shifts the logic levels from 5V to 3.3V.

  • Check the image (fig. 1) bellow for a visual representation of the different logic levels.

Wi-Fi ESP8266 E-12 Wi-Fi module (#6)

I guess it's pretty obvious what this part is used for and that's connecting to a local Wi-Fi network (preconfigured in the source code) and sending the sensor data to www.thingspeak.com

On/Off Switch (#10)

It seems that one cannot upload a new source code file on the Arduino Uno while having the TX pin connected to another component. If you try to do so you would get a lot of errors in Arduino IDE. While uploading a new sketch the TX pin should be "floating". To do so, I've used a on/off switch to disconnect the TX line from the ESP8266 whenever I want to upload an new code on the board. (check schematics down bellow)

MQ-7 Gas Sensor (#5)

Used for reading the CO level in the air. The value provided is measured in ppm.

  • As stated earlier check the datasheet to see the working principle. The sensor needs to be powered for 90s@5v, time during which no reading is done, and 60s@1.4V, time which represents the reading period.
  • Check the datasheet for info on calibrating the sensor.

Reset button (#9)

Since the hole wiring will be hidden inside a box a the end of this project, with the Arduino Uno stuck with hot glue at the bottom of box, uploading a new sketch on the board it would pose quite a problem when it comes to physically reseting the board without opening the box. To solve this issue we would need an external reset button. That's exactly what this big red button does. It resets the board.

The LED's (#9)

  • 11 - general error indicator (for debugging the error we would need to connect the board to a pc and check the Serial Monitor Interface in Arduino IDE for the error message)
  • 12 - signals the presence/absence of the ESP8266 in the current system
  • 13 - signals if ESP8266 is connected/not connected to the local network
  • 15 - blinks whenever the MQ-7 is heating
  • 16 - blinks whenever Arduino Uno reads data from sensors

The Buzzer

Whenever the CO level read from the MQ-7 gas sensor exceeds a certain value hardcoded in the code, an alarm will be triggered by using the buzzer.

Software requirements:

In order to see the value of sensor data, we will need a private channel on thingspeak.com. We will also need Arduino IDE to write/upload the code for Arduino Uno.

List of software requirements:

  • Private channel on Thingspeak.com and
  • Arduino IDE (Preferably latest version).

You can download latest version of Arduino IDE from arduino.cc.

In order for the sketch to work we will also need the DHT11 library which you can download in the attachment section down bellow. For a step by step tutorial on how to add this library to Arduino IDE check the following link: https://www.arduino.cc/en/Guide/Libraries

Now lets create a private channel on thingspeak.com

Creating private channel on Thingspeak.com

To make a private channel on thingspeak.com follow these steps:

  • Open your web browser and go to thingspeak.com and click on 'Sign Up' tab in right top corner, (Image no.1)
  • Fill in the details and click on 'Create account', (Image no.2)
  • Now click on 'New Channel' tab, (Image no.3)
  • Again fill in details for channel and enable 4 fields (as we will be sending 4 sensor values), scroll down and click on 'Save Channel' tab, (Image no.4/5)
  • On this page click on 'API Keys' tab and note down your 'Write API Key'.

That's all folks, now you have your private ThingSpeak channel. Now lets put all electronics component together.

The Code

The code for Portable weather station is quite simple. I have commented code properly for ease of portability. Before you burn the code take care of following things.

  • Make sure that all libraries are installed,
  • Replace hyphens (--------) with SSID of your access point (wifi router) in line 14 of the code,
  • Replace hyphens (--------) with PASSWORD of your wifi network in line 15 of the code,
  • Replace hyphens (--------) with your ThingSpeak's private channel write API key in line 17 and
  • While uploading the code to the Arduino make sure that the on/off switch on the TX line is set to "off" so that you can upload the code

Now that we have our hardware and software in place, only thing remaining is packaging.

The logic

If you find the code pretty difficult to understand take a look on the logic diagram down bellow:

Packaging and enclosing the system

Down bellow you are going to find some useful photos taken while I was preparing the enclosure for the system. Make sure you have the tools required to make a box like the one bellow (elecrtic file, soldering iron, hot glue gun...)

  • As you can see in the third image above I've used some generic "mother" type pins soldered together for providing power/ground to the components of the system. I've then hot glue the piece to the side panel of the box, inside of it.

Results

You can check the results of this project by clicking on the following link which should redirect you to the public view of my thingspeak channel: https://thingspeak.com/channels/152176

Problems encountered during development

  • Sometimes some parts of the system went unresponsive due to poor contact on the breadboard. If the ESP8266 becomes unresponsive out of a sudden, first thing I would suggest doing would be to check the connections once again
  • If you see a lot of garbage in the Serial Monitor console make sure the baud rate in the console is set accordingly with the ESP8266 settings.

For more info on changing the baud rate of the Serial Montior console check the following link: https://learn.adafruit.com/adafruit-arduino-lesson-5-the-serial-monitor/other-things-to-do

For more info on changing the baud rate setting of the ESP8266 check the following link: http://www.esp8266.com/viewtopic.php?f=13&t=718

  • Make sure you calibrate the MQ-7 sensor correctly as if not you would receive some big measurement errors

For more info on that check the following link: http://forum.arduino.cc/index.php?topic=55799.msg399839#msg399839

Future projects tips

  • DHT11 isn't quite precise, in the sense that it can give random errors. A DHT22 sensor would prove much more accurate, but it is also a little bit more expensive than the DHT11
  • ESP8266 proved to be a little bit unstable during the development phase. A ESP32 or a NodeMCU board might be better for a future project

Some random photos taken during developing stage

References:

Code

Main CodeC/C++
#include<stdlib.h>
#include "DHT.h"

//-----ESP8266 macros---------
#define SSID "------"//your network name
#define PASS "------"//your network password
#define IP "184.106.153.149" // thingspeak.com
#define Baud_Rate 9600 //Another common value is 115200
#define GREEN_LED 3 //optional LED's for debugging
#define RED_LED 4 //optional LED's for debugging
#define YELLOW_LED 5 //optional LED's for debugging
#define ESP_FOUND_LED 6 //optional LED's for debugging
#define DELAY_TIME 3000 //time in ms between posting data to ThingSpeak

//Can use a post also
String GET = "GET /update?key=------";
//String FIELD1 = "&field1=";
String FIELD2 = "&field2=";
String FIELD3 = "&field3=";

bool updated;

//----Relay/MQ-7 macros
#define RELAY 8
#define MQ7_ANALOG_IN_PIN 0
#define HEATING_LED 9
#define READING_LED 10
#define BUZZER 11

#define MQ7_HEATER_5_V_TIME_MILLIS 60000
#define MQ7_HEATER_1_4_V_TIME_MILLIS 90000
#define GAS_LEVEL_READING_PERIOD_MILLIS 1000

unsigned long startMillis;
unsigned long switchTimeMillis;
unsigned int gasLevel;
boolean heaterInHighPhase;

//----Temperature sensor macros
#define DHTPIN 7     // what pin the DHT sensor is connected to
#define DHTTYPE DHT11   // Change to DHT22 if that's what you have

DHT dht(DHTPIN, DHTTYPE);

//this runs once
void setup()
{
  //initalize DHT sensor
  dht.begin();

  //start the clock
  startMillis = millis();

  //initialize network LEDs
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(ESP_FOUND_LED, OUTPUT);


  //initialize MQ-7 LEDs
  pinMode(HEATING_LED, OUTPUT);
  pinMode(READING_LED, OUTPUT);
  pinMode(BUZZER, OUTPUT);

  //initialize MQ-7 power supply
  pinMode(RELAY, OUTPUT);

  //set baud rate
  Serial.begin(Baud_Rate);
  delay(1000);

  //-----connect to network---------
  Serial.println("Checking if ESP8266 is online...");
connectionStart:
  Serial.println("AT");
  delay(5000);

  if (Serial.find("OK")) {
    digitalWrite(ESP_FOUND_LED, HIGH);
    Serial.println("ESP8266 found <module online>...");
    Serial.println("Trying to connect to network...");
    //connect to your wifi netowork
    bool connected = false;

    do {
      networkBlinkConnecting();

      connected = connectWiFi();

      if (!connected) //signal failure
        for (int i = 0; i < 3; i++)
          networkBlinkError();
    } while (!connected);

    Serial.println("Connection achived....");
    digitalWrite(YELLOW_LED, HIGH); // indicate connection achived

  } else {
    Serial.println("ESP8266 not found...");
    Error();
    goto connectionStart;
  }

}

//this runs over and over
void loop() {

  if (heaterInHighPhase) {
    // 5v phase of cycle. see if need to switch low yet
    if (millis() > switchTimeMillis) {
      Serial.println("Reading from sensors....");
      turnHeaterLow();
    }
    blinkHeating();
  }
  else {
    // 1.4v phase of cycle. see if need to switch high yet
    if (millis() > switchTimeMillis) {
      Serial.println("Heating the gas sensor....");
      turnHeaterHigh();
    }

    // Read temperature and humidity
    float h = dht.readHumidity();
    float f = dht.readTemperature(false);
    unsigned int gasLevel = readGasLevel();
    blinkReading();

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(f) || isnan(gasLevel)) {
      networkBlinkError();
      return;
    }
    else if (gasLevel >= 60) {
      tone(BUZZER, 3000); // Send 1KHz sound signal...
    }
    else {
      noTone(BUZZER);     // Stop sound...
    }

    //update ThingSpeak channel with new values
    updated = updateValues(String(f), String(h), String(gasLevel));

    //if update succeeded light up green LED, else light up red LED
    Serial.println(updated);
    if (updated) {
      networkBlinkSending();
    } else {

      networkBlinkError();
    }

    blinkReading();
  }
}

//----network update function--------------
bool updateValues(String temp, String humid, String gasLevel) {

  //initialize your AT command string
  String cmd = "AT+CIPSTART=\"TCP\",\"";

  //add IP address and port
  cmd += IP;
  cmd += "\",80";

  //connect
  Serial.println(cmd);
  delay(500);

  if (Serial.find("Error")) {
    return false;
  }

  //build GET command, ThingSpeak takes Post or Get commands for updates, I use a Get
  cmd = GET;
  //cmd += FIELD1;
  cmd += temp;
  cmd += FIELD2;
  cmd += humid;
  cmd += FIELD3;
  cmd += gasLevel;

  cmd += "\r\n";

  //Use AT commands to send data
  Serial.print("AT+CIPSEND=");
  Serial.println(cmd.length());
  if (Serial.find(">")) {
    //send through command to update values
    Serial.print(cmd);
  } else {
    Serial.println("AT+CIPCLOSE");
  }

  if (Serial.find("OK")) {
    //success! Your most recent values should be online.
    return true;
  } else {
    return false;
  }
}

//----network functions--------------
boolean connectWiFi() {
  //set ESP8266 mode with AT commands
  Serial.println("AT+CWMODE=1");
  delay(2000);

  //build connection command
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";

  //connect to WiFi network and wait 5 seconds
  Serial.println(cmd);
  delay(5000);

  //if connected return true, else false
  if (Serial.find("OK")) {
    return true;
  } else {
    return false;
  }
}

void Error() {
  networkBlinkError();
  Serial.println("Error");
}

//----MQ-7 functions--------------

void blinkHeating() {
  digitalWrite(HEATING_LED, HIGH);
  delay(200);
  digitalWrite(HEATING_LED, LOW);
  delay(200);
}

void blinkReading() {
  digitalWrite(READING_LED, HIGH);
  delay(GAS_LEVEL_READING_PERIOD_MILLIS / 2);
  digitalWrite(READING_LED, LOW);
  delay(GAS_LEVEL_READING_PERIOD_MILLIS / 2);
}
//--read from gas sensor---------
unsigned int readGasLevel() {
  return analogRead(MQ7_ANALOG_IN_PIN);
}

//----network LEDs--------

void networkBlinkSending() {
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  delay(500);
  digitalWrite(GREEN_LED, LOW);
  delay(500);
}

void networkBlinkError() {
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(RED_LED, HIGH);
  delay(200);
  digitalWrite(RED_LED, LOW);
  delay(200);
}

void networkBlinkConnecting() {
  digitalWrite(YELLOW_LED, HIGH);
  delay(200);
  digitalWrite(YELLOW_LED, LOW);
  delay(200);
}

//--- relay logic
void turnHeaterHigh() {
  // 5v phase
  digitalWrite(RELAY, HIGH);
  heaterInHighPhase = true;
  switchTimeMillis = millis() + MQ7_HEATER_5_V_TIME_MILLIS;
}

void turnHeaterLow() {
  // 1.4v phase
  digitalWrite(RELAY, LOW);
  heaterInHighPhase = false;
  switchTimeMillis = millis() + MQ7_HEATER_1_4_V_TIME_MILLIS;
}

Custom parts and enclosures

DHT 11 lib
DHT.zip
MQ-7 Datasheet

Schematics

Schematic PNG
Schita smp
Fritzing schematics
Schita_SMP.fzz

Comments

Similar projects you might like

Personal Weather Station (Arduino+ ESP8266 + Thingspeak)

Project tutorial by Jayraj Desai

  • 51,517 views
  • 32 comments
  • 107 respects

Weather Station for Drones

Project tutorial by Giuseppe Caccavale

  • 11,512 views
  • 4 comments
  • 35 respects

Arduino UNO Mini-Weather Station

Project tutorial by Igor Fonseca Albuquerque

  • 25,840 views
  • 21 comments
  • 67 respects

Weather Station with Thingspeak

Project showcase by Tittiamo

  • 3,531 views
  • 2 comments
  • 7 respects

Mobile Weather Station Being Powered by Solar Energy

Project tutorial by Kutluhan Aktar

  • 2,971 views
  • 0 comments
  • 15 respects

Weather Station v.1.0

Project showcase by derapados

  • 11,688 views
  • 3 comments
  • 39 respects
Add projectSign up / Login