Arduino NodeMCU WebServer实时显示距离传感器数据

enter image description here

Arduino 非常流行,有初学者友好的学习平台,社群,以及大量开源、创意项目 可以直接依葫芦画瓢复制一个项目,也可以激发自己的想象创建属于自己的独一无二的作品

一切从探索未知开始

我利用ChatGPT创建了一个有趣的demo应用

  • 简单的电路连接,
  • arduno IDE
  • nodemcu
  • sharp IR距离传感器

enter image description here

用这个 demo 作为教学基础,确实可以帮助初学者更好地理解 Arduino 和编程的实际应用。以下是从这个 demo 中可以提取的一些关键知识点,适合讲解给 Arduino 或编程新手:

1. Arduino 与 Web 开发的结合

  • 基础硬件控制: 初学者可以了解如何通过 Arduino 控制传感器(如 IR 传感器)。通过 analogRead() 函数读取模拟传感器数据,进一步理解传感器的工作原理以及如何将数据传递到其他模块。
  • Wi-Fi 连接: 学生能够学习如何通过 Wi-Fi 将 Arduino 或 NodeMCU 连接到网络。使用 WiFi.begin() 和 WiFi.localIP() 来配置和连接网络,这部分涉及到网络基础,特别是在嵌入式系统中如何进行联网。
  • Web 服务器: 通过 ESP8266WebServer 库,学生可以学习如何在 Arduino 上搭建 Web 服务器,响应 HTTP 请求,输出 HTML 页面,处理 GET 请求。这是进入 Web 开发的基础。

2. 嵌入式 Web 页面开发

  • HTML & CSS: 学生可以通过编辑 HTML 页面和使用 Bootstrap 来实现前端开发。这部分能够让他们理解如何使用 Web 技术(HTML、CSS)来创建动态交互的用户界面,甚至可以改进页面布局和视觉效果。
  • JavaScript: 学生将学习如何通过 JavaScript 使用 fetch() API 从 Arduino 后端请求实时数据,并更新页面。这涉及到前端开发中如何与后端通信,如何动态更新网页内容,而不刷新整个页面。
  • JSON 数据交换: 通过 /get_data 接口返回的数据,学生会了解如何在前端与后端之间通过 JSON 格式传输数据。理解 JSON 格式是编程中非常常见的技术,尤其是在 Web 开发和嵌入式开发中。

3. 传感器与数据处理

  • IR 传感器原理: 学生将学习 IR 传感器如何工作,如何读取其输出,并通过公式将传感器的电压值转换为距离值。可以让学生了解传感器的工作原理,并学会如何校准和处理传感器的数据。
  • 数据处理与显示: 通过实时获取传感器数据并在 Web 页面上显示,学生可以理解如何将数据采集、处理和展示整合在一个应用中。这是实际应用中常见的编程任务。

4. 时间同步与网络编程

  • NTP 时间同步: 学生可以了解如何使用 NTP 客户端从网络时间服务器获取精确的时间。这不仅涉及到如何获取 UTC 时间,还让学生理解如何进行时区转换,获取特定区域的时间(如北京时间)。
  • 时间格式化: 使用 strftime() 函数来格式化时间,学生将学习如何将原始时间戳转换成易于阅读的日期和时间格式,这对于 Web 开发中日期时间的处理非常重要。

5. 项目集成与调试

  • 硬件与软件集成: 学生会学到如何将硬件(如传感器)和软件(如 Web 服务器、数据处理)结合起来,进行项目开发。
  • 调试技巧: 在开发过程中,学生会遇到如何调试 Arduino 代码、调试网络通信、调试前端 JavaScript 的问题。通过这些实践,他们可以提高解决问题的能力。

6. 提升用户体验

  • 界面设计: 通过 Bootstrap 和 Font Awesome 图标,学生可以学习如何创建现代、响应式的用户界面,以及如何使用图标和样式美化页面,提高用户体验。
  • 动态页面更新: 使用 JavaScript 定时更新页面数据,而不需要整个页面刷新,可以帮助学生理解如何提高应用的响应速度和交互性,提升 Web 应用的性能。

教学建议:

  • 分模块讲解: 把每个知识点分成几个模块,例如从 Arduino 控制传感器,到搭建 Web 服务器,再到前端开发和数据交互。这样可以逐步引导学生理解每个部分,并通过实际操作加深记忆。
  • 实战演练: 在教学过程中,让学生动手操作,修改代码并观察效果。比如让学生修改 HTML 页面、调整传感器数据的公式、增加其他传感器,甚至扩展功能。
  • 问题解决: 在教学过程中,适时引导学生遇到问题时如何调试、排错。例如,如何通过串口输出调试信息、如何查看浏览器控制台日志等。

通过这样系统的教学,学生不仅能够运行这个 demo,还能学到如何在实际项目中应用这些知识,理解嵌入式开发和 Web 开发的结合,打下坚实的编程基础。


#include <ESP8266WiFi.h> #include <WiFiUdp.h> #include <NTPClient.h> #include <ESP8266WebServer.h> #include <time.h> // Wi-Fi 配置 const char* ssid = "Your_SSID"; // 替换为你的 Wi-Fi 名称 const char* password = "Your_PASS"; // 替换为你的 Wi-Fi 密码 // NTP 客户端配置 WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 8 * 3600, 60000); // 北京时间 UTC+8,刷新间隔60秒 // HTTP 服务器 ESP8266WebServer server(80); // 定义模拟输入引脚(IR 传感器连接的引脚) const int sensorPin = A0; // 获取格式化时间字符串 String getFormattedDateTime() { time_t rawTime = timeClient.getEpochTime(); // 获取时间戳 struct tm* timeInfo = localtime(&rawTime); // 转换为本地时间 char buffer[20]; // 用于存储格式化日期时间 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeInfo); // 格式化日期时间 return String(buffer); } // HTML 页面 const char* htmlPage = R"( <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Beijing Time & Distance</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet"> <style> body { background-color: #2C3E50; color: #ECF0F1; font-family: 'Roboto', sans-serif; } .card { margin-top: 15%; max-width: 400px; margin-left: auto; margin-right: auto; text-align: center; background: linear-gradient(145deg, #1F3A60, #34495E); border-radius: 15px; box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2); } .icon { font-size: 2em; margin-right: 10px; } .icon-time { color: #3498DB; } .icon-distance { color: #E74C3C; } .card-text { font-size: 1.3em; } .card-title { font-size: 1.8em; color: #F39C12; } </style> </head> <body> <div class="container"> <div class="card shadow-lg"> <div class="card-body"> <h5 class="card-title">Sensor Data Monitor</h5> <p class="card-text"> <i class="fas fa-clock icon icon-time"></i><strong>Current Date and Time: </strong><span id="time" class="text-primary"></span> </p> <p class="card-text"> <i class="fas fa-ruler-vertical icon icon-distance"></i><strong>Distance: </strong><span id="distance" class="text-success"></span> cm </p> <p>Page refreshes every second.</p> </div> </div> </div> <script> function fetchData() { fetch('/get_data') .then(response => response.json()) .then(data => { document.getElementById("time").innerText = data.time; document.getElementById("distance").innerText = data.distance; }); } setInterval(fetchData, 1000); fetchData(); </script> </body> </html> )"; void setup() { Serial.begin(115200); // 连接 Wi-Fi WiFi.begin(ssid, password); Serial.print("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println("\nConnected to Wi-Fi!"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // 初始化 NTP 客户端 timeClient.begin(); // 配置 HTTP 服务器 server.on("/", HTTP_GET, []() { server.send(200, "text/html", htmlPage); // 直接返回内嵌的 HTML 页面 }); server.on("/get_data", HTTP_GET, []() { // 获取当前日期时间 timeClient.update(); String currentDateTime = getFormattedDateTime(); // 获取 IR 传感器数据 int sensorValue = analogRead(sensorPin); float voltage = sensorValue * (3.3 / 1023.0); float distance = 27.86 / (voltage - 0.42); // 假设公式,需根据传感器校准调整 // 返回 JSON 格式的数据 String jsonResponse = "{\"time\": \"" + currentDateTime + "\", \"distance\": " + String(distance, 2) + "}"; server.send(200, "application/json", jsonResponse); }); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); }

评论