基于ThingsCloud与ESP32开发的自定义氛围灯复现

项目源于我在B站刷到的氛围灯设计,利用ThingsCloud云平台与ESP32完成,具有炫彩氛围灯的效果,我对官方给出的例程完成了复现。


前言

本项目是个人对ThingsCloud分享的开源项目的复现


`

一、前期准备

1、VScode:作为esp32编写代码及调试下载的平台,使用platform插件配置esp32编译环境,具体参考其他大佬的讲解。
2、ESP32硬件开发板一块:淘宝购买普通款即可
3、WS2812灯环(注意是灯环)
4、杜邦线、面包板等

二、硬件介绍

1、ESP-WROOM-32

在这里插入图片描述

2、WS2812灯环

WS2812数字灯带采用串行通讯方式进行数据传输,每个灯带芯片都包含了一个控制器和三个LED灯。在传输过程中,控制器会接收到来自外部的RGB颜色值和亮度信息,并通过内部控制电路对LED灯进行控制。

具体地说,WS2812使用了一种特殊的时序控制方式,将RGB颜色值和亮度信息转化为一系列高低电平信号,通过串行通讯方式传输到下一个灯带芯片。每个灯带芯片会根据接收到的数据控制三个LED灯的亮度和颜色,同时将剩余的数据传输给下一个芯片,最终形成一个连续的灯带效果。

由于WS2812芯片集成了控制电路和LED灯,使得其具有简单、紧凑的结构和较低的功耗。同时,该灯带支持大量的颜色、亮度、变化效果组合,可以满足不同场景的需求。

通俗的说,WS2812只有一个输入口,但可以通过控制每一个芯片接收数据的不同来控制RGB颜色。
在这里插入图片描述

三、软件介绍

打开vscode,创建一个ESP32工程,导入thingscloud开源的氛围灯例程代码,我将详细的进行分析:

1.引入库

代码如下:

#include <Arduino.h>
#include <Adafruit_NeoPixel.h>//RGB外设库头文件
#include <DHT.h>//DHT11温湿度监测
#include <ThingsCloudMQTT.h>//thingscloud的MQTT协议头文件
#include <ThingsCloudWiFiManager.h>//wifi管理头文件
#include <ArduinoJson.h>
#include <WiFi.h>
#include <PubSubClient.h>
//=========================================================================
//mqtt相比htpp是更适合于物联网云端与用户端通信的协议,htpp仅适合于云端接收设备数据,而mqtt还另外具有上位机向设备发送命令的作用
#ifdef __AVR__
  #include <avr/power.h>
#endif

2.配置wifi、mqtt、RGB

由于我对代码进行了详细注释,故不做额外解释,代码如下:

const char ssid[] = "";    // WIFI账户
const char password[] = "";     // WIFI密码
//thingscloud云平台配置
// 在 ThingsCloud 控制台的设备详情页中,复制以下设备连接信息
#define mqtt_broker "bj-2-mqtt.iot-api.com"
#define mqtt_port 1883
#define PROJECT_KEY ""
String ACCESS_TOKEN = "";
//=============================================================================
WiFiClient net;//给库WIFiclient实例化一个类net

void callback(char *topic,byte *payload,unsigned int length);
PubSubClient mqtt(mqtt_broker,mqtt_port,callback,net);//实例化库PUBsubclient的一个类mqtt


//RGB灯配置
#define LED_COUNT 12//告诉字符串特定字符串上有多少个像素,即彩灯数量
#define PIN_PIXS 18//设置使18号引脚来控制灯环
#define BRIGHTNESS 50 // 设置亮度,从0到255取值
Adafruit_NeoPixel strip=Adafruit_NeoPixel(LED_COUNT,PIN_PIXS,NEO_GBR+NEO_KHZ800);//该函数用于实例化一个此类
  //Adafruit_NeoPixel(LED_COUNT,PIN_PIXS,NEO_GBR+NEO_KHZ800);//该函数用于实例化一个此类,三个参数分别为灯环LED数,引脚号,800KHz比特流设定
int red =0;
int green =0;
int blue =0;
int rgb=255;
String glow_mode ="1";//发光模式
u8_t speed=50;
bool led_state=false;

unsigned long lastMillis = 0;

3.自定义RGB显示效果

这些显示效果均来自库Adafruit_NeoPixel,github有开源库和例程。

uint32_t Wheel(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 colorWipe(uint32_t c, uint8_t wait) {
    
    
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    
    
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
  }
void rainbow(uint8_t wait) {
    
    
  uint16_t i, j;

  for(j=0; j<256; j++) {
    
    
    for(i=0; i<strip.numPixels(); i++) {
    
    
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
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< strip.numPixels(); i++) {
    
    
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

4.wifi连接及提示函数

void connect()
{
    
    
  Serial.print("check wifi connect......");
  while (WiFi.status()!=WL_CONNECTED)//若没有连接成功
{
    
    
  Serial.print(".");
  delay(1000);
}

Serial.print("\nconnecting...");
if(mqtt.connect("", ACCESS_TOKEN.c_str(), PROJECT_KEY))//connect函数的三个参数为:id,username,password
//connect函数说明:连接mqtt服务,布尔型,判断是否连接成功
{
    
    
  //subscribe函数的参数topic是主题,用于查看是否订阅成功,订阅主题只需要在设备mqtt成果连接云平台后执行一次即可
  mqtt.subscribe("command/send/+");//这个主题是接收下发的命令
  mqtt.subscribe("attributes/push");//这个主题是:当云平台下发属性给设备时,设备会通过以上订阅主题,收到json结构的消息
  mqtt.subscribe("attributes/get/response/+");//这个主题是:接收属性获取的响应
}
Serial.print("\nconnecting successful!");
}

5.解析云平台的属性

void parse_cloud_attributes(JsonObject obj){
    
    
  if(obj.containsKey("red")){
    
    //obj调用其方法containskey,判断是否包含指定的键值red
    red = obj["red"];
  }
  if(obj.containsKey("green")){
    
    
    green = obj["green"];
  }
  if(obj.containsKey("blue")){
    
    
    blue = obj["blue"];
  }
  if(obj.containsKey("rgb_number")){
    
    
    rgb = obj["rgb_number"];
  }
  if(obj.containsKey("glow_mode")){
    
    
    const char *mode =obj["glow_mode"];
    glow_mode=String(mode);
  }
  if(obj.containsKey("speed")){
    
    
    speed = obj["speed"];
    speed=100-speed;
  }
  if(obj.containsKey("led_state")){
    
    
    led_state = obj["led_state"];
  }
}

6.回调函数

void callback(char *topic,byte *payload,unsigned int length){
    
    
  unsigned int termination_pos;//定义无符号整型变量t_p
  if(strlen(topic)+length+9>=mqtt.getBufferSize()){
    
    //strlen计算第一个字符到\0之间字符个数,getbuffersize函数获取页面缓冲区的大小,默认8KB大小
    termination_pos = length-1;
  }
else
    termination_pos = length;

payload[termination_pos] = '\0';
String payload_str((char*)payload);
String topic_str(topic);

Serial.printf("%s -> %s\n",topic,payload_str.c_str());
//调用
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc,payload_str);
if(error)
{
    
    
  Serial.printf("deserialize error : %s\n",error.f_str());
  return;
}
JsonObject obj = doc.as<JsonObject>();

if(String(topic)=="attributes/get/response/1000"){
    
    //如果接收到了属性获取的响应
  if(obj.containsKey("result")&&obj.containsKey("attributes")){
    
    
    JsonObject attributes = doc["attributes"];
    parse_cloud_attributes(attributes);
  }
}
if(String(topic)=="attributes/push"){
    
    //如果接收下发的属性
   parse_cloud_attributes(obj);
}
}

7.setup函数

void setup() {
    
    
  // put your setup code here, to run once:

  Serial.begin(115200);
  WiFi.begin(ssid,password);
  connect();
  delay(1000);
  mqtt.publish("attributes/get/1000","{}");//publish发布对应主题消息
  strip.begin();//配置ws2812的输入引脚
  strip.show(); // Turn OFF all pixels ASAP
  strip.setBrightness(BRIGHTNESS);//亮度约为五分之一
 // client.enableDebuggingMessages();  // 允许 SDK 的日志输出
 // client.setWifiCredentials(ssid, password);  // 连接 WiFi AP

  //dht11.begin();//初始化dht11
}

8.loop函数

void loop() {
    
    
  // put your main code here, to run repeatedly:
   if(led_state)
   {
    
    
    if(glow_mode=="1"){
    
    colorWipe(rgb,speed);}
    else if (glow_mode=="2")
    {
    
    
      theaterChase(rgb,speed);
    }
    else if (glow_mode=="3")
    {
    
    
      rainbow(5);
    }
    else if (glow_mode=="4")
    {
    
    
      rainbowCycle(2);
    }
    else if(glow_mode=="5"){
    
    
      theaterChaseRainbow(1);
    }
   }
   else{
    
    //由于led_state初值是false,则一开始执行该语句,显示流水LED灯
    for(uint16_t i=0;i<strip.numPixels();i++)
{
    
    
  strip.setPixelColor(i,0);
  strip.show();
}

   }

   if(!mqtt.connected())//若mqtt没有连接成功,则重复进行连接
   {
    
    
    connect();
   }
   mqtt.loop();//处理消息以及保持心跳
   }

四、效果展示

在这里插入图片描述
在这里插入图片描述
对于thingscloud的相关主题订阅、下发以及数据的传输等我还没有掌握,目前先记录下实践效果,等后续进一步理解esp32与mqtt协议后,将对以上代码中关于解析json函数与回调函数做进一步说明。

猜你喜欢

转载自blog.csdn.net/qq_53092944/article/details/130092890
今日推荐