ESP8266 Weather Station displaying temperature, humidity, pressure & dust on an OLED display with a touch button.
Things used in this project
Hardware components
Story
A simple weather station displaying temperature, humidity, pressure & dust information and the current time/date on an OLED display using an ESP8266, BME280 sensor and a Grove dust sensor with touch sensor control.
The wiring of this project is extremely simple as all components (except the dust sensor & touch sensor) use the i2c interface, making use of four pins only. As both the OLED display and the BME280 sensor make use of this interface, the wiring is as follows:
VCC (on the sensor/OLED) - 3.3V (on the microcontroller)
GND - GND
SCL - D1
SDA - D2
The wiring for the dust sensor is as follows:
VCC (on the sensor) - 3.3V (on the microcontroller)
GND - GND
Signal - D3
The wiring for the touch sensor is as follows:
VCC (on the sensor) - 3.3V ( on the microcontroller)
GND - GND
Signal - D0
More information about the code and wiring is shown in this video:
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);
}
The article was first published in hackster, June 1, 2022
cr: https://www.hackster.io/infoelectorials/esp8266-weather-station-v2-3b8629
author: Electorials Electronics