How to make BME280 based Weather Station using ESP32







                         CODE 



#include <WiFi.h>

#include <WebServer.h>

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <math.h>

// =====================================================
// ESP32-C3 SAFE PINS
// =====================================================
#define TFT_CS    7
#define TFT_RST   2
#define TFT_DC    3
#define TFT_SCLK  4
#define TFT_MOSI  6

// =====================================================
// BME280 I2C
// =====================================================
#define BME_SDA   8
#define BME_SCL   9

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
Adafruit_BME280 bme;

// =====================================================
// WIFI HOTSPOT
// =====================================================
const char* AP_SSID = "ESP32-Weather";
const char* AP_PASSWORD = "12345678";

WebServer server(80);

// =====================================================
// COLORS
// =====================================================
#define BLACK          0x0000
#define WHITE          0xFFFF
#define BLUE           0x001F
#define YELLOW         0xFFE0
#define RED            0xF800
#define GREEN          0x07E0
#define CYAN           0x07FF
#define PINK           0xF81F
#define ORANGE         0xFD20
#define CLOUD          0xFFFF
#define LIGHT_PURPLE   0xB81F

// =====================================================
// DATE & TIME
// Internally 24-hour format
// TFT par 12-hour format show hoga
// =====================================================
int hours   = 12;
int minutes = 0;
int seconds = 0;

int day   = 26;
int month = 9;
int year  = 2026;

int dayOfWeek = 6;

// =====================================================
// DAY NAMES
// =====================================================
const char* dayNames[] = {
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday"
};

// =====================================================
// TIMERS
// =====================================================
unsigned long lastSecond = 0;
unsigned long lastSensorUpdate = 0;

// =====================================================
// BME VALUES
// =====================================================
float temperature = 0.0;
float humidity = 0.0;
float pressure = 0.0;

// =====================================================
// TIME STATUS
// =====================================================
bool timeSynced = false;

// =====================================================
// SETUP
// =====================================================
void setup() {

  Serial.begin(115200);

  // =================================================
  // TFT SPI
  // =================================================
  SPI.begin(
    TFT_SCLK,
    -1,
    TFT_MOSI,
    TFT_CS
  );

  tft.initR(INITR_MINI160x80);

  tft.setRotation(3);

  tft.fillScreen(BLACK);

  // =================================================
  // BME280
  // =================================================
  Wire.begin(
    BME_SDA,
    BME_SCL
  );

  bool bmeOK = bme.begin(0x76);

  if (!bmeOK) {
    bmeOK = bme.begin(0x77);
  }

  if (!bmeOK) {

    Serial.println(
      "BME280 NOT FOUND!"
    );
  }
  else {

    Serial.println(
      "BME280 OK"
    );
  }

  // First sensor reading
  readBME280();

  // =================================================
  // ESP32 HOTSPOT
  // =================================================
  WiFi.mode(WIFI_AP);

  WiFi.softAP(
    AP_SSID,
    AP_PASSWORD
  );

  IPAddress IP = WiFi.softAPIP();

  Serial.println();
  Serial.println(
    "=============================="
  );

  Serial.println(
    "ESP32 HOTSPOT STARTED"
  );

  Serial.print(
    "SSID: "
  );

  Serial.println(
    AP_SSID
  );

  Serial.print(
    "PASSWORD: "
  );

  Serial.println(
    AP_PASSWORD
  );

  Serial.print(
    "OPEN: http://"
  );

  Serial.println(
    IP
  );

  Serial.println(
    "=============================="
  );

  // =================================================
  // WEB SERVER
  // =================================================
  server.on(
    "/",
    handleRoot
  );

  server.on(
    "/settime",
    handleSetTime
  );

  server.begin();

  Serial.println(
    "Web server started"
  );

  // =================================================
  // DRAW UI
  // =================================================
  drawUI();

  lastSecond = millis();

  lastSensorUpdate = millis();
}

// =====================================================
// LOOP
// =====================================================
void loop() {

  // =================================================
  // WEB SERVER
  // =================================================
  server.handleClient();

  // =================================================
  // CLOCK UPDATE
  // =================================================
  if (millis() - lastSecond >= 1000) {

    lastSecond += 1000;

    seconds++;

    // Seconds
    if (seconds >= 60) {

      seconds = 0;

      minutes++;
    }

    // Minutes
    if (minutes >= 60) {

      minutes = 0;

      hours++;
    }

    // New day
    if (hours >= 24) {

      hours = 0;

      // Next weekday
      dayOfWeek++;

      if (dayOfWeek >= 7) {

        dayOfWeek = 0;
      }

      // Next date
      day++;

      // New month
      if (day > daysInMonth(month, year)) {

        day = 1;

        month++;

        // New year
        if (month > 12) {

          month = 1;

          year++;
        }
      }

      drawDate();
    }

    // Update time
    drawTime();
  }

  // =================================================
  // BME280 UPDATE
  // =================================================
  if (millis() - lastSensorUpdate >= 500) {

    lastSensorUpdate = millis();

    readBME280();

    drawSensorValues();
  }
}

// =====================================================
// DAYS IN MONTH
// =====================================================
int daysInMonth(
  int m,
  int y
) {

  switch (m) {

    case 1:
      return 31;

    case 2:

      if (
        (y % 400 == 0) ||
        (
          (y % 4 == 0) &&
          (y % 100 != 0)
        )
      ) {

        return 29;
      }

      return 28;

    case 3:
      return 31;

    case 4:
      return 30;

    case 5:
      return 31;

    case 6:
      return 30;

    case 7:
      return 31;

    case 8:
      return 31;

    case 9:
      return 30;

    case 10:
      return 31;

    case 11:
      return 30;

    case 12:
      return 31;
  }

  return 30;
}

// =====================================================
// CALCULATE DAY OF WEEK
// =====================================================
int calculateDayOfWeek(
  int d,
  int m,
  int y
) {

  int yy = y;

  int mm = m;

  if (mm < 3) {

    mm += 12;

    yy--;
  }

  int k = yy % 100;

  int j = yy / 100;

  int h =
    (
      d +
      (13 * (mm + 1)) / 5 +
      k +
      k / 4 +
      j / 4 +
      5 * j
    ) % 7;

  // Zeller:
  // 0 = Saturday
  // 1 = Sunday
  // ...
  int result =
    (h + 6) % 7;

  return result;
}

// =====================================================
// READ BME280
// =====================================================
void readBME280() {

  temperature =
    bme.readTemperature();

  humidity =
    bme.readHumidity();

  pressure =
    bme.readPressure()
    / 100.0F;

  Serial.print(
    "Temp: "
  );

  Serial.print(
    temperature,
    1
  );

  Serial.print(
    " C | Hum: "
  );

  Serial.print(
    humidity,
    0
  );

  Serial.print(
    "% | Press: "
  );

  Serial.print(
    pressure,
    0
  );

  Serial.println(
    " hPa"
  );
}

// =====================================================
// WEB PAGE
// =====================================================
void handleRoot() {

  String html = "";

  html += "<!DOCTYPE html>";

  html += "<html>";

  html += "<head>";

  html +=
    "<meta name='viewport' "
    "content='width=device-width, "
    "initial-scale=1'>";

  html +=
    "<title>ESP32 Weather Clock</title>";

  html += "<style>";

  html +=
    "body{"
    "background:#111;"
    "color:white;"
    "font-family:Arial;"
    "text-align:center;"
    "padding-top:40px;"
    "}";

  html +=
    "button{"
    "background:#00c8ff;"
    "color:#000;"
    "border:0;"
    "padding:15px 30px;"
    "font-size:18px;"
    "border-radius:10px;"
    "}";

  html += "</style>";

  html += "</head>";

  html += "<body>";

  html +=
    "<h1>ESP32 Weather Clock</h1>";

  html +=
    "<p>Mobile Date & Time Sync</p>";

  html +=
    "<button onclick='syncTime()'>"
    "SYNC TIME NOW"
    "</button>";

  html +=
    "<p id='status'>"
    "Syncing..."
    "</p>";

  html += "<script>";

  // =================================================
  // SEND MOBILE DATE/TIME
  // =================================================
  html +=
    "function syncTime(){";

  html +=
    "let d=new Date();";

  html +=
    "let data="

    "d.getFullYear()+','+"

    "(d.getMonth()+1)+','+"

    "d.getDate()+','+"

    "d.getHours()+','+"

    "d.getMinutes()+','+"

    "d.getSeconds();";

  html +=
    "fetch('/settime?t='+data)"

    ".then(r=>r.text())"

    ".then(x=>{"

    "document.getElementById('status')"
    ".innerHTML=x;"

    "});";

  html += "}";

  // Automatically sync when page opens
  html +=
    "window.onload=function(){"
    "syncTime();"
    "};";

  html += "</script>";

  html += "</body>";

  html += "</html>";

  server.send(
    200,
    "text/html",
    html
  );
}

// =====================================================
// RECEIVE MOBILE TIME
// =====================================================
void handleSetTime() {

  if (!server.hasArg("t")) {

    server.send(
      400,
      "text/plain",
      "Time data missing"
    );

    return;
  }

  String data =
    server.arg("t");

  Serial.println();

  Serial.print(
    "Mobile time received: "
  );

  Serial.println(
    data
  );

  int values[6];

  int index = 0;

  int start = 0;

  for (
    int i = 0;
    i <= data.length();
    i++
  ) {

    if (
      i == data.length() ||
      data[i] == ','
    ) {

      if (index < 6) {

        values[index] =
          data.substring(
            start,
            i
          ).toInt();

        index++;
      }

      start = i + 1;
    }
  }

  // =================================================
  // CHECK DATA
  // =================================================
  if (index == 6) {

    year =
      values[0];

    month =
      values[1];

    day =
      values[2];

    hours =
      values[3];

    minutes =
      values[4];

    seconds =
      values[5];

    // Calculate weekday
    dayOfWeek =
      calculateDayOfWeek(
        day,
        month,
        year
      );

    timeSynced = true;

    // Reset one-second timer
    lastSecond =
      millis();

    // Update display
    drawDate();

    drawTime();

    // Serial
    Serial.println(
      "TIME UPDATED FROM MOBILE!"
    );

    Serial.print(
      "Date: "
    );

    Serial.print(day);

    Serial.print("/");

    Serial.print(month);

    Serial.print("/");

    Serial.println(year);

    Serial.print(
      "24H Time: "
    );

    Serial.print(hours);

    Serial.print(":");

    Serial.print(minutes);

    Serial.print(":");

    Serial.println(seconds);

    server.send(
      200,
      "text/plain",
      "Time synced successfully!"
    );
  }

  else {

    server.send(
      400,
      "text/plain",
      "Invalid time data"
    );
  }
}

// =====================================================
// MAIN UI
// =====================================================
void drawUI() {

  tft.fillScreen(
    BLACK
  );

  // =================================================
  // CITY
  // =================================================
  tft.setTextSize(2);

  tft.setTextColor(
    LIGHT_PURPLE
  );

  tft.setCursor(
    5,
    5
  );

  tft.print(
    "London"
  );

  // =================================================
  // DATE
  // =================================================
  drawDate();

  // =================================================
  // WEATHER
  // =================================================
  tft.setTextSize(1);

  tft.setTextColor(
    ORANGE
  );

  tft.setCursor(
    5,
    25
  );

  tft.print(
    "Clouds"
  );

  // =================================================
  // TIME
  // =================================================
  drawTime();

  // =================================================
  // LABELS
  // =================================================
  tft.setTextSize(1);

  tft.setTextColor(
    PINK
  );

  tft.setCursor(
    60,
    53
  );

  tft.print(
    "Press"
  );

  tft.setCursor(
    101,
    53
  );

  tft.print(
    "Temp"
  );

  tft.setCursor(
    136,
    53
  );

  tft.print(
    "Humi"
  );

  // =================================================
  // VALUES
  // =================================================
  drawSensorValues();

  // =================================================
  // WEATHER ICON
  // =================================================
  drawWeatherIcon();
}

// =====================================================
// DATE + DAY
// =====================================================
void drawDate() {

  // Clear day
  tft.fillRect(
    88,
    0,
    72,
    16,
    BLACK
  );

  tft.setTextSize(1);

  tft.setTextColor(
    ORANGE
  );

  // Wednesday
  if (dayOfWeek == 3) {

    tft.setCursor(
      87,
      5
    );
  }

  // Thursday
  else if (dayOfWeek == 4) {

    tft.setCursor(
      91,
      5
    );
  }

  else {

    tft.setCursor(
      98,
      5
    );
  }

  tft.print(
    dayNames[dayOfWeek]
  );

  // =================================================
  // DATE
  // =================================================
  tft.fillRect(
    88,
    17,
    72,
    10,
    BLACK
  );

  tft.setTextColor(
    GREEN
  );

  tft.setCursor(
    91,
    19
  );

  if (day < 10)
    tft.print("0");

  tft.print(day);

  tft.print("/");

  if (month < 10)
    tft.print("0");

  tft.print(month);

  tft.print("/");

  tft.print(year);
}

// =====================================================
// TIME - 12 HOUR FORMAT
// =====================================================
void drawTime() {

  // Clear complete time area
  tft.fillRect(
    55,
    30,
    105,
    22,
    BLACK
  );

  // =================================================
  // 12 HOUR CONVERSION
  // =================================================
  int displayHour =
    hours;

  if (displayHour == 0) {

    displayHour = 12;
  }

  else if (displayHour > 12) {

    displayHour -= 12;
  }

  // =================================================
  // MAIN TIME
  // =================================================
  tft.setTextSize(2);

  tft.setTextColor(
    CYAN
  );

  tft.setCursor(
    62,
    33
  );

  // Hour
  if (displayHour < 10)
    tft.print("0");

  tft.print(
    displayHour
  );

  tft.print(":");

  // Minute
  if (minutes < 10)
    tft.print("0");

  tft.print(
    minutes
  );

  tft.print(":");

  // Second
  if (seconds < 10)
    tft.print("0");

  tft.print(
    seconds
  );

  // =================================================
  // AM / PM
  // =================================================
  tft.setTextSize(1);

  tft.setTextColor(
    WHITE
  );

  tft.setCursor(
    46,
    38
  );

  if (hours < 12) {

    tft.print(
      "AM"
    );
  }

  else {

    tft.print(
      "PM"
    );
  }
}

// =====================================================
// BME280 VALUES
// =====================================================
void drawSensorValues() {

  tft.setTextSize(1);

  // =================================================
  // PRESSURE
  // =================================================
  tft.fillRect(
    58,
    64,
    45,
    10,
    BLACK
  );

  tft.setTextColor(
    YELLOW
  );

  tft.setCursor(
    58,
    65
  );

  int p =
    (int)round(
      pressure
    );

  if (p > 999)
    p = 999;

  if (p < 0)
    p = 0;

  tft.print(
    p
  );

  tft.print(
    "hPa"
  );

  // =================================================
  // TEMPERATURE
  // =================================================
  tft.fillRect(
    104,
    64,
    35,
    10,
    BLACK
  );

  tft.setTextColor(
    BLUE
  );

  tft.setCursor(
    101,
    65
  );

  tft.print(
    temperature,
    1
  );

  tft.print(
    "C"
  );

  // =================================================
  // HUMIDITY
  // =================================================
  tft.fillRect(
    140,
    64,
    20,
    10,
    BLACK
  );

  tft.setTextColor(
    RED
  );

  tft.setCursor(
    136,
    65
  );

  int h =
    (int)round(
      humidity
    );

  if (h > 99)
    h = 99;

  if (h < 0)
    h = 0;

  tft.print(
    h
  );

  tft.print(
    "%"
  );
}

// =====================================================
// WEATHER ICON
// =====================================================
void drawWeatherIcon() {

  int sunX = 23;

  int sunY = 55;

  // =================================================
  // SUN
  // =================================================
  tft.fillCircle(
    sunX,
    sunY,
    8,
    CYAN
  );

  // =================================================
  // SUN RAYS
  // =================================================
  for (
    int i = 0;
    i < 360;
    i += 45
  ) {

    float angle =
      i * 0.0174533;

    int x1 =
      sunX +
      cos(angle) * 11;

    int y1 =
      sunY +
      sin(angle) * 11;

    int x2 =
      sunX +
      cos(angle) * 14;

    int y2 =
      sunY +
      sin(angle) * 14;

    tft.drawLine(
      x1,
      y1,
      x2,
      y2,
      CYAN
    );
  }

  // =================================================
  // CLOUD
  // =================================================
  tft.fillCircle(
    25,
    65,
    7,
    CLOUD
  );

  tft.fillCircle(
    34,
    64,
    9,
    CLOUD
  );

  tft.fillCircle(
    44,
    66,
    6,
    CLOUD
  );

  tft.fillRect(
    22,
    65,
    27,
    7,
    CLOUD
  );
}

Post a Comment

Previous Post Next Post

Contact Form