智能多模式氛围灯
使用的是 ws2812数字灯珠 + esp826601s +mqtt 使用arduino IDE开发
能够实现使用mqtt控制多种彩灯模式
效果演示:
ws2812数字灯珠
有信号的输入和输出
有信号的输入和输出
DO是信号输出 DI是信号输入
将多个RGB灯串联,信号进行传输然后实现灯带。
有很多种 我使用是这种来充当led灯
联合esp826601s使用
只需要一个GPIO给ws2812 信号端就可以
因此考虑使用esp8266 -01s的GPIO2
对esp8266 mqtt 使用arduino开发没有基础的同学可以先看这几篇文章
前期使用 fast led 库 多次尝试不成功,
查资料发现 由于ws2812 需要连续的扫描 频率很大,而esp01s频率不足所以在前期尝试的时候都没成功,但是使用ws2812只需要一个引脚 使用12f显得浪费
查找了很多资料发现使用Adafruit_NeoPixel.h 可以实现
下面会讲
只需要ws2812 的信号引脚接到 esp01s的GPIO2
5v接到电源5v
GND接地
这里推荐使用 这种模块 方便简单
接线省事很多
Adafruit_NeoPixel库
用于控制基于单线的LED像素和条带
安装
IDE内安装:
– 在arduino IDE中 项目—》加载库—-》管理库
– 然后使用搜索栏搜索Neopixel strip。
– 选择版本进行安装
源码安装:
- 找到源码 GitHub链接下载下来
- 下载后,将文件夹重命名为“ Adafruit_NeoPixel”并安装在Arduino Libraries文件夹中
- 重新启动Arduino IDE,打开示例 找到这个库的示例代码
支持的芯片
使用
有两种创建灯带形式
- GRB:绿红蓝三基色 值从0到255
- GRBW:在RGB的基础上加上一种白光,增加亮度的作用。
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); // 创建 GRB灯带
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800); // 创建 GRBW灯带
在使用时 显示的形式不一样
函数
- begin() 灯带初始化
- setPixelColor() 设置灯带的颜色(第一个参数是灯珠索引,第二个是颜色值(GRB或GRBW))
- setBrightness() 设置灯带的亮度(第一个参数是灯珠索引,第二个是亮度值0-255)
- show() 显示灯带
…
这些函数控制对象 就是前面创建的灯带对象(可以看下面的示例代码)
在使用时可以根据自己需要显示的样子
编写控制灯珠颜色 亮度变化的代码
当然也可以使用这个库提供的一些示例代码 也是很有意思的
彩灯模式
彩虹灯
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< pixels.numPixels(); i++) {
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
}
pixels.show();
delay(wait);
}
}
另一种彩虹灯
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<pixels.numPixels(); i++) {
pixels.setPixelColor(i, Wheel((i+j) & 255));
}
pixels.show();
delay(wait);
}
}
更多彩灯模式 可以到Adafruit_NeoPixel 库的示例中进行查找 使用
代码
通过mqtt发送指令 esp模块收到指令 并控制ws2812显示相应的彩灯模式
完整代码
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define PIN 2
#define NUM_LEDS 8
#define BRIGHTNESS 50
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);// RGBW 与RGB在创建灯带时不一样
const char* ssid = "niehen_pc";
const char* password = "*";
const char* mqtt_server = "192.168.137.41";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 1;
String tmpTopic;
String strplayload;
int bright = 0;
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
tmpTopic = String((char *)topic);
payload[length] = '\0';
strplayload = String((char*)payload);
client.publish("led_color/status", "get older ");
if (strplayload == "off") { // 判断是否是off 关闭指令
value = 0;
client.publish("led_color/status", "led_play stop");
}else {
int isint = 0;// 如果有字母 就为1 全数字就为0
for (int i=0; i< strplayload.length();i++) // 检测接收到的命令里面是否含有 非数字的字符
{
if (!isDigit(strplayload[i]))
{
isint = 1;
break;
}
}
if(isint == 0){
int older_led = strplayload.toInt() ; // 转换为 int类型
if(older_led >=0 && older_led<=2){
value = older_led;
char* pub_status = "led_play is running";
pub_status[19] = '0' + value;
client.publish("led_color/status",pub_status);
}
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.publish("led_color/status", "init...");
// ... and resubscribe
client.subscribe("led_color/transform/older");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
pixels.setBrightness(BRIGHTNESS);
pixels.begin();
pulseWhite(1,5);
delay(10);
pulseWhite(0,5);// 出现bug 开灯后 有一个灯亮 这是解决办法
}
void loop() {
if (value == 0){
pulseWhite(0,20);
}else if(value == 1)
rainbow(20);
else if(value == 2)
rainbowCycle(20);
if (!client.connected()) {
reconnect();
}
client.loop();
}
void pulseWhite(uint8_t result,uint8_t wait) { // 第一个参数为要变为的亮度值 第二个参数为变化间隔的时间单位为毫秒
for(uint16_t i=0; i<pixels.numPixels(); i++) {
pixels.setPixelColor(i, pixels.Color(result,result,result) );
}
delay(wait);
pixels.show();
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<pixels.numPixels(); i++) {
pixels.setPixelColor(i, Wheel((i+j) & 255));
}
pixels.show();
delay(wait);
}
}
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< pixels.numPixels(); i++) {
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
}
pixels.show();
delay(wait);
}
}