藍牙模組補充說明(四):無線連結兩個Arduino控制板

本文將示範讓兩個Arduino控制板透過藍牙連線傳遞訊息。

Arduino藍牙無線通信實驗

本單元的實驗材料:

  • 兩個Arduino控制板
  • 兩個藍牙模組:其中一個必須是HC-05,另一個可以是HC-05或HC-06。
  • (選擇性的)兩個1KΩ(棕黑紅)~4.7KΩ(黃紫紅)電阻
  • Android或iPhone手機一支

讓HC-05與另一個藍牙模組在通電時自動配對

藍牙模組有「主控端」和「從端」兩種模式,在配對時,一定是由「主控端」主導,探索其他「從端」並與之配對連線;從端無法彼此互連。

HC-05模組可以透過AT命令,設定成「主控端(Master)」或「從端(Slave)」;HC-06模組只能當「從端」。因此在配對連線實驗中,至少要有一個HC-05模組。

每個藍牙模組都有一個唯一的位址,主控端模組可透過AT+BIND命令(註:“bind”代表「繫結」)紀錄要配對的從端位址,設定好之後,它就能在通電(開機)時,自動探索並和指定位址的從端相連,這中間的過程,不需要Arduino介入,也就是不必寫任何程式碼。

藍牙模組能在開機時自動配對連結

一旦藍牙自動連線完成,Arduino控制板就能透過藍牙傳輸訊息。

使用手機的「藍牙掃描器」App取得藍牙裝置的位址

進行配對之前,我們得先知道從端的位址。取得位址的方法有兩種:

  • 使用手機App掃描
  • 透過AT命令讀取(僅適用於HC-05模組,參閱下一節說明)

在一般情況下,開啟手機藍牙時,手機應該會找到並顯示探索到的設備位址,接著顯示它的名稱。為了方便檢視探索到的藍牙裝置位址,請先在手機上安裝藍牙掃描器軟體,請到Google商店或者Apple的App Store搜尋“Bluetooth Scanner”,便能找到相關App(筆者安裝的是這個Bluetooth Scanner)。

接著,請參考底下的接線,利用Arduino控制板的5V電源供電給藍牙模組:

藍牙模組的電源接線

線路接好之後,插上Arduino的USB線讓模組通電,接著開啟手機的藍牙,透過手機探索藍牙設備。

底下是在Android手機上,透過Bluetooth Scanner軟體搜尋到的HC-06模組畫面,從中可看到此模組的名稱、位址和無線信號強度:

Bluetooth Scanner APP操作畫面

請先把這個位址抄寫下來。

透過AT命令取得從端位址

如果「從端」也是HC-05模組,除可透過手機App取得它的位址之外,還能透過“AT+ADDR?”命令顯示位址(註:HC-06不具備這個指令;HC-06模組的AT命令,請參閱「HC-05與HC-06藍牙模組補充說明(三):使用Arduino設定AT命令」)。

請參考底下的接線,HC-05模組的Key腳位在開機時,必須處於「高」電位,模組才能進入AT命令狀態。

HC-05設置AT命令的接線

我們將透過Arduino的序列埠監控視窗設定藍牙模組的AT命令,請先將底下的程式上傳到Arduino。此程式碼的相關說明,請參閱這一篇文章

程式上傳完畢後,打開「序列埠監控視窗」,輸入AT命令看看,藍牙模組將回應OK

AT命令測試

如果沒有回應OK,代表此模組沒有進入AT命令模式,請確認模組的Key腳位有接高電位。

輸入AT+ADDR?命令,它將傳回模組的位址:

AT+ADDR?命令

藍牙裝置位址

透過手機App和AT指令查詢到的位址格式不同,兩種寫法都行,但採用AT命令設定位址時,必須使用下圖右邊的格式

補充說明:藍牙裝置位址(Bluetooth Device Address,簡稱BD_ADDR)由一連串16進位數字組成,總長48位元。裝置位址相當於藍牙裝置的序號,每個裝置都不同,它可細分成三個部份:

  • NAP:未定義位址部分(Non-significant Address Part),由IEEE分配給製造商的編碼。
  • UAP:較高位址部分(Upper Address Part),用於產生錯誤偵測碼以及藍牙裝置的跳頻順序。
  • LAP:較低位址部分(Lower Address Part),製造商設定的編碼。

藍牙裝置位址的格式

將藍牙模組設定成Master(主控端)並紀錄Slave(從端)的位址

請將要當作主控端的HC-05模組按照上一節的電路接好,Arduino控制板同樣執行上一節的程式。

HC-05模組在出貨時,通常都是「從端」模式。必須先用AT指令改成「主控端」,請開啟「序列埠監控視窗」,輸入AT+ROLE=1,藍牙將傳回OK,代表已經設定成主控端;日後若要改成「從端」,請輸入AT+ROLE=0。

AT+ROLE=1命令

接著輸入AT+BIND=命令,後面跟著要配對的從端設備位址,只要位址格式無誤,HC-05將回應OK,代表位址紀錄完成。

AT+BIND命令

以上設定都會永久保存在藍牙晶片,直到你重新設定。

一對一藍牙無線通訊實驗

本單元將實驗透過藍牙連結兩個Arduino控制板,其中一個板子充當「命令發送者」,發出‘1’或‘0’訊息,藉以控制另一個板子上的LED開關。

請將兩個Arduino都依照底下的接線組裝好:

藍牙序列埠模組與Arduiono的接線

在準備充當「命令發送者」的Arduino上傳底下的程式碼,不一定要是連接HC-05模組的那個Arduino,因為藍牙模組之間的配對連線,跟Arduino沒有關係。對Arduino來說,這兩個相連的藍牙模組,就相當於在Arduino之間用導線連接一樣。

接著在另一個,充當「接收命令者」的Arduino板上傳底下的程式碼:

開啟兩個Arduino板的電源(先後順序不重要),觀察主控端藍牙的LED狀態燈,將先快速閃爍,與從端建立連線後,閃爍速度會變慢。

請先確認Arduino編輯器的序列埠連線是在「命令發送者」的板子:

選擇「命令發送者」的序列埠

接著開啟「序列監控視窗」,輸入‘1’和‘0’試試看:

控制LED

延伸閱讀

182 thoughts on “藍牙模組補充說明(四):無線連結兩個Arduino控制板

  1. 老師您好,我是SHAWN,我現在寫成這樣
    private static String HC06address = “98:D3:31:FD:37:F8”;
    private static String HC05address = “98:D3:33:80:7F:FC”;

    btSocket=btAdapt.getRemoteDevice(HC06address).createRfcommSocketToServiceRecord(uuid);
    btSocket=btAdapt.getRemoteDevice(HC05address).createRfcommSocketToServiceRecord(uuid);
    我用這樣子抓這2個的MAC位址,但還是只能連一個而已,無法同時連上去,老師可以跟你要MAIL傳我整個程式碼給您看看嗎。 謝謝老師

  2. 老師您好 ,我照著您的範例去做

    設定完主從端也重新將Arduino接上了

    兩個藍芽的燈號也同時變慢

    但是我輸入1跟0卻沒有跑出LED ON OFF的回應

  3. 老師您好,我是一位arduino的新手,我最近在做arduino生理訊號感測器傳送至另外一片arduino板進行馬達控制,我使用的是HC-06對HC-06的藍芽配對進行資料傳輸,查詢其他論壇均無相關內容,我依照老師的範本進行撰寫,想讓接收端能收到訊號參數並且進行馬達控制。但是我無法得知其訊號是否有接收到,我利用老師範本,更改為取得參數進行LED亮滅,以下程式碼
    發送端:
    #include // 引用程式庫
    // 定義連接藍牙模組的序列埠
    SoftwareSerial BT(9, 8); // 接收腳, 傳送腳
    int EMG; // 儲存接收資料的變數(數字)
    void setup() {
    Serial.begin(9600); // 與電腦序列埠連線
    Serial.println(“BT is ready!”);
    // 藍牙透傳模式的預設連線速率。
    BT.begin(9600);
    }
    void loop() {
    EMG = analogRead(0); //讀取接腳0類比數值
    EMG=map(EMG,0,1023,0,4950); //將數位訊號換算成電壓
    Serial.println(EMG); //數值顯示於監控視窗
    delay(1000);
    // 若收到「序列埠監控視窗」的資料,則送到藍牙模組
    if (Serial.available()) {
    EMG = Serial.read();
    BT.print(EMG);
    }
    // 若收到藍牙模組的資料,則送到「序列埠監控視窗」
    if (BT.available()) {
    EMG = BT.read();
    Serial.print(EMG);
    }
    }

    接收端:
    #include // 引用程式庫

    // 定義連接藍牙模組的序列埠
    SoftwareSerial BT(9, 8); // 接收腳, 傳送腳
    char val; // 儲存接收資料的變數
    const byte LED_PIN = 13; // 定義LED腳位

    void setup() {
    Serial.begin(9600); // 與電腦序列埠連線
    // 設定HC-05藍牙模組,AT命令模式的連線速率。
    BT.begin(9600);
    pinMode(LED_PIN, OUTPUT);
    }

    void loop() {

    // 若收到藍牙模組的資料,則送到「序列埠監控視窗」
    if (BT.available()) {
    byte val = BT.read();
    if (val >2000) {
    digitalWrite(LED_PIN, HIGH);
    // 回應命令發送端,告知「已開燈」
    BT.println(“LED ON”);
    } else if (val <2000) {
    digitalWrite(LED_PIN, LOW);
    // 回應命令發送端,告知「已關燈」
    BT.println("LED OFF");
    Serial.print(val);
    }
    Serial.println(val);
    }
    }

    望請老師給予建議!!謝謝!!!

  4. 老師您好,我利用2個HC06完成了老師上文的教學範例,再進一步利用生理訊號的參數控制從屬端LED的亮滅,但是要傳輸生理訊號的參數另外一端卻無法接收到訊號,請問老師這個部份能給予意見嗎?
    此外找到了可以更改HC-06主從之指令 :
    AT+ROLE=M :將裝置更變為主裝置。
    AT+ROLE=S :將裝置更變為從屬裝置。
    不知此指令是否有用?

    麻煩老師給予意見,謝謝!!

  5. 老師
    我想問說我有用AT設定他的位置了
    也都說OK
    改AT跟測試的包率不一樣我也有注意了
    但是五丟1跟0他都沒反應
    然後我有去查
    當輸入AT+MRAD?時
    他應該會顯示上一次所連到的藍牙位置但卻不是我設的的那個藍牙位置
    然後我也有試著讓他們配對
    AT+P AIR=,
    Param1:設備蓝牙地址 Param2:連接時間
    但他卻不讓我配對
    是我哪個地方沒有注意到嗎
    我也有爬過許多的文但是始終沒有成功
    請求老師協助
    拜託了!!!

  6. 老師您好
    我最近照著您的範例下去操作
    但在主從端通訊實驗中 無論在主端丟0或1都無法接收到回覆 我參照之前的留言 更改過鮑率後在做測試也是沒有回覆 我當初有懷疑過是否是從端藍牙沒有和主端確實連結到 但是照著老師您上方的做法 將藍牙用AT+BIND 綁定雙方的位址應該就能夠連線到了吧(PS兩個藍牙都是HC-05且都已設定AT+CMODE=0)
    所以想請問老師有什麼解決辦法才能夠讓兩顆藍牙成功執行老師您的程式 麻煩您了 謝謝!!

  7. 謝謝老師後來我透過AT+PAIR 以及AT+LINK這兩個指令成功連結主端和從端了
    我在這裡再提出一個問題 現在我的兩塊藍牙模組在斷電後在重新接上電源必須每次都要再重新透過AT指令進行配對且連線
    有沒有解決辦法可以一上電就自動連線
    因為後來我的專題需要焊接電路板上 在切換電源的過程中 主端以及從端就無法進行溝通了

    1. 感謝告知。

      藍牙配對之後,從端的位址就紀錄在主控端的快閃記憶體,所以只要一通電它們兩個就自動配對了,我實驗的結果並不需要重新下AT命令,除非要更換配對目標。

      thanks,
      jeffrey

  8. 老師您好,請問老師要如何讓接收端的數值與發送端數值相同呢??
    我在進行藍芽配對後,要將主控端感測到的數值傳送到接收端,目前知道要丟出數據需要進行封包才可以將數據丟出,
    但是因為接收端數值與主控端數值不同,使得接收端動作無法如預想。

    對於此,希望老師給予建議,謝謝

    1. Arduino程式不用管到封包,輸出字元,接收到的就是字元。你可以參考10-12頁,把字串轉成數字的例子,或者17-22頁的自訂格式訊息。

      thanks,
      jeffrey

  9. 嗨 老師
    請問Arduino UNO連接HC-06按監控螢幕輸入任何指令都沒有反應??我RX,TX有適著交換接過一樣的說…..
    Arduino藍芽連接手機顯示”已配對”… 如何讓它連線,紅燈不閃爍??

    1. 你所謂的「紅燈」,是藍牙模組上面的狀態燈嗎?若是的話,它一定會閃,只是連線之後變慢罷了。

      thanks,
      jeffrey

  10. 想問一下從端的程式部分
    } else if (val == ‘0’) {
    我把這行的if (val == ‘0’) 砍掉 只剩下 } else {
    為什麼程式執行起來再主端輸入1會跑出LED ON->LED OFF->LED OFF(連續出現兩次的OFF)
    且從端ARDUINO的LED也是照顯示這樣跑
    請問這是為什麼?

    1. 序列埠傳送的都是數位資料,藍牙裝置也是;從Arduino的類比腳接收到的類比資料,也是轉換成數位的0~1023值,相關範例可參閱第十章「透過序列埠調整燈光亮度」一節的說明。

      thanks,
      jeffrey

  11. 你好 我是felix 请问可以一个主控端连接多个从端吗?即连接多个Arduino板(不是同时连接,而是主端储存多个从端地址,一个从端靠近时主动了解)

    1. 理论上可行,但是蓝芽模块必须处于AT模式才能让Arduino下指令。以这个模块的AT命令说明文档为例,第17页的AT+INQ命令,可以让蓝牙探索外设,并传回外设的地址。

      接著你可以通过第19页的AT+PAIR命令,与特定的外设配对,底下的命令将在20秒内,探索并与1234,56,abcdef地址的装置配对:

      AT+PAIR=1234,56,abcdef,20\r\n

      接著通过20页的AT+LINK命令连接:

      AT+LINK=1234,56,abcdef\r\n

      运行上面两个命令之前,可能要先在master上运行AT+INIT命令重启:

      AT+INIT\r\n

      这些命令我没有实际测试过,请自行尝试。

      thanks,
      jeffrey

  12. 您好,我上傳了程式但還是無法成功不知道是哪裡出問題,是我主端使用nano板,從端使用UNO板的關係嗎,還是因為兩個板子都是相容板的關係

  13. 老師你好 我是liumincheng
    請問老師是否有用過拿mega2560當主機上面放3個藍芽hc-05模組id 1,2,3透過id2 id3來連接2個arduino uno已接上藍芽hc-05模組的終端 在用手機藍芽連接mega2560上的id1藍芽模組傳訊息或控制2個uno終端 是否有相關參考的程式
    因為很想實驗看看arduino 藍芽2對2和3對3 但都沒有想關程式可參考 只找到1對1的的參考資料

    1. 沒有。因為一個藍牙主控端理論上可同時連接7個從端,只是HC-05的韌體不支援一對多連線。我覺得你可以考慮把藍牙主控程式放在手機端,或者,換一塊控制板。有些ARM處理器,可安裝執行Linux, Android系統的控制板一片售價才幾十元人民幣,加上USB藍牙,就能連接各種藍牙設備。

      thanks,
      jeffrey

  14. 不好意思
    老師我想問您
    上面有人問unity是否可以連藍芽
    那這個功能免費版可以辦到嗎
    還是一定要升級成專業版之類的?

  15. 嗨~請問一下兩個 HC-05 互連的話一個Master、一個Slave,可以手機 APP INVENTOR 2 連上一個 Master HC-05 然後控制 Slave HC-05 嗎? 謝謝!

  16. 嗯…因知道可以一對一互連,app inventor 2 對 hc-05 控制只有差不多10公尺左右,才想說是否可以透過這樣的作法來達成超過10公尺的通訊,且app inventor 2目前無法技援 bluetooth 4.0,我市面上買的 HC-08、HM-10都不能用~

    1. 如果你要遙控的距離比較遠, 你可以考慮使用”NRF24L01″這個模組, 跟Arduino溝通的部份, 也有人寫好library, 可以直接套用. 如果沒記錯的話, NRF24L01有效距離是100公尺. 如果要再增加有效距離, 可以再加上天線來增強訊號.

    2. 非常感謝kevin的補充,另外就是換一個App開發工具,既然App Inventor無法達到你的需求,你應該改用像Google的Android Studio或者Cordova之類的工具。

      thanks,
      jeffrey

  17. 你好~ 再請問一下 NRF24L01 模組可以一對多 或 多對多 連線控制嗎? 就是假設若需要2組來控制LED的話(搭配8051使用),一組會用到2個 NRF24L01 一個發射一個接收,第二組也是用2個NRF24L01一個發射一個接收,且第一組和第二組的通訊傳資料是可以各自獨立動作的,NRF24L01可以這樣作嗎? 謝謝~

  18. 我想請問2個HC05能互連結嗎?
    因為手邊的都是HC05的模組 我用兩個HC05打過AT+ROLE 和AT+BIND 讓它們互聯
    程式是用老師你寫的接收端和發送端
    但是無法出現老師你說的結果LED NO 和LED OFF

  19. 老師我2個HC05都設定好了 但是2個HC05 有連線卻無法動作
    UNO上的LED燈依然不亮 程式和接腳都是按照老師你畫的接
    老師知道是啥原因嗎

    1. 首先請確認RxD和TxD的接線,然後確認程式碼。

      你可以先移除藍牙板,把一個Uno板的8腳連到另一個Uno板的9腳,反之亦然,從主控端發出的訊號,如果能點亮另一個板子的LED,代表程式沒問題。
      再來查看藍牙板子是否有問題,請試試兩個板子是否都能在slave模式下運作。

      thanks,
      jeffrey

  20. 老師你好
    我購買了HC-05無底板的模組
    我RX TX KEY 連接上之後
    (RX電阻用了棕黑紅)
    下AT指令是亂碼該怎麼處裡??

  21. 老師,請問一下,為什麼會進不了BT.available()的狀態呢?
    (code是用老師的,master用A0, A1,slave用8,9)

  22. 老師你好~我在網路上看到藍牙分為SCO跟ACL,最多可以對七個從端連接,這個意思是可以一對七個同時連接嗎?
    還是需要設定什麼才能辦到。

  23. 老師你好我是用HC-05 2個互傳
    所以留言的方法都試了!
    沒有顯示LEDON LEDOFF
    我把begin都改過了 主端從端
    都設了 還是不行
    有什麼方法出問題了!!

  24. 老師我是用 兩個ch05做實驗 設定也確定好了
    led同時變慢 傳送資料時主端tx燈亮 接收端rx也亮
    但是 (主端com3) 監控視窗 沒有任何回應 (led on led off)
    打開(接收端com4) 監控視窗卻接收到 ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮ 的訊息
    可以請老師解惑嗎 程式都是照網頁上

  25. 老師您好,我用的是HC-05 HC-06 AT模式測試成功,程式碼也要用老師的範例,但無論如何從主端發送命令接收端依然都沒有反應,我也照老師留言所說的方發先將藍芽移除把Arduino RX TX接到另一塊Arduino上面,也無法從主端接收到資料麻煩老師解答,謝謝

  26. 老師您好,

    拜讀您的書想學習 Arduino ,目前卡在藍芽傳輸的問題,我成功的用了兩個 HC-05溝通傳遞數值,接收傳感器的數值
    但以假設 BTSerial.read();的方法只能讀取一組傳感器的資料,我該如何接收跟傳遞多組傳感器給另外一台 Arduino
    我現在大致上有用到 溫度&電壓的數值,再麻煩老師您抽空回覆,謝謝。

    1. 由於HC-05的韌體僅支援一對一連線,因此在一對多連線的場合,你可以考慮使用nRF24L01無線收發器模組、乙太網路、W-Fi無線網路或者ZigBee,這其中最經濟的方案是nRF24L01,但是你可能要克服電源干擾的問題,建議先用兩個模組一對一連線測試看看。ZigBee的成本最高,比較不建議。

      thanks,
      jeffrey

  27. 老師您好,您可能有點誤會我的意思,我的確是使用一對一而已,只不過A當遙控器(含螢幕顯示),B負責接感知器(溫度、電壓),但是要透過藍芽從B傳回A, 若我兩個Sensor的數值都放在 BTSerial.write(volts); & BTSerial.write(TEMP); 丟回A 會產生兩個數值在A跳來跳去,因為我只會用A主機做 BTSerial.read();,我是想請教老師如何在A對應相對正確的感知器回傳數值,網路上大多數的範例都是利用 Android 手機,但我是想要用 Arduino 掛螢幕接收,再煩請老師指教,謝謝。

    1. 你可以把所有感測器數值都組成一個字串,中間用逗號分隔,把這些數值一次傳遞出去。
      接收端再透過字串分割的方式,取出每個資料元素。
      相關的程式寫法,請參閱這一篇回應

      thanks,
      jeffrey

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *