Send Sensor Data to a Web Server via ESP8266
Difficulty Level: Intermediate
Project Overview
This project demonstrates how to send sensor data to a web server using an ESP8266 and display the data on a web page. It’s an excellent starting point for IoT projects that require remote monitoring of environmental conditions, such as home automation, weather stations, or greenhouse management.
In this project, we will:
- Use an ESP8266 microcontroller to read temperature and humidity data from a DHT11 sensor.
- Send the collected data to a web server using HTTP POST requests.
- Process and validate the incoming data on the server side using PHP.
- Visualize the real-time data on a web page with JavaScript and Chart.js for an interactive user experience.
This setup provides a practical introduction to IoT concepts like sensor interfacing, network communication, and data visualization.
Components Required
- 1 x ESP8266 (ESP-01 or NodeMCU recommended)
- 1 x DHT11 or DHT22 Temperature and Humidity Sensor (DHT22 offers higher accuracy)
- 1 x 10kΩ pull-up resistor (for stabilizing the DHT data line)
- Jumper wires
- Breadboard
- Optional: USB-to-Serial adapter (e.g., FTDI module) for programming ESP-01
Setting Up the ESP8266
Before diving into the code, ensure your ESP8266 is ready:
1. Install the ESP8266 Board Manager in the Arduino IDE:
- Go to File > Preferences
, add http://arduino.esp8266.com/stable/package_esp8266com_index.json
to the "Additional Boards Manager URLs."
- Open Tools > Board > Boards Manager
, search for "ESP8266," and install it.
2. Install Required Libraries:
- ESP8266WiFi
(pre-installed with the board package).
- DHT
by Adafruit (install via Sketch > Include Library > Manage Libraries
).
- ArduinoJson
(for JSON data handling).
3. Update Firmware: Use the ESP8266 Flasher tool if your module’s firmware is outdated.
4. Configure Arduino IDE: Select your ESP8266 board (e.g., "NodeMCU 1.0" or "Generic ESP8266 Module") and the correct COM port.
Wiring Diagram
For the DHT Sensor:
- VCC: Connect to the 3.3V pin on the ESP8266 (5V may damage the sensor).
- GND: Connect to the GND pin on the ESP8266.
- DATA: Connect to GPIO2 (D4 on NodeMCU) with a 10kΩ pull-up resistor between VCC and DATA.
Note: Double-check connections to avoid erratic readings or sensor damage.
Arduino Code
Below is the optimized Arduino code to read sensor data and send it to the web server:
#include <ESP8266WiFi.h> #include <DHT.h> #include <ArduinoJson.h> #define DHTPIN 2 // Pin where the DHT sensor is connected (GPIO2) #define DHTTYPE DHT11 // Use DHT11 or DHT22 depending on your sensor DHT dht(DHTPIN, DHTTYPE); const char* ssid = "Your_SSID"; // Replace with your Wi-Fi SSID const char* password = "Your_PASSWORD"; // Replace with your Wi-Fi password const char* server = "your_server_ip"; // Replace with your server IP or domain WiFiClient client; void setup() { Serial.begin(115200); dht.begin(); // Connect to Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); } void loop() { float temp = dht.readTemperature(); // Read temperature in Celsius float hum = dht.readHumidity(); // Read humidity in percentage if (isnan(temp) || isnan(hum)) { Serial.println("Failed to read from DHT sensor!"); delay(2000); return; } if (client.connect(server, 80)) { Serial.println("Connected to server"); // Create JSON object StaticJsonDocument<200> jsonDoc; jsonDoc["temp"] = temp; jsonDoc["hum"] = hum; String postData; serializeJson(jsonDoc, postData); // Send HTTP POST request client.println("POST /api/receive-data.php HTTP/1.1"); client.println("Host: " + String(server)); client.println("Content-Type: application/json"); client.print("Content-Length: "); client.println(postData.length()); client.println(); client.println(postData); // Wait for server response (optional for debugging) while (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } client.stop(); Serial.println("Data sent to server: " + postData); } else { Serial.println("Connection to server failed"); } delay(10000); // Send data every 10 seconds }
Tips:
- Replace your_server_ip
with your server’s IP address or domain (e.g., 192.168.1.100
or example.com
).
- Adjust delay(10000)
to change the data-sending frequency.
Server-Side Code (PHP)
This PHP script securely receives and processes the JSON data from the ESP8266:
<?php header("Content-Type: application/json"); // Get raw POST data $data = json_decode(file_get_contents("php://input")); if (!isset($data->temp) || !isset($data->hum)) { echo json_encode(["status" => "error", "message" => "Invalid data"]); exit(); } // Sanitize input $temp = filter_var($data->temp, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); $hum = filter_var($data->hum, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); if ($temp === false || $hum === false) { echo json_encode(["status" => "error", "message" => "Invalid temperature or humidity values"]); exit(); } // Log data to a file (optional) $log_entry = date('Y-m-d H:i:s') . " | Temp: $temp °C | Hum: $hum %\n"; file_put_contents("sensor_data.log", $log_entry, FILE_APPEND); // Optional: Save to a database (e.g., MySQL) // $conn = new mysqli("localhost", "username", "password", "database"); // $conn->query("INSERT INTO sensor_data (temperature, humidity, timestamp) VALUES ($temp, $hum, NOW())"); // Return response to ESP8266 echo json_encode(["status" => "success", "temp" => $temp, "hum" => $hum]); ?>
Notes:
- Place this file (e.g., receive-data.php
) in your server’s /api/
directory.
- Uncomment and configure the MySQL code if you want to store data persistently.
JSON API for Data Handling
To serve data for visualization, create a separate PHP file (e.g., get-data.php
):
<?php header("Content-Type: application/json"); // Simulate fetching latest data (replace with database query if applicable) $latest_data = [ "status" => "success", "temp" => 25.5, // Example value "hum" => 60.2 // Example value ]; echo json_encode($latest_data); ?>
Data Visualization
Use this HTML/JavaScript code to display real-time data with Chart.js:
<!DOCTYPE html> <html> <head> <title>Sensor Data Dashboard</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> </head> <body> <canvas id="sensorChart" width="400" height="200"></canvas> <script> const ctx = document.getElementById('sensorChart').getContext('2d'); const chart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [{ label: 'Temperature (°C)', data: [], borderColor: 'red', fill: false }, { label: 'Humidity (%)', data: [], borderColor: 'blue', fill: false }] }, options: { scales: { y: { beginAtZero: true } } } }); function fetchData() { fetch('/api/get-data.php') .then(response => response.json()) .then(data => { const time = new Date().toLocaleTimeString(); chart.data.labels.push(time); chart.data.datasets[0].data.push(data.temp); chart.data.datasets[1].data.push(data.hum); if (chart.data.labels.length > 20) { chart.data.labels.shift(); chart.data.datasets[0].data.shift(); chart.data.datasets[1].data.shift(); } chart.update(); }); } setInterval(fetchData, 10000); // Update every 10 seconds fetchData(); // Initial fetch </script> </body> </html>
Upload and Test
1. Upload the Arduino code to your ESP8266 via the Arduino IDE.
2. Host the PHP scripts on a web server (e.g., XAMPP, a Raspberry Pi, or a cloud server).
3. Open the Serial Monitor (Ctrl+Shift+M
) to verify Wi-Fi connection and data transmission.
4. Visit your web page (e.g., http://your_server_ip/dashboard.html
) to see the live chart.
Troubleshooting:
- No data on the server? Check the IP address and ensure port 80 is open.
- Sensor errors? Verify wiring and pull-up resistor placement.
Enhancements & Next Steps
- Database Storage: Use MySQL or SQLite to log data for historical trends.
- MQTT Protocol: Replace HTTP with MQTT for faster, bidirectional communication.
- Alerts: Add email/SMS notifications via services like Twilio or SMTP when thresholds are crossed.
- Cloud Integration: Connect to AWS IoT, Google Cloud, or Firebase for scalability.
- Mobile App: Build a simple app using Flutter or React Native to view data on the go.
Conclusion
This project showcases a complete IoT workflow: collecting sensor data with an ESP8266, sending it to a web server, and visualizing it in real time. It’s a versatile foundation for countless applications, from smart homes to industrial monitoring systems.
FAQ
Q: Can I use a different sensor instead of DHT11?
A: Yes! The DHT22 offers better accuracy, or you could use a BME280 for temperature, humidity, and pressure. Adjust the code accordingly.
Q: Why isn’t my ESP8266 connecting to Wi-Fi?
A: Ensure the SSID and password are correct, and check if your router is on the 2.4 GHz band (ESP8266 doesn’t support 5 GHz).
Q: How do I make the data update faster?
A: Reduce the delay()
value in the Arduino code, but avoid overwhelming the server with too many requests.
Q: Can I host this on a free server?
A: Yes, platforms like Heroku or 000webhost support PHP hosting, though you may need to tweak the setup for external requests.
Q: What if my server isn’t accessible from outside my network?
A: Use port forwarding on your router or a service like Ngrok to expose your local server to the internet.
Further Reading for Engagement
Want to dive deeper? Check out these topics on our site:
Getting Started with IoT: A Beginner’s Guide
How to Set Up a Local Web Server with XAMPP
Exploring MQTT: Lightweight Messaging for IoT
Resources
Libraries
Tools
Tutorials
Setting Up a Server with Apache