Hey,
welcome, my friend! Today in this post, I’m going to show you how to create a
super simple and useful live sensor data reader using an ESP8266 as a Soft
Access Point (AP) Wi-Fi on a web server. There are many ways in this world to
send data from one source to another, usually requiring an internet connection,
a concept known as the Internet of Things (IoT). However, in this project, we
don’t need the internet. We will simply send data or readings from the NodeMCU
to browser devices using Wi-Fi.
Parts Require:-
ESP8266 Node MCU x1
Ultrasonic Sensor x1
Rotary Encoder x1
LM35 Temperature Sensor x1
Code:-
Here is the complete code for the Arduino IDE. Just copy it from here and paste it into your Arduino IDE. Then, select the port and COM board, and upload the code.
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> const int trigPin = D1; const int echoPin = D2; const int lm35Pin = A0; const int rotaryPinA = D5; const int rotaryPinB = D6; const int buttonPin = D7; ESP8266WebServer server(80); volatile int encoderValue = 0; volatile bool buttonPressed = false; int lastEncoded = 0; long duration; int distance; float temperature; void IRAM_ATTR handleRotary() { int MSB = digitalRead(rotaryPinA); // MSB = most significant bit int LSB = digitalRead(rotaryPinB); // LSB = least significant bit int encoded = (MSB << 1) | LSB; // converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; // adding it to the previous encoded value if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue++; if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue--; encoderValue = constrain(encoderValue, 0, 360); lastEncoded = encoded; // store this value for next time } void IRAM_ATTR handleButtonPress() { buttonPressed = true; } void handleRoot() { String html = "<!DOCTYPE html><html><head>"; html += "<meta charset='UTF-8'>"; html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>"; html += "<style>"; html += "body { font-family: 'Arial', sans-serif; background-color: #f0f0f0; margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; }"; html += ".box { width: 90%; max-width: 300px; height: 150px; margin: 10px; border-radius: 20px; text-align: center; font-size: 24px; color: #ffffff; display: flex; align-items: center; justify-content: center; }"; html += ".distance-box { background-color: #3498db; border: 4px solid #2c3e50; }"; html += ".temperature-box { background-color: #2ecc71; border: 4px solid #27ae60; }"; html += ".progress-container { position: relative; width: 200px; height: 200px; margin-top: 20px; }"; html += ".progress { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 24px; color: #333; background: conic-gradient(#3498db 0deg, #2ecc71 360deg); }"; html += ".progress::after { content: ''; width: 180px; height: 180px; border-radius: 50%; background: #f0f0f0; position: absolute; }"; html += ".progress span { position: relative; z-index: 1; }"; html += ".boom { animation: boomAnimation 1s ease-in-out infinite; color: red; font-size: 36px; font-weight: bold; }"; html += "@keyframes boomAnimation { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } }"; html += "</style>"; html += "</head><body>"; html += "<div class='box distance-box' id='distanceBox'><span id='distance'>Loading...</span></div>"; html += "<div class='box temperature-box' id='temperatureBox'><span id='temperature'>Loading...</span></div>"; html += "<div class='progress-container'><div class='progress' id='progress'><span id='encoderValue'>Loading...</span></div></div>"; html += "<script>"; html += "function fetchData() {"; html += "fetch('/getDistance').then(response => response.json()).then(data => {"; html += "document.getElementById('distance').innerText = 'Distance: ' + data.distance + ' CM';"; html += "document.getElementById('distanceBox').style.backgroundColor = getDistanceColor(data.distance);"; html += "});"; html += "fetch('/getTemperature').then(response => response.text()).then(data => {"; html += "document.getElementById('temperature').innerText = 'Temperature: ' + data + ' °C';"; html += "document.getElementById('temperatureBox').style.backgroundColor = getTemperatureColor(parseFloat(data));"; html += "});"; html += "fetch('/getEncoder').then(response => response.text()).then(data => {"; html += "let progressElem = document.getElementById('progress');"; html += "let encoderValueElem = document.getElementById('encoderValue');"; html += "if (data === 'BOOM!') {"; html += "encoderValueElem.innerHTML = '<span class=\"boom\">BOOM!</span>';"; html += "progressElem.style.background = 'conic-gradient(red 0deg, red 360deg)';"; html += "} else {"; html += "encoderValueElem.innerText = data + '°';"; html += "progressElem.style.background = 'conic-gradient(hsl(' + data + ', 100%, 50%) 0deg, hsl(' + data + ', 100%, 50%) ' + data + 'deg, #eee ' + data + 'deg 360deg)';"; html += "}"; html += "});"; html += "}"; html += "function getDistanceColor(value) {"; html += "var hue = 120 - (value * 1.2);"; // Adjust the hue calculation to start with red and transition to green html += "return 'hsl(' + hue + ', 100%, 50%)';"; // Create color in HSL format html += "}"; html += "function getTemperatureColor(temp) {"; html += "var hue = temp > 45 ? 270 : temp < 11 ? 240 : 240 + (temp - 11) * 2.7;"; html += "return 'hsl(' + hue + ', 100%, 50%)';"; html += "}"; html += "setInterval(fetchData, 100);"; html += "</script>"; html += "</body></html>"; server.send(200, "text/html", html); } void handleGetDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2; String json = "{\"distance\":" + String(distance) + "}"; server.send(200, "application/json", json); } float readTemperature() { int rawValue = analogRead(lm35Pin); float voltage = (rawValue / 1023.0) * 3.3; // Calculate voltage (0-3.3V) float temperatureCelsius = voltage * 100.0; // Convert voltage to temperature in Celsius return temperatureCelsius; } void handleTemperature() { temperature = readTemperature(); server.send(200, "text/plain", String(temperature)); } void handleEncoder() { if (buttonPressed) { server.send(200, "text/plain", "BOOM!"); buttonPressed = false; } else { server.send(200, "text/plain", String(encoderValue)); } } void setup() { Serial.begin(115200); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(lm35Pin, INPUT); pinMode(rotaryPinA, INPUT); pinMode(rotaryPinB, INPUT); pinMode(buttonPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(rotaryPinA), handleRotary, CHANGE); attachInterrupt(digitalPinToInterrupt(rotaryPinB), handleRotary, CHANGE); attachInterrupt(digitalPinToInterrupt(buttonPin), handleButtonPress, FALLING); const char* ssid="ESP8266 Live Data"; //SSID of this device const char* password="12345678"; // Password of this Device // Set up the ESP8266 as a Wi-Fi Access Point WiFi.softAP(ssid, password); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); server.on("/", handleRoot); server.on("/getDistance", handleGetDistance); server.on("/getTemperature", handleTemperature); server.on("/getEncoder", handleEncoder); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); }
We have
integrated three sensors in this project:
- Ultrasonic Sensor: Measures the distance of
an object from the sensor. The measured distance is displayed on the web
page, and the background color of the display box changes based on the
distance.
- LM35 Temperature Sensor: Measures the ambient
temperature. The temperature is displayed in degrees Celsius, with the
background color of the display box changing based on the temperature.
- Rotary Encoder: Captures the rotation
angle, which is displayed on a circular progress bar. If the encoder’s
button is pressed, a “BOOM!” message is shown with an animation.
The data
from these sensors is refreshed every 100 milliseconds, providing a real-time
update on the web page.
How to Use
- Setup: Connect the ESP8266
NodeMCU to your computer and upload the provided code using the Arduino
IDE.
- Power Up: Once the code is uploaded,
power the ESP8266. It will create a Wi-Fi network named "ESP8266 Live
Data" with the password "12345678".
- Connect: Use your smartphone or
computer to connect to the "ESP8266 Live Data" Wi-Fi network.
- Access the Web Server: Open a web browser and
navigate to the IP address 192.168.4.1. You will see a web page displaying the live
sensor data.
- Observe the Data: Place objects at varying
distances from the ultrasonic sensor, observe temperature changes around
the LM35 sensor, and rotate the rotary encoder to see real-time updates on
the web page.
Comments
Post a Comment