源码
#include <WiFi.h>
#include <WebServer.h>
// 替换为你的WiFi网络名称和密码
const char* ssid = "123";
const char* password = "1234678901";
WebServer server(80); // 创建一个Web服务器对象,监听80端口
// 定义ADC引脚
const int adcPin = 2; // 使用GPIO 2作为ADC输入
void setup() {
Serial.begin(115200);
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// 设置服务器路由
server.on("/", handleRoot); // 当访问根目录时调用handleRoot函数
server.on("/readADC", handleReadADC); // 当访问/readADC时调用handleReadADC函数
// 启动服务器
server.begin();
}
void loop() {
server.handleClient(); // 处理客户端请求
}
void handleRoot() {
String html = "<html><head><style>body { background-color: #ADD8E6; }</style>";
html += "<script>";
html += "function updateADC() {";
html += " var xhr = new XMLHttpRequest();";
html += " xhr.onreadystatechange = function() {";
html += " if (this.readyState == 4 && this.status == 200) {";
html += " document.getElementById('adcValue').innerHTML = this.responseText;";
html += " }";
html += " };";
html += " xhr.open('GET', '/readADC', true);";
html += " xhr.send();";
html += "}";
html += "setInterval(updateADC, 1000);"; // 每秒更新一次
html += "</script>";
html += "</head><body>";
html += "<h1>ESP32-C3 ADC Readings</h1>";
html += "<p>Voltage: <span id='adcValue'>0</span> V</p>";
html += "</body></html>";
server.send(200, "text/html", html); // 发送网页内容
}
void handleReadADC() {
int adcValue = analogRead(adcPin); // 读取ADC值
float voltage = (adcValue * 3.3) / 4095.0; // 转换ADC值为电压
server.send(200, "text/plain", String(voltage, 2)); // 发送电压值,保留两位小数
}
网页实现数据显示的思路
-
数据采集:首先,需要确定你想要显示的数据来源。在ESP32-C3的情况下,这可能是一个ADC读取、GPIO状态、传感器数据等。
-
数据格式化:采集到的数据需要被格式化成可以发送给客户端(通常是浏览器)的格式,通常是JSON或纯文本。
-
服务器端设置:
- 创建一个Web服务器,用于处理来自客户端的请求。
- 定义路由,这些路由会响应对特定URL的请求。
- 在路由的处理函数中,采集数据,并将其格式化后发送给客户端。
-
客户端(网页)设计:
- 创建HTML页面,用于显示数据和提供用户界面。
- 使用CSS来美化网页,使其更加友好和易于使用。
- 使用JavaScript来处理用户交互和从服务器动态获取数据。
数据如何更新的思路
服务器端:
-
数据源:确保服务器端有实时或定期更新的数据源,例如数据库、传感器、API等。
-
数据监听:服务器端需要监听数据源的变化,或者定期检查数据是否更新。
-
数据推送:
- 轮询(Polling):客户端定期发送请求到服务器,询问是否有新数据。
- 长轮询(Long Polling):客户端发送请求到服务器,服务器保持连接打开直到有新数据可发送。
- 服务器发送事件(Server-Sent Events, SSE):服务器主动向客户端推送数据。
- WebSocket:建立一个持久的连接,服务器可以在任何时间向客户端发送数据。
客户端:
-
初始化:客户端加载页面并初始化数据展示。
-
数据请求:根据采用的更新策略,客户端发送请求到服务器。
-
数据处理:
- 接收服务器响应的数据。
- 更新页面上的数据展示。
以下是不同更新策略的具体实现思路:
轮询(Polling):(实现的)
- 客户端:使用
setInterval
或setTimeout
在JavaScript中定期发送AJAX请求到服务器。
function fetchData() {
fetch('/data')
.then(response => response.json())
.then(data => {
updateUI(data);
setTimeout(fetchData, 5000); // 每5秒请求一次
});
}
fetchData();
- 服务器端:处理请求并返回当前数据。
void handleData() {
// 获取数据
String jsonData = getLatestData();
server.send(200, "application/json", jsonData);
}
长轮询(Long Polling):
- 客户端:发送请求到服务器,并等待直到服务器有新数据返回。
function longPolling() {
fetch('/data')
.then(response => response.json())
.then(data => {
updateUI(data);
longPolling(); // 重新发起长轮询
});
}
longPolling();
- 服务器端:保持连接打开,直到有新数据可发送。
void handleData() {
// 等待直到有新数据
String jsonData = waitForNewData();
server.send(200, "application/json", jsonData);
}
服务器发送事件(Server-Sent Events, SSE):
- 客户端:创建一个
EventSource
来监听服务器发送的事件。
var eventSource = new EventSource('/events');
eventSource.onmessage = function(event) {
var data = JSON.parse(event.data);
updateUI(data);
};
- 服务器端:发送事件到客户端。
void handleEvents() {
// 发送新数据作为事件
String eventData = getEventData();
server.sendContent("data: " + eventData + "\n\n");
}
WebSocket:
- 客户端:建立WebSocket连接,并监听消息。
var socket = new WebSocket('ws://example.com/socket');
socket.onmessage = function(event) {
var data = JSON.parse(event.data);
updateUI(data);
};
- 服务器端:处理WebSocket连接,并在有新数据时发送消息。
void onWebSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
if (type == WStype_TEXT) {
// 发送新数据
String data = getWebSocketData();
webSocket.sendTXT(num, data);
}
}
选择哪种策略取决于应用的需求,例如数据更新频率、延迟敏感度、服务器和客户端的资源限制等。轮询是最简单的方法,但可能不是最高效的;WebSocket提供了全双工通信,但实现起来相对复杂。