lingzhiLab 发表于 2025-2-20 09:29

零知开源——网页控制WS2812B

本帖最后由 lingzhiLab 于 2025-2-20 10:53 编辑

#申请原创# ​
零知-ESP32               
使用ESP32微控制器对8 bit-2812 RGB灯带进行控制,实现了多种不同的灯光效果。实现彩虹颜色轮换函数,连续颜色变换效果。实现闪烁和颜色渐变效果,随机进行颜色闪烁。实现流水灯和呼吸灯效果,利用PWM调整亮度。
       ESP32实现Web网页控制WS2812B点亮不同颜色的效果。

1、使用工具电脑、Windows系统
零知-ESP32开发板
Micro-usb线
WS2812RGB灯


2、硬件连接
                        零知-ESP32开发板
                                                       WS2812B      
                        
                        5V
                                                VCC
                        
                        GND
                                                GND
                        
                        23
                                                Din
                        
硬件连接示意图

3、代码部分
   网页控制部分   将Adafruit_NeoPixel.h和WiFi.h导入至项目中
   定义一些变量用于存放WS2812RGB和网页HTTP的参数

// 引入Adafruit_NeoPixel库
#include <Adafruit_NeoPixel.h>
#include <WiFi.h>
// 连接的WS2812B的引脚,根据实际情况修改
#define PIN 23
// 灯珠数量,根据实际情况修改
#define NUM_LEDS 8

// 创建Adafruit_NeoPixel对象
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

// 用于解析HTTP GET值的字符串
String redString = "0";
String greenString = "0";
String blueString = "0";
int pos1 = 0;
int pos2 = 0;
int pos3 = 0;
int pos4 = 0;
// 存储HTTP请求的变量
String header;

// 设置web服务器端口号为80
WiFiServer server(80);

    设置串口波特率为115200并打开
    初始化WS2812B,配置WiFi网络或热点,ESP32连接网络
void setup() {
    Serial.begin(115200);
    // 初始化WS2812B
    pixels.begin();
    pixels.setBrightness(86);//设置亮度数值S(max=255)
    pixels.show();               //灯带显示

    // 连接Wi-Fi网络,这里需要修改成自己的SSID和密码
    const char* ssid = "xx";
    const char* password = "xx";
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status()!= WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();

    pixels.setPixelColor(0, pixels.Color(255, 0, 0));
    pixels.show();
} 配置网页,生成调色器控制像素输出到WS2812RGB上显示不同颜色
void loop() {
    WiFiClient client = server.available();   // 监听传入的客户端
    if (client) {                           // 如果有新客户端连接
      String currentLine = "";
      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();
                              // Display the HTML web page
                              client.println("<!DOCTYPE html><html>");
                              client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
                              client.println("<link rel=\"icon\" href=\"data:,\">");
                              client.println("<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\">");
                              client.println("<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.min.js\"></script>");
                              client.println("</head><body><div class=\"container\"><div class=\"row\"><h1>ESP Color Picker</h1></div>");
                              client.println("<a class=\"btn btn-primary btn-lg\" href=\"#\" id=\"change_color\" role=\"button\">Change Color</a> ");
                              client.println("<input class=\"jscolor {onFineChange:'update(this)'}\" id=\"rgb\"></div>");
                              client.println("<script>function update(picker) {document.getElementById('rgb').innerHTML = Math.round(picker.rgb) + ', ' +Math.round(picker.rgb) + ', ' + Math.round(picker.rgb);");
                              client.println("document.getElementById(\"change_color\").href=\"?r\" + Math.round(picker.rgb) + \"g\" +Math.round(picker.rgb) + \"b\" + Math.round(picker.rgb) + \"&\";}</script></body></html>");
                        if (header.indexOf("GET /?r") >= 0) {
                            pos1 = header.indexOf('r');
                            pos2 = header.indexOf('g');
                            pos3 = header.indexOf('b');
                            pos4 = header.indexOf('&');
                            redString = header.substring(pos1 + 1, pos2);
                            greenString = header.substring(pos2 + 1, pos3);
                            blueString = header.substring(pos3 + 1, pos4);
                            // 设置WS2812B的颜色
                            pixels.clear();

                            // 将RGB值转换为整数
                            if (redString.startsWith("0x")) {
                              redString = redString.substring(2);
                            }
                            int red = strtol(redString.c_str(), NULL, 16);
                            // 对green和blue值也进行同样的操作
                            int green = strtol(greenString.c_str(), NULL, 16);
                            int blue = strtol(blueString.c_str(), NULL, 16);

                            for (int i = 0; i < NUM_LEDS; i++) {
                              pixels.setPixelColor(i, pixels.Color(red, green, blue));
                            }
                            pixels.show();                        }
                        break;
                  } else {
                        currentLine = "";
                  }
                } else if (c!= '\r') {
                  currentLine += c;
                }
            }
      }
      // 清空header变量
      header = "";
      client.stop();
      Serial.println("Client disconnected.");
      Serial.println("");
    }
}
不同点亮效果部分实现WS2812RGB闪烁、呼吸灯和流水灯、颜色循环点亮等效果
#include<Arduino.h>
#include <Adafruit_NeoPixel.h>

#define WS2812_PIN 23                  //灯带引脚
#define WS2812_NUM 8               //灯的数量
#define Bright255                     //灯珠亮度
#define Delay_T 10                     //延时时间

#define WS2812_C_RED      18//红色
#define WS2812_C_ORANGE   54//橙色
#define WS2812_C_YELLOW   90//黄色
#define WS2812_C_GREEN      126 //绿色
#define WS2812_C_CYAN       162 //青色
#define WS2812_C_BIUE       198 //蓝色
#define WS2812_C_PURPIE   234 //紫色

//使用RGB模式控制ws2812类型灯带
Adafruit_NeoPixel strip(WS2812_NUM, WS2812_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
    WS2812_Init();//初始化
}

void loop() {
    for (uint8_t i = 0; i < 3; i++) {
      //---起始灯珠---结束灯珠---灯珠颜色--------//
      WS2812_ColoredLight(0, WS2812_NUM, WS2812_C_PURPIE);
      delay(1000); // 延时1S
      WS2812_StopAppointLight(0, WS2812_NUM);
      delay(1000); // 延时1S
    }

    // 调用新添加的函数
    WS2812_Blink(0, WS2812_NUM % 2, WS2812_C_GREEN, 5, 500);
    WS2812_Fade(WS2812_NUM / 2, WS2812_NUM, WS2812_C_YELLOW, WS2812_C_RED, 100);
    WS2812_RandomBlink(0, WS2812_NUM, 3, 300);

    WS2812_RunningLight(0, WS2812_NUM, 100);
   
    WS2812_BreathingLight_PWM(0, WS2812_NUM, 10);

    // 彩虹灯效(注意注释中的警告)
    WS2812_Start_ContinuousColoredLight(0, 16);
}

/**
* @briefWS2812的初始化
* @param无
* @retval 无
**/

void WS2812_Init(void)
{
    //Adafruit_NeoPixel strip(LED_NUM, LED_PIN, NEO_GRB + NEO_KHZ800);

    strip.begin();            //初始化灯带
    strip.setBrightness(Bright);//设置亮度数值S(max=255)
    strip.show();               //灯带显示

}


/**
* @brief点亮第n到m个彩色LED灯(慎用,会进入死循环)
* @paramStart,开始的灯珠
* @paramStop,结束的灯珠
* @retval 无
**/

void WS2812_Start_ContinuousColoredLight(uint8_t Start, uint8_t Stop)//
{
uint8_t x=0,y=0;
    for (uint8_t j = 0; j < 256; j++)
    {
      //--------灯珠颜色------起始灯珠-------结束灯珠-------//
      strip.fill(Rainbow(j & 255),Start, Stop);//连续点亮多个灯珠
       // Serial.println("x=");
       // Serial.println(x);
      //strip.setPixelColor(1, Rainbow(j & 255));//点亮一个灯珠
      strip.show();
      //Serial.println("y=");
      // Serial.println(y);
      //x++;
       // y++;
      delay(Delay_T);
    }
//Serial.println("ok");
}


/**
* @brief关闭第n到m个彩色LED灯
* @paramStart,开始的灯珠
* @paramStop,结束的灯珠
* @retval 无
**/

void WS2812_StopAppointLight(uint8_t Start, uint8_t Stop)
{
      strip.fill(strip.Color(0, 0, 0),Start, Stop);//熄灭点亮多个灯珠
      strip.show();
      delay(Delay_T);
}


/**
* @brief设置第n到m个LED灯
* @paramStart,开始的灯珠
* @paramStop,结束的灯珠
* @paramColor, LED的颜色
* @retval 无
**/

void WS2812_ColoredLight(uint8_t Start, uint8_t Stop, uint8_t Color)//
{
      //--------灯珠颜色------起始灯珠-------结束灯珠-------//
    strip.fill(Rainbow(Color),Start, Stop);
    strip.show();
    delay(Delay_T);
    //Serial.println("ok");
}

/**
* @brief点亮第n个LED灯,颜色自定
* @paramlocation,第几个灯珠
* @paramColored,色号(0 <= Colored < 256)
* @retval 无
**/

void WS2812_OneLight(uint8_t location, uint8_t Colored)
{
    strip.setPixelColor(location, Rainbow(Colored));//点亮一个灯珠
    strip.show();
    delay(Delay_T);
}

/**
* @brief关闭所以灯
* @param无
* @retval 无
**/
void WS2812_Clear(void)
{
    strip.clear();
    strip.show();
    strip.fill(strip.Color(0, 0, 0),0, WS2812_NUM);//熄灭点亮多个灯珠
    // strip.show();
    // delay(Delay_T);
}


/**
* @brief颜色循环函数
* @paramWheelPos,颜色
* @retval 无
**/

uint32_t Rainbow(byte WheelPos)
{
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

// 闪烁效果函数
void WS2812_Blink(uint8_t Start, uint8_t Stop, uint8_t Color, uint8_t times, uint16_t blinkDelay) {
    for (uint8_t i = 0; i < times; i++) {
      WS2812_ColoredLight(Start, Stop, Color);
      delay(blinkDelay);
      WS2812_StopAppointLight(Start, Stop);
      delay(blinkDelay);
    }
}

// 渐变效果函数
void WS2812_Fade(uint8_t Start, uint8_t Stop, uint8_t startColor, uint8_t endColor, uint16_t stepDelay) {
    for (uint8_t i = startColor; i <= endColor; i++) {
      WS2812_ColoredLight(Start, Stop, i);
      delay(stepDelay);
    }
    for (uint8_t i = endColor; i >= startColor; i--) {
      WS2812_ColoredLight(Start, Stop, i);
      delay(stepDelay);
    }
}

// 随机颜色闪烁函数
void WS2812_RandomBlink(uint8_t Start, uint8_t Stop, uint8_t times, uint16_t blinkDelay) {
    for (uint8_t i = 0; i < times; i++) {
      uint8_t randomColor = random(0, 256);
      WS2812_ColoredLight(Start, Stop, randomColor);
      delay(blinkDelay);
      WS2812_StopAppointLight(Start, Stop);
      delay(blinkDelay);
    }
}

// 流水灯效果函数
void WS2812_RunningLight(uint8_t Start, uint8_t Stop, uint16_t stepDelay) {
    for (uint8_t i = Start; i < Stop; i++) {
      WS2812_OneLight(i, WS2812_C_PURPIE);
      delay(stepDelay);
      WS2812_OneLight(i, 0);
    }
}

// 呼吸灯效果函数(使用PWM概念,通过改变占空比来实现亮度变化)
void WS2812_BreathingLight_PWM(uint8_t Start, uint8_t Stop, uint16_t stepDelay) {
    for (int dutyCycle = 0; dutyCycle < 255; dutyCycle++) {
      for (uint8_t i = Start; i < Stop; i++) {
            uint32_t color = strip.Color(0, 0, dutyCycle);
            strip.setPixelColor(i, Rainbow(color));
      }
      strip.show();
      delay(stepDelay);
    }
    for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) {
      for (uint8_t i = Start; i < Stop; i++) {
            uint32_t color = strip.Color(0, 0, dutyCycle);
            strip.setPixelColor(i, Rainbow(color));
      }
      strip.show();
      delay(stepDelay);
    }
}      
4、成果展示      
      打开esp32的ip地址,显示调色板
      

      点击Change Color后串口打印输出
      

      WS2812RGB被点亮成红色
         


      不同点亮效果的视频
         https://live.csdn.net/v/436104?spm=1001.2014.3001.5501
https://i-blog.csdnimg.cn/img_convert/23d797f1ef743067db5f18c2aea05f8f.jpegESP32控制WS2812RGB

data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==




页: [1]
查看完整版本: 零知开源——网页控制WS2812B