浏览量: 330 次浏览

智能多模式氛围灯

2020年2月12日 0 作者 Nie Hen

使用的是 ws2812数字灯珠 + esp826601s +mqtt 使用arduino IDE开发
能够实现使用mqtt控制多种彩灯模式

效果演示:

ws2812数字灯珠

enter description here
有信号的输入和输出
有信号的输入和输出

DO是信号输出 DI是信号输入
将多个RGB灯串联,信号进行传输然后实现灯带。
enter description here

有很多种 我使用是这种来充当led灯
enter description here

联合esp826601s使用

只需要一个GPIO给ws2812 信号端就可以
因此考虑使用esp8266 -01s的GPIO2

对esp8266 mqtt 使用arduino开发没有基础的同学可以先看这几篇文章

esp8266 mqtt 使用arduino开发教程

MQTT协议介绍与应用

esp8266-01s介绍与使用

前期使用 fast led 库 多次尝试不成功,
查资料发现 由于ws2812 需要连续的扫描 频率很大,而esp01s频率不足所以在前期尝试的时候都没成功,但是使用ws2812只需要一个引脚 使用12f显得浪费

查找了很多资料发现使用Adafruit_NeoPixel.h 可以实现
下面会讲

只需要ws2812 的信号引脚接到 esp01s的GPIO2
5v接到电源5v
GND接地
这里推荐使用 这种模块 方便简单
enter description here

接线省事很多
enter description here

Adafruit_NeoPixel库

用于控制基于单线的LED像素和条带

安装

IDE内安装:
– 在arduino IDE中 项目—》加载库—-》管理库
– 然后使用搜索栏搜索Neopixel strip。
– 选择版本进行安装

源码安装:

  • 找到源码 GitHub链接下载下来
  • 下载后,将文件夹重命名为“ Adafruit_NeoPixel”并安装在Arduino Libraries文件夹中
  • 重新启动Arduino IDE,打开示例 找到这个库的示例代码
支持的芯片

enter description here

使用

有两种创建灯带形式

  • 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);
  }
}