回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【Arduino 动手做】使用 ESP32 + Arduino 实现互联网控制的 LED 灯带 简单

头像 驴友花雕 2025.06.22 11 0

使用 ESP32 控制 RGB LED 灯带,该灯带托管一个用 Arduino 框架编写的 HTTP 服务器。可在本地网络和互联网上工作。

介绍
在本教程中,我将向您展示如何使用 ESP32 和 Arduino IDE 创建由 Web 浏览器控制的 WS2812 LED 灯带。

ESP32 正在运行一个 HTTP 服务器,每次点击按钮时主题都会更改。该 HTTP 服务器可通过本地网络和互联网访问。

默认情况下有 5 个 LED 主题可用:
彩虹
白色光泽
红色光芒
只有白色
离开
但是您可以轻松添加您能想象到的任何主题(和代码:)。

在源代码中,我们使用单独的 FreeRTOS 任务来处理 HTTP 服务器和 LED 灯带主题 - 由于该代码清晰、易于理解和修改。

准备硬件
接线非常简单:

1. 将 5V 直流电源连接到 LED 灯带。本教程中使用的 LED 灯带包含 60 个像素,长度为 1 米,每米电流消耗为 3.5 A。请根据您使用的像素数量购买合适的 5V 直流电源转换器。

2. 将 ESP32 连接到 LED 灯带:

LED 灯带仅包含 3 个输入引脚:+5V、GND和Din。ESP32 由 3.3V 供电,这得益于板载 LDO 线性稳压器。将电源连接到 LDO 输入引脚 - 在我的开发板上,它被称为V5,但在您的开发板上,它的名称可能不同。将 LED 灯带数据输入引脚连接Din到G12开发板上的引脚。

准备 ESP32 固件
借助Husarnet ,LED 灯带不仅可以通过局域网控制,还可以通过互联网控制。Husarnet 提供了经过修改的 ESP32-IDF,因此您可以使用与 ESP32 标准 Arduino 软件包几乎相同的 API。Husarnet 还可以轻松与 Arduino IDE 集成。

现在打开 Arduino IDE,并按照以下说明步骤操作:

1.在Arduino IDE中安装NeoPixelBus库:

打开Tools -> Manage Libraries
搜索NeoPixelBus by Makuna
点击Install按钮
2. 安装 Husarnet IDF for ESP32:

打开File -> Preferences
在附加董事会管理器 URL 字段中添加此链接:
https://github.com/husarnet/arduino-esp32/releases/download/1.0.4-1/package_esp32_index.json
3. 安装 ESP32 开发板

打开Tools -> Board: "..." -> Boards Manager ...
搜索esp32-husarnet
点击Install按钮
我们在此添加了一个针对 ESP32 的官方 Arduino 核心的修改版(主要涉及 IPv6 支持相关更改)- https://github.com/husarnet/arduino-esp32 。如果您之前安装过原版 Arduino 核心,建议您删除系统中所有其他适用于 ESP32 的 Arduino 核心。

4.选择ESP32开发板:

打开Tools -> Board "..."
选择ESP32 Dev Module部分ESP32 Arduino​
4. 运行演示:

克隆项目代码:
git clone https://github.com/DominikN/ESP32_ledstrip_webserver.git
修改第 9 行,设置 LED 灯带的像素数量。此代码旨在根据此处定义的像素数量自动缩放 LED 主题。
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      60
修改第 22 至 33 行以添加您的 Wi-Fi 网络凭据。在这里添加多个网络凭据非常方便——如果您将项目移动到不同的物理目的地,则无需每次都重新编程 ESP32。
// Add your networks credentials here
const char* ssidTab[NUM_NETWORKS] = {
"wifi-network-1",
"wifi-network-2",
"wifi-network-3",
"wifi-network-4"
};
const char* passwordTab[NUM_NETWORKS] = {
"wifi-pass-1",
"wifi-pass-2",
"wifi-pass-3",
"wifi-pass-4"
};
将 LED 灯带的输入数据引脚连接到G12ESP32 开发板的引脚
将项目上传到您的 ESP32 开发板(根据您的开发板,您需要按“BOOT”按钮,或在闪烁时将 Pin0 或 IO0 短接至 GND)
在 Arduino IDE 中打开Tools -> Serial Monitor并等待 ESP32 连接到 Wi-Fi 网络。几秒钟后,您应该会看到类似这样的链接(代码中串行端口的默认波特率为 115200):
[10009675] Visit 
https://app.husarnet.com/husarnet/fc94f91f5992989f83474cc8abf7329bf8ae7f3ee4a9xxxxyyyyzzzz 
to configure the device .
复制该链接并在网络浏览器中打开它
为您的设备命名(例如 ledstrip),单击Add to network并选择Create new network- 并为其命名(例如 ledstripnet)
打开ledstripnet并左键单击ledstrip元素
选择Make the Web UI public并单击update按钮
在网络Info栏中,ledstripnet您应该会看到Web UI一个按钮,上面有一个指向控制面板的公共链接。每次通过该链接为 ESP32 开发板供电时,您都可以访问 Web UI 来控制 LED 灯带。
5.(可选)改进 - 如果您不想让任何公共链接指向您的 ESP32,您需要将您的笔记本电脑添加到“ledstripnet”网络:

在你的 Linux 设备上安装 Husarnet(https://docs.husarnet.com/getting-started/ )并将其添加到你的网络
在您的 Linux 设备上打开 Web 浏览器并将地址写入具有 8000 端口的 ESP32,例如。http://ledstrip:8000
概括
为您的 ESP32 创建可访问互联网的 Web 用户界面非常简单。该 Wi-Fi 模块集成了大量的 RAM 和闪存,结合 FreeRTOS,您可以轻松托管 HTTP 服务器来控制任何您想要控制的东西。LED 灯带就是一个​​很好的例子 :)。

我希望你会喜欢这个项目!:)

 

00.jpg
01.jpg
02.jpg
03.jpg

项目代码

 

代码
#include <WiFi.h>
#include <NeoPixelBus.h>
#include <Husarnet.h>

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN            12

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      60

NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(NUMPIXELS, PIN);

uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;

int j = 0;

#define NUM_NETWORKS 4

// Add your networks credentials here
const char* ssidTab[NUM_NETWORKS] = {
  "wifi-network-1",
  "wifi-network-2",
  "wifi-network-3",
  "wifi-network-4"
};
const char* passwordTab[NUM_NETWORKS] = {
  "wifi-pass-1",
  "wifi-pass-2",
  "wifi-pass-3",
  "wifi-pass-4"
};

HusarnetServer server(8000);

String header;

void setup() {
  Serial.begin(115200);

  strip.Begin();
  strip.Show();

  bool connectedSuccess = 0;
  for (int i = 0; i < NUM_NETWORKS; i++) {
    Serial.print("Connecting to ");
    Serial.println(ssidTab[i]);
    WiFi.begin(ssidTab[i], passwordTab[i]);
    for (int j = 0; j < 10; j++) {
      if (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      } else {
        connectedSuccess = true;
      }
    }
    Serial.println("");
    if (connectedSuccess == true) {
      break;
    }
  }
  if (connectedSuccess == false) {
    Serial.println("WiFi network unreachable");
    while (1) {
      ;
    }
  }

  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Husarnet.selfHostedSetup("default");
  // Husarnet.join(husarnetJoinCode, hostName); // alternative way, to clicking a link from a terminal. Visit app.husarnet.com -> network -> add element -> join code tab.
  Husarnet.start();

  server.begin();

  xTaskCreate(
    taskLED,          /* Task function. */
    "taskLED",        /* String with name of task. */
    10000,            /* Stack size in bytes. */
    NULL,             /* Parameter passed as input of the task */
    2,                /* Priority of the task. */
    NULL);            /* Task handle. */

  xTaskCreate(
    taskWifi,          /* Task function. */
    "taskWifi",        /* String with name of task. */
    10000,            /* Stack size in bytes. */
    NULL,             /* Parameter passed as input of the task */
    1,                /* Priority of the task. */
    NULL);            /* Task handle. */
}

void rainbow(int j) {
  int k = 0;
  int l = 0;
  int m = 0;

  for (int i = 0; i < NUMPIXELS; i++) {
    if ( ( i >= 0 ) && ( i < NUMPIXELS * 1 / 3 ) ) {
      red = 255 * k / (NUMPIXELS / 3);
      green = 0;
      blue = 255 - (255 * k / (NUMPIXELS / 3) );
      k++;
    }
    if ( ( i >= NUMPIXELS * 1 / 3 ) && ( i < NUMPIXELS * 2 / 3 ) ) {
      red = 255 - (255 * l / (NUMPIXELS / 3) );
      green = 255 * l / (NUMPIXELS / 3);
      blue = 0;
      l++;
    }
    if ( ( i >= NUMPIXELS * 2 / 3 ) && ( i < NUMPIXELS * 3 / 3 ) ) {
      red = 0;
      green = 255 - (255 * m / (NUMPIXELS / 3) );
      blue = 255 * m / (NUMPIXELS / 3);
      m++;
    }

    strip.SetPixelColor((i + j) % NUMPIXELS, RgbColor(red, green, blue));
  }

  strip.Show();
  delay(50);
}

void white_shine(int j) {
  int k = 0;
  int l = 0;
  int m = 0;

  for (int i = 0; i < NUMPIXELS; i++) {
    if ( ( i >= 0 ) && ( i < NUMPIXELS * 1 / 3 ) ) {
      red = 255 * k / (NUMPIXELS / 3);
      green = 255 * k / (NUMPIXELS / 3);
      blue = 255 * k / (NUMPIXELS / 3);
      k++;
    }
    if ( ( i >= NUMPIXELS * 1 / 3 ) && ( i < NUMPIXELS * 2 / 3 ) ) {
      red = 255 - (255 * l / (NUMPIXELS / 3) );
      green = 255 - (255 * l / (NUMPIXELS / 3) );
      blue = 255 - (255 * l / (NUMPIXELS / 3) );
      l++;
    }
    if ( ( i >= NUMPIXELS * 2 / 3 ) && ( i < NUMPIXELS * 3 / 3 ) ) {
      red = 0;
      green = 0;
      blue = 0;
      m++;
    }
    Serial.printf("\r\n[R,G,B] = [%d,%d,%d]", red, green, blue);
    strip.SetPixelColor((i + j) % NUMPIXELS, RgbColor(red, green, blue));
  }
  strip.Show();
  delay(40);
}

void red_shine(int j) {
  int k = 0;
  int l = 0;
  int m = 0;
  
  for (int i = 0; i < NUMPIXELS; i++) {
    if ( ( i >= 0 ) && ( i < NUMPIXELS * 1 / 3 ) ) {
      red = 255;
      green = 255 - 255 * k / (NUMPIXELS / 3);
      blue = 255 - 255 * k / (NUMPIXELS / 3);
      k++;
    }
    if ( ( i >= NUMPIXELS * 1 / 3 ) && ( i < NUMPIXELS * 2 / 3 ) ) {
      red = 255;
      green = (255 * l / (NUMPIXELS / 3) );
      blue = (255 * l / (NUMPIXELS / 3) );
      l++;
    }
    if ( ( i >= NUMPIXELS * 2 / 3 ) && ( i < NUMPIXELS * 3 / 3 ) ) {
      red = 255;
      green = 255;
      blue = 255;
      m++;
    }
    strip.SetPixelColor((i + j) % NUMPIXELS, RgbColor(red, green, blue));
  }
  strip.Show();
  delay(40);
}

void led_white()
{
  for (int i = 0; i < NUMPIXELS; i++) {
    red = 255;
    green = 255;
    blue = 255;
    strip.SetPixelColor((i + j) % NUMPIXELS, RgbColor(red, green, blue));
  }
  delay(5);
  strip.Show();
}

void led_off() {
  for (int i = 0; i < NUMPIXELS; i++) {
    red = 0;
    green = 0;
    blue = 0;
    strip.SetPixelColor((i + j) % NUMPIXELS, RgbColor(red, green, blue));
  }
  delay(100);
  strip.Show();
}


char* getModeName(uint8_t modeNo) {
  switch (modeNo) {
    case 0:
      return "rainbow";
    case 1:
      return "white shine";
    case 2:
      return "red shine";
    case 3:
      return "only white";
    case 4:
      return "off";
  }
  return "error";
}

uint8_t modeRGB = 0;
void taskLED( void * parameter )
{
  while (1) {
    switch (modeRGB) {
      case 0:
        rainbow(j++);
        break;
      case 1:
        white_shine(j++);
        break;
      case 2:
        red_shine(j++);
        break;
      case 3:
        led_white();
        break;
      case 4:
        led_off();
        break;
      default:
        rainbow(j++);
        break;
    }
    if (j >= NUMPIXELS) {
      j = 0;
    }
  }

  Serial.println("Ending task LED");
  vTaskDelete( NULL );
}

void loop() {
  while (1) {
    delay(1000);
  }
}

static const char* htmlHead = R"rawText(
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html { 
font-family: Helvetica; 
display: inline-block; 
margin: 0px auto; 
text-align: center;
}

.button { 
background: 
linear-gradient(to right, #FB6060 0%, #EC305D 100%);
border: none;
text-decoration: none;
margin: 2px;   
padding: 25px 25px; 
width: 300px; 
border-radius: 12px; 
color: white;
font-size: 30px; 
cursor: pointer;
}
</style>
</head>   
)rawText";
  
void taskWifi( void * parameter ) {


  
  while (1) {
    HusarnetClient client = server.available();

    if (client) {
      Serial.println("New Client.");
      String currentLine = "";
      Serial.printf("connected: %d\n", (int)client.connected());
      while (client.connected()) {

        if (client.available()) {
          char c = client.read();
          //          Serial.write(c);
          header += c;
          if (c == '\n') {
            if (currentLine.length() == 0) {
              client.println("HTTP/1.1 200 OK");
              client.println("Content-type:text/html");
              client.println("Connection: close");
              client.println();

              if (header.indexOf("GET /0") >= 0) {
                modeRGB = 1;
              }
              if (header.indexOf("GET /1") >= 0) {
                modeRGB = 2;
              }
              if (header.indexOf("GET /2") >= 0) {
                modeRGB = 3;
              }
              if (header.indexOf("GET /3") >= 0) {
                modeRGB = 4;
              }
              if (header.indexOf("GET /4") >= 0) {
                modeRGB = 0;
              }

              // Head
              client.println("<!DOCTYPE html><html>");
              client.println(htmlHead);
              // Body
              client.println("<body><h1>ESP32 Web RGB strip control</h1>");
              client.print("<p><a href=\"/");
              client.print(modeRGB);
              client.print("\"><button class=\"button\">");
              client.print(getModeName(modeRGB));
              client.println("</button></a></p>");
              client.println("</body></html>");

              client.println();
              break;
            } else {
              currentLine = "";
            }
          } else if (c != '\r') {
            currentLine += c;
          }
        }
      }

      header = "";

      client.stop();
      Serial.println("Client disconnected.");
      Serial.println("");
    }
  }
}

【Arduino 动手做】使用 ESP32 实现互联网控制的 LED 灯带
项目链接:https://www.hackster.io/donowak/internet-controlled-led-strip-using-esp32-arduino-2ca8a9
项目作者:多米尼克

项目视频 :https://www.youtube.com/watch?v=qtcwGlR5Vmc
项目代码:https://www.hackster.io/code_files/228004/download
https://github.com/DominikN/ESP32_ledstrip_webserver

 

00170.gif

评论

user-avatar
icon 他的勋章
    展开更多