Bitronix Lab Project Lab

Weather Station Project

Build a complete IoT system with sensors, telemetry, cloud storage, and a live dashboard mindset.

Bitronix Lab logo Innovating ideas, empowering future

Weather Station: Complete IoT Project

Complete Weather Station Project

This project combines all the concepts from previous tutorials to build a complete IoT weather station with cloud integration, real-time monitoring, and historical data analysis.

Project Scope: Build a weather station that measures temperature, humidity, pressure, and light intensity, stores data in the cloud, and provides real-time visualization through a web dashboard.

Learning Objectives:

  • Integrate multiple sensors into a single system
  • Implement cloud connectivity
  • Create data visualization dashboards
  • Handle data storage and retrieval
  • Deploy production-ready IoT applications

System Architecture Overview

Complete System Architecture:

Layer 1 (Edge): ESP32 + Sensors (DHT22, BMP280, LDR)

Layer 2 (Gateway): WiFi connectivity + MQTT

Layer 3 (Cloud): InfluxDB (time-series DB) + Node.js API

Layer 4 (Frontend): React Dashboard + Grafana

Data Flow:

Component Function Update Rate
DHT22 Temperature & Humidity Every 30s
BMP280 Pressure & Altitude Every 30s
LDR Light Intensity Every 10s
InfluxDB Data Storage Real-time
Dashboard Visualization WebSocket (live)

Hardware Assembly

Required Components:

  • ESP32 (main microcontroller)
  • DHT22 (temperature & humidity)
  • BMP280 (pressure & altitude)
  • LDR + 10k ohm resistor (light sensor)
  • 0.96" OLED Display (local display)
  • Solar Panel 5V (optional, for outdoor use)
  • 18650 Battery (power backup)
  • TP4056 Charging Module (battery charging)
  • Weatherproof Enclosure (outdoor housing)

Wiring Diagram:

ESP32 3.3V -> DHT22 VCC, BMP280 VCC, LDR circuit

ESP32 GPIO 21 (SDA) -> DHT22 Data, BMP280 SDA, OLED SDA

ESP32 GPIO 22 (SCL) -> BMP280 SCL, OLED SCL

ESP32 GPIO 34 (ADC0) -> LDR + 10k divider

All GND pins connected to common ground

Power Considerations: When using a battery, ensure proper voltage regulation (min 3V, max 3.6V for ESP32).

ESP32 Firmware Development

Complete Arduino Sketch:

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_BMP280.h>
#include <Wire.h>

// WiFi credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// MQTT Server
const char* mqtt_server = "192.168.1.100";
const char* mqtt_user = "weather";
const char* mqtt_pass = "password123";

WiFiClient espClient;
PubSubClient client(espClient);

// Sensors
DHT dht(21, DHT22);
Adafruit_BMP280 bmp280;
const int ldrPin = 34;

unsigned long lastSensorRead = 0;
const long sensorReadInterval = 30000; // 30 seconds

void setup() {
  Serial.begin(115200);
  
  // Initialize sensors
  dht.begin();
  if (!bmp280.begin(0x76)) {
    Serial.println("BMP280 not found!");
  }
  
  // Connect to WiFi
  connectWiFi();
  client.setServer(mqtt_server, MQTT_PORT);
}

void connectWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected!");
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("WeatherStation", mqtt_user, mqtt_pass)) {
      Serial.println("MQTT connected");
    } else {
      delay(5000);
    }
  }
}

void publishSensorData() {
  // Read temperature and humidity
  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();
  
  // Read pressure
  float pressure = bmp280.readPressure() / 100.0;
  
  // Read light intensity
  int lightRaw = analogRead(ldrPin);
  float lightPercent = (lightRaw / 4095.0) * 100;
  
  // Publish to MQTT
  char buffer[50];
  
  snprintf(buffer, sizeof(buffer), "%.2f", temp);
  client.publish("weather/temperature", buffer);
  
  snprintf(buffer, sizeof(buffer), "%.2f", humidity);
  client.publish("weather/humidity", buffer);
  
  snprintf(buffer, sizeof(buffer), "%.2f", pressure);
  client.publish("weather/pressure", buffer);
  
  snprintf(buffer, sizeof(buffer), "%.1f", lightPercent);
  client.publish("weather/light", buffer);
  
  Serial.printf("T:%.2f H:%.2f P:%.2f L:%.1f\n", 
    temp, humidity, pressure, lightPercent);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  
  unsigned long currentTime = millis();
  if (currentTime - lastSensorRead >= sensorReadInterval) {
    publishSensorData();
    lastSensorRead = currentTime;
  }
}

Cloud Integration with InfluxDB

Setup InfluxDB:

# Install InfluxDB
wget https://dl.influxdata.com/influxdb/releases/influxdb_1.8.0_amd64.deb
sudo dpkg -i influxdb_1.8.0_amd64.deb
sudo systemctl start influxdb

# Create database
influx
> CREATE DATABASE weather_data
> CREATE USER weather WITH PASSWORD 'weather123'
> GRANT ALL ON weather_data TO weather
> EXIT

Node.js Backend to Store Data:

const mqtt = require('mqtt');
const influx = require('influx');

const client = mqtt.connect('mqtt://localhost:1883', {
  username: 'weather',
  password: 'password123'
});

const influxDB = new influx.InfluxDB({
  host: 'localhost',
  database: 'weather_data',
  username: 'weather',
  password: 'weather123',
  schema: [
    {
      measurement: 'weather',
      fields: {
        temperature: influx.FieldType.FLOAT,
        humidity: influx.FieldType.FLOAT,
        pressure: influx.FieldType.FLOAT,
        light: influx.FieldType.FLOAT
      },
      tags: ['location']
    }
  ]
});

client.on('message', (topic, message) => {
  const topicParts = topic.split('/');
  const measurementType = topicParts[1];
  const value = parseFloat(message.toString());
  
  // Store in InfluxDB
  influxDB.writePoints([{
    measurement: 'weather',
    tags: { location: 'outside' },
    fields: {
      [measurementType]: value
    }
  }]);
});

client.subscribe('weather/#');

Real-Time Dashboard

Express API to Query Data:

const express = require('express');
const app = express();

app.get('/api/current', async (req, res) => {
  const results = await influxDB.query(`
    SELECT LAST(*) FROM weather
  `);
  res.json(results[0]);
});

app.get('/api/history', async (req, res) => {
  const results = await influxDB.query(`
    SELECT * FROM weather WHERE time > now() - 24h
  `);
  res.json(results);
});

app.listen(3000, () => {
  console.log('API server running on port 3000');
});

React Dashboard Component:

import React, { useState, useEffect } from 'react';
import { LineChart, Line, XAxis, YAxis } from 'recharts';

function WeatherDashboard() {
  const [current, setCurrent] = useState({});
  const [history, setHistory] = useState([]);

  useEffect(() => {
    // Fetch current data
    fetch('/api/current')
      .then(r => r.json())
      .then(data => setCurrent(data[0]));

    // Fetch historical data
    fetch('/api/history')
      .then(r => r.json())
      .then(data => setHistory(data[0]));
  }, []);

  return (
    <div style={{padding: '20px'}}>
      <h1>Weather Station Dashboard</h1>
      <div>
        <p>Temperature: {current.temperature}°C</p>
        <p>Humidity: {current.humidity}%</p>
        <p>Pressure: {current.pressure} mb</p>
        <p>Light: {current.light}%</p>
      </div>
      <LineChart width={800} height={300} data={history}>
        <XAxis dataKey="time" />
        <YAxis />
        <Line type="monotone" dataKey="temperature" stroke="#ff7300" />
      </LineChart>
    </div>
  );
}

export default WeatherDashboard;

Deployment & Testing

Pre-Deployment Checklist:

  • ✓ Test all sensors individually
  • ✓ Verify WiFi connectivity
  • ✓ Test MQTT communication
  • ✓ Verify InfluxDB data storage
  • ✓ Test dashboard connectivity
  • ✓ Check power consumption
  • ✓ Test in outdoor conditions

Outdoor Installation:

1. Place in weather-protected enclosure (allow air circulation)
2. Ensure proper sensor orientation (avoid direct sun on temp sensor)
3. Mount on pole or elevated surface (away from obstacles)
4. Verify WiFi signal strength (minimum -70 dBm)
5. Set up automatic data logging and archiving
6. Configure alerts for extreme weather conditions

Performance Metrics:

Metric Expected Value Acceptable Range
Update Frequency 30 seconds 20-60 seconds
Data Accuracy ±0.5°C ±1°C
Uptime 99.5% >95%
Power Consumption 50-100 mW <200 mW

Congratulations! You've built a complete production-ready IoT weather station! Next steps: Add more sensors, implement machine learning for predictions, or deploy multiple stations for regional monitoring.