ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

释放双眼,带上耳机,听听看~!

本教程展示了如何构建一个 ESP32 Web 服务器,该服务器显示一个带有多个滑块的网页。滑块控制不同 PWM 通道的占空比,以控制多个 LED 的亮度。您可以使用此项目可以替换 LED 来控制需要 PWM 信号的直流电机或其它执行器。客户端和 ESP32 之间的通信是使用 WebSocket 协议完成的。此外,只要有变化,所有客户端都会同时更新其滑块值。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

您还可以修改本教程中提供的代码,将滑块添加到您的项目中,以设置阈值或您需要在代码中使用的任何其它值。

对于这个项目,ESP32 板将使用 Arduino 内核进行编程。您可以使用Arduino IDE或任何其它合适的 IDE。

* 该项目展示了如何使用一个滑块构建 Web 服务器,但它使用 HTTP 请求——在本教程中,我们将使用 WebSocket 协议。

项目概况

下图显示了我们将为这个项目构建的网页:

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)
  • 网页包含三张卡片;
  • 每张卡片都有一段显示卡片标题(Fader 1、Fader 2、Fader 3);
  • 每张卡中都有一个范围滑块,您可以移动它来设置相应 LED 的亮度;
  • 在每张卡片中,另一段显示当前 LED 亮度(百分比);
  • 当您为滑块设置新位置时,它会更新所有客户端(如果您打开了多个 Web 浏览器选项卡(或多个设备),它们几乎会在发生更改时同时更新)。

这个怎么运作?

  • ESP 托管一个 Web 服务器,该服务器显示一个带有三个滑块的网页;
  • 当您为滑块设置新位置时,客户端通过 WebSocket 协议将滑块编号和滑块值发送到服务器。例如,如果您将滑块编号 3 设置为位置编号 40,它将发送此消息3s40到服务器。
ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)
  • 服务器 (ESP) 接收滑块编号和相应的值,并相应地调整 PWM 占空比。此外,它还用新的当前滑块值通知所有其它客户端——这使我们几乎可以立即更新所有客户端。
ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)
  • ESP32 输出具有相应占空比的 PWM 信号来控制 LED 亮度。占空比为 0% 表示 LED 完全关闭,占空比为 50% 表示 LED 半亮,占空比为 100% 表示 LED 全亮;
ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)
  • 每当您打开一个新的 Web 浏览器窗口(这是新客户端连接时),它都会向 ESP32(也通过 WebSocket 协议)发送一条消息,其中包含该消息获取值. 当 ESP32 收到此消息时,它会发送当前滑块值。这样,每当您打开一个新选项卡时,它总是显示当前和更新的值。
ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

先决条件

在继续本教程之前,请确保检查以下所有先决条件。

1) 所需零件

要关注这个项目,您需要:

  • ESP32开发板
  • 3x LED
  • 3x 220Ohm 电阻
  • 面包板
  • 连接线

如果没有三个 LED 来测试这个项目,也可以简单地在串行监视器中查看结果或使用其它需要 PWM 信号才能运行的执行器。

2) Arduino IDE 和 ESP32 开发板插件

我们将使用 Arduino IDE 对 ESP32 进行编程。因此,您必须安装 ESP32 插件。如果您还没有,请按照下一个教程:

一、ESP32开发环境搭建(arduino)

3) 文件系统上传插件

要将构建此项目所需的 HTML、CSS 和 JavaScript 文件上传到 ESP32 闪存 (SPIFFS),我们将使用 Arduino IDE 插件:  SPIFFS  Filesystem uploader。如果您还没有安装文件系统上传器插件,请按照下一个教程安装:

4) 库

要构建此项目,您需要安装以下库:

您可以使用 Arduino Library Manager 安装第一个库。转到 Sketch  >  Include Library  >  Manage Libraries 并搜索库名称。

这ESPAsyncWebServer和异步TCP库无法通过 Arduino Library Manager 安装,因此您需要将库文件复制到 Arduino Installation Libraries 文件夹。或者,在您的 Arduino IDE 中,您可以转到 Sketch >  Include Library  >  Add .zip Library 并选择您刚刚下载的库。

原理图

将三个 LED 连接到 ESP32。我们正在使用 GPIO 12、13 和 14。您可以使用任何其它合适的 GPIO。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

推荐阅读:  ESP32 Pinout Reference:您应该使用哪些 GPIO 引脚?

组织你的文件

为了使项目井井有条并更容易理解,我们将创建四个文件来构建 Web 服务器:

  • 处理 Web 服务器的Arduino 程序;
  • index.html:定义网页的内容;
  • sytle.css:设置网页样式;
  • script.js:对网页的行为进行编程——处理当你移动滑块时发生的事情,发送、接收和解释通过 WebSocket 协议接收到的消息。
ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

您应该将 HTML、CSS 和 JavaScript 文件保存在 Arduino 程序文件夹中名为 data 的文件夹中,如上图所示。我们会将这些文件上传到 ESP32 文件系统 (SPIFFS)。

您可以下载所有项目文件:

HTML 文件

将以下内容复制到index.html文件。

<!DOCTYPE html>
<html>
<head>
    <title>ESP IOT DASHBOARD</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/png" href="favicon.png">
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <div class="topnav">
        <h1>Multiple Sliders</h1>
    </div>
    <div class="content">
        <div class="card-grid">
            <div class="card">
                <p class="card-title">Fader 1</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider1" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue1"></span> &percnt;</p>
            </div>
            <div class="card">
                <p class="card-title"> Fader 2</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider2" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue2"></span> &percnt;</p>
            </div>
            <div class="card">
                <p class="card-title"> Fader 3</p>
                <p class="switch">
                    <input type="range" onchange="updateSliderPWM(this)" id="slider3" min="0" max="100" step="1" value ="0" class="slider">
                </p>
                <p class="state">Brightness: <span id="sliderValue3"></span> &percnt;</p>
            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

 

让我们快速浏览一下 HTML 文件中最相关的部分。

创建滑块

以下标签为第一个滑块(Fader 1)创建卡片。

<div class="card">
  <p class="card-title">Fader 1</p>
  <p class="switch">
    <input type="range" onchange="updateSliderPWM(this)" id="slider1" min="0" max="100" step="1" value ="0" class="slider">
  </p>
  <p class="state">Brightness: <span id="sliderValue1"></span> &percnt;</p>
</div>

第一段显示卡片的标题(Fader 1)。您可以将文本更改为您想要的任何内容。

<p class="card-title">Fader 1</p>

要在 HTML 中创建滑块,请使用<input>标签。这<input>标签指定用户可以输入数据的字段。

输入类型多种多样。要定义滑块,请使用类型属性与范围。在滑块中,您还需要使用分钟和最大限度属性(在这种情况下,0和100, 分别)。

您还需要定义其它属性,例如:

  • 这步属性指定有效数字之间的间隔。在我们的例子中,我们将其设置为1;
  • 这班级设置滑块样式(class=“switch”);
  • 这ID这样我们就可以使用 JavaScript (id=”slider1″);
  • 这改变调用函数的属性(updateSliderPWM(this)) 当您为滑块设置新位置时。此函数(在 JavaScript 文件中定义)通过 WebSocket 协议将当前滑块值发送到客户端。这这个关键字是指 HTML 滑块元​​素。

滑块位于带有switch名称。所以,这里是实际创建滑块的标签。

<p class="switch">
  <input type="range" onchange="updateSliderPWM(this)" id="slider1" min="0" max="100" step="1" value ="0" class="slider">
</p>

最后,有一段带有<span>标记,以便我们可以通过引用其 id (id=”sliderValue1″)。

<p class="state">Brightness: <span id="sliderValue1"></span> &percnt;</p>

创建更多滑块

要创建更多滑块,您需要复制创建完整卡片的所有 HTML 标记。但是,首先,您需要考虑每个滑块和滑块值都需要一个唯一的 id。在我们的例子中,我们有三个具有以下 id 的滑块:滑块1,滑块2,滑块3,以及具有以下 id 的滑块值的三个占位符:Fader1,Fader2,Fader3.

例如,这是 2 号滑块的卡片。

<div class="card">
  <p class="card-title"> Fader 2</p>
  <p class="switch">
    <input type="range" onchange="updateSliderPWM(this)" id="slider2" min="0" max="100" step="1" value ="0" class="slider">
  </p>
  <p class="state">Brightness: <span id="sliderValue2"></span> &percnt;</p>
</div>

CSS 文件

将以下内容复制到style.css文件。

html {
    font-family: Arial, Helvetica, sans-serif;
    display: inline-block;
    text-align: center;
  }
  h1 {
    font-size: 1.8rem;
    color: white;
  }
  p {
    font-size: 1.4rem;
  }
  .topnav {
    overflow: hidden;
    background-color: #0A1128;
  }
  body {
    margin: 0;
  }
  .content {
    padding: 30px;
  }
  .card-grid {
    max-width: 700px;
    margin: 0 auto;
    display: grid;
    grid-gap: 2rem;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }
  .card {
    background-color: white;
    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
  }
  .card-title {
    font-size: 1.2rem;
    font-weight: bold;
    color: #034078
  }
  .state {
    font-size: 1.2rem;
    color:#1282A2;
  }
  .slider {
    -webkit-appearance: none;
    margin: 0 auto;
    width: 100%;
    height: 15px;
    border-radius: 10px;
    background: #FFD65C;
    outline: none;
  }
  .slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #034078;
    cursor: pointer;
  }
  .slider::-moz-range-thumb {
    width: 30px;
    height: 30px;
    border-radius: 50% ;
    background: #034078;
    cursor: pointer;
  }
  .switch {
    padding-left: 5%;
    padding-right: 5%;
  }

 

让我们快速浏览一下设置滑块样式的 CSS 文件的相关部分。在此示例中,我们需要使用供应商前缀外貌属性。

.slider {
  -webkit-appearance: none;
  margin: 0 auto;
  width: 100%;
  height: 15px;
  border-radius: 10px;
  background: #FFD65C;
  outline: none;
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #034078;
  cursor: pointer;
}
.slider::-moz-range-thumb {
  width: 30px;
  height: 30px;
  border-radius: 50% ;
  background: #034078;
  cursor: pointer;
}
.switch {
  padding-left: 5%;
  padding-right: 5%;
}

Vendor前缀

Vendor前缀允许浏览器在新的 CSS 功能被完全支持之前支持它们。最常用的浏览器使用以下前缀:

  • -webkit- Chrome、Safari、较新版本的 Opera、几乎所有 iOS 浏览器、
  • -moz- 火狐,
  • -o-  Opera 的旧版本,
  • -ms- Microsoft Edge 和 Internet Explorer。

Vendor前缀是临时的。一旦您使用的浏览器完全支持这些属性,您就不需要它们了。您可以使用以下参考来检查您使用的属性是否需要前缀:http ://shouldprefix.com/

让我们来看看.滑块选择器(设置滑块本身的样式):

.slider {
  -webkit-appearance: none;
  margin: 0 auto;
  width: 100%;
  height: 15px;
  border-radius: 10px;
  background: #FFD65C;outline: none;
}

环境-webkit-外观至没有任何覆盖应用于 Google Chrome、Safari 和 Android 浏览器中滑块的默认 CSS 样式。

-webkit-appearance: none;

设置-webkit-appearance为none 自动在其父容器内对齐滑块。

margin: 0 auto;

滑块的宽度设置为100%和高度为15像素。 边界半径被设定为10像素.

margin: 0 auto;
width: 100%;
height: 15px;
border-radius: 10px;

设置滑块的背景颜色并设置outline为none.

background: #FFD65C;
outline: none;

然后,格式化滑块手柄。利用-webkit-适用于 Chrome、Opera、Safari 和 Edge 网络浏览器和-moz-对于火狐。

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #034078;
  cursor: pointer;
}
.slider::-moz-range-thumb {
  width: 30px;
  height: 30px;
  border-radius: 50% ;
  background: #034078;
  cursor: pointer;
}

设置-webkit-外观和外貌属性没有任何覆盖默认属性。

-webkit-appearance: none;
appearance: none;

设置一个具体的宽度,高度和边界半径的处理程序。使用 a标签 设置相同的宽度和高度边界半径的50%的圆圈。

width: 30px;
height: 30px;
border-radius: 50%;

然后,设置背景颜色并设置光标到一个指针.

background: #034078;
cursor: pointer;

随意使用滑块属性给它一个不同的外观。

JavaScript 文件

将以下内容复制到script.js文件。

var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onload);

function onload(event) {
    initWebSocket();
}

function getValues(){
    websocket.send("getValues");
}

function initWebSocket() {
    console.log('Trying to open a WebSocket connection…');
    websocket = new WebSocket(gateway);
    websocket.onopen = onOpen;
    websocket.onclose = onClose;
    websocket.onmessage = onMessage;
}

function onOpen(event) {
    console.log('Connection opened');
    getValues();
}

function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
}

function updateSliderPWM(element) {
    var sliderNumber = element.id.charAt(element.id.length-1);
    var sliderValue = document.getElementById(element.id).value;
    document.getElementById("sliderValue"+sliderNumber).innerHTML = sliderValue;
    console.log(sliderValue);
    websocket.send(sliderNumber+"s"+sliderValue.toString());
}

function onMessage(event) {
    console.log(event.data);
    var myObj = JSON.parse(event.data);
    var keys = Object.keys(myObj);

    for (var i = 0; i < keys.length; i++){
        var key = keys[i];
        document.getElementById(key).innerHTML = myObj[key];
        document.getElementById("slider"+ (i+1).toString()).value = myObj[key];
    }
}

 

以下是这段代码的作用列表:

  • 初始化与服务器的 WebSocket 连接;
  • 向服务器发送消息以获取当前滑块值;
  • 使用响应更新网页上的滑块值;
  • 通过 WebSocket 协议处理数据交换。

让我们看一下这段 JavaScript 代码,看看它是如何工作的。

网关是 WebSocket 接口的入口点。window.location.hostname获取当前页面地址(Web 服务器 IP 地址)。

var gateway = ws://${window.location.hostname}/ws;

创建一个名为的新全局变量网络套接字.

var websocket;

添加一个事件监听器,它将调用负载网页加载时的功能。

window.addEventListener('load', onload);

这onload()函数调用初始化WebSocket()初始化与服务器的 WebSocket 连接的函数。

function onload(event) {
  initWebSocket();
}

这initWebSocket()函数在前面定义的网关上初始化 WebSocket 连接。我们还为打开、关闭 WebSocket 连接或接收到消息时分配了几个回调函数。

function initWebSocket() {
  console.log('Trying to open a WebSocket connection…');
  websocket = new WebSocket(gateway);
  websocket.onopen = onOpen;
  websocket.onclose = onClose;
  websocket.onmessage = onMessage;
}

请注意,当 websocket 连接打开时,我们将调用获取值功能。

function onOpen(event) {
  console.log('Connection opened');
  getValues();
}

这getStates()函数向服务器发送消息获取值获取所有滑块的当前值。然后,我们必须处理在服务器端(ESP32)收到该消息时发生的情况。

function getStates(){
  websocket.send("getValues");
}

我们处理通过 websocket 协议收到的消息onMessage()功能。

function onMessage(event) {
  console.log(event.data);
  var myObj = JSON.parse(event.data);
  var keys = Object.keys(myObj);

  for (var i = 0; i < keys.length; i++){
    var key = keys[i];
    document.getElementById(key).innerHTML = myObj[key];
    document.getElementById("slider"+ (i+1).toString()).value = myObj[key];
  }
}

服务器以 JSON 格式发送状态,例如:

{
  sliderValue1 : 20;
  sliderValue2: 50;
  sliderValue3: 0;
}

这onMessage()函数简单地遍历所有值并将它们放置在 HTML 页面上的相应位置。

当您移动滑块更新时,PWM()函数会运行。

function updateSliderPWM(element) {
  var sliderNumber = element.id.charAt(element.id.length-1);
  var sliderValue = document.getElementById(element.id).value;
  document.getElementById("sliderValue"+sliderNumber).innerHTML = sliderValue;
  console.log(sliderValue);
  websocket.send(sliderNumber+"s"+sliderValue.toString());
}

此函数从滑块中获取值并使用正确的值更新相应的段落。此函数还会向服务器发送消息,以便 ESP32 更新 LED 亮度。

websocket.send(sliderNumber+"s"+sliderValue.toString());

消息以以下格式发送:

  • 滑块编号s滑块值

例如,如果您将 3 号滑块移动到位置 40,它将发送以下消息:

3s40

Arduino程序

将以下代码复制到您的 Arduino IDE  中

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "SPIFFS.h"
#include <Arduino_JSON.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

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

AsyncWebSocket ws("/ws");
// Set LED GPIO
const int ledPin1 = 12;
const int ledPin2 = 13;
const int ledPin3 = 14;

String message = "";
String sliderValue1 = "0";
String sliderValue2 = "0";
String sliderValue3 = "0";

int dutyCycle1;
int dutyCycle2;
int dutyCycle3;

// setting PWM properties
const int freq = 5000;
const int ledChannel1 = 0;
const int ledChannel2 = 1;
const int ledChannel3 = 2;

const int resolution = 8;

//Json Variable to Hold Slider Values
JSONVar sliderValues;

//Get Slider Values
String getSliderValues(){
  sliderValues["sliderValue1"] = String(sliderValue1);
  sliderValues["sliderValue2"] = String(sliderValue2);
  sliderValues["sliderValue3"] = String(sliderValue3);

  String jsonString = JSON.stringify(sliderValues);
  return jsonString;
}

// Initialize SPIFFS
void initFS() {
  if (!SPIFFS.begin()) {
    Serial.println("An error has occurred while mounting SPIFFS");
  }
  else{
   Serial.println("SPIFFS mounted successfully");
  }
}

// Initialize WiFi
void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}

void notifyClients(String sliderValues) {
  ws.textAll(sliderValues);
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    message = (char*)data;
    if (message.indexOf("1s") >= 0) {
      sliderValue1 = message.substring(2);
      dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle1);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (message.indexOf("2s") >= 0) {
      sliderValue2 = message.substring(2);
      dutyCycle2 = map(sliderValue2.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle2);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }    
    if (message.indexOf("3s") >= 0) {
      sliderValue3 = message.substring(2);
      dutyCycle3 = map(sliderValue3.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle3);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (strcmp((char*)data, "getValues") == 0) {
      notifyClients(getSliderValues());
    }
  }
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %sn", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnectedn", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}


void setup() {
  Serial.begin(115200);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  initFS();
  initWiFi();

  // configure LED PWM functionalitites
  ledcSetup(ledChannel1, freq, resolution);
  ledcSetup(ledChannel2, freq, resolution);
  ledcSetup(ledChannel3, freq, resolution);

  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin1, ledChannel1);
  ledcAttachPin(ledPin2, ledChannel2);
  ledcAttachPin(ledPin3, ledChannel3);


  initWebSocket();
  
  // Web Server Root URL
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });
  
  server.serveStatic("/", SPIFFS, "/");

  // Start server
  server.begin();

}

void loop() {
  ledcWrite(ledChannel1, dutyCycle1);
  ledcWrite(ledChannel2, dutyCycle2);
  ledcWrite(ledChannel3, dutyCycle3);

  ws.cleanupClients();
}

 

代码如何运作

让我们快速浏览一下这个项目的相关部分。

在以下变量中插入您的WIFI网络凭据以将 ESP32 连接到您的本地网络:

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

getSliderValues()函数使用当前滑块值创建一个 JSON 字符串。

String getSliderValues(){
  sliderValues["sliderValue1"] = String(sliderValue1);
  sliderValues["sliderValue2"] = String(sliderValue2);
  sliderValues["sliderValue3"] = String(sliderValue3);

  String jsonString = JSON.stringify(sliderValues);
  return jsonString;
}

notifyClients()函数用当前滑块值通知所有客户端。每当您为滑块设置新位置时,调用此函数允许我们通知所有客户端的更改。

void notifyClients(String sliderValues) {
  ws.textAll(sliderValues);
}

handleWebSocketMessage(),顾名思义,处理服务器通过 WebSocket 协议从客户端接收消息时发生的事情。我们在 JavaScript 文件中看到,服务器可以接收获取值消息或带有滑块编号和滑块值的消息。

当它收到获取值消息,它发送当前的滑块值。

if (strcmp((char*)data, "getValues") == 0) {
  notifyClients(getSliderValues());
}

如果它收到另一条消息,我们检查哪个滑块对应于该消息并更新相应的占空比值。最后,我们通知所有客户发生了变化。这是滑块 1 的示例:

if (message.indexOf("1s") >= 0) {
  sliderValue1 = message.substring(2);
  dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 255);
  Serial.println(dutyCycle1);
  Serial.print(getSliderValues());
  notifyClients(getSliderValues());
}

在 loop()函数里面 ,我们更新 PWM 通道的占空比来调整 LED 的亮度。

void loop() {
  ledcWrite(ledChannel1, dutyCycle1);
  ledcWrite(ledChannel2, dutyCycle2);
  ledcWrite(ledChannel3, dutyCycle3);

  ws.cleanupClients();
}

上传代码和文件

插入网络凭据后,保存代码。转到 Sketch  >  Show Sketch Folder,然后创建一个名为 data的文件夹。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

在该文件夹中,应该保存 HTML、CSS 和 JavaScript 文件。

然后,将代码上传到您的 ESP32 开发板。确保您选择了正确的板和 COM 端口。此外,请确保您已添加网络凭据。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

上传代码后,需要上传文件。转到 工具 >  ESP32 数据程序上传 并等待文件上传。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

全部上传成功后,以 115200 的波特率打开串口监视器。按下 ESP32 EN/RST 按钮,它应该会打印 ESP32 IP 地址。

示范

在本地网络上打开浏览器并粘贴 ESP32 IP 地址。您应该可以访问 Web 服务器页面来控制 LED 的亮度。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

移动滑块以控制 LED 的亮度。

ESP32 Web 服务器 (WebSocket):网页多个滑动开关控制 LED 亮度 (PWM)

打开多个选项卡或使用其它设备连接到 Web 服务器,并注意滑块值几乎会在发生更改时立即更新。

总结

在本教程中,您学习了如何使用 ESP32 构建 Web 服务器,该服务器为具有多个滑块的网页提供服务。滑块允许您控制连接到 ESP32 的 LED 的亮度。此外,我们使用 WebSocket 协议在 ESP32 和客户端之间进行通信。

我们希望您从本教程中学到了很多东西。如果您成功遵循本教程并让项目正常运行,请在下面的评论中告诉我吧。

给TA打赏
共{{data.count}}人
人已打赏
ESP32-进阶免费项目

在 Arduino IDE 中安装 ESP32 文件系统上传器插件

2022-8-28 15:10:56

ESP32-进阶免费项目

ESP32 继电器模块 – 控制交流电器(Web 服务器)

2022-8-30 0:12:47

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索
'); })();