查看: 1822|回复: 10

[分享] Blinker项目实例:Nodemcu驱动ws2812(附项目代码)

[复制链接]

该用户从未签到

发表于 2020-3-7 21:41 | 显示全部楼层 |阅读模式
!!!页面很难插入图片,完整请看附件!!!
!!!页面很难插入图片,完整请看附件!!!
!!!页面很难插入图片,完整请看附件!!!

##一、 实验目的和要求
#1)设计并开发一个网络应用软件系统 二、 实验内容和原理 实验内容:        本实验的目的是设计并开发一个物联网彩灯系统,用于智能化的居家氛围布置、照明。系统的操控方式为手机APP控制,通过MQTT远程实现。完成的功能有自由控制颜色、亮度,既可以所有的LED灯一起进行操作,也可以对单独LED等进行操作;一键彩灯,按下按钮,即可按照设定好的氛围光亮起彩灯,营造独特的氛围。本实验对氛围光只设定一个模式作为例子,具体应用时完全可以添加更多的模式。另外,彩灯不仅使用与氛围布置,还兼容学习场合,一键可以调整至护眼模式。
开发语言:C语言(Arduino平台)
#三、 架构设计:
1、 硬件部分。硬件包括一块Nodemcu开发板、一个WS2812灯带、一台智能手机。
1Nodemcu开发板。NodeMCU,是一个开源的物联网平台,使用esp8266作为核心 它使用Lua脚本语言编程,同时也可以使用Arduino进行编程。硬件配置主要有16GPIO引脚,可实现1个模拟I/O11个数字I/O。通讯接口有一个USB口、一个串口和一个Wifi通讯模块。本实验主要用到GPIO引脚来驱动WS2812,使用Wifi模块连接网络与服务器、手机进行通讯。

2WS2812WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和12V高压可编程定电流控制部分,有效保证了像素点光的颜色高度一致。数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。LED具有低电压驱动,环保节能,亮度高,散射角度大,一致性好,超低功率,超长寿命等优点。将控制电路集成于LED上面,电路变得更加简单,体积小,安装更加简便。
2、 软件部分。blinker是一套跨硬件、跨平台的物联网解决方案,提供APP端、设备端、服务器端支持,使用公有云服务进行数据传输存储。可用于智能家居、数据监测等领域,可以帮助用户更好更快地搭建物联网项目。Blinker由服务器端、app端、设备端组成,可以部署到几乎所有物联网平台,使用WiFiMQTT等方式接入,服务器端可以部署到阿里云、腾讯云、OneNET、百度云、AWSgoogle cloud等平台,通过界面布局器,DIY用户可自己拖拽布局设备控制界面,自由打造专属的物联网设备。![在这里插入图片描述]()3、 系统连接。
1NodemcuWS2812的连接方式如下:

以上红色箭头分别是D7GNDVCC,其中NodemcuVccws2812Vcc相连,NodemcuGNDws2812GND相连,NodemcuD7ws2812S(信号线)相连。


需要注意的是,ws2812所有的灯全亮电流超过500mA,无法通过电脑进行供电,需要外接电源。因此ws2812其实有两根VCC和两根GND。这两根线是短路的,具体连接的时候一根GND连接NodemcuGND,另一根GND连接5V直流电源的GND。但是VCC不能两根都连,一根VCC连接5V直流电源,另外一根VCC悬空。另外,信号线和NodemcuD7相连即可。(1Nodemcu和手机APP的通信。本实验没有直接搭建服务器,而是采用了blinker解决方案的服务器。Nodemcu需要处于一个有wifi的局域网环境下,通过wifi接入Internet。通讯使用MQTT方式,即便用户离开了现场也能够进行操控。Nodemcu将秘钥发送到blinker服务器并建立连接,手机APP通过开关按键发送秘钥到服务器同样建立连接。服务器识别到Nodemcu和客户端同时发来了秘钥后,开始在两者之间传递命令协议。每个命令的发出都需要两步,一是客户端向Nodemcu发送指令,二是Nodemcu返回一个确认信息,客户端接收到之后确认操作完成。
三、主要仪器设备
1、一块Nodemcu开发板
2、一个WS2812灯条
3Blinker手机app
四、设计要点        1)下载正确的库文件。本实验对ws2812的操作与对单个LED不同,点亮单个基色LED编写好PWM程序就可以调节亮度,不同亮度的三基色LED叠在一起就能呈现不同的颜色。但是ws2812是成线性排列的,所有的LED公用同一个根信号线,因此不能对LED进行单独操作。此处需要用到ws2812的库函数对其进行操作。        github中搜索blinker library找到资源并下载,将下载好的blinker库解压到 我的电脑>文档>Arduino>libraries 文件夹中


2)获得IoT设备秘钥。秘钥相当于一个设备的ID,服务器要找到特定的IoT设备,必须依赖该秘钥。打开blinker app,点击右上角的‘+’号,选择Arduino,获得秘钥并复制。
3)代码中的IoT秘钥、wifi名称、wifi秘钥必须正确输入,否则设备无法与服务器连接。


4)组件名称要和代码对应。如LEDNum对应Number_1LED_R对应Number_2.

四、 实验结果与分析
1、搭建好的硬件如下:
2APP界面及组件如下:
3、工作时间显示:工作时间能够实时更新
2、自由控制(整体)模式:按下自由模式,按钮高亮,点击任一颜色,灯颜色改变,手机上显示对应RGB值。图中可以看出选中绿色RGB[0,255,52]
3、七彩模式:按下七彩模式,按钮高亮,ws2812直接显示一个绚烂的彩色灯条。
4、逐个调节模式。按下逐个调节模式按钮,按钮高亮。这时可以按顺序依次调节每一个灯珠的RGB值,当从第一个到最后一个都调整过以后,又重新回到第一个,循环进行。实验中为了显示每个灯珠都可以自由调节,特意相邻的灯珠选择了反差明显的颜色。
5、护眼照明模式。按下护眼照明模式按钮,按钮高亮。一键调整至护眼模式,此时是柔和的黄光。
以上结果达到预期要求。另外需要说明的是,本实验对灯光效果只设定一个模式作为例子,具体应用时完全可以添加更多的模式。
五、实验注意1、本实验主要的代码内容是硬件设备Nodemcu上的,编写硬件代码比较麻烦的是参数的选取(关系到硬件是否能正产工作)。实验时一开始时将ws2812144个灯珠全部点亮,带来了严重的问题,电脑突然掉电。重启后Windows系统提示USB口电流过大,无法继续使用。幸好内部电路没有破坏性损坏,冷却下来之后仍然能继续工作,否则我的电脑就会损失一个USB口。2、明确电脑无法直接给ws2812供电之后,又找了一个220V5V的电源适配器来给ws2812供电(先接在面包板上再借ws2812)。这样一来144LED灯珠都能正常工作。然而偶然触摸面包板温度非常高,迅速拔掉电源后发现面包板已经严重融化。可见144个灯珠同时亮起电流过大。3、最终才确定只点亮20LED灯珠,防止再次出现意外。
六、附实验代码(C语言)
```c
六、附实验代码(C语言)#define BLINKER_WIFI#include
<Blinker.h>#include<math.h>
char auth[] = "692310ffgrt";//IoT秘钥
char ssid[] = "ONEPLUS";//wifi名称
char pswd[] = "55555555"; //wifi秘钥
bool tab[5] = { false };
bool modestate[4] = { false }; //工作模式选项卡
bool AutoBit= false; //判断手动模式是否有效
bool SingleAdjust= false;//判断逐个调节是否有效
int LEDserial=0;//
int Offset=20;  //灯珠整体移动若干单位
#include <Adafruit_NeoPixel.h>#ifdef __AVR__  #include <avr/power.h>#endif #if defined (__AVR_ATtiny85__)  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);#endif  #define PIN            13#define NUMPIXELS      20#define RGB_1 "RGBKey"#define Tab_1 "tab-mode"#define Number_1 "LEDNum"#define Number_2 "LED_R"#define Number_3 "LED_G"#define Number_4 "LED_B"  BlinkerRGB WS2812(RGB_1);BlinkerTab Tab1(Tab_1);//定义数据结构
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
BlinkerNumber Number1 (Number_1);
BlinkerNumber Number2 (Number_2);
BlinkerNumber Number3 (Number_3);
BlinkerNumber Number4 (Number_4); //*************************************************************//选项卡触发函数
void tab1_callback(uint8_t tab_set){    //BLINKER_LOG("get tab set: ", tab_set);   
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));     
switch (tab_set)    {        
case BLINKER_CMD_TAB_0 :            
tab[0] = true;            //BLINKER_LOG("tab 0 set");            
AutoBit=!AutoBit;//手动位取反            
break;        
case BLINKER_CMD_TAB_1 :            
tab[1] = true;            //BLINKER_LOG("tab 1 set");            
Mode1();//开启Mode1,灯光模式1            
break;                    
case BLINKER_CMD_TAB_2 :            
tab[2] = true;            //BLINKER_LOG("tab 2 set");            
SingleAdjust=!SingleAdjust;//开启Mode2,灯光模式2            break;        
case BLINKER_CMD_TAB_3 :            
tab[3] = true;            //BLINKER_LOG("tab 3 set");            
Mode3();//开启Mode3,流水灯模式            
break;        
case BLINKER_CMD_TAB_4 :            
tab[4] = true;            //BLINKER_LOG("tab 4 set");            
break;        
default:            
break;    }}
void tab1_feedback(){
   
for(uint8_t num = 0; num < 5; num++)    {        
if (tab[num])        {            
Tab1.tab(num);            
tab[num] = false;        }    }   
Tab1.print();}  //*******************************************************************//自由模式整体调节/逐个调节服务函数
void ws2812_callback(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value){   
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));   
if (AutoBit==true){           digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));         
Mode0(r_value,g_value,b_value,bright_value);       return NULL;    }   
else if(SingleAdjust==true){      digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));      
Mode2(r_value,g_value,b_value,bright_value);    }}
//********************************************************************//自由控制(整体调节)Mode0
void Mode0(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value){   
pixels.setBrightness(bright_value);   
for(int i = 0; i < NUMPIXELS; i++){   
pixels.setPixelColor(i, r_value, g_value, b_value);        }   
pixels.show();     
Number2.print(r_value);   
Number3.print(g_value);   
Number4.print(b_value);}
//********************************************************************//七色模式Mode1
void Mode1(){   
int r=0;    int g=0;    int b=0;    int i=0;    int full=NUMPIXELS;   
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));   
for(int i=0;i<NUMPIXELS;i++){           if(i<full/3){            r=255;            g=ceil(255*3*i/full);            b=0;            }else if(i<full/2){                r=ceil(750-i*(250*6/full));                g=255;                b=0;            }else if(i<full*2/3){                r=0;                g=255;                b=ceil(i*(250*6/full)-750);            }else if(i<full*5/6){                r=0;                g=ceil(1250-i*(250*6/full));                b=255;            }else{                r=ceil(150*i*(6/full)-750);                g=0;                b=255;                  }             pixels.setPixelColor(i, pixels.Color(r,g,b));             }    pixels.show();     }//********************************************************************//逐个调节Mode2
void Mode2(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value){     pixels.setBrightness(bright_value);    pixels.setPixelColor(LEDserial, r_value, g_value, b_value);      pixels.show();        LEDserial=LEDserial+1;    LEDserial= LEDserial % NUMPIXELS;    Number2.print(r_value);    Number3.print(g_value);    Number4.print(b_value);    }//*******************************************************************//护眼照明模式 黄光Mode3
void Mode3(){        int bright_value=200;        int r_value=255;        int g_value=215;        int b_value=0;        pixels.setBrightness(bright_value);        for(int i = 0; i < NUMPIXELS; i++){        pixels.setPixelColor(i, r_value, g_value, b_value);        }               pixels.show();           Number2.print(r_value);        Number3.print(g_value);        Number4.print(b_value);}//*******************************************************************//显示数值
void dataRead(const String & data){    uint32_t BlinkerTime = millis();     Number1.print(BlinkerTime/1000);}  //*********************************************************************
void setup(){    Serial.begin(115200);    BLINKER_DEBUG.stream(Serial);        Blinker.attachData(dataRead);     pinMode(LED_BUILTIN, OUTPUT);//引脚设置为输出模式   
digitalWrite(LED_BUILTIN, LOW);     Blinker.begin(auth, ssid, pswd);       pixels.begin();//开启pixelws2812输出   
WS2812.attach(ws2812_callback);   
Tab1.attach(tab1_callback,
tab1_feedback);     
}
void loop(){    Blinker.run();}
```
图片1.png
图片2.png
图片3.png
图片4.png
图片5.png
图片6.png
图片7.png
图片12.png
图片11.png
图片10.png
图片9.png
图片8.png
图片27.png
图片26.png
图片25.png
图片22.png
图片24.png
图片23.png
图片21.png
图片19.png
图片20.png
图片17.png
图片16.png
图片15.png
图片14.png
图片13.png

blinker实例.zip

941.62 KB, 下载次数: 168

该用户从未签到

发表于 2020-3-11 08:36 来自手机 | 显示全部楼层
再来个小爱同学就完美了

该用户从未签到

发表于 2020-3-17 00:01 | 显示全部楼层
你好,我编译时显示
Adafruit_NeoPixel.h: No such file or directory
,请问是哪里没对?

该用户从未签到

发表于 2020-3-17 00:23 | 显示全部楼层
上面那个库文件的问题解决了,可是还是有好多错误,貌似上面的程序的格式有错,请问可以给我源程序吗?
  • TA的每日心情
    慵懒
    2020-3-23 11:15
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2020-3-17 11:43 | 显示全部楼层
    本帖最后由 edayer 于 2020-3-17 11:46 编辑

    代码没隔行段落差评
    求 TCS3200d乱入

    https://www.arduino.cn/thread-94764-1-1.html
  • TA的每日心情
    开心
    2020-4-2 00:20
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2020-4-2 00:24 | 显示全部楼层
    大神能加一个小爱同学的教程吗

    该用户从未签到

    发表于 2020-4-5 22:10 | 显示全部楼层
    稍微修改后的版本,http://t.cn/A6Z3K2gc
  • TA的每日心情
    无聊
    2020-5-23 14:40
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2020-4-9 18:14 | 显示全部楼层
    努力学习中!谢谢分享!
  • TA的每日心情
    开心
    2020-6-2 01:22
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    发表于 2020-5-31 20:36 | 显示全部楼层
    本帖最后由 涟水河 于 2020-5-31 21:19 编辑

    编译搞定了,还在试
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    5分钟带你快速了解新一代开发板:M5STACK
    5分钟带你快速了解新一代
    一、什么是M5Stack M5Stack是一种模块化、可堆叠扩展的开发板,每个模块
    创客火首发无人机编队套装,开启不一样的人工智能教育
    创客火首发无人机编队套装
    2017年国务院发布《新一代人工智能发展规划》,提出要广泛开展人工智能科普活动,在中
    [2019-4-20]RPG无人世界
    [2019-4-20]RPG无人世界
    剧情:主角玄影,为了逃避██的追杀迫不得已发动████在濒死状态来到█
    求助多个开关控制一条WS2812方法
    求助多个开关控制一条WS28
    本人已经写好不同的VIOD的模式 用的是Adafruit_NeoPixel库 但现在需要三个不同的开
    使用VSCode下载arduino的时候报错
    使用VSCode下载arduino的
    在VSCode中选择端口和板子的型号时提示Please check the "arduino.commandPath" in th
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表