浏览量: 332 次浏览

智能无线多级控制照明灯

2020年2月12日 1 作者 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() 显示灯带

    这些函数控制对象 就是前面创建的灯带对象(可以看下面的示例代码)

在使用时可以根据自己需要显示的样子
编写控制灯珠颜色 亮度变化的代码
当然也可以使用这个库提供的一些示例代码 也是很有意思的

示例代码

内含注释

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

//使用的引脚
#define PIN            6
//数字灯珠数量
#define NUMPIXELS      16

// 当我们设置NeoPixel库时,我们告诉它要使用多少像素,以及使用哪个pin发送信号。

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second
void setup() {
  // 这是5V 16MHz的小饰品,如果不使用小饰品,可以去掉这三条线
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  pixels.begin(); // 这将初始化neopix库。
}
void loop() {

  // 对于一组NeoPixel,第一个NeoPixel是0,第二个是1,一直到像素数减1为止.
  for(int i=0;i<NUMPIXELS;i++){
    // pixels.Color 设置RGB的值 区间是 0,0,0 到 255,255,255
    pixels.setPixelColor(i, pixels.Color(0,150,0)); // 中等明亮的绿色。
    pixels.show(); // 这会将更新的像素颜色发送到硬件。
    delay(delayval); // 延迟一段时间(以毫秒为单位)。
  }
}

这个库的GitHub链接

代码

在这个项目中 只需要显示白色
多级调节 其实也就是调节灯珠的亮度
mqtt发过来一个数字值,然后控制亮度变化
思路很简单

使用的函数

将LED灯珠变为全部白色 设置亮度只需要改变传入的第一个参数即可

在亮度等级调整的时候,为了变换没有那么突兀,程序里面采用的是逐渐变化.而不是直接的全部设为目标亮度。


int bright = 0; void pulseWhite(uint8_t result,uint8_t wait) { // 第一个参数为要变为的亮度值 第二个参数为变化间隔的时间单位为毫秒 if (bright < result){ for(int j = bright; j < result ; j++){ for(uint16_t i=0; i<pixels.numPixels(); i++) { pixels.setPixelColor(i, pixels.Color(j,j,j) ); } delay(wait); pixels.show(); } bright = result; }else if(bright > result){ for(int j = bright; j >= result ; j--){ for(uint16_t i=0; i<pixels.numPixels(); i++) { pixels.setPixelColor(i, pixels.Color(j,j,j) ); } delay(wait); pixels.show(); } bright = result; } }

完整代码:

// 作者 : 涅痕 
// 更多IOT开发 访问 niehen.cn
#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 = 0;
String tmpTopic;
String strplayload;
int bright = 0;

void setup_wifi() {
  delay(10);
  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("itgzs/led_light/status", "get older ");
  if (strplayload == "off") {  // 判断是否是off 关闭指令
      value = 0;
      client.publish("itgzs/led_light/status", "led_light 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<=5){
          value = older_led;
          client.publish("led_light/status","led_light is running");
        }
    }
  }

}                                                                                                                                                                                                                                                                                                   
void reconnect() {

  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_light/status", "init...");

      client.subscribe("led_light/older");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      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 {
    pulseWhite(value*51,20); // 5个等级

    }
   if (!client.connected()) {
    reconnect();
  }
  client.loop();
}
void pulseWhite(uint8_t result,uint8_t wait) {  // 第一个参数为要变为的亮度值 第二个参数为变化间隔的时间单位为毫秒
  if (bright < result){
  for(int j = bright; j < result ; j++){
      for(uint16_t i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, pixels.Color(j,j,j) );
        }
        delay(wait);
        pixels.show();
      }
      bright = result;
  }else if(bright > result){
  for(int j = bright; j >= result ; j--){
      for(uint16_t i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, pixels.Color(j,j,j) );
        }
        delay(wait);
        pixels.show();
      }
      bright = result;
  }  
}