Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
Electorials Electronics
Published © GPL3+

ESP8266 Weather Station v2

ESP8266 Weather Station displaying temperature, humidity, pressure & dust on an OLED display with a touch button.

BeginnerFull instructions provided30 minutes484
ESP8266 Weather Station v2

Things used in this project

Hardware components

Wemos D1 Mini
Espressif Wemos D1 Mini
×1
Gravity: I2C BME280 Environmental Sensor
DFRobot Gravity: I2C BME280 Environmental Sensor
×1
1.3-inch i2c OLED Display
Or any ESP8266 board.
×1
Jumper wires (generic)
Jumper wires (generic)
×11
Breadboard (generic)
Breadboard (generic)
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
For the microcontroller.
×1
Grove - Dust Sensor(PPD42NS)
Seeed Studio Grove - Dust Sensor(PPD42NS)
×1
Capacitive Touch Sensor
×1
PCBWay Custom PCB
PCBWay Custom PCB
×1

Story

Read more

Code

Project Code

C/C++
#include <ESP8266WiFi.h>
#include <time.h>
#include <U8x8lib.h>
#include "DFRobot_BME280.h"
 
const char* ssid = "WIFI";              
const char* password = "PASSWORD";      
 
const char* NTP_SERVER = "ch.pool.ntp.org";
const char* TZ_INFO    = "GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00";  // enter your time zone (https://remotemonitoringsystems.ca/time-zone-abbreviations.php)
 
tm timeinfo;
time_t now;
long unsigned lastNTPtime;
unsigned long lastEntryTime;
 
U8X8_SH1106_128X64_NONAME_SW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // OLEDs without Reset of the Display
 
typedef DFRobot_BME280_IIC    BME;    // 
BME   bme(&Wire, 0x77);   // select TwoWire peripheral and set sensor address
#define SEA_LEVEL_PRESSURE    1015.0f
 
const int touchPin = D0;
int touchState = 0;
int pageNumber = 0;
 
int dustPin = D3;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 2000; 
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
 
void printLastOperateStatus(BME::eStatus_t eStatus) // show last sensor operate status
{
  switch(eStatus) {
  case BME::eStatusOK:    Serial.println("everything ok"); break;
  case BME::eStatusErr:   Serial.println("unknow error"); break;
  case BME::eStatusErrDeviceNotDetected:    Serial.println("device not detected"); break;
  case BME::eStatusErrParameter:    Serial.println("parameter error"); break;
  default: Serial.println("unknow status"); break;
  }
}
 
void setup()
{
  pinMode(touchPin, INPUT);
  pinMode(dustPin,INPUT);
  starttime = millis(); 
  u8x8.begin();
  Serial.begin(9600);
  WiFi.begin(ssid, password);
 
  int counter = 0;
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(200);    
    if (++counter > 100) 
      ESP.restart();
  }
 
  configTime(0, 0, NTP_SERVER);
  // See https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv for Timezone codes for your region
  setenv("GMT0BST,M3.5.0/1,M10.5.0", TZ_INFO, 1);
 
  if (getNTPtime(10)) 
  {  
    // Wait up to 10 seconds to sync
  } 
  else 
  {
    ESP.restart();
  }
  showTime(&timeinfo);
  lastNTPtime = time(&now);
  lastEntryTime = millis();
    
  bme.reset();
  while(bme.begin() != BME::eStatusOK) {
    printLastOperateStatus(bme.lastOperateStatus);
    delay(2000);
  }
  delay(100);
}
 
void loop()
{ 
  duration = pulseIn(dustPin, LOW);
  lowpulseoccupancy = lowpulseoccupancy+duration;
  if ((millis()-starttime) >= sampletime_ms)
  {
    ratio = lowpulseoccupancy/(sampletime_ms*10.0);  
    concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; 
    lowpulseoccupancy = 0;
    starttime = millis();
  }
  touchState = digitalRead(touchPin);
  getNTPtime(10);
  showTime(&timeinfo);
  
  float   temp = bme.getTemperature();
  uint32_t press = bme.getPressure();
  float   alti = bme.calAltitude(SEA_LEVEL_PRESSURE, press);
  float   humi = bme.getHumidity();
 
  char temp_buff[9]; char hum_buff[9]; char pres_buff[9]; char alt_buff[9]; char dust_buff[15];
  char cel_buff[11] = "C";
  char per_buff[11] = "%";
  char pa_buff[11] = " Pa";
  char met_buff[11] = "m";
  char pcs_buff[11] = " pcs";
 
  dtostrf(temp, 3, 1, temp_buff);
  strcat(temp_buff, cel_buff); 
  dtostrf(humi, 3, 0, hum_buff);
  strcat(hum_buff, per_buff);
  dtostrf(press, 5, 0, pres_buff);
  strcat(pres_buff, pa_buff);
  dtostrf(alti, 5, 2, alt_buff);
  strcat(alt_buff, met_buff);
  dtostrf(concentration, 3, 1, dust_buff);
  strcat(dust_buff, pcs_buff);
  
  if(touchState == HIGH){
    if(pageNumber < 2){
      u8x8.clearDisplay();
      pageNumber=pageNumber + 1;
    }
    else {
      pageNumber = 0;
    }
  }
 
  if(pageNumber == 0){
  u8x8.setFont(u8x8_font_artossans8_r);
  u8x8.setCursor(0,2);
  u8x8.print("Temp: ");
  u8x8.setCursor(6,2); 
  u8x8.print(temp_buff);
  u8x8.setCursor(0,4);
  u8x8.print("Humi: "); 
  u8x8.setCursor(6,4);
  u8x8.print(hum_buff);
  u8x8.setCursor(0,6);
  u8x8.print("Pres: "); 
  u8x8.setCursor(6,6);
  u8x8.print(pres_buff);
  }
  else if(pageNumber == 1){
  u8x8.setFont(u8x8_font_artossans8_r);
  u8x8.setCursor(0,2);
  u8x8.print("Alti: ");
  u8x8.setCursor(6,2); 
  u8x8.print(alt_buff);
  u8x8.setCursor(0,4);
  u8x8.print("Dust: ");
  u8x8.setCursor(6,4);
  u8x8.print(dust_buff);
  }
  else if(pageNumber == 2){
  u8x8.setFont(u8x8_font_artossans8_r);
  u8x8.setCursor(0,2);
  u8x8.print("Page 3"); 
  }
}
  
bool getNTPtime(int sec) 
{
  {
    uint32_t start = millis();
    do
    {
      time(&now);
      localtime_r(&now, &timeinfo);
      delay(10);
    } while (((millis() - start) <= (1000 * sec)) && (timeinfo.tm_year < (2016 - 1900)));
    
    if (timeinfo.tm_year <= (2016 - 1900)) 
        return false;  // the NTP call was not successful
  }
  return true;
}
 
void showTime(tm *localTime) 
{
  char time_output[30];
  
  u8x8.setFont(u8x8_font_artossans8_n);
  u8x8.setCursor(0,0);
  sprintf(time_output, "%02d:%02d", localTime->tm_hour, localTime->tm_min);
  u8x8.print(time_output);
  
  u8x8.setFont(u8x8_font_artossans8_r);
  u8x8.setCursor(7,0);
  sprintf(time_output, "%02d/%02d/%02d", localTime->tm_mday, localTime->tm_mon + 1, localTime->tm_year - 100);
  u8x8.print(time_output);
}

Credits

Electorials Electronics

Electorials Electronics

85 projects • 64 followers
I'm an electronic hobbyist interested in anything, from Arduino to drones. I plan to educate people with the content on my website.

Comments