Blinker項目實例:Nodemcu驅動ws2812(附項目代碼)

##一、 實驗目的和要求
#(1)設計並開發一個網絡應用軟件系統 二、 實驗內容和原理 實驗內容: 本實驗的目的是設計並開發一個物聯網彩燈系統,用於智能化的居家氛圍佈置、照明。系統的操控方式爲手機APP控制,通過MQTT遠程實現。完成的功能有自由控制顏色、亮度,既可以所有的LED燈一起進行操作,也可以對單獨LED等進行操作;一鍵彩燈,按下按鈕,即可按照設定好的氛圍光亮起彩燈,營造獨特的氛圍。本實驗對氛圍光只設定一個模式作爲例子,具體應用時完全可以添加更多的模式。另外,彩燈不僅使用與氛圍佈置,還兼容學習場合,一鍵可以調整至護眼模式。
開發語言:C語言(Arduino平臺)

#三、 架構設計:
1、 硬件部分。硬件包括一塊Nodemcu開發板、一個WS2812燈帶、一臺智能手機。
(1) Nodemcu開發板。NodeMCU,是一個開源的物聯網平臺,使用esp8266作爲核心 它使用Lua腳本語言編程,同時也可以使用Arduino進行編程。硬件配置主要有16個GPIO引腳,可實現1個模擬I/O和11個數字I/O。通訊接口有一個USB口、一個串口和一個Wifi通訊模塊。本實驗主要用到GPIO引腳來驅動WS2812,使用Wifi模塊連接網絡與服務器、手機進行通訊。在這裏插入圖片描述

(2) WS2812。WS2812B是一個集控制電路與發光電路於一體的智能外控LED光源。其外型與一個5050LED燈珠相同,每個元件即爲一個像素點。像素點內部包含了智能數字接口數據鎖存信號整形放大驅動電路,還包含有高精度的內部振盪器和12V高壓可編程定電流控制部分,有效保證了像素點光的顏色高度一致。數據協議採用單線歸零碼的通訊方式,像素點在上電覆位以後,DIN端接受從控制器傳輸過來的數據,首先送過來的24bit數據被第一個像素點提取後,送到像素點內部的數據鎖存器,剩餘的數據經過內部整形處理電路整形放大後通過DO端口開始轉發輸出給下一個級聯的像素點,每經過一個像素點的傳輸,信號減少24bit。像素點採用自動整形轉發技術,使得該像素點的級聯個數不受信號傳送的限制,僅僅受限信號傳輸速度要求。LED具有低電壓驅動,環保節能,亮度高,散射角度大,一致性好,超低功率,超長壽命等優點。將控制電路集成於LED上面,電路變得更加簡單,體積小,安裝更加簡便。

2、 軟件部分。blinker是一套跨硬件、跨平臺的物聯網解決方案,提供APP端、設備端、服務器端支持,使用公有云服務進行數據傳輸存儲。可用於智能家居、數據監測等領域,可以幫助用戶更好更快地搭建物聯網項目。Blinker由服務器端、app端、設備端組成,可以部署到幾乎所有物聯網平臺,使用WiFi、MQTT等方式接入,服務器端可以部署到阿里雲、騰訊雲、OneNET、百度雲、AWS、google cloud等平臺,通過界面佈局器,DIY用戶可自己拖拽佈局設備控制界面,自由打造專屬的物聯網設備。在這裏插入圖片描述3、 系統連接。
(1)Nodemcu和WS2812的連接方式如下:在這裏插入圖片描述
以上紅色箭頭分別是D7、GND和VCC,其中Nodemcu的Vcc和ws2812的Vcc相連,Nodemcu的GND和ws2812的GND相連,Nodemcu的D7和ws2812的S(信號線)相連。
在這裏插入圖片描述
需要注意的是,ws2812所有的燈全亮電流超過500mA,無法通過電腦進行供電,需要外接電源。因此ws2812其實有兩根VCC和兩根GND。這兩根線是短路的,具體連接的時候一根GND連接Nodemcu的GND,另一根GND連接5V直流電源的GND。但是VCC不能兩根都連,一根VCC連接5V直流電源,另外一根VCC懸空。另外,信號線和Nodemcu的D7相連即可。(1)Nodemcu和手機APP的通信。本實驗沒有直接搭建服務器,而是採用了blinker解決方案的服務器。Nodemcu需要處於一個有wifi的局域網環境下,通過wifi接入Internet。通訊使用MQTT方式,即便用戶離開了現場也能夠進行操控。Nodemcu將祕鑰發送到blinker服務器並建立連接,手機APP通過開關按鍵發送祕鑰到服務器同樣建立連接。服務器識別到Nodemcu和客戶端同時發來了祕鑰後,開始在兩者之間傳遞命令協議。每個命令的發出都需要兩步,一是客戶端向Nodemcu發送指令,二是Nodemcu返回一個確認信息,客戶端接收到之後確認操作完成。

三、主要儀器設備
1、一塊Nodemcu開發板
2、一個WS2812燈條
3、Blinker手機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_1,LED_R對應Number_2.

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

四、 實驗結果與分析
1、搭建好的硬件如下:
在這裏插入圖片描述

在這裏插入圖片描述
2、APP界面及組件如下:

在這裏插入圖片描述

3、工作時間顯示:工作時間能夠實時更新
在這裏插入圖片描述

2、自由控制(整體)模式:按下自由模式,按鈕高亮,點擊任一顏色,燈顏色改變,手機上顯示對應RGB值。圖中可以看出選中綠色RGB是[0,255,52]
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述 在這裏插入圖片描述

3、七彩模式:按下七彩模式,按鈕高亮,ws2812直接顯示一個絢爛的彩色燈條。

在這裏插入圖片描述
在這裏插入圖片描述

4、逐個調節模式。按下逐個調節模式按鈕,按鈕高亮。這時可以按順序依次調節每一個燈珠的RGB值,當從第一個到最後一個都調整過以後,又重新回到第一個,循環進行。實驗中爲了顯示每個燈珠都可以自由調節,特意相鄰的燈珠選擇了反差明顯的顏色。
在這裏插入圖片描述
在這裏插入圖片描述

5、護眼照明模式。按下護眼照明模式按鈕,按鈕高亮。一鍵調整至護眼模式,此時是柔和的黃光。

在這裏插入圖片描述
在這裏插入圖片描述
以上結果達到預期要求。另外需要說明的是,本實驗對燈光效果只設定一個模式作爲例子,具體應用時完全可以添加更多的模式。

五、實驗注意1、本實驗主要的代碼內容是硬件設備Nodemcu上的,編寫硬件代碼比較麻煩的是參數的選取(關係到硬件是否能正產工作)。實驗時一開始時將ws2812的144個燈珠全部點亮,帶來了嚴重的問題,電腦突然掉電。重啓後Windows系統提示USB口電流過大,無法繼續使用。幸好內部電路沒有破壞性損壞,冷卻下來之後仍然能繼續工作,否則我的電腦就會損失一個USB口。2、明確電腦無法直接給ws2812供電之後,又找了一個220V轉5V的電源適配器來給ws2812供電(先接在麪包板上再借ws2812)。這樣一來144個LED燈珠都能正常工作。然而偶然觸摸麪包板溫度非常高,迅速拔掉電源後發現麪包板已經嚴重融化。可見144個燈珠同時亮起電流過大。3、最終才確定只點亮20個LED燈珠,防止再次出現意外。

六、附實驗代碼(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();//開啓pixel對ws2812輸出    
WS2812.attach(ws2812_callback);    
Tab1.attach(tab1_callback, 
tab1_feedback);     
 } 
void loop(){    Blinker.run();}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章