文章目录
- 一、WS2812彩灯介绍
- 二、安装Adafruit_NeoPixel驱动库
- 三、Adafruit_NeoPixel库常用接口
- 四、使用示例
- 五、网页端控制WS2812B灯带实例
一、WS2812彩灯介绍
WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,外型与5050LED灯珠相同,每个灯珠都是一个像素点。像素点内包含数字接口、数据锁存、信号整形放大驱动电路,还包含高精度的内部振荡器和12V高压可编程定电流控制部分。
数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
按照数据传输协议即可对WS2812进行驱动,当然对于WS2812有许多开源的驱动库,例如:Adafruit_NeoPixel驱动库
二、安装Adafruit_NeoPixel驱动库
在Arduino IDE中点击【项目】—【加载库】—【管理库】,查找Adafruit_NeoPixel库,选择最新版本,点击安装。
三、Adafruit_NeoPixel库常用接口
接口 | 说明 |
---|---|
Adafruit_NeoPixel led(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800) | 创建对象:像素点数量、信号引脚、像素类型标准(一般默认即可) |
led.begin() | 对象初始化 |
led.clear() | 将颜色值清除到0 |
led.setPixelColor(i, led.Color(255, 0, 0)) | 设置颜色值:像素点序号、像素颜色 |
led.show() | 显示刷新:每次设置完毕必须调用此函数 |
led.setBrightness() | 设置亮度:范围0~255 |
led.Color() | 将RGB单独颜色值打包成32位颜色值 |
四、使用示例
#include <Adafruit_NeoPixel.h> // 操作WS2812B需要使用的库
#define PIN 0 //GPIO0接口
#define NUMPIXELS 35 //彩灯个数
Adafruit_NeoPixel led(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
led.begin();
led.setBrightness(255); //设置亮度 (0~255)
for(int i=0; i<NUMPIXELS; ++i) { //所有灯全部设为红色
led.setPixelColor(i,led.Color(255, 0, 0)); //红色
}
led.show(); //刷新显示
delay(1000);
}
void loop() {
}
五、网页端控制WS2812B灯带实例
我们可以将ESP8266设置为AP模式,然后ESP8266开启HTTP服务器,手机或者电脑先连接ESP8266的WiFi(ESP8266,12345678),然后访问ESP8266的IP:192.168.4.1
,就可以看到ESP8266的内置网页,本例中的网页很简陋,就是一些按钮,用来切换灯带的状态,包括:
- 关灯
- 红色常亮(小灯全部红色,保存常亮)
- 橙色常亮
- 黄色常亮
- 绿色常亮
- 蓝色常亮
- 靛青色常亮
- 紫色常亮
- 红色跑马(有10个红色小灯在灯带上循环跑动)
- 橙色跑马
- 黄色跑马
- 绿色跑马
- 蓝色跑马
- 靛青色跑马
- 紫色跑马
- 七彩跑马(彩虹七色,每种颜色5个小灯,循环流动)
- 七彩变换(彩虹七色,循环切换)
注意:需要根据自身灯带情况,修改:
#define NUMPIXELS 35 //彩灯个数
/*
ESP8266-NodeMCU作为HttpServer服务器控制WS2812B灯带
*/
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
#include <ESP8266WebServer.h> // web服务器通信库需要使用
#include <Adafruit_NeoPixel.h> // 操作WS2812B需要使用的库
#include <Ticker.h> //使用Ticker库定时器
#define PIN 0 //GPIO0接口
#define NUMPIXELS 35 //彩灯个数
Adafruit_NeoPixel led(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Ticker timer1;
int color_change = 0;
Ticker timer2;
int run_count = 0;
Ticker timer3;
int run_color = 1;
/* 1. 设置Wifi接入信息 */
const char* ssid = "ESP8266"; // 需要连接到的WiFi名
const char* password = "12345678"; // 连接的WiFi密码
/* 2. 创建一个web服务器对象,使用80端口,HTTP网络服务器标准端口号即为80 */
ESP8266WebServer esp8266_server(80);
/* 3. 处理访问网站根目录“/”的访问请求 */
void handleRoot() {
String htmlCode = "<!DOCTYPE html>\n";
htmlCode += " <html>\n";
htmlCode += " <head>\n";
htmlCode += " <meta charset=\"UTF-8\"/>\n";
htmlCode += " <title>ESP8266 Butoon Ctrl</title>\n";
htmlCode += " </head>\n";
htmlCode += " <body>\n";
htmlCode += " <h2 align=\"center\">esp8266控制开关</h2>";
htmlCode += " <div>\n";
htmlCode += " <form action=\"/LED_OFF\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"关灯\"></form>\n";
htmlCode += " </div>\n";
htmlCode += " <div>\n";
htmlCode += " <form action=\"/LED_RED_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"红色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_ORANGE_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"橙色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_YELLOW_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"黄色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_GREEN_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"绿色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_BLUE_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"蓝色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_CYAN_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"靛青色常亮\"></form>\n";
htmlCode += " <form action=\"/LED_PURPLE_HOLD\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"紫色常亮\"></form>\n";
htmlCode += " </div>\n";
htmlCode += " <div>\n";
htmlCode += " <form action=\"/LED_RED_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"红色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_ORANGE_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"橙色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_YELLOW_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"黄色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_GREEN_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"绿色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_BLUE_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"蓝色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_CYAN_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"靛青色跑马\"></form>\n";
htmlCode += " <form action=\"/LED_PURPLE_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"紫色跑马\"></form>\n";
htmlCode += " </div>\n";
htmlCode += " <div>\n";
htmlCode += " <form action=\"/LED_COLORS_RUN\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"七彩跑马\"></form>\n";
htmlCode += " <form action=\"/LED_COLORS_CHANGE\" method=\"POST\" align=\"center\"><input type=\"submit\" value=\"七彩变换\"></form>\n";
htmlCode += " </div>\n";
htmlCode += " </body>\n";
htmlCode += " </html>\n";
esp8266_server.send(200, "text/html", htmlCode); // NodeMCU将调用此函数。
}
/* 4. 设置处理404情况的函数'handleNotFound' */
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}
//=========================================================
void handle_LED_OFF() {
timer1.detach();
timer2.detach();
timer3.detach();
Serial.println("handle_LED_OFF");
led.clear(); //将颜色值清除到0
led.begin(); //显示刷新
delay(1000);
}
//-------------------------------------------
void handle_LED_RED_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 0, 0)); //红色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_ORANGE_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 165, 0)); //橙色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_YELLOW_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 255, 0)); //黄色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_GREEN_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 255, 0)); //绿色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_BLUE_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 0, 255)); //蓝色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_CYAN_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 255, 255)); //靛青色
}
led.show(); //刷新显示
delay(1000);
}
void handle_LED_PURPLE_HOLD() {
timer1.detach();
timer2.detach();
timer3.detach();
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(139, 0, 255)); //紫色
}
led.show(); //刷新显示
delay(1000);
}
//-------------------------------------------
void handle_LED_RED_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 1;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_ORANGE_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 2;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_YELLOW_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 3;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_GREEN_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 4;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_BLUE_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 5;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_CYAN_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 6;
timer3.attach(0.1,timer3_cb,0);
}
void handle_LED_PURPLE_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
run_color = 7;
timer3.attach(0.1,timer3_cb,0);
}
//-------------------------------------------
void handle_LED_COLORS_RUN() {
timer1.detach();
timer2.detach();
timer3.detach();
run_count = 0;
timer2.attach(0.1,timer2_cb,0);
}
void handle_LED_COLORS_CHANGE() {
timer1.detach();
timer2.detach();
timer3.detach();
color_change = 0;
timer1.attach(1,timer1_cb,0);
}
//-------------------------------------------
void timer1_cb(int led_pin) {
switch(color_change) {
case 0:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 0, 0)); //红色
}
led.show(); //刷新显示
delay(1000);
break;
case 1:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 165, 0)); //橙色
}
led.show(); //刷新显示
delay(1000);
break;
case 2:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(255, 255, 0)); //黄色
}
led.show(); //刷新显示
delay(1000);
break;
case 3:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 255, 0)); //绿色
}
led.show(); //刷新显示
delay(1000);
break;
case 4:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 0, 255)); //蓝色
}
led.show(); //刷新显示
delay(1000);
break;
case 5:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(0, 255, 255)); //靛青色
}
led.show(); //刷新显示
delay(1000);
break;
case 6:
for(int i=0; i<NUMPIXELS; ++i) {
led.setPixelColor(i,led.Color(139, 0, 255)); //紫色
}
led.show(); //刷新显示
delay(1000);
break;
}
color_change++;
color_change = color_change%7;
}
void timer2_cb(int led_pin) {
led.clear();
led.show();
delay(1000);
for(int i=run_count; i<run_count+5; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 0, 0)); //红色
}
for(int i=run_count+5; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 165, 0)); //橙色
}
for(int i=run_count+10; i<run_count+15; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 255, 0)); //黄色
}
for(int i=run_count+15; i<run_count+20; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 255, 0)); //绿色
}
for(int i=run_count+20; i<run_count+25; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 0, 255)); //蓝色
}
for(int i=run_count+25; i<run_count+30; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 255, 255)); //靛青色
}
for(int i=run_count+30; i<run_count+35; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(139, 0, 255)); //紫色
}
led.show();
delay(1000);
run_count++;
run_count = run_count%35;
}
void timer3_cb(int led_pin) {
led.clear();
led.show();
delay(1000);
switch(run_color) {
case 1:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 0, 0)); //红色
}
led.show(); //刷新显示
delay(1000);
break;
case 2:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 165, 0)); //橙色
}
led.show(); //刷新显示
delay(1000);
break;
case 3:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(255, 255, 0)); //黄色
}
led.show(); //刷新显示
delay(1000);
break;
case 4:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 255, 0)); //绿色
}
led.show(); //刷新显示
delay(1000);
break;
case 5:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 0, 255)); //蓝色
}
led.show(); //刷新显示
delay(1000);
break;
case 6:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(0, 255, 255)); //靛青色
}
led.show(); //刷新显示
delay(1000);
break;
case 7:
for(int i=run_count; i<run_count+10; ++i) {
led.setPixelColor(i%NUMPIXELS,led.Color(139, 0, 255)); //紫色
}
led.show(); //刷新显示
delay(1000);
break;
}
run_count++;
run_count = run_count%35;
}
//=========================================================
void setup() {
/* 1. 初始化串口通讯波特率为115200*/
Serial.begin(115200);
/* 2. 开启wifi连接,连接成功后打印IP地址 */
WiFi.softAP(ssid, password); // 此语句是重点。WiFi.softAP用于启动NodeMCU的AP模式。
// 括号中有两个参数,ssid是WiFi名。password是WiFi密码。
// 这两个参数具体内容在setup函数之前的位置进行定义。
Serial.print("\r\nAccess Point: "); // 串口监视器输出热点ssid
Serial.println(ssid);
Serial.print("IP address: "); // 串口监视器输出热点IP
Serial.println(WiFi.softAPIP());
/* 3. 开启http网络服务器功能 */
esp8266_server.begin(); // 启动http网络服务器
esp8266_server.on("/", handleRoot); // 设置请求根目录时的处理函数函数
esp8266_server.onNotFound(handleNotFound); // 设置无法响应时的处理函数
esp8266_server.on("/LED_OFF", handle_LED_OFF); // 设置关灯的处理函数函数
esp8266_server.on("/LED_RED_HOLD", handle_LED_RED_HOLD); // 设置红色常亮的处理函数函数
esp8266_server.on("/LED_ORANGE_HOLD", handle_LED_ORANGE_HOLD); // 设置橙色常亮的处理函数函数
esp8266_server.on("/LED_YELLOW_HOLD", handle_LED_YELLOW_HOLD); // 设置黄色常亮的处理函数函数
esp8266_server.on("/LED_GREEN_HOLD", handle_LED_GREEN_HOLD); // 设置绿色常亮的处理函数函数
esp8266_server.on("/LED_BLUE_HOLD", handle_LED_BLUE_HOLD); // 设置蓝色常亮的处理函数函数
esp8266_server.on("/LED_CYAN_HOLD", handle_LED_CYAN_HOLD); // 设置靛青色常亮的处理函数函数
esp8266_server.on("/LED_PURPLE_HOLD", handle_LED_PURPLE_HOLD); // 设置紫色常亮的处理函数函数
esp8266_server.on("/LED_RED_RUN", handle_LED_RED_RUN); // 设置红色跑马的处理函数函数
esp8266_server.on("/LED_ORANGE_RUN", handle_LED_ORANGE_RUN); // 设置橙色跑马的处理函数函数
esp8266_server.on("/LED_YELLOW_RUN", handle_LED_YELLOW_RUN); // 设置黄色跑马的处理函数函数
esp8266_server.on("/LED_GREEN_RUN", handle_LED_GREEN_RUN); // 设置绿色跑马的处理函数函数
esp8266_server.on("/LED_BLUE_RUN", handle_LED_BLUE_RUN); // 设置蓝色跑马的处理函数函数
esp8266_server.on("/LED_CYAN_RUN", handle_LED_CYAN_RUN); // 设置靛青色跑马的处理函数函数
esp8266_server.on("/LED_PURPLE_RUN", handle_LED_PURPLE_RUN); // 设置紫色跑马的处理函数函数
esp8266_server.on("/LED_COLORS_RUN", handle_LED_COLORS_RUN); // 设置七彩跑马的处理函数函数
esp8266_server.on("/LED_COLORS_CHANGE", handle_LED_COLORS_CHANGE);// 设置七彩变换的处理函数函数
Serial.println("HTTP esp8266_server started");// 告知用户ESP8266网络服务功能已经启动
/* 4. 初始化WS2812B */
led.begin();
led.setBrightness(255); //设置亮度 (0~255)
}
void loop() {
esp8266_server.handleClient(); // 处理http访问,需要一直运行
}