ESP32 Web Server (WebSocket) 实现多控件多引脚调节(PWM)

ESP32 Web Server (WebSocket) 实现多控件多引脚调节(PWM)


本教程将展示如何构建一个ESP32 web服务器,该服务器可以显示带有多个滑块的网页。滑块控制不同PWM通道的占空比来控制多个led的亮度。也可以代替led,你可以使用这个项目来控制直流电机或其他需要PWM信号的驱动器。客户端与ESP32之间的通信是通过WebSocket协议完成的。此外,每当有一个变化,所有客户端同步更新他们的滑块值。
在这里插入图片描述

  • 控制界面
    在这里插入图片描述
  • 所需库

AsyncTCP
ESPAsyncWebServer

Arduino_JSON在Arduino IDE 管理库搜索下载。
在这里插入图片描述

  • 文件架构
    在这里插入图片描述

  • 编译信息

使用 1.0  版本的库 WiFi 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi 
使用 1.1.1  版本的库 AsyncTCP 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\AsyncTCP 
使用 1.0  版本的库 SPIFFS 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\SPIFFS 
使用 1.0  版本的库 FS 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\FS 
使用 1.2.3  版本的库 ESPAsyncWebServer-master 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\ESPAsyncWebServer-master 
使用 1.0.1  版本的库 Wire 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\Wire 
使用 0.1.0  版本的库 Arduino_JSON 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\Arduino_JSON 
"C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\1.22.0-97-gc752ad5-5.2.0/bin/xtensa-esp32-elf-size" -A "d:\\arduino\\MyHexDir/Multiple_Sliders32.ino.elf"
项目使用了 820374 字节,占用了 (6%) 程序存储空间。最大为 13369344 字节。
全局变量使用了39504字节,(12%)的动态内存,余留288176字节局部变量。最大为327680字节。

实例代码

#include <Arduino.h>

#include <WiFi.h>
#include <AsyncTCP.h>
#include "SPIFFS.h"

#include <ESPAsyncWebServer.h>
#include <Wire.h>

#include <ESPAsyncWebServer.h>

#include <Arduino_JSON.h>

const char *ssid = "MERCURY_D268G";
const char *password = "pba5ayzk";
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 %s\n", client->id(), client->remoteIP().toString().c_str());
    break;
  case WS_EVT_DISCONNECT:
    Serial.printf("WebSocket client #%u disconnected\n", 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();
}
  • 上传完代码后,需要上传FS文件

在这里插入图片描述

源码和相关文件资源

https://gitee.com/perseverance51/esp32-project/tree/master
  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用ESP32作为Web服务器的话,我们可以通过将HTML代码嵌入到ESP32的代码中来创建一个基本的Web页面。 首先,我们需要引入ESP32的相关库。然后,创建一个ESP32Web服务器实例,监听指定的端口号。接下来,我们可以设置一个处理根路径请求的处理函数,这个函数会返回我们嵌入的HTML代码作为响应。 以下是一个简单的示例代码: ``` #include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; WebServer server(80); const char* htmlContent = R"( <!DOCTYPE html> <html> <body> <h1>Hello ESP32!</h1> <p>This is a sample HTML page embedded in ESP32 web server.</p> </body> </html> )"; void handleRoot() { server.send(200, "text/html", htmlContent); } void setup() { WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.print("IP address: "); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.begin(); } void loop() { server.handleClient(); } ``` 以上代码首先连接到指定的WiFi网络,然后创建一个Web服务器实例,并设置处理根路径请求的处理函数。 在`handleRoot`函数中,我们使用`server.send`函数将HTTP响应发送给客户端,响应的内容即为我们嵌入的HTML代码。 在`setup`函数中,我们将Web服务器开始监听,并打印ESP32的IP地址。 最后,在`loop`函数中,我们使用`server.handleClient`来处理来自客户端的请求。 通过以上代码,我们可以使用ESP32作为Web服务器提供一个简单的HTML页面。当我们访问ESP32的IP地址时,就会看到浏览器中显示的嵌入的HTML页面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值