Skip to main content

Arduino DHT11 Temperature & Humidity Monitoring System

Updated 8 min readMarkdown

1. Project Overview

This project uses an Arduino UNO and DHT11 sensor to measure temperature and humidity and display the readings on a live web dashboard using Python Flask.

Technologies Used

  • Arduino UNO
  • DHT11 Temperature and Humidity Sensor
  • Arduino IDE
  • Python
  • Flask
  • PySerial
  • HTML, CSS and JavaScript

System Architecture

DHT11 Sensor
     |
     v
Arduino UNO
     |
     v
USB Serial Communication
     |
     v
Python Flask Application
     |
     v
Web Dashboard
     |
     v
Live Temperature & Humidity

2. Hardware Requirements

Component Quantity
Arduino UNO 1
DHT11 Sensor 1
Jumper Wires 3
USB Cable 1
Computer/Laptop 1

DHT11 Connections

DHT11 Pin Arduino UNO
VCC 5V
DATA Digital Pin 2
GND GND

For a bare four-pin DHT11 sensor, check its pinout and use the required pull-up resistor. Three-pin modules often include this resistor.


3. Arduino IDE Setup

Step 1: Install Arduino IDE

Download Arduino IDE:

https://www.arduino.cc/en/software

Install and open Arduino IDE.

Step 2: Install DHT11 Library

  1. Open Arduino IDE.
  2. Navigate to Sketch → Include Library → Manage Libraries.
  3. Search for DHT sensor library.
  4. Install DHT sensor library by Adafruit.
  5. Install Adafruit Unified Sensor if requested.

Step 3: Arduino Code

Create a new Arduino sketch and upload the following code.

#include <DHT.h>

// Sensor configuration
#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void setup() {

    // Start serial communication
    Serial.begin(9600);

    // Initialize DHT11
    dht.begin();
}

void loop() {

    // Read sensor values
    float temperature = dht.readTemperature();
    float humidity = dht.readHumidity();

    // Check sensor readings
    if (isnan(temperature) || isnan(humidity)) {

        Serial.println("ERROR");

    }
    else {

        // Send data to Python
        Serial.print(temperature);
        Serial.print(",");
        Serial.println(humidity);

    }

    delay(2000);
}

Expected Serial Output

28.00,65.00
29.00,64.00
30.00,63.00

The first value represents temperature in Celsius, and the second represents humidity in percentage.


4. Python Environment Setup

Step 1: Install Python

Download Python from:

https://www.python.org/downloads/

During installation, select Add Python to PATH.

Verify installation:

python --version

Step 2: Create Project Folder

Open PowerShell or Command Prompt.

mkdir DHT11_Website
cd DHT11_Website

Step 3: Create Python Virtual Environment

A virtual environment keeps project dependencies separate from other Python projects.

python -m venv venv

Step 4: Activate Virtual Environment

Windows PowerShell:

.\venv\Scripts\Activate.ps1

If PowerShell blocks activation, run:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Then activate again:

.\venv\Scripts\Activate.ps1

Windows Command Prompt:

venv\Scripts\activate.bat

After successful activation, you should see:

(venv) C:\...\DHT11_Website>

Step 5: Install Required Libraries

pip install flask pyserial

Verify installed packages:

pip list

Step 6: Save Dependencies

pip freeze > requirements.txt

5. Project Structure

The project will contain one Python application file.

DHT11_Website/
│
├── venv/
│
├── app.py
│
└── requirements.txt

The HTML, CSS and JavaScript code will be included inside app.py, so a separate HTML file is not required.


6. Create the Python Application

Create a file named app.py.

Copy the following complete code:

from flask import Flask, jsonify, render_template_string
import serial
import threading
import time

app = Flask(__name__)

# Arduino Configuration
SERIAL_PORT = "COM3"
BAUD_RATE = 9600

# Sensor Variables
temperature = 0
humidity = 0

connection_status = "Disconnected"
last_updated = "--"


# =====================================
# ARDUINO SERIAL COMMUNICATION
# =====================================

def read_arduino():

    global temperature, humidity
    global connection_status, last_updated

    while True:

        try:

            print("Connecting to Arduino...")

            arduino = serial.Serial(
                SERIAL_PORT,
                BAUD_RATE,
                timeout=2
            )

            time.sleep(2)

            connection_status = "Connected"

            print("Arduino Connected!")

            while True:

                line = arduino.readline().decode(
                    "utf-8",
                    errors="ignore"
                ).strip()

                if not line or line == "ERROR":
                    continue

                try:

                    values = line.split(",")

                    if len(values) == 2:

                        temp = float(values[0])
                        hum = float(values[1])

                        temperature = temp
                        humidity = hum

                        last_updated = time.strftime("%H:%M:%S")

                        print(
                            f"Temperature: {temp} C | "
                            f"Humidity: {hum} %"
                        )

                except ValueError:

                    continue

        except Exception as error:

            connection_status = "Disconnected"

            print("Arduino Error:", error)

            time.sleep(3)


# =====================================
# HTML DASHBOARD
# =====================================

HTML_PAGE = """

<!DOCTYPE html>
<html>

<head>

    <title>DHT11 Monitoring System</title>

    <meta name="viewport"
          content="width=device-width, initial-scale=1">

    <style>

        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            font-family: Arial, sans-serif;
            background: #eef2f7;
            color: #172554;
        }

        header {
            background: #172554;
            color: white;
            padding: 30px 15px;
            text-align: center;
        }

        header h1 {
            margin: 0 0 10px;
        }

        .container {
            max-width: 900px;
            margin: 50px auto;
            padding: 15px;
        }

        .cards {
            display: flex;
            justify-content: center;
            gap: 25px;
            flex-wrap: wrap;
        }

        .card {
            background: white;
            width: 300px;
            padding: 35px 20px;
            border-radius: 18px;
            text-align: center;
            box-shadow: 0 5px 20px #0001;
        }

        .icon {
            font-size: 45px;
        }

        .value {
            font-size: 48px;
            font-weight: bold;
            margin: 20px 0;
        }

        .temperature {
            color: #ef4444;
        }

        .humidity {
            color: #2563eb;
        }

        .status-box {
            background: white;
            padding: 22px;
            border-radius: 15px;
            margin-top: 30px;
            text-align: center;
        }

        .connected {
            color: #16a34a;
        }

        .disconnected {
            color: #dc2626;
        }

        footer {
            text-align: center;
            padding: 25px;
            color: #64748b;
        }

    </style>

</head>

<body>

    <header>

        <h1>🌡️ DHT11 Monitoring System</h1>

        <p>Live Temperature and Humidity Dashboard</p>

    </header>


    <div class="container">

        <div class="cards">

            <div class="card">

                <div class="icon">🌡️</div>

                <h2>Temperature</h2>

                <div class="value temperature"
                     id="temperature">

                    -- °C

                </div>

                <p>Room Temperature</p>

            </div>


            <div class="card">

                <div class="icon">💧</div>

                <h2>Humidity</h2>

                <div class="value humidity"
                     id="humidity">

                    -- %

                </div>

                <p>Air Humidity</p>

            </div>

        </div>


        <div class="status-box">

            <h3>

                Arduino Status:

                <span id="status" class="disconnected">

                    Checking...

                </span>

            </h3>

            <p>

                Last Updated:

                <span id="updated">--</span>

            </p>

        </div>

    </div>


    <footer>

        Arduino UNO + DHT11 | Python Flask IoT Dashboard

    </footer>


    <script>

        async function updateData() {

            try {

                const response = await fetch("/data");

                const data = await response.json();


                document.getElementById("temperature").innerText =
                    data.temperature + " °C";


                document.getElementById("humidity").innerText =
                    data.humidity + " %";


                const status =
                    document.getElementById("status");


                status.innerText = data.status;


                status.className =
                    data.status === "Connected"
                    ? "connected"
                    : "disconnected";


                document.getElementById("updated").innerText =
                    data.updated;

            }

            catch (error) {

                document.getElementById("status").innerText =
                    "Connection Error";

            }

        }


        updateData();

        // Update every two seconds
        setInterval(updateData, 2000);

    </script>

</body>

</html>

"""


# =====================================
# FLASK ROUTES
# =====================================

@app.route("/")
def home():

    return render_template_string(HTML_PAGE)


@app.route("/data")
def get_data():

    return jsonify({

        "temperature": temperature,

        "humidity": humidity,

        "status": connection_status,

        "updated": last_updated

    })


# =====================================
# START APPLICATION
# =====================================

if __name__ == "__main__":

    thread = threading.Thread(
        target=read_arduino,
        daemon=True
    )

    thread.start()

    app.run(
        host="127.0.0.1",
        port=5000,
        debug=False
    )

7. Configure Arduino COM Port

Before running the application, identify the Arduino COM port.

  1. Open Arduino IDE.
  2. Connect Arduino UNO.
  3. Select Tools → Port.
  4. Note the COM port number.

For example:

SERIAL_PORT = "COM3"

If your Arduino uses COM5, change it to:

SERIAL_PORT = "COM5"

Important: Close Arduino IDE Serial Monitor before running the Python application because both applications cannot normally access the same serial port simultaneously.


8. Run the Application

Make sure your virtual environment is activated.

python app.py

Expected terminal output:

Connecting to Arduino...
Arduino Connected!

Temperature: 28.0 C | Humidity: 65.0 %
Temperature: 29.0 C | Humidity: 64.0 %

Running on http://127.0.0.1:5000

Open your web browser:

http://127.0.0.1:5000

Your live dashboard will display the temperature, humidity and Arduino connection status.


9. Troubleshooting

Problem Possible Solution
COM port error Check the correct Arduino COM port
Access denied Close Arduino Serial Monitor
Arduino disconnected Check USB cable and connection
No sensor readings Check DHT11 wiring and library installation
Website not opening Check whether Flask is running on port 5000
Python module not found Activate virtual environment and install dependencies

10. Useful Commands

Task Command
Create virtual environment python -m venv venv
Activate environment venv\Scripts\activate
Install Flask pip install flask
Install PySerial pip install pyserial
Save dependencies pip freeze > requirements.txt
Run application python app.py
Deactivate environment deactivate

11. Future Improvements

After completing the basic project, students can extend it with:

  1. Live temperature and humidity graphs.
  2. Historical sensor data storage using SQLite.
  3. Download sensor readings as CSV.
  4. Temperature threshold alerts.
  5. Multiple sensor monitoring.
  6. Professional IoT dashboard design.
  7. Remote access through a suitable network deployment.

Project Conclusion: This project demonstrates how Arduino hardware, sensor technology, serial communication and Python web development can be integrated to create a simple real-time IoT monitoring system.

45 views

No comments yet. Be the first to comment.