|
15| 0
|
[ESP8266/ESP32] ESP32-C5 FireBeetle 2 搭建离线版的课堂交互网页 |
|
ESP32-C5 FireBeetle 2 搭建离线版的课堂交互网页 注:此文参考卓尔大佬的文章,谢谢! 1.1 产品简介FireBeetle 2 ESP32-C5 IO套装包括两部分:Firebeetle 2 ESP32-C5 开发板和其专用的IO扩展底板。IO扩展板方便快速连接各种传感器外设,让Firebeetle 2 ESP32-C5开发板到手即用,无需焊接。 FireBeetle 2 ESP32-C5 是一款搭载乐鑫 ESP32-C5 模组的低功耗 IoT 开发板,面向智能家居和广泛物联网场景,集高性能计算、多协议支持与智能电源管理于一体,为各种部署需求提供高可靠性、高灵活性与长续航的解决方案。 支持 2.4 & 5 GHz 双频 Wi-Fi 6 ESP32-C5 是乐鑫首款支持2.4 G和5 G 双频Wi-Fi 6的芯片。相较于 2.4GHz 频段,5GHz 具备更高传输速率、更低延迟及更少干扰特性,可提供更稳定、更低延迟的无线连接。同时,Wi-Fi 6 技术通过 OFDMA 频分复用 和目标唤醒时间(TWT,Target Wake Time) 机制,显著提升网络容量并降低设备功耗,延长电池使用时间,让设备长久续航。 FireBeetle 2 ESP32-C5 凭借双频 Wi-Fi 6 支持,可满足智能家居、物联网等场景对高吞吐与低功耗的双重需求。 多协议融合,扩展无线连接性 开发板支持 Wi-Fi、Thread、BLE、Zigbee 协议,可构建 Matter Wi-Fi/Thread 终端设备,实现跨平台智能家居设备互联。结合外部 MCU,还可作为 Thread 边界路由器、Matter 网关 或 Zigbee 网桥,覆盖复杂场景需求。 高效电源管理,部署更灵活 FireBeetle 2 ESP32-C5提供了高效和易用的电源管理,为各种部署需求提供可靠、灵活的供电解决方案。
搭配专用IO扩展底板,无需焊接 Firebeetle 2 ESP32-C5开发板推出专属的IO扩展板,其IO引脚全部引出,并且精心做了功能分区,方便直接快速连接各种传感器外设,真正让开发板做到了到手即用,无需焊接。 2.1 打开Arduino,配置环境 环境配置参考: 请点击下方链接查看添加板卡的详细步骤: 注意:仅esp32板卡环境 3.3.0-alpha1分支版本才支持ESP32-C5。 2.2 输入代码 #include <WiFi.h>#include <WebServer.h> // 手机热点配置(替换为您的热点SSID和密码) const char* ssid = "jzai"; // 替换为手机热点的SSID const char* password = "88998899"; // 替换为手机热点的密码 // 创建Web服务器对象,监听80端口(HTTP协议) WebServer server(80); // HTML内容(主题,保持与原代码一致) const char* htmlContent = R"rawliteral( <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>打地鼠小游戏</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Arial Rounded MT Bold', 'Arial', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); padding: 20px; } .game-container { width: 100%; max-width: 600px; background-color: rgba(255, 255, 255, 0.9); border-radius: 20px; padding: 25px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); text-align: center; } h1 { color: #333; margin-bottom: 20px; font-size: 2.5rem; text-shadow: 2px 2px 0 #ffcc00; } .game-info { display: flex; justify-content: space-between; margin-bottom: 20px; font-size: 1.2rem; font-weight: bold; } .score, .timer { background-color: #ffcc00; padding: 10px 20px; border-radius: 10px; box-shadow: 0 4px 0 #e6b800; } .game-board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 25px; } .hole { width: 100%; aspect-ratio: 1; background-color: #8B4513; border-radius: 50%; position: relative; overflow: hidden; box-shadow: inset 0 10px 0 rgba(0, 0, 0, 0.3); cursor: pointer; } .mole { width: 80%; height: 80%; background-color: #8B4513; border-radius: 50%; position: absolute; bottom: -80%; left: 10%; transition: bottom 0.3s; cursor: pointer; } .mole::before { content: ''; position: absolute; width: 40%; height: 40%; background-color: #333; border-radius: 50%; top: 20%; left: 30%; } .mole::after { content: ''; position: absolute; width: 60%; height: 30%; background-color: #ff6666; border-radius: 50%; bottom: 10%; left: 20%; } .mole.up { bottom: 10%; } .controls { margin-top: 20px; } button { background-color: #4CAF50; color: white; border: none; padding: 12px 30px; font-size: 1.2rem; border-radius: 10px; cursor: pointer; transition: all 0.3s; box-shadow: 0 4px 0 #3d8b40; } button:hover { background-color: #45a049; transform: translateY(2px); box-shadow: 0 2px 0 #3d8b40; } button:active { transform: translateY(4px); box-shadow: 0 0 0 #3d8b40; } .game-over { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); justify-content: center; align-items: center; z-index: 10; } .game-over-content { background-color: white; padding: 30px; border-radius: 15px; text-align: center; max-width: 400px; width: 90%; } .game-over h2 { color: #ff3333; margin-bottom: 20px; font-size: 2rem; } .final-score { font-size: 1.5rem; margin-bottom: 20px; } @media (max-width: 500px) { .game-board { grid-template-columns: repeat(2, 1fr); } h1 { font-size: 2rem; } } </style> </head> <body> <div class="game-container"> <h1>打地鼠小游戏</h1> <div class="game-info"> <div class="score">得分: <span id="score">0</span></div> <div class="timer">时间: <span id="time">30</span>秒</div> </div> <div class="game-board" id="gameBoard"> <!-- 地鼠洞将通过JavaScript生成 --> </div> <div class="controls"> <button id="startBtn">开始游戏</button> </div> </div> <div class="game-over" id="gameOver"> <div class="game-over-content"> <h2>游戏结束!</h2> <p class="final-score">你的得分: <span id="finalScore">0</span></p> <button id="restartBtn">再玩一次</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // 游戏元素 const gameBoard = document.getElementById('gameBoard'); const scoreDisplay = document.getElementById('score'); const timeDisplay = document.getElementById('time'); const startBtn = document.getElementById('startBtn'); const gameOverScreen = document.getElementById('gameOver'); const finalScoreDisplay = document.getElementById('finalScore'); const restartBtn = document.getElementById('restartBtn'); // 游戏变量 let score = 0; let timeLeft = 30; let gameActive = false; let timer; let moleTimer; // 创建地鼠洞 for (let i = 0; i < 9; i++) { const hole = document.createElement('div'); hole.className = 'hole'; const mole = document.createElement('div'); mole.className = 'mole'; mole.dataset.id = i; hole.appendChild(mole); gameBoard.appendChild(hole); // 添加点击事件 mole.addEventListener('click', hitMole); } const moles = document.querySelectorAll('.mole'); // 开始游戏 startBtn.addEventListener('click', startGame); // 重新开始游戏 restartBtn.addEventListener('click', function() { gameOverScreen.style.display = 'none'; startGame(); }); function startGame() { // 重置游戏状态 score = 0; timeLeft = 30; gameActive = true; scoreDisplay.textContent = score; timeDisplay.textContent = timeLeft; startBtn.disabled = true; // 清除所有活动的地鼠 moles.forEach(mole => { mole.classList.remove('up'); }); // 开始计时 timer = setInterval(function() { timeLeft--; timeDisplay.textContent = timeLeft; if (timeLeft <= 0) { endGame(); } }, 1000); // 开始地鼠出现 showRandomMole(); } function showRandomMole() { if (!gameActive) return; // 随机选择一个地鼠 const randomIndex = Math.floor(Math.random() * moles.length); const mole = moles[randomIndex]; // 显示地鼠 mole.classList.add('up'); // 设置地鼠消失的时间(0.5-2秒之间随机) const hideTime = Math.random() * 1500 + 500; setTimeout(() => { mole.classList.remove('up'); // 如果游戏还在进行中,继续显示下一个地鼠 if (gameActive) { showRandomMole(); } }, hideTime); } function hitMole(e) { if (!gameActive) return; // 确保点击的是地鼠而不是洞 if (e.target.classList.contains('up')) { // 增加分数 score++; scoreDisplay.textContent = score; // 播放点击效果 e.target.style.backgroundColor = '#ff3333'; setTimeout(() => { e.target.style.backgroundColor = '#8B4513'; }, 200); // 立即隐藏被点击的地鼠 e.target.classList.remove('up'); } } function endGame() { gameActive = false; clearInterval(timer); startBtn.disabled = false; // 显示游戏结束画面 finalScoreDisplay.textContent = score; gameOverScreen.style.display = 'flex'; } }); </script> </body> </html> )rawliteral"; void handleRoot() { // 发送HTTP响应,状态码200,内容类型为text/html server.send(200, "text/html", htmlContent); } void setup() { // 初始化串口,用于调试 Serial.begin(115200); Serial.println("Starting ESP32-C5 Web Server..."); // 设置ESP32为STA模式,连接手机热点 WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.print("Connecting to WiFi: "); Serial.println(ssid); // 等待连接,最多尝试20秒 int timeout = 20; while (WiFi.status() != WL_CONNECTED && timeout > 0) { delay(1000); Serial.print("."); timeout--; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi Connected"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // 打印STA模式的IP地址 } else { Serial.println("\nFailed to connect to WiFi. Check SSID/password or signal strength."); return; // 连接失败,停止后续操作 } // 设置Web服务器路由 server.on("/", handleRoot); server.onNotFound([]() { server.send(404, "text/plain", "404: Page Not Found"); }); // 启动服务器 server.begin(); Serial.println("HTTP Server Started"); } void loop() { // 处理客户端HTTP请求 server.handleClient(); delay(10); // 短暂延时以确保稳定性 } 3.1 查看效果 无论是电脑还是手机只要接入同一个热点网络,那么它就可以通过查看串口监视中的IP进行连接游玩。 ![]() ![]() 4 接下来的方向 我觉得可以搭建一个离线的小型服务器,这样学生的数据可以收集起来,方便老师统计。 比如学生的答题,只要学生提交数据,老师这边就可以得到学生反馈。 这有点类似学习平板的同步反馈。 或者做个本地游戏。多人竞技游戏,支持2-4个玩家同时游戏,每个玩家连接自己的设备,实时显示玩家排名。 这应该也是一个不错的方法。 |
沪公网安备31011502402448© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed