Android與Arduino的藍芽通訊

想成為Maker,自然要從Single A (ArduinoAndroid皆可)進階至Double A (Android+Arduino)。今天要讓大家都學會用手機傳訊息到Arduino系統BTCom

很多人想學Coding,各種程式語言千百種(/英文都學不好了,還…),但不得其門而入。歐吉尚衷心建議跟著小學生的腳步學就對了別想一步登Maker! 不要想太多挑一個跟自己有緣的(符合自己目標需求、提供模組多的、自己會想Try看看的)工具,然後動手去Try就對了例如歐吉尚目標很明確,就是要用Android手機控制家電、遙控汽車、機器人、飛行器與一些監控器等。因此歐吉尚的第一支Double A程式,就設定為讓AndroidArduino透過Bluetooth(藍芽)通訊。

為什麼選Bluetooth? 因為逛電器行時,發現他跟我很有緣,我第一眼就喵到(我買串列埠界面的的,350元台幣,淘寶約17~30人民幣)。同時間也喵到超聲波感測器,心想,我未來的遙控飛行器應該要自動避開障礙物,…於是就直接全部打包回家了!

既然是第一支Double A程式,當然就得是「Hello World!」。只是這次是希望能從Android手機送出「Hello World!」訊息,透過藍芽,讓遠端Arduino的序列埠監控器秀出來!



BOM 
項目
台灣
淘寶(不含運費)
Arduino UNO R3
450台幣
12~40人民幣
Bluetooth HC-06
350台幣
17~30人民幣
MIT AI2 Companion (Android)
Free
MIT App Inventor 2 (Windows)
Free




藍芽模組建議買內建串列埠的,因為接腳數少,Programming也較簡單。不過買的時候千萬注意型號,市面上好像有HC-05HC-06HC-07等,出廠設定的鮑率(Baud Rate; 每秒所送信號變化的次數)好像不太一樣。可別像歐吉尚,買回來後,很高興的照著課本Step-by-step,但始終無法成功。萬念俱灰下才發現,原來課本用的是HC-05,而我買的竟然是HC-06! (昏倒)

HC-06 藍芽模組



HC-06Arduino的腳位對應:

HC-06藍芽模組(串列埠)
Arduino Uno Pin
VCC
5V
GND
GND
TXD
Pin 10 (RX)
RXD
Pin 11 (TX)





BTCom: Android 程式規劃
Android手機App的介面應該要包涵搜尋/連接藍芽裝置的選單、斷線、訊息傳送窗等原件(Button)。其中,訊息傳送窗希望能包涵提示標籤(Label)、文字輸入盒(TextBox)與傳送按鈕(Button)。而AI2新增的元件佈局(Layout)功能,剛好符合需求(使用Vertical/Horizontal Arrangement)




腳本的安排利用AI2內見的藍芽模組,將搜尋到的藍芽裝置以清單列顯示,以讓使用者選擇,此時其他功能選項呈失效狀態。待使用者選擇適當的藍芽裝置(HC-06)以後,將搜尋清單列按鈕失效,並致能其他功能選項,讓使用者可以輸入。




建立/初始化欲傳送的訊息字btCommand,設定當傳送鈕(Send)被敲下時,將訊息編輯盒(TextBox)的內容存入串變數btCommand,並透過藍芽裝置傳送。直到斷線按鈕被敲下,再致能搜尋清單列按鈕,並讓其他功能選項失效。




拼圖(Coding)完後,選擇BuildàApp (provide QR code for .pak)AI2完成編譯並產生QR Code




如果懶得寫程式可以使用下面QR Code下載,若有Bug煩請告知,感恩!







BTCom: Arduino Uno 端程式
利用Arduino的序列埠模擬函式(SoftwareSerial)來建立與HC-06的串列通訊,使用者無須了解底層的藍芽通訊協定,只要把它當一般的串列埠就可以了! (現在的小孩寫程式好幸福啊,不但需要的函式庫都有了,連Bluetooth轉串列埠的功能,廠商都很有默契似的把它內建了!)

HC-06擷取訊息,顯示訊息及輸入指令的工作都交給Arduino的序列埠,使用者也可以由Arduino將指令透過我們自訂的腳位寫回HC-06(不過我只用原廠設定)。因為HC-06的鮑率(Baud Rate)出廠設定為9600bps,跟我預設的串列埠監控器一樣慢,這可能使得每次傳送的訊息被切割成數筆藍芽串列埠資料的讀取,因此我用了多讀了幾次到FIFO(我只Create 128 Bytes,應該夠用來控致許多終端設備了)


Arduino BTCom範例程式用串列埠顯示結果

#include <SoftwareSerial.h>
#include <Wire.h>

// the maximum received command length from an Android system (over the bluetooth)
#define MAX_BTCMDLEN 128

// 建立一個軟體模擬的序列埠不要接反了!
// HC-06    Arduino
// TX       RX/Pin10
// RX       TX/Pin11
SoftwareSerial BTSerial(10,11); // Arduino RX/TX

byte cmd[MAX_BTCMDLEN]; // received 128 bytes from an Android system
int len = 0; // received command length

void setup() {
    Serial.begin(9600);   // Arduino起始鮑率:9600
    BTSerial.begin(9600); // HC-06 出廠的鮑率:每個藍牙晶片的鮑率都不太一樣,請務必確認
}

void loop() {
    char str[MAX_BTCMDLEN];
    int insize, ii;  
    int tick=0;
    while ( tick<MAX_BTCMDLEN ) { // 因為包率同為9600, Android送過來的字元可能被切成數份
        if ( (insize=(BTSerial.available()))>0 ){ // 讀取藍牙訊息
            for ( ii=0; ii<insize; ii++ ){
                cmd[(len++)%MAX_BTCMDLEN]=char(BTSerial.read());
            }
        } else {
            tick++;
        }
    }
    if ( len ) { // 用串列埠顯示從Android手機傳過來的訊息
        sprintf(str,"%s",cmd);
        Serial.println(str);
        cmd[0] = '\0';
    }
    len = 0;
}






BTCom: 執行結果
請先手機的開啟藍芽通訊,並找到HC-06裝置並配對,原廠的初始密碼為「1234(~~不好意思,歐吉尚用的是郭董的零元手機)




開啟手機的QR Droid(可至Google Play下載)對準螢幕的QR Code識別,即可將程式BTCom下載至手機。如下如所示,執行時須先搜尋欲配對的藍芽裝置(其他功能先隱藏),而AI2專案中所使用的藍芽模組會自動將附近搜尋到的裝置整理成選單列(List)



執行BTCom,待配對完成,Bluetooth Listener將失效,並致能其他功能(斷線與訊息編輯盒)




開啟Arduino的串列埠監聽器,在BTCom App編輯盒中輸入「Hello World!」並敲下 Send鈕。




BTCom: 使用LCD1602顯示執行結果
記得之前Arduino開箱文有用到整合I2CLCD1602顯示器,趕快學以致用拿來TryArduino System端的程式,只要將對標準串列埠的輸出改為對LCD1602輸出即可。只要對前一個程式稍作修改,如下範例中藍色字體的部分。


Arduino BTCom範例程式LCD1602顯示結果

#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // 使用整合I2CLCD1602顯示

// the maximum received command length from an Android system (over the bluetooth)
#define MAX_BTCMDLEN 128

// 建立一個軟體模擬的序列埠不要接反了!
// HC-06    Arduino
// TX       RX/Pin10
// RX       TX/Pin11
SoftwareSerial BTSerial(10,11); // Arduino RX/TX

// Addr, En, Rw, Rs, d4,d5,d6,d7 backlight, polarity
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE); // 使用整合I2CLCD1602顯示

byte cmd[MAX_BTCMDLEN]; // received 128 bytes from an Android system
int len = 0; // received command length

void setup() {
    Serial.begin(9600);   // Arduino起始鮑率:9600
    BTSerial.begin(9600); // HC-06 出廠的鮑率:每個藍牙晶片的鮑率都不太一樣,請務必確認
   
    // 初始化LCD1602
    lcd.begin(16, 2);
    lcd.clear();
    lcd.backlight();
}

void loop() {
    char str[MAX_BTCMDLEN];
    int insize, ii;  
    int tick=0;
    while ( tick<MAX_BTCMDLEN ) { // 因為包率同為9600, Android送過來的字元可能被切成數份
        if ( (insize=(BTSerial.available()))>0 ){  // 讀取藍牙訊息
            for ( ii=0; ii<insize; ii++ ){
                cmd[(len++)%MAX_BTCMDLEN]=char(BTSerial.read());
            }
        }
        else {
            tick++;
        }
    }
    if ( len ) { // LCD1602顯示從Android手機傳過來的訊息
        sprintf(str,"%s",cmd);
        // Serial.println(str);
        // 將對串列埠的輸出改為對LCD1602輸出
        lcd.clear();
        lcd.print(str);
        cmd[0] = '\0';
    }
    len = 0;
}





拿另外一支手機來Try9600bps其實對人來說夠快了操作過程幾乎在Send按下的同時,LCD1602就把訊息顯示出來了!



寫到這邊,您是否覺得眼前人生突然變成彩色的呢聰明的你其實很容易舉一反三,利用前面的程式,稍加修改就可以控制遠端燈光的開關了下次我們就來破解,最近Kickstarter有在募資(中國大陸前一陣子也在募資)的「可以用手機App遙控的無線電源插座」,超簡單你也可以開公司!