DHT11 + Raspberry Pi + ThingSpeak + GitHub Pages
A fully standalone IoT project — sensor reads temperature & humidity, Raspberry Pi sends data to the cloud, and a live dashboard on GitHub Pages lets you monitor from anywhere in the world.
This is a fully standalone IoT project where:
| DHT11 Pin | Meaning |
|---|---|
| VCC | Power (3.3V or 5V) |
| DATA | Data output |
| GND | Ground |
| DHT11 Pin | Raspberry Pi Pin | Physical Pin # |
|---|---|---|
| VCC | 3.3V | Pin 1 |
| DATA | GPIO4 | Pin 7 |
| GND | GND | Pin 6 |
Open the terminal on your Raspberry Pi and run these commands:
sudo apt update sudo apt install python3-pip -y
pip3 install adafruit-circuitpython-dht requests
sudo apt install libgpiod2 -y| Package | Purpose |
|---|---|
| adafruit-circuitpython-dht | Library to read DHT11/DHT22 sensor data |
| requests | Python library to make HTTP requests (send data to ThingSpeak) |
| libgpiod2 | Low-level GPIO library required by Adafruit DHT library |
mkdir iot-project cd iot-project
Visit 👉 https://thingspeak.com
Create a free account (you can use your MathWorks account)
Click "New Channel" button
Fill in the channel details:
| Field | Name |
|---|---|
| Field 1 | Temperature |
| Field 2 | Humidity |
Click Save Channel
Go to the API Keys tab. You will get:
| Key | Purpose | Example |
|---|---|---|
| Channel ID | Unique identifier for your channel | 3272751 |
| Write API Key | Used by Raspberry Pi to SEND data | ABC123XYZ... |
| Read API Key | Used by website to FETCH data | DEF456UVW... |
nano send_to_thingspeak.py
import time import requests import board import adafruit_dht # ─── Configuration ─── WRITE_API_KEY = "YOUR_WRITE_API_KEY" THINGSPEAK_URL = "https://api.thingspeak.com/update" # ─── Initialize DHT11 on GPIO4 ─── dht = adafruit_dht.DHT11(board.D4) # GPIO4 while True: try: temperature = dht.temperature humidity = dht.humidity if temperature is not None and humidity is not None: payload = { "api_key": WRITE_API_KEY, "field1": temperature, "field2": humidity } requests.post(THINGSPEAK_URL, data=payload) print(f"Sent → Temp: {temperature}°C Humidity: {humidity}%") except Exception as e: print("Sensor error:", e) time.sleep(15) # ThingSpeak minimum interval
| Line / Block | What It Does |
|---|---|
import adafruit_dht | Imports the DHT sensor library |
board.D4 | Refers to GPIO4 on Raspberry Pi |
dht.temperature | Reads the current temperature in °C |
dht.humidity | Reads the current humidity in % |
requests.post(...) | Sends data to ThingSpeak via HTTP POST |
payload | Dictionary with API key + field values |
time.sleep(15) | Waits 15 seconds (ThingSpeak free tier minimum) |
try/except | Catches sensor read errors (common with DHT11) |
python3 send_to_thingspeak.py
Sent → Temp: 28°C Humidity: 64% Sent → Temp: 28°C Humidity: 63% Sent → Temp: 29°C Humidity: 62% ... (every 15 seconds)
try/except block handles this gracefully. The script continues running.
Now we build the viewer side. This HTML page fetches data from ThingSpeak using the Read API Key and displays it live.
Create a new file called index.html in the repository and paste this code:
<!DOCTYPE html> <html> <head> <title>IoT Temperature Monitoring</title> <style> body { font-family: Arial; text-align: center; } .card { display: inline-block; padding: 20px; margin: 15px; border-radius: 10px; box-shadow: 0 0 10px #aaa; width: 220px; } </style> </head> <body> <h1>🌍 IoT Temperature & Humidity Dashboard</h1> <div class="card"> <h2>🌡 Temperature</h2> <p id="temp">-- °C</p> </div> <div class="card"> <h2>💧 Humidity</h2> <p id="hum">-- %</p> </div> <script> const url = "https://api.thingspeak.com/channels/3272751/feeds.json?api_key=YOUR_READ_API_KEY&results=1"; function fetchData() { fetch(url) .then(res => res.json()) .then(data => { const feed = data.feeds[0]; document.getElementById("temp").innerText = feed.field1 + " °C"; document.getElementById("hum").innerText = feed.field2 + " %"; }); } fetchData(); setInterval(fetchData, 5000); // Refresh every 5 seconds </script> </body> </html>
| Part | What It Does |
|---|---|
fetch(url) | Makes HTTP GET request to ThingSpeak REST API |
feeds.json?results=1 | Gets only the latest 1 entry from the channel |
feed.field1 | Temperature value from ThingSpeak Field 1 |
feed.field2 | Humidity value from ThingSpeak Field 2 |
setInterval(fetchData, 5000) | Auto-refreshes data every 5 seconds |
3272751 → Your actual Channel IDYOUR_READ_API_KEY → Your actual Read API Key
28 °C
64 %
Commit this index.html file to your GitHub repository.
https://yourusername.github.io/iot-dashboard/
Go to your ThingSpeak Channel Settings and add these links:
| Setting | Value |
|---|---|
| Link to External Site | https://yourusername.github.io/iot-dashboard/ |
| Link to GitHub | https://github.com/yourusername/iot-dashboard |
| Layer | Technology | Role |
|---|---|---|
| Sensor Layer | DHT11 | Measures temperature & humidity |
| Edge Device | Raspberry Pi | Reads sensor, processes, sends to cloud |
| Programming | Python | Device-side scripting |
| Protocol | HTTP POST / GET | Data transmission |
| Cloud Platform | ThingSpeak | Data storage + REST API |
| Frontend | HTML + JavaScript | Dashboard UI |
| Hosting | GitHub Pages | Free static site hosting |
| Access | Any Browser | View from phone, PC, tablet |
| Enhancement | How |
|---|---|
| Add more sensors | Connect BMP280, MQ-2 — add more fields in ThingSpeak |
| Add charts | Use Chart.js or ThingSpeak iframe widgets in your HTML |
| Add alerts | Use ThingSpeak React app or IFTTT for email/SMS alerts |
| Use MQTT | Switch from HTTP to MQTT for faster, lighter communication |
| Add database | Use Firebase or MongoDB for extended data storage |
| Mobile app | Build a Flutter/React Native app using the same API |
| Run on boot | Add Python script to crontab so it starts automatically |
# Open crontab editor crontab -e # Add this line at the bottom: @reboot python3 /home/pi/iot-project/send_to_thingspeak.py &