加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 1 工作原理
    • 2 硬件準(zhǔn)備
    • 3 軟件準(zhǔn)備
    • 4 編寫程序
    • 5 關(guān)聯(lián)米家APP和Blinker設(shè)備
    • 6 語(yǔ)音控制測(cè)試
    • 7 進(jìn)階用法
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Arduino應(yīng)用開發(fā)——通過(guò)小愛(ài)同學(xué)控制燈光

10/06 08:55
375
閱讀需 38 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

我之前發(fā)布了一篇關(guān)于如果用手機(jī)APP控制LED燈的文章,是基于Blink APP和它的服務(wù)器實(shí)現(xiàn)的,這一講我們?cè)谥暗幕A(chǔ)上做一些擴(kuò)展,通過(guò)手機(jī)的小愛(ài)同學(xué),使用語(yǔ)音控制燈光。沒(méi)有看過(guò)上一篇博客的同學(xué)可以先看一下。

Arduino應(yīng)用開發(fā)——手機(jī)APP控制LED

1 工作原理

Blinker APP控?zé)粼恚?/strong>

Blinker廠家有自己的一個(gè)服務(wù)器,我們的設(shè)備(esp8266esp32、手機(jī)等)都可以通過(guò)網(wǎng)絡(luò)接入到這個(gè)服務(wù)器,手機(jī)app我們看不到源碼不確定是以什么樣的方式接入的,我主要講一下MCU(esp8266、esp32等)這邊,MCU是通過(guò)WIFI連接到互聯(lián)網(wǎng)的,然后通過(guò)MQTT協(xié)議接入到Blinker的服務(wù)器,MCU作為客戶端,服務(wù)器作為服務(wù)端。具體MQTT的實(shí)現(xiàn)原理這里不多說(shuō)了,光是MQTT這一個(gè)話題都可以寫好多文章了,想深入了解的同學(xué)可以自行查閱資料。

當(dāng)MQTT連成功之后,MCU會(huì)一直偵聽,等待服務(wù)器下發(fā)數(shù)據(jù)。這個(gè)時(shí)候我們可以通過(guò)手機(jī)app操作,比如點(diǎn)一下開燈,服務(wù)器收到這個(gè)開燈命令后會(huì)通過(guò)MQTT發(fā)送命令到MCU,MCU接收到數(shù)據(jù)并解析命令后執(zhí)行點(diǎn)燈的操作。服務(wù)器在這里相當(dāng)于一個(gè)中轉(zhuǎn)站,把手機(jī)的操作轉(zhuǎn)發(fā)到設(shè)備端,實(shí)現(xiàn)了手機(jī)和設(shè)備之間的互動(dòng)。不過(guò)有一點(diǎn)要說(shuō)明的是,設(shè)備和服務(wù)器是通過(guò)MQTT連接的,而手機(jī)app和服務(wù)器則不一定是用MQTT,個(gè)人覺(jué)得用http的可能性更大,但是看不到源碼,所以實(shí)際上是怎么通訊的就不清楚了,這個(gè)也不是很重要,并不影響實(shí)際的使用。

小愛(ài)同學(xué)控?zé)粼?/strong>:

說(shuō)明:這里的小愛(ài)同學(xué)可以是小米手機(jī)里面的小愛(ài),也可以是小米的智能音箱。

前面我們已經(jīng)把我們的設(shè)備(esp8266、esp32等)連接到了Blinker的服務(wù)器,實(shí)現(xiàn)了數(shù)據(jù)的上傳下發(fā)。而Blinker本身是有對(duì)接小愛(ài)同學(xué)的,并且設(shè)定好了一些固定的語(yǔ)音指令。我們只通過(guò)米家APP關(guān)聯(lián)Blinker的賬號(hào)就能實(shí)現(xiàn)小愛(ài)同學(xué)和Blinker服務(wù)器的聯(lián)動(dòng),再結(jié)合之前Blinker服務(wù)器和我們的硬件設(shè)備的連接,就可以間接的實(shí)現(xiàn)小愛(ài)同學(xué)和硬件設(shè)備的交互。

簡(jiǎn)單來(lái)說(shuō)就是我們的語(yǔ)音指令通過(guò)小愛(ài)同學(xué)發(fā)送到Blinker的服務(wù)器,再由Blinker的服務(wù)器轉(zhuǎn)發(fā)到我們的硬件設(shè)備。Blinker服務(wù)器在這里起到一個(gè)數(shù)據(jù)解析、中轉(zhuǎn)的作用。

2 硬件準(zhǔn)備

我這里以ESP8266和ESP32為例講解,其他MCU方法和原理都是一樣的,所以根據(jù)自己的MCU選擇其中一種即可。

硬件配置如下:

模塊 型號(hào) 說(shuō)明
ESP8266 ESP-12F 這是安信可的一款模組,內(nèi)部主要是用樂(lè)鑫的ESP8266EX再加上一個(gè)片外FLASH組成,開發(fā)板型號(hào)是NodeMCU-12F(CH340版本)
ESP32 ESP-WROOM-32 MCU是樂(lè)鑫的一款芯片,開發(fā)板型號(hào)ESP32 DEVKITV1

具體的硬件參數(shù)和電路原理圖這里就不發(fā)出來(lái)了,不同廠家做的開發(fā)板引腳可能會(huì)有點(diǎn)差別。

3 軟件準(zhǔn)備

版本說(shuō)明:

本文測(cè)試時(shí)各軟件使用的版本如下:

軟件 版本 備注
Arduino IDE 1.8.16 Blinker需要配合1.8.x及以上版本的Arduino IDE
ESP8266 package 3.0.2 Blinker需配合使用3.0.0或以上release版本的ESP8266 package
ESP32 package 3.0.2 Blinker需配合使用2.0.0或以上版本的ESP32 package
Blinker arduino package 0.3.9 當(dāng)前最新版本,以后可能會(huì)有更新
Blinker APP 2.5.2(安卓版) 當(dāng)前最新版本,以后可能會(huì)有更新
米家APP 7.5.705.5319(安卓版) 當(dāng)前最新版本,以后可能會(huì)有更新

3.1 Arduino IDE環(huán)境搭建

這個(gè)在我的博客里面講過(guò)很多次了,這里就不再說(shuō)了,不懂的同學(xué)先按上一講把環(huán)境搭好(根據(jù)自己的MCU選擇對(duì)應(yīng)的教程)。

Arduino應(yīng)用開發(fā)——手機(jī)APP控制LED

esp8266開發(fā)入門教程(基于Arduino)——環(huán)境安裝

ESP32 Arduino開發(fā)環(huán)境搭建

3.2 Blinker APP賬號(hào)注冊(cè)和使用

這個(gè)內(nèi)容比較多,這里不再贅述了,不懂的同學(xué)先看下上一講的第4點(diǎn)。

Arduino應(yīng)用開發(fā)——手機(jī)APP控制LED

4 編寫程序

上一講的教程講了怎么用Blinker APP創(chuàng)建設(shè)備并實(shí)現(xiàn)遠(yuǎn)程控制

這一講在這基礎(chǔ)上增加小愛(ài)同學(xué)的語(yǔ)音控制。我們保留上一講的功能,然后增加電源控制和設(shè)備查詢這兩個(gè)回調(diào)函數(shù),這兩個(gè)函數(shù)的接口在Blinker的庫(kù)源碼中已經(jīng)定義好了,我們直接使用即可。我們通過(guò)電源控制回調(diào)函數(shù)實(shí)現(xiàn)LED燈的開關(guān)控制。

示例代碼:

提示:代碼中的WIFI的賬號(hào)和密碼根據(jù)實(shí)際情況修改。

#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT         // 燈設(shè)備            
// #define BLINKER_MIOT_OUTLET        // 插座設(shè)備   
// #define BLINKER_MIOT_MULTI_OUTLET  // 多個(gè)插座設(shè)備         
// #define BLINKER_MIOT_SENSOR        // 傳感器設(shè)備   
// #define BLINKER_MIOT_FAN           // 風(fēng)扇設(shè)備 
// #define BLINKER_MIOT_AIR_CONDITION // 空調(diào)設(shè)備          

#include <Blinker.h>

char auth[] = "e6fce38e525a";    // 設(shè)備密鑰
char ssid[] = "test";            // WIFI賬號(hào)
char pswd[] = "123456789";       // WIFI密碼

#define LED_PIN 2                // LED引腳

// 新建組件對(duì)象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;
bool oState = false;

// 電源控制回調(diào)函數(shù)
void miotPowerState(const String & state)
{
    BLINKER_LOG("need set power state: ", state);

    if (state == BLINKER_CMD_ON) 
    {// 打開開關(guān)
        digitalWrite(LED_PIN, HIGH);  // 開燈

        BlinkerMIOT.powerState("on");
        BlinkerMIOT.print();

        oState = true;
    }
    else if (state == BLINKER_CMD_OFF) 
    {// 關(guān)閉開關(guān)
        digitalWrite(LED_PIN, LOW);  // 關(guān)燈

        BlinkerMIOT.powerState("off");
        BlinkerMIOT.print();

        oState = false;
    }
}

// 查詢?cè)O(shè)備狀態(tài)回調(diào)函數(shù)
void miotQuery(int32_t queryCode)
{
    BLINKER_LOG("MIOT Query codes: ", queryCode);

    switch (queryCode)
    {
        case BLINKER_CMD_QUERY_ALL_NUMBER :         // 查詢所有設(shè)備
            BLINKER_LOG("MIOT Query All");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :  // 查詢電源類設(shè)備
            BLINKER_LOG("MIOT Query Power State");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        default :                                   // 查詢其他設(shè)備
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
    }
}

// 按下按鍵即會(huì)執(zhí)行該函數(shù)
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));  // 翻轉(zhuǎn)LED燈狀態(tài)
}

// 如果未綁定的組件被觸發(fā),則會(huì)執(zhí)行其中內(nèi)容
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup()
{
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    BLINKER_DEBUG.debugAll();
    
    // 初始化LED的IO
    pinMode(LED_PIN, OUTPUT);
    digitalWrite(LED_PIN, HIGH);

    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);                 // 未綁定設(shè)備回調(diào)
    Button1.attach(button1_callback);             // 按鍵回調(diào)
    BlinkerMIOT.attachPowerState(miotPowerState); // 電源控制回調(diào)
    BlinkerMIOT.attachQuery(miotQuery);           // 查詢?cè)O(shè)備狀態(tài)回調(diào)
}

void loop() {
    Blinker.run();
}

5 關(guān)聯(lián)米家APP和Blinker設(shè)備

打開 米家APP,點(diǎn)擊我的,點(diǎn)擊其他平臺(tái)設(shè)備,點(diǎn)擊添加,在列表中找到點(diǎn)燈科技,點(diǎn)擊綁定賬號(hào),登錄你的Blinker賬號(hào),最后點(diǎn)擊同步設(shè)備即可。設(shè)備同步成功之后就可以看到你在Blinker APP上創(chuàng)建的所有設(shè)備。

提示1:Blinker賬號(hào)的注冊(cè)以及APP的使用請(qǐng)?zhí)D(zhuǎn)到3.2查看。我在上一篇博客有詳細(xì)的教程。

提示2:同步設(shè)備可能會(huì)出現(xiàn)失敗的情況,我一開始同步的時(shí)候一直失敗,過(guò)了一段時(shí)間之后再嘗試又沒(méi)出現(xiàn)了,不知道是不是APP的bug。

在這里插入圖片描述請(qǐng)?zhí)砑訄D片描述請(qǐng)?zhí)砑訄D片描述請(qǐng)?zhí)砑訄D片描述請(qǐng)?zhí)砑訄D片描述請(qǐng)?zhí)砑訄D片描述


6 語(yǔ)音控制測(cè)試

特別說(shuō)明:我沒(méi)有小愛(ài)同學(xué)的智能音箱,我這里是直接用小米的手機(jī)來(lái)測(cè)試的。

注:其他品牌的手機(jī)可以下載米家APP,但是沒(méi)法使用小愛(ài)同學(xué)。

把燒錄好代碼的設(shè)備通上電,通過(guò)串口打印的一些信息,我們可以看到設(shè)備正常連上網(wǎng)絡(luò)之后會(huì)連接到Blinker的服務(wù)器,連接成功之后可以在Blinker的APP上看到設(shè)備的狀態(tài)由 ‘離線’ 變成 ‘在線’。

小愛(ài)同學(xué)支持的開關(guān)類控制語(yǔ)音如下:

打開/關(guān)閉{門口}{}

提示1:{}里面的內(nèi)容是通配多種關(guān)鍵詞的,你可以在Blinker APP修改設(shè)備的名稱,然后語(yǔ)音對(duì)應(yīng)的命令也要跟著改變,保持一致才能正確的控制設(shè)備。

對(duì)著小米手機(jī)呼叫小愛(ài)同學(xué),收到回應(yīng)之后再說(shuō)打開燈,就能看到設(shè)備的LED燈被打開了。同理,關(guān)閉燈的指令也是一樣的操作。

通過(guò)串口打印的信息也可以看到開燈和關(guān)燈相關(guān)的指令。

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

至此,從小愛(ài)同學(xué)到硬件設(shè)備的整個(gè)流程就走通了。流程走通了之后我們就可以在這個(gè)基礎(chǔ)上增加更多的功能,比如控制燈的亮度,設(shè)備工作模式等等,也可以修改設(shè)備的名稱,或者控制更多其他類型的設(shè)備。

7 進(jìn)階用法

通過(guò)Blinker關(guān)聯(lián)小愛(ài)同學(xué)控制設(shè)備其實(shí)有很大的局限性,因?yàn)樾?ài)同學(xué)所有的語(yǔ)音指令都是Blinker定義好的,不支持做過(guò)多的修改,而且目前支持的語(yǔ)音指令實(shí)在是有點(diǎn)少,當(dāng)我們需要自定義一些指令時(shí)并不能通過(guò)這套代碼實(shí)現(xiàn)。不過(guò)如果只是玩一下或者學(xué)習(xí)的話,還是可以去研究一下的。

關(guān)于Blinker以及小愛(ài)同學(xué)所支持的設(shè)備和語(yǔ)音指令在點(diǎn)燈科技的官網(wǎng)上其實(shí)有比較詳細(xì)的介紹。

點(diǎn)燈科技小米小愛(ài)技術(shù)文檔:https://diandeng.tech/doc/xiaoai

我們這里也基于這些給定的語(yǔ)音指令做一些進(jìn)階的操作。

前面的示例我們通過(guò)小愛(ài)同學(xué)控制了燈的亮滅,然后現(xiàn)在我們?cè)黾覮ED燈亮度、色溫以及模式的控制。

特別說(shuō)明:要實(shí)際控制燈的亮度和色溫的話我們需要用到RGB燈,而且有些比較簡(jiǎn)單的GRB燈只能調(diào)節(jié)三色燈的亮滅,最多也只能調(diào)出8種顏色,如果需要調(diào)節(jié)出多種色溫,還需要調(diào)節(jié)三色燈里面每一個(gè)燈的亮度。每個(gè)燈的亮度階梯越多,能跳出來(lái)的色彩就越多。如果是單色LED的話最多只能調(diào)亮度,是沒(méi)辦法改變顏色的,亮度調(diào)節(jié)可以通過(guò)PWM實(shí)現(xiàn)。

我這里因?yàn)楝F(xiàn)在手頭上也沒(méi)有合適的燈,這里就不做具體的演示了,我這里只講一下怎么把小愛(ài)語(yǔ)音和LED燈的控制代碼關(guān)聯(lián)起來(lái),至于實(shí)際的一些操作,感興趣的同學(xué)可以自己再補(bǔ)充。

7.1 亮度控制

小愛(ài)同學(xué)支持的亮度控制語(yǔ)音如下:

{臥室}{}{亮度調(diào)高一點(diǎn)}
亮度范圍為1-100

注:括號(hào)里面的的關(guān)鍵字是可以用戶自己修改定義的。比如:燈可以換成其他關(guān)鍵字,如氛圍燈、大燈等,這個(gè)是跟你在Blinker APP里面修改的設(shè)備名稱保持一致的。

示例代碼:

提示:我這里只把新增的函數(shù)列出來(lái),等后面把亮度、色溫以及模式的控制全部講完之后再列一個(gè)完整的代碼。

// 燈光亮度控制回調(diào)函數(shù)
void miotBright(const String & bright)
{
    BLINKER_LOG("need set brightness: ", bright);  // 打印需要設(shè)置的亮度

    uint8_t colorW = bright.toInt();

    BLINKER_LOG("now set brightness: ", colorW);
    
    // 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改PWM占空比的值,從而達(dá)到調(diào)節(jié)燈亮度的目的
    
    BlinkerMIOT.brightness(colorW);
    BlinkerMIOT.print();
}

// 燈光亮度控制初始化
BlinkerMIOT.attachBrightness(miotBright);

測(cè)試結(jié)果:

特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。

對(duì)著小愛(ài)同學(xué)說(shuō):把燈的亮度調(diào)到60。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了這個(gè)命令,并且把要調(diào)節(jié)的亮度值60解析出來(lái)了,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮?,因此,LED燈是沒(méi)有變化的。

在這里插入圖片描述

7.2 色溫控制

小愛(ài)同學(xué)支持的色溫控制語(yǔ)音如下:

{臥室}{}調(diào)為{紅色}
顏色范圍為0-16777215(0xFFFFFF)

示例代碼:
提示:我這里只把新增的函數(shù)列出來(lái),等后面把亮度、色溫以及模式的控制全部講完之后再列一個(gè)完整的代碼。

// 燈光色溫控制回調(diào)函數(shù)
void miotColor(int32_t color)
{
    BLINKER_LOG("need set color: ", color);
	
	// 從接收到的數(shù)據(jù)中解析得到需要配置的R G B三色光的亮度值
    uint8_t colorR = color >> 16 & 0xFF;
    uint8_t colorG = color >>  8 & 0xFF;
    uint8_t colorB = color       & 0xFF;

    BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB);
	
	// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改R G B三個(gè)燈的亮度從而達(dá)到修改燈顏色的目的
	
    BlinkerMIOT.color(color);
    BlinkerMIOT.print();
}

// 燈光色溫控制初始化
BlinkerMIOT.attachColor(miotColor);

測(cè)試結(jié)果:

特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。

對(duì)著小愛(ài)同學(xué)說(shuō):把燈調(diào)為紫色。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了改命令,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮?,因此,LED燈是沒(méi)有變化的。

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

提示:這里RGB三元光的亮度范圍是0-255,把三種亮度不同的光混合在一起就能產(chǎn)生多種多樣的顏色。

7.3 模式控制

小愛(ài)同學(xué)支持的色溫控制語(yǔ)音如下:

{臥室}{}設(shè)置為{xx模式}

在這里插入圖片描述
示例代碼:

提示:我這里只把新增的函數(shù)列出來(lái),后面有完整的代碼。

// 模式控制回調(diào)函數(shù)
void miotMode(uint8_t mode)
{
    BLINKER_LOG("need set mode: ", mode);  // 打印接收到需要設(shè)置的模式,數(shù)值是(0-6),對(duì)應(yīng)7種模式

    if (mode == BLINKER_CMD_MIOT_DAY) {
        // 日光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_NIGHT) {
        // 夜光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_COLOR) {
        // 彩光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_WARMTH) {
        // 溫馨模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_TV) {
        // 電視模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_READING) {
        // 閱讀模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_COMPUTER) {
        // 電腦模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }

    BlinkerMIOT.mode(mode);
    BlinkerMIOT.print();
}

// 模式控制初始化
BlinkerMIOT.attachMode(miotMode);

測(cè)試結(jié)果:

特別說(shuō)明:因?yàn)槲业挠布](méi)有接入能調(diào)光的燈,所以這里我只把接收到的語(yǔ)音指令打印了出來(lái),硬件上并沒(méi)有做實(shí)際的操作。

對(duì)著小愛(ài)同學(xué)說(shuō):把燈調(diào)為夜光模式。通過(guò)串口打印的信息我們可以看到,設(shè)備已經(jīng)收到了改命令,只不過(guò)我實(shí)際上并沒(méi)有做控?zé)舻牟僮鳎虼?,LED燈是沒(méi)有變化的。

在這里插入圖片描述

前面我也講過(guò),Blinker這套方案有比較大的局限性,就比如這里的模式,雖然支持多種模式,但是每一個(gè)模式都只能通過(guò)固定的關(guān)鍵字(日光、夜光、彩光等)來(lái)觸發(fā),不能自定義,如果是控?zé)暨€好,很多都可以用上,但是如果控制的是其他設(shè)備,這些模式的關(guān)鍵字就牛頭不對(duì)馬嘴了。

我也沒(méi)有找到改指令關(guān)鍵字的接口,應(yīng)該是Blinker沒(méi)有開放這個(gè)接口或者不支持這個(gè)功能。這一點(diǎn)是不太友好的,不過(guò)Blinker畢竟是一個(gè)公司,目的還是盈利,而且維護(hù)服務(wù)器也是需要成本的,白嫖黨也不能要求太多。

完整的進(jìn)階示例代碼:

#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT         // 燈設(shè)備            
// #define BLINKER_MIOT_OUTLET        // 插座設(shè)備   
// #define BLINKER_MIOT_MULTI_OUTLET  // 多個(gè)插座設(shè)備         
// #define BLINKER_MIOT_SENSOR        // 傳感器設(shè)備   
// #define BLINKER_MIOT_FAN           // 風(fēng)扇設(shè)備 
// #define BLINKER_MIOT_AIR_CONDITION // 空調(diào)設(shè)備          

#include <Blinker.h>

char auth[] = "e6fce38e525a";    // 設(shè)備密鑰
char ssid[] = "tst";             // WIFI賬號(hào)
char pswd[] = "123456789";       // WIFI密碼

#define LED_PIN 2                // LED引腳

// 新建組件對(duì)象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

int counter = 0;
bool oState = false;

// 電源控制回調(diào)函數(shù)
void miotPowerState(const String & state)
{
    BLINKER_LOG("need set power state: ", state);

    if (state == BLINKER_CMD_ON) 
    {// 打開開關(guān)
        digitalWrite(LED_PIN, HIGH);  // 開燈

        BlinkerMIOT.powerState("on");
        BlinkerMIOT.print();
 
        oState = true;
    }
    else if (state == BLINKER_CMD_OFF) 
    {// 關(guān)閉開關(guān)
        digitalWrite(LED_PIN, LOW);  // 關(guān)燈

        BlinkerMIOT.powerState("off");
        BlinkerMIOT.print();

        oState = false;
    }
}

// 查詢?cè)O(shè)備狀態(tài)回調(diào)函數(shù)
void miotQuery(int32_t queryCode)
{
    BLINKER_LOG("MIOT Query codes: ", queryCode);

    switch (queryCode)
    {
        case BLINKER_CMD_QUERY_ALL_NUMBER :         // 查詢所有設(shè)備
            BLINKER_LOG("MIOT Query All");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :  // 查詢電源類設(shè)備
            BLINKER_LOG("MIOT Query Power State");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        default :                                   // 查詢其他設(shè)備
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
    }
}

// 燈光亮度控制回調(diào)函數(shù)
void miotBright(const String & bright)
{
    BLINKER_LOG("need set brightness: ", bright);

    uint8_t colorW = bright.toInt();

    BLINKER_LOG("now set brightness: ", colorW);
    
    // 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改PWM占空比的值從而達(dá)到調(diào)節(jié)燈亮度的目的
    
    BlinkerMIOT.brightness(colorW);
    BlinkerMIOT.print();
}

// 燈光色溫控制回調(diào)函數(shù)
void miotColor(int32_t color)
{
    BLINKER_LOG("need set color: ", color);
	
	// 從接收到的數(shù)據(jù)中解析得到需要配置的R G B三色光的亮度值
    uint8_t colorR = color >> 16 & 0xFF;
    uint8_t colorG = color >>  8 & 0xFF;
    uint8_t colorB = color       & 0xFF;
	
    BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB);
	
	// 在此處我們可以根據(jù)實(shí)際情況添加一些控制的代碼,比如:通過(guò)修改R G B三個(gè)燈的亮度從而達(dá)到修改燈顏色的目的
	
    BlinkerMIOT.color(color);
    BlinkerMIOT.print();
}

// 模式控制回調(diào)函數(shù)
void miotMode(uint8_t mode)
{
    BLINKER_LOG("need set mode: ", mode);  // 打印接收到需要設(shè)置的模式,數(shù)值是(0-6),對(duì)應(yīng)7種模式

    if (mode == BLINKER_CMD_MIOT_DAY) {
        // 日光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_NIGHT) {
        // 夜光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_COLOR) {
        // 彩光模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_WARMTH) {
        // 溫馨模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_TV) {
        // 電視模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_READING) {
        // 閱讀模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }
    else if (mode == BLINKER_CMD_MIOT_COMPUTER) {
        // 電腦模式,在這里面可以添加自己實(shí)際需要控制的代碼
    }

    BlinkerMIOT.mode(mode);
    BlinkerMIOT.print();
}

// 按下按鍵即會(huì)執(zhí)行該函數(shù)
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));  // 翻轉(zhuǎn)LED燈狀態(tài)
}

// 如果未綁定的組件被觸發(fā),則會(huì)執(zhí)行其中內(nèi)容
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup()
{
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    BLINKER_DEBUG.debugAll();
    
    // 初始化LED的IO
    pinMode(LED_PIN, OUTPUT);
    digitalWrite(LED_PIN, HIGH);

    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);                 // 未綁定設(shè)備回調(diào)
    Button1.attach(button1_callback);             // 按鍵回調(diào)
    BlinkerMIOT.attachPowerState(miotPowerState); // 電源控制回調(diào)
    BlinkerMIOT.attachQuery(miotQuery);           // 查詢?cè)O(shè)備狀態(tài)回調(diào)
    BlinkerMIOT.attachBrightness(miotBright);     // 燈光亮度控制回調(diào)
    BlinkerMIOT.attachColor(miotColor);           // 燈光色溫控制回調(diào)
    BlinkerMIOT.attachMode(miotMode);             // 模式控制回調(diào)
}

void loop() {
    Blinker.run();
}

結(jié)束語(yǔ)

好了,關(guān)于如何在Arduino上通過(guò)小愛(ài)同學(xué)控制燈光就到這里。Blinker的這套框架局限性比較大,只適用于某些設(shè)備,也只能使用比較固定的命令,不能做過(guò)多的修改,這一點(diǎn)是不太好的,但好處是比較省事,不需要我們做語(yǔ)音這部分的開發(fā),有利有弊吧,對(duì)于學(xué)生黨或者剛?cè)腴T的初學(xué)者來(lái)說(shuō)是可以去玩一下的,而且Blinker維護(hù)服務(wù)器本身也是需要成本的,能免費(fèi)提供這個(gè)平臺(tái)給大家用就算不錯(cuò)了,白嫖黨要求也不能太過(guò)分是吧。如果有條件的話就自己搭服務(wù)器,這樣可操作性會(huì)大大的增加。

想了解更多Arduino的內(nèi)容,可以關(guān)注一下博主,后續(xù)我還會(huì)繼續(xù)分享更多的經(jīng)驗(yàn)給大家。

還有什么問(wèn)題的話,歡迎在評(píng)論區(qū)留言。

如果這篇文章能夠幫到你,就…你懂得。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜