×

使用基于ESP32的Web服务器的互联网控制LED

消耗积分:2 | 格式:zip | 大小:0.54 MB | 2022-12-20

分享资料个

描述

项目概况

在这个例子中,我们将弄清楚如何制作一个基于 ESP32 的网络服务器来控制 LED 状态,它可以从世界任何地方访问。

我在这个项目中使用了 Mac 计算机,但您可以在任何可以运行 Arduino IDE 的计算机上执行此操作,即使是在像 Raspberry Pi 这样的廉价低功耗计算机上也是如此。

使用 Arduino IDE 准备 ESP32

为了开始使用 Arduino IDE 和 Arduino 编程语言对 ESP32 进行编程,您需要一个特殊的附加组件。通过以下链接了解如何在 Mac OS 上为 ESP32 准备 Arduino IDE

所需材料

对于本教程,您需要以下项目:

  • ESP32开发板
  • 5mm LED
  • 电阻220ohm
  • 带 I2C 模块的 16x2 LCD 显示屏
  • 面包板
  • 跳线
  • 微型 USB 数据线

构建电路

按照下面的示意图进行连接。

首先将 ESP32 和 GND 上的 3V3 电源电压输出连接到面包板上。使用 GPIO 引脚 23 作为数字输出引脚,通过电阻将 LED 连接到 ESP32。之后,将 16x2 LCD 显示器的 SDA 引脚连接到 GPIO 引脚 21,将 SCL 连接到 GPIO 引脚 22。

 
pYYBAGOhCIKAKlEUAALM8Pa4yXE350.jpg
毛边素描
 

SPIFFS 文件系统快速概览

SPIFFS全称是“Serial Peripheral Interface Flash File System”,即通过SPI传输数据的闪存文件系统。相应地,SPIFFS 是一种简化的文件系统,专为具有通过 SPI 总线传输数据的闪存芯片(例如 ESP32 闪存)的微控制器而设计。

在以下情况下,SPIFFS 最适合与 ESP32 一起使用:

  • 创建用于存储设置的文件。
  • 永久数据存储。
  • 创建文件来存储少量数据(而不是为此使用 microSD 卡)。
  • 存储用于创建 Web 服务器的 HTML 和 CSS 文件。

在 Mac OS 上安装 SPIFFS 引导加载程序

您可以直接使用 Arduino IDE 上的插件创建、保存和写入存储在 ESP32 文件系统中的文件。

首先,确保您安装了最新版本的 Arduino IDE,然后执行以下操作:

  • 打开以下链接并下载压缩包“ ESP32FS-1.0.zip”
  • 转到位于Documents文件夹中的 Arduino IDE 目录。创建一个tools文件夹(如果不存在)。在tools目录创建另一个文件夹ESP32FS。在ESP32FS内部创建另一个,称为tool
  • 将步骤 1 中下载的 ZIP 存档解压缩到工具文件夹中。
  • 重新启动您的 Arduino IDE。
  • 查看插件是否安装成功,打开Arduino IDE,点击“Tools”,查看该菜单中是否有“ESP32 Sketch Data Upload”项。
 
pYYBAGOhCJmALw9uAAJ0iDNjM_s912.png
 

安装库

ESPAsyncWebServer 和 AsyncTCP 库允许您使用 ESP32 文件系统中的文件创建 Web 服务器。有关这些库的更多信息,请查看以下链接

安装 ESPAsyncWebServer 库

  • 单击此处下载图书馆的 ZIP 存档。
  • 解压缩此存档。您应该获得 ESPAsyncWebServer-master 文件夹。
  • 将其重命名为“ESPAsyncWebServer”。

安装 AsyncTCP 库

  • 单击此处下载图书馆的 ZIP 存档。
  • 解压缩此存档。您应该获得 AsyncTCP-master 文件夹。
  • 将其重命名为“AsyncTCP”。

将 ESPAsyncWebServer 和 AsyncTCP 文件夹移动到位于Documents目录内的库文件夹中。

最后,重启 Arduino IDE。

使用以下内容创建一个 index.html 文件

切换按钮的 HTML/CSS 模板取自以下来源另外创建了两个 JS 脚本。第一个在显示 HTML 页面之前检查 LED 的当前状态。第二个用于通过更改复选框的状态来更改 LED 的状态。

html>
<html>
<head>

<title>Internet controlled LED using ESP32 based web servertitle>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" type="text/css" href="style.css">

// Verify the current status of LED
<script type="text/javascript">
    document.addEventListener("DOMContentLoaded", function(event) {
    var button_text = "";
    button_text = document.getElementById("status").innerHTML;
    if (button_text == "ON") {
        document.getElementById("switch1").checked = true;
    }
    else if (button_text == "OFF") {
        document.getElementById("switch1").checked = false;
    }
});
script>

// Change the state of LED   
<script type="text/javascript">
    function fun1()
    {
    var text = document.getElementById("status").innerHTML;
    var chbox=document.getElementById("switch1");
        if (chbox.checked == true && text == "OFF") {
            window.location.pathname = '/on';
            chbox.checked = true;
        }
        else
        {
            window.location.pathname = '/off';
            chbox.checked = false;
        }
    }
script>
head>

<body >
    <h1>Internet controlled LED using ESP32 based web server <div id="status" style = "display: none;">%STATE%div>h1>
        <span class="switch">
            <span class="switch-border1">
                <span class="switch-border2">
                    <input id="switch1" type="checkbox" onclick="fun1()"/>
                    <label for="switch1">label>
                    <span class="switch-top">span>
                    <span class="switch-shadow">span>
                    <span class="switch-handle">span>
                    <span class="switch-handle-left">span>
                    <span class="switch-handle-right">span>
                    <span class="switch-handle-top">span>
                    <span class="switch-handle-bottom">span>
                    <span class="switch-handle-base">span>
                    <span class="switch-led switch-led-green">
                        <span class="switch-led-border">
                            <span class="switch-led-light">
                                <span class="switch-led-glow">span>
                            span>
                        span>
                    span>
                    <span class="switch-led switch-led-red">
                        <span class="switch-led-border">
                            <span class="switch-led-light">
                                <span class="switch-led-glow">span>
                            span>
                        span>
                    span>
                span>
            span>
        span>
body>
html>

使用以下内容创建一个 style.css 文件

body {
    font-family: arial, verdana, sans-serif;
    font-size: 8px;
    background: #1E1E20;
    text-align: center;
}
h1{
    color: white;
    font-size:30px;
}
.switch {
    display: inline-block;
    margin: 10em 2em;
    position: relative;
    border-radius: 3.5em;
    -webkit-box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
    -moz-box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
    box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
}
.switch label {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
}
.switch input {
    display: none;
}
.switch span {
    display: block;
    -webkit-transition: top 0.2s;
    -moz-transition: top 0.2s;
    -ms-transition: top 0.2s;
    -o-transition: top 0.2s;
    transition: top 0.2s;
}
.switch-border1 {
    border: 0.1em solid #000;
    border-radius: 3.5em;
    -webkit-box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
    -moz-box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
    box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
}
.switch-border2 {
    width: 6.6em;
    height: 12.6em;
    position: relative;
    border: 0.1em solid #323232;
    background-image: -webkit-gradient(linear, left top, right top, from(#2D2D2D), color-stop(0.5, #4B4B4B), to(#2D2D2D));
    background-image: -webkit-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -moz-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -ms-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -o-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: linear-gradient(to right, #2D2D2D, #4B4B4B, #2D2D2D);
    border-radius: 3.4em;
}
.switch-border2:before,
.switch-border2:after {
    content: '';
    display: block;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0;
    opacity: .3;
    border-radius: 3.4em;
}
.switch-border2:before {
    background: -webkit-gradient(linear, left top, left bottom, from(#000), to(rgba(0,0,0,0)));
    background: -webkit-linear-gradient(#000, rgba(0,0,0,0));
    background: -moz-linear-gradient(#000, rgba(0,0,0,0));
    background: -ms-linear-gradient(#000, rgba(0,0,0,0));
    background: -o-linear-gradient(#000, rgba(0,0,0,0));
    background: linear-gradient(#000, rgba(0,0,0,0));
}
.switch-border2:after {
    background: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(#000));
    background: -webkit-linear-gradient(rgba(0,0,0,0), #000);
    background: -moz-linear-gradient(rgba(0,0,0,0), #000);
    background: -ms-linear-gradient(rgba(0,0,0,0), #000);
    background: -o-linear-gradient(rgba(0,0,0,0), #000);
    background: linear-gradient(rgba(0,0,0,0), #000);
}
.switch-top {
    width: 100%;
    height: 84%;
    position: absolute;
    top: 8%;
    left: 0;
    z-index: 1;
    background-image: -webkit-gradient(linear, left top, right top, from(#2D2D2D),             color-stop(0.5, #4B4B4B), to(#2D2D2D));
    background-image: -webkit-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -moz-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -ms-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: -o-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
    background-image: linear-gradient(to right, #2D2D2D, #4B4B4B, #2D2D2D);
    border-radius: 3.4em;
}
.switch-shadow {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    border-radius: 3.4em;
    -webkit-box-shadow: 0 0 2em black inset;
    -moz-box-shadow: 0 0 2em black inset;
    box-shadow: 0 0 2em black inset;
}
.switch-handle-left,
    .switch-handle-right {
    content: '';
    display: block;
    width: 3.6em;
    height: 0;
    position: absolute;
    top: 6.6em;
    z-index: 2;
    border-bottom: 4.5em solid #111;
    border-left: 0.7em solid transparent;
    border-right: 0.7em solid transparent;
    border-radius: 0;
}
.switch-handle-left {
    left: 0.8em;
}
.switch-handle-right {
    right: 0.8em;
}
.switch-handle {
    width: 3.6em;
    height: 4.5em;
    position: absolute;
    top: 6.6em;
    left: 1.5em;
    z-index: 3;
    background: #333;
    background-image: -webkit-gradient(linear, left top, right top, from(#111), color-stop(0.4, #777), color-stop(0.5, #888), color-stop(0.6, #777), to(#111));
    background-image: -webkit-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -moz-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -ms-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -o-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: linear-gradient(to right, #111, #777 40%, #888, #777 60%, #111);
    border-radius: 0;
}
.switch-handle-top {
    width: 5em;
    height: 5em;
    position: absolute;
    top: 8.5em;
    left: 0.8em;
    z-index: 4;
    background-color: #555;
    background-image: -webkit-gradient(linear, left top, right top, from(#5F5F5F), to(#878787));
    background-image: -webkit-linear-gradient(left, #5F5F5F, #878787);
    background-image: -moz-linear-gradient(left, #5F5F5F, #878787);
    background-image: -ms-linear-gradient(left, #5F5F5F, #878787);
    background-image: -o-linear-gradient(left, #5F5F5F, #878787);
    background-image: linear-gradient(to right, #5F5F5F, #878787);
    border-top: 0.2em solid #AEB2B3;
    border-radius: 2.5em;
}
.switch-handle-bottom {
    width: 3.6em;
    height: 3.6em;
    position: absolute;
    top: 4.7em;
    left: 1.5em;
    z-index: 3;
    background: #333;
    background-image: -webkit-gradient(linear, left top, right top, from(#111), color-stop(0.4, #777), color-stop(0.5, #888), color-stop(0.6, #777), to(#111));
    background-image: -webkit-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -moz-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -ms-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: -o-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
    background-image: linear-gradient(to right, #111, #777 40%, #888, #777 60%, #1    11);
    border-top: 0.2em solid #141414;
    border-radius: 1.8em;
}
.switch-handle-base {
    width: 4.2em;
    height: 4.2em;
    position: absolute;
    top: 3.8em;
    left: 1.2em;
    z-index: 2;
    border-top: 0.2em solid rgba(255,255,255,0.35);
    border-radius: 2.1em;
    -webkit-box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
    -moz-box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
    box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
}
.switch-led {
    position: absolute;
    left: 2em;
    border-radius: 1.4em;
}
.switch-led-border {
    border: 0.2em solid black;
    border-radius: 1.3em;
}
.switch-led-light {
    border-radius: 1.1em;
    -webkit-box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
    -moz-box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
    box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
}
.switch-led-glow {
    width: 2em;
    height: 2em;
    position: relative;
    border-radius: 1em;
}
.switch-led-glow:before {
    content: '';
    display: block;
    width: 0.6em;
    height: 0.6em;
    position: absolute;
    top: 0.3em;
    left: 0.7em;
    background: rgba(255,255,255,0.2);
    border-radius: 0.3em;
    -webkit-box-shadow: 0 0 1em rgba(255,255,255,0.75);
    -moz-box-shadow: 0 0 1em rgba(255,255,255,0.75);
    box-shadow: 0 0 1em rgba(255,255,255,0.75);
}
.switch-led-glow:after {
    content: '';
    display: block;
    width: 0;
    height: 0;
    position: absolute;
    top: 0;
    left: 0;
    opacity: 0.2;
    filter: alpha(opacity=20);
    border: 1em solid #fff;
    border-color: transparent #fff transparent #fff;
    border-radius: 1em;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -o-transform: rotate(45deg);
    transform: rotate(45deg);
}
.switch-led:after {
    display: block;
    width: 100%;
    position: absolute;
    left: 0;
    color: #666;
    font-family: arial, verdana, sans-serif;
    font-weight: bold;
    text-align: center;
    text-shadow: 0 0.1em rgba(0,0,0,0.7);
}
.switch-led-green:after {
    content: 'ON';
    top: -1.8em;
}
.switch-led-red:after {
    content: 'OFF';
    bottom: -1.8em;
}
.switch-led-green {
    top: -5em;
    border-top: 0.1em solid rgba(0,161,75,0.5);
    border-bottom: 0.1em solid rgba(255,255,255,0.25);
}
.switch-led-green .switch-led-light {
    background: rgb(0,161,75);
    border: 0.1em solid rgb(0,104,56);
}
.switch-led-red {
    bottom: -5em;
    border-top: 0.1em solid rgba(237,28,36,0.2);
    border-bottom: 0.1em solid rgba(255,255,255,0.25);
    -webkit-box-shadow: 0 0 3em rgb(237,28,36);
    -moz-box-shadow: 0 0 3em rgb(237,28,36);
    box-shadow: 0 0 3em rgb(237,28,36);
}
.switch-led-red .switch-led-light {
    background: rgb(237,28,36);
    border: 0.1em solid rgb(161,30,45);
}
.switch-led-red .switch-led-glow {
    background: #fff;
    background: rgba(255, 255, 255, 0.3);
    filter: alpha(opacity=30);
}
/* Switch on */
.switch input:checked~.switch-handle-left, .switch input:checked~.switch-handle-right {
    top: 1.5em;
    border-bottom: 0;
    border-top: 4.5em solid #111;
}
.switch input:checked~.switch-handle {
    top: 1.5em;
}
.switch input:checked~.switch-handle-top  {
    top: -1em;
    border-top: 0;
    border-bottom: 0.2em solid #AEB2B3;
}
.switch input:checked~.switch-handle-bottom {
    top: 4.2em;
    border-top: 0;
    border-bottom: 0.2em solid #141414;
}
.switch input:checked~.switch-handle-base {
    top: 4.5em;
    border-top: 0;
    border-bottom: 0.2em solid rgba(255,255,255,0.35);
}
.switch input:checked~.switch-led-green {
    -webkit-box-shadow: 0 0 3em rgb(0,161,75);
    -moz-box-shadow: 0 0 3em rgb(0,161,75);
    box-shadow: 0 0 3em rgb(0,161,75);
}
.switch input:checked~.switch-led-green .switch-led-glow {
    background: #fff;
    background: rgba(255, 255, 255, 0.4);
    filter: alpha(opacity=40);
}
.switch input:checked~.switch-led-red {
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
}
.switch input:checked~.switch-led-red .switch-led-glow {
    background: rgba(255, 255, 255, 0);
    filter: alpha(opacity=0);
}

Arduino代码

主要是,代码基于使用 SPIFFS 从 ESP32 Web 服务器获取的 Arduino 代码和如何在 Arduino IDE 上使用带 ESP32 的 I2C LCD

// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"
#include 

// Replace with your network credentials
const char* ssid = "YourNetworkName";
const char* password = "YourPassword";

// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;

// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);

// Set LED GPIO
const int ledPin = 23;

// Stores LED state
String ledState;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Replaces placeholder with LED state value
String processor(const String& var){
    Serial.println(var);
    if(var == "STATE"){
        if(digitalRead(ledPin)){
            ledState = "ON";
        }
    else{
        ledState = "OFF";
        }
        Serial.print(ledState);
        return ledState;
    }
return String();
}
void setup(){

// initialize LCD
    lcd.init();

// turn on LCD backlight
    lcd.backlight();

// Serial port for debugging purposes

Serial.begin(115200);
    pinMode(ledPin, OUTPUT);

// Initialize SPIFFS file server 
    if(!SPIFFS.begin(true)){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
    }

// Connect to Wi-Fi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi..");
    }

// Print IP address of web server on serial interface
    Serial.println(WiFi.localIP());

// Print IP address of web server on LCD display
    lcd.setCursor(0, 0);
    lcd.print("IP address is ");
    lcd.setCursor(0, 1);
    lcd.print(WiFi.localIP());

// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", String(), false, processor);
});

// Route to load style.css file
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/style.css", "text/css");
});

// Route to set GPIO to HIGH
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, HIGH);
    request->send(SPIFFS, "/index.html", String(), false, processor);
});

// Route to set GPIO to LOW
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, LOW);
    request->send(SPIFFS, "/index.html", String(), false, processor);
});

// Start server
    server.begin();
}

void loop(){
}

使用 SPIFFS 加载器上传 arduino 代码和文件

  • 打开 Arduino 代码的 sketch 文件夹。
  • 在此文件夹中,创建一个名为“data”的新文件夹。
  • 在数据文件夹中,您需要放置index.htmlstyle.css。
  • 上传Arduino代码
  • 然后,要上传文件,请单击“工具”>“ESP32 草图数据上传”上的 Arduino IDE

测试本地网络服务器

确定ESP32 web服务器IP地址,可以通过两种方式找到。

  • Arduino IDE 上的串口监视器(工具 > 串口监视器)
 
poYBAGOhCKqAfgk9AAN70OhPUC8188.png
 
  • 液晶显示
 
poYBAGOhCOKALPRHAAjTzri-3Zo867.jpg
 

接下来,打开您选择的 Web 浏览器并将以下 IP 地址粘贴到地址栏中。你应该得到类似于下面截图的输出。

 
pYYBAGOhCOeAVlhwAABzx6Z0FIA570.png
从 ESP32 文件系统提供 HTML 内容。
 

使用 Ngrok 从世界任何地方访问本地 Web 服务器

Ngrok 是一个平台,允许您组织从外部互联网远程访问 Web 服务器或在您的 PC 上运行的某些其他服务。通过在 ngrok 开始时创建的安全隧道组织访问。

  • 点击此链接并注册。
  • 创建帐户后,登录并转到“身份验证”选项卡。复制“您的隧道授权令牌”字段中的行。
  • 单击导航栏中的“下载”选项卡。
  • 选择与您的操作系统匹配的 ngrok 版本并下载。
  • 解压缩下载的文件夹并运行命令行。
  • 通过输入以下命令连接您的帐户
./ngrok authtoken <YOUR_AUTH_TOKEN>
  • 在端口 80 上启动 HTTP 隧道
./ngrok http Your_IP_Address:80

如果一切都正确完成,那么隧道状态应该变为“在线”,并且重定向链接应该出现在“转发”列中。通过将此链接输入浏览器,您可以从世界任何地方访问网络服务器。

 
poYBAGOhCPOAVJjCAAE0r9Rxr08493.png
 

我希望您发现本指南有用,并感谢阅读。我已经向您展示了一个控制 LED 的简单示例,但是您可以通过将 LED 替换为您想要控制的另一个输出(例如继电器)来使任务复杂化。

如果您有任何问题或反馈?在下面发表评论。如果你喜欢这篇文章,请订阅我的博客来支持我。感谢大家的赞许!


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !