The WebPlotter example creates a real-time data visualization interface accessible through any web browser. Designed for ESP32 educational platform with enhanced data processing capabilities, real-time plotting features, and seamless integration with sensor monitoring systems. Perfect for visualizing sensor data, debugging algorithms, or monitoring system performance in real-time.
Watch this step-by-step video tutorial demonstrating how to use a DHT sensor with the Web Plotter app:
Follow these instructions step by step:
Connect the ESP32 board to your computer using a USB cable.
Launch the Arduino IDE on your computer.
Select the appropriate ESP32 board (e.g. ESP32 Dev Module) and COM port.
Navigate to the Libraries icon on the left bar of the Arduino IDE.
Search "DIYables ESP32 WebApps", then find the DIYables ESP32 WebApps Library by DIYables
Click Install button to install the library.


#include <DIYables_ESP32_Platform.h>
#include <DIYablesWebApps.h>
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
ESP32ServerFactory serverFactory;
DIYablesWebAppServer webAppsServer(serverFactory, 80, 81);
DIYablesHomePage homePage;
DIYablesWebPlotterPage webPlotterPage;
unsigned long lastDataTime = 0;
const unsigned long DATA_INTERVAL = 1000;
float timeCounter = 0;
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("DIYables ESP32 WebApp - Web Plotter Example");
webAppsServer.addApp(&homePage);
webAppsServer.addApp(&webPlotterPage);
webAppsServer.setNotFoundPage(DIYablesNotFoundPage());
webPlotterPage.setPlotTitle("Real-time Data Plotter");
webPlotterPage.setAxisLabels("Time (s)", "Values");
webPlotterPage.enableAutoScale(true);
webPlotterPage.setMaxSamples(50);
if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) {
while (1) {
Serial.println("Failed to start WebApp server!");
delay(1000);
}
}
webPlotterPage.onPlotterDataRequest([]() {
Serial.println("Web client requested data");
sendSensorData();
});
Serial.println("\nWebPlotter is ready!");
Serial.println("Usage Instructions:");
Serial.println("1. Connect to the WiFi network");
Serial.println("2. Open your web browser");
Serial.println("3. Navigate to the Arduino's IP address");
Serial.println("4. Click on 'Web Plotter' to view real-time data");
Serial.println("\nGenerating simulated sensor data...");
}
void loop() {
webAppsServer.loop();
if (millis() - lastDataTime >= DATA_INTERVAL) {
lastDataTime = millis();
sendSensorData();
timeCounter += DATA_INTERVAL / 1000.0;
}
}
void sendSensorData() {
float temperature = 25.0 + 5.0 * sin(timeCounter * 0.5) + random(-100, 100) / 100.0;
float humidity = 50.0 + 20.0 * cos(timeCounter * 0.3);
float light = 512.0 + 300.0 * (2.0 * abs(fmod(timeCounter * 0.2, 2.0) - 1.0) - 1.0);
float analogValue = analogRead(A0);
webPlotterPage.sendPlotData(temperature, humidity, light / 10.0, analogValue / 100.0);
Serial.print(temperature, 1);
Serial.print("\t");
Serial.print(humidity, 1);
Serial.print("\t");
Serial.print(light / 10.0, 1);
Serial.print("\t");
Serial.println(analogValue / 100.0, 2);
}
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
DIYables WebApp - Web Plotter Example
INFO: Added app /
INFO: Added app /web-plotter
DIYables WebApp Library
Platform: ESP32
Network connected!
IP address: 192.168.0.2
HTTP server started on port 80
Configuring WebSocket server callbacks...
WebSocket server started on port 81
WebSocket URL: ws://192.168.0.2:81
WebSocket server started on port 81
==========================================
DIYables WebApp Ready!
==========================================
📱 Web Interface: http://192.168.0.2
🔗 WebSocket: ws://192.168.0.2:81
📋 Available Applications:
🏠 Home Page: http://192.168.0.2/
📊 Web Plotter: http://192.168.0.2/web-plotter
==========================================
If you do not see anything, reboot ESP32 board.
Take note of the IP address displayed, and enter this address into the address bar of a web browser on your smartphone or PC.
Example: http://192.168.0.2
You will see the home page like below image:
Or you can also access the page directly by IP address followed by /web-plotter. For example: http://192.168.0.2/web-plotter
Watch as the ESP32 generates simulated sensor data and plots it in real-time. You'll see multiple colored lines representing different data streams.
Transform the plotting interface to match your unique project requirements and create stunning data visualizations:
Replace simulated data with real sensor readings:
void sendTemperatureData() {
float temperature = analogRead(A0) * (5.0 / 1023.0) * 100;
webPlotterPage.sendPlotData(temperature);
}
void sendMultipleSensors() {
float temperature = readTemperature();
float humidity = readHumidity();
float light = analogRead(A1) / 10.0;
float pressure = readPressure();
webPlotterPage.sendPlotData(temperature, humidity, light, pressure);
}
void sendSensorArray() {
float sensors[6] = {
analogRead(A0) / 10.0,
analogRead(A1) / 10.0,
analogRead(A2) / 10.0,
digitalRead(2) * 50,
millis() / 1000.0,
random(0, 100)
};
webPlotterPage.sendPlotData(sensors, 6);
}
void setupCustomPlot() {
webPlotterPage.setPlotTitle("Environmental Monitoring Station");
webPlotterPage.setAxisLabels("Time (minutes)", "Sensor Readings");
webPlotterPage.setYAxisRange(0, 100);
webPlotterPage.setMaxSamples(100);
}
void setupDynamicPlot() {
webPlotterPage.setPlotTitle("Smart Garden Monitor");
webPlotterPage.setAxisLabels("Sample #", "Values");
webPlotterPage.enableAutoScale(true);
webPlotterPage.onPlotterDataRequest([]() {
Serial.println("Client connected - sending initial data");
sendInitialDataBurst();
});
}
float movingAverage(float newValue) {
static float readings[10];
static int index = 0;
static float total = 0;
total -= readings[index];
readings[index] = newValue;
total += readings[index];
index = (index + 1) % 10;
return total / 10.0;
}
void sendFilteredData() {
float rawValue = analogRead(A0);
float filteredValue = movingAverage(rawValue);
webPlotterPage.sendPlotData(rawValue / 10.0, filteredValue / 10.0);
}
void sendTimestampedData() {
unsigned long currentTime = millis() / 1000;
float sensorValue = analogRead(A0) / 10.0;
webPlotterPage.sendPlotData(currentTime, sensorValue);
Serial.print("Time: ");
Serial.print(currentTime);
Serial.print("s, Value: ");
Serial.println(sensorValue);
}
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
void sendEnvironmentalData() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
float lightLevel = analogRead(A0) / 10.0;
if (!isnan(temperature) && !isnan(humidity)) {
webPlotterPage.sendPlotData(temperature, humidity, lightLevel);
Serial.print("T: ");
Serial.print(temperature);
Serial.print("°C, H: ");
Serial.print(humidity);
Serial.print("%, Light: ");
Serial.println(lightLevel);
}
}
void sendMotorData() {
int motorSpeed = analogRead(A0);
int currentDraw = analogRead(A1);
int motorPosition = digitalRead(2);
float speedPercent = (motorSpeed / 1023.0) * 100;
float currentAmps = (currentDraw / 1023.0) * 5.0;
float positionDegrees = motorPosition * 90;
webPlotterPage.sendPlotData(speedPercent, currentAmps, positionDegrees);
}
float setpoint = 50.0;
float kp = 1.0, ki = 0.1, kd = 0.01;
float integral = 0, previousError = 0;
void sendPIDData() {
float input = analogRead(A0) / 10.0;
float error = setpoint - input;
integral += error;
float derivative = error - previousError;
float output = (kp * error) + (ki * integral) + (kd * derivative);
previousError = error;
webPlotterPage.sendPlotData(setpoint, input, error, output);
}
unsigned long lastPlotUpdate = 0;
const unsigned long PLOT_INTERVAL = 100;
void efficientDataSending() {
if (millis() - lastPlotUpdate >= PLOT_INTERVAL) {
lastPlotUpdate = millis();
float value1 = analogRead(A0) / 10.0;
float value2 = analogRead(A1) / 10.0;
webPlotterPage.sendPlotData(value1, value2);
}
}
float lastSentValue = 0;
const float CHANGE_THRESHOLD = 5.0;
void sendOnChange() {
float currentValue = analogRead(A0) / 10.0;
if (abs(currentValue - lastSentValue) > CHANGE_THRESHOLD) {
webPlotterPage.sendPlotData(currentValue);
lastSentValue = currentValue;
}
}
1. No data appearing on plot
Check WiFi connection status
Verify WebSocket connection in browser console
Ensure sendPlotData() is being called regularly
Check Serial Monitor for error messages
2. Plot appears jumpy or erratic
Implement data filtering (moving average)
Reduce data sending frequency
Check for sensor noise or connection issues
Verify power supply stability
3. Browser performance issues
Reduce maximum samples (setMaxSamples())
Lower data transmission rate
Close other browser tabs
Use hardware acceleration in browser
4. WebSocket connection drops
Check WiFi signal strength
Verify router settings (firewall, port blocking)
Implement reconnection logic in custom code
Monitor ESP32 memory usage
void debugPlotterData() {
Serial.println("=== Plotter Debug Info ===");
Serial.print("Free RAM: ");
Serial.println(freeMemory());
Serial.print("Connected clients: ");
Serial.println(server.getConnectedClients());
Serial.print("Data rate: ");
Serial.println("Every " + String(DATA_INTERVAL) + "ms");
Serial.println("========================");
}
void generateTestPattern() {
static float phase = 0;
float sine = sin(phase) * 50 + 50;
float cosine = cos(phase) * 30 + 70;
float triangle = (phase / PI) * 25 + 25;
webPlotterPage.sendPlotData(sine, cosine, triangle);
phase += 0.1;
if (phase > 2 * PI) phase = 0;
}
void sendFormattedData() {
float temp = 25.5;
float humidity = 60.3;
String dataLine = String(temp, 1) + "\t" + String(humidity, 1);
webPlotterPage.sendPlotData(dataLine);
}
void setupMultipleApps() {
server.addApp(new DIYablesHomePage());
server.addApp(new DIYablesWebDigitalPinsPage());
server.addApp(new DIYablesWebSliderPage());
server.addApp(&webPlotterPage);
server.addApp(new DIYablesNotFoundPage());
webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) {
float scaleFactor = slider1 / 255.0;
});
}
void controlAndPlot() {
int targetSpeed = analogRead(A0);
analogWrite(9, targetSpeed / 4);
int actualSpeed = analogRead(A1);
int motorCurrent = analogRead(A2);
webPlotterPage.sendPlotData(
targetSpeed / 4.0,
actualSpeed / 4.0,
motorCurrent / 10.0
);
}
The below is complete code for adapting this web app with a DHT11 sensor:
#include <DIYables_ESP32_Platform.h>
#include <DIYablesWebApps.h>
#include <DHT.h>
#define DHT_PIN 21
#define DHT_TYPE DHT11
DHT dht(DHT_PIN, DHT_TYPE);
const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
ESP32ServerFactory serverFactory;
DIYablesWebAppServer webAppsServer(serverFactory, 80, 81);
DIYablesHomePage homePage;
DIYablesWebPlotterPage webPlotterPage;
unsigned long lastDataTime = 0;
const unsigned long DATA_INTERVAL = 1000;
float timeCounter = 0;
void setup() {
Serial.begin(9600);
delay(1000);
dht.begin();
Serial.println("DIYables ESP32 WebApp - Web Plotter Example");
webAppsServer.addApp(&homePage);
webAppsServer.addApp(&webPlotterPage);
webAppsServer.setNotFoundPage(DIYablesNotFoundPage());
webPlotterPage.setPlotTitle("Real-time Data Plotter");
webPlotterPage.setAxisLabels("Time (s)", "Values");
webPlotterPage.enableAutoScale(true);
webPlotterPage.setMaxSamples(50);
if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) {
while (1) {
Serial.println("Failed to start WebApp server!");
delay(1000);
}
}
webPlotterPage.onPlotterDataRequest([]() {
Serial.println("Web client requested data");
sendSensorData();
});
Serial.println("\nWebPlotter is ready!");
Serial.println("Usage Instructions:");
Serial.println("1. Connect to the WiFi network");
Serial.println("2. Open your web browser");
Serial.println("3. Navigate to the Arduino's IP address");
Serial.println("4. Click on 'Web Plotter' to view real-time data");
Serial.println("\nGenerating simulated sensor data...");
}
void loop() {
webAppsServer.loop();
if (millis() - lastDataTime >= DATA_INTERVAL) {
lastDataTime = millis();
sendSensorData();
timeCounter += DATA_INTERVAL / 1000.0;
}
delay(10000);
}
void sendSensorData() {
float temperature = 25.0 + 5.0 * sin(timeCounter * 0.5) + random(-100, 100) / 100.0;
float humidity = 50.0 + 20.0 * cos(timeCounter * 0.3);
float light = 512.0 + 300.0 * (2.0 * abs(fmod(timeCounter * 0.2, 2.0) - 1.0) - 1.0);
float analogValue = analogRead(A0);
webPlotterPage.sendPlotData(temperature, humidity, light / 10.0, analogValue / 100.0);
Serial.print(temperature, 1);
Serial.print("\t");
Serial.print(humidity, 1);
Serial.print("\t");
Serial.print(light / 10.0, 1);
Serial.print("\t");
Serial.println(analogValue / 100.0, 2);
}
void sendEnvironmentalData() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temperature) && !isnan(humidity)) {
webPlotterPage.sendPlotData(temperature, humidity);
Serial.print("T: ");
Serial.print(temperature);
Serial.print("°C, H: ");
Serial.println(humidity);
}
}
The below is a step-by-step video tutorial demonstrating how to use a DHT sensor with the Web Plotter app:
After mastering the WebPlotter example, explore:
MultipleWebApps - Combine plotting with control interfaces
WebMonitor - Add debugging capabilities alongside plotting
Custom Applications - Build your own specialized plotting tools
Data Analysis - Implement statistical analysis of plotted data