用手機App遙控家電開關

繼上一回BTCom Project--Android手機傳送命令(簡訊)Arduino板子後。這一回,我們要讓Arduino根據我們手機傳送的命令作動作,而最簡單的方式就是控制電源開關。



假設家裡有電視(TV)、音響(Sound)、房間燈光(Room)與電扇(Fan)想要透過手機App遙控開關。為了延用之前的藍芽簡訊程式 BTCom,我們必須先定義Android與Arduino的通訊協定(Protocol),就是讓Arduino看懂我們的指令(Instruction)

硬說是通訊協定,也沒那麼偉大,簡單說就是從手機傳給Arduino的指令格式,定義為:

<DeviceName><逗號><ON/OFF>


其中<DeviceName>可以是 {tv, sound, room, fan} 其中一個。例如,想要開啟電視,我們傳送的指令為「tv,on」;相反地,「tv,off」指令會把電視關掉。這樣子的用法,設計者可以設計自己專屬的指令格式,而且可沿用之前開發的Android App,並保持未來做更複雜控制指令的彈性。當然,設計者也可以使用不同的按鍵(Button)對應不同的命令,但App的用途就受到限制(不能Reuse)


實作的部分則偷懶一下,用四顆LED燈泡表示欲被遠端手機App遙控的電器設備。實際運作則需搭配繼電器(Relay),此時驅動LED燈泡的訊號則接至繼電器的訊號端


可以的話直接買多路的繼電器開關比較划算,可以控制較多的家電。以下BOM表參考一下,以後建商或室內設計師跟你吹牛說送你的「智慧家電控制中心」多高貴,那肯定是騙很大! (若是在大陸製造成本可以控制在100塊人民幣以內)



BOM

項目
台灣
淘寶(不含運費)
Arduino UNO R3
450台幣
12~40人民幣
Bluetooth HC-06
350台幣
17~30人民幣
單路10A繼電器
90~180台幣
3.5~12人民幣
410A繼電器
195台幣
13~24人民幣
MIT AI2 Companion (Android)
Free
MIT App Inventor 2 (Windows)
Free





BTCom: Android程式規劃
Android手機程式仍然跟上一回一樣使用AI2,程式碼不用變。如果懶得寫程式可以使用下面QR Code下載,若有Bug煩請告知,感恩!



不過這支App會被Android手機歸屬於來路不明的程式,安裝前請先將安全性設為允許不明來源的安裝,請放心! 不會收集用戶端資訊的! 安裝完成請記得取消允許不明來源的安裝,以免產生安全漏洞。









BTCom: Arduino Uno 端程式規劃

Arduino BTCom範例程式:

#include <SoftwareSerial.h>

#define MAX_BTCMDLEN 128
#define BTSW_TV     7  // pin7  BlueTooth Switch for TV
#define BTSW_Sound  6  // pin6  BlueTooth Switch for Sound
#define BTSW_Room   5  // pin5  BlueTooth Switch for Room
#define BTSW_Fan    4  // pin4  BlueTooth Switch for Fan

// 建立一個軟體模擬的序列port
SoftwareSerial BTSerial(10,11); // HC-06/TX-->PIN10(Arduino/RX), HC-06/RX-->PIN11(Arduino/TX);

byte btCmdBuff[MAX_BTCMDLEN]; // up to 128 bytes BT command received from the Android system
int btCmdLen = 0; // received BT command length

void setup() {
    //Serial.begin(9600); // serial port for debugging
    BTSerial.begin(9600); // 建立藍芽軟體串列埠
    pinMode(BTSW_TV,OUTPUT);     // 設定電視開關
    pinMode(BTSW_Sound,OUTPUT);  // 設定音響開關
    pinMode(BTSW_Room,OUTPUT);   // 設定房間開關
    pinMode(BTSW_Fan,OUTPUT);    // 設定風扇開關
    digitalWrite(BTSW_TV,LOW);
    digitalWrite(BTSW_Sound,LOW);
    digitalWrite(BTSW_Room,LOW);
    digitalWrite(BTSW_Fan,LOW);
}

void loop() {
    listenBTCmd();
    //showBTCmd(); // for debugging
    executeBTCmd();
}

void executeBTCmd() {
    char cmd[MAX_BTCMDLEN];
    if ( btCmdLen>0 ) {
        sprintf(cmd,"%s",btCmdBuff);
        //Serial.println(cmd);
     
        if ( strcmp("tv,on",cmd)==0 ) {
            digitalWrite(BTSW_TV,HIGH);
        }
        if ( strcmp("tv,off",cmd)==0 ) {
            digitalWrite(BTSW_TV,LOW);
        }
        if ( strcmp("sound,on",cmd)==0 ) {
            digitalWrite(BTSW_Sound,HIGH);
        }
        if ( strcmp("sound,off",cmd)==0 ) {
            digitalWrite(BTSW_Sound,LOW);
        }
        if ( strcmp("room,on",cmd)==0 ) {
            digitalWrite(BTSW_Room,HIGH);
        }
        if ( strcmp("room,off",cmd)==0 ) {
            digitalWrite(BTSW_Room,LOW);
        }
        if ( strcmp("fan,on",cmd)==0 ) {
            digitalWrite(BTSW_Fan,HIGH);
        }
        if ( strcmp("fan,off",cmd)==0 ) {
            digitalWrite(BTSW_Fan,LOW);
        }
    }
}

void listenBTCmd() {
    char tmp; 
    btCmdLen = 0;
    memset(btCmdBuff,0,MAX_BTCMDLEN);
    while( BTSerial.available()>0 ) {
        if( (tmp=BTSerial.read())=='O' ){
            btCmdLen = 0;
        }
        btCmdBuff[(btCmdLen++)%MAX_BTCMDLEN] = tmp;
    }
}

void showBTCmd() {
    char cmd[MAX_BTCMDLEN];
    if ( btCmdLen>0 ) {
        sprintf(cmd,"%s",btCmdBuff);
        Serial.println(cmd);
    }
}