2015年3月3日 星期二

Arduino : 兩個 HC-05 藍牙模組互連

2015年3月3日 星期二
「如何讓兩個 HC-05 互連後交換資料?」在我的 blog 中被問了 N 回,不過,因為原本只有一片 HC-05 ,根本沒有機會實作,也在留言回覆中說明無法測試,更別說要教人家。是說,講了這麼明白了,還是持續有人在問這個問題,A~嗯~大家辛苦了!別人的留言也要看啦!

上回淘寶時,看 HC-05 比在沒屋頂買的便宜好多,順便淘了 HC-05 要來玩兩片互連。有時間,沒東西;有了東西,反而沒時間......,放了好久,總算拿出來試,底下是測試的筆記。



設定 HC-05


首先,當然是要以 AT command mode ,先設定一下兩片 HC-05,主要是讓它們扮演不同的角色:slave 和 master (出廠時,預設是 slave);除此之外, 通訊時,UART 的 baud rate 也要設為一樣......。

假設兩片 HC-05 要以 115200 的 baud rate 通訊,並且只鎖定對方連線,可能要進行以下的設定:

在當 slave 的 HC-05 必須執行的 AT command :
  • AT+UART=115200,0,0
  • AT+CMODE=0
  • AT+ROLE=0
  • AT+ADDR?

如果「AT+ADDR?」回應的內容是:

+ADDR:14:1:61757

要記下 +ADDR: 後面的那串數字「14:1:61757」(slave 的 address),設定 master 時會用到。

在當 master 的 HC-05 必須執行的 AT command :
  • AT+UART=115200,0,0
  • AT+CMODE=0
  • AT+ROLE=1
  • AT+BIND=14,1,61757  
    (注意:14,1,61757 請自行置換成您查到的 slave address)

照上面的 AT commands 來看,slave 和 master 不同的地方在後兩道指令:

  • 「AT+ROLE=」用來設定模組的角色是 slave ( 0 ) ,還是 master ( 1 )。
  • 「AT+ADDR?」用來查詢 client 的 address。
  • 「AT+BIND=」用來指定要主動連哪一個 address 的 slave。
特別注意:「AT+ADDR?」查到的 address 中是用冒號「:」當分隔符號,而在 BIND 指令中用的卻是用逗號「,」當分隔符號哦!


經過前述的設定後,照說,當 master 找到 slave 時,就會自動連線了。接著就可以利用兩片 HC-05 上的 TXD 和 RXD 來傳送及接收資料。

Arduino 接線


HC-05 要怎麼和 Arduino 連接呢?其實兩片 HC-05 交換資料和一片 HC-05 與其它藍牙裝置交換資料,接線的方法並沒有什麼不同,最重要的是前一步驟,利用 AT command 要將「UART」、「ROLE」及 master 的「BIND」設對啦!

我們可以選擇用 Arduino 的 D0、D1 來連接 HC-05,或是利用 Arduino 的 D10、D11,以 SoftwareSerial 的方式來連接 HC-05,腳位對應如下:

方法一 (HC-05 TXD、RXD接在D0、D1):
  • HC-05 TXD ----- Arduino D0
  • HC-05 RXD ----- Arduino D1

方法二 (用 SoftwareSerial,HC-05 TXD、RXD接在D10、D11):
  • HC-05 TXD ----- Arduino D10
  • HC-05 RXD ----- Arduino D11


如果使用方法二,記得要導入 SoftwareSerial 的函數庫,在程式的最前面加入:

#include <SoftwareSerial.h>

並建立一個「SoftwareSerial」的物件才能使用,而方法一只要直接用「Serial」即可。


Arduino 程式


我寫了個測試的程式,在插 slave HC-05 的 Arduino 加一片 LCD(1602A),當 master 那塊 Arduino 傳來字串,slave 接收到後,將字串顯示在 LCD 上

slave 端程式碼(HC-05 TXD、RXD接在D10、D11)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(10, 11); // HC-05的TXD,RXD腳位
LiquidCrystal_I2C lcd(0x27,16,2);  // 設定 LCD
void setup()
{
  lcd.init();            // initialize the lcd
  lcd.backlight();
  BTSerial.begin(115200);
}
void loop()
{
  // 檢查是否有資料傳來
  if (BTSerial.available()) {
    delay(100);  //稍候一下,讓資料都到
    lcd.clear(); //清除 LCD 畫面
    // 讀取所有資料,並顯示在 LCD
    while (BTSerial.available() > 0) {
      lcd.write( BTSerial.read() );
    }
  }
}

上面程式中,關於 HC-05 的指令如下:

  • 建立SoftwareSerial : SoftwareSerial BTSerial(10, 11)
  • 設定鮑率:BTSerial.begin(115200);
  • 檢查是否有資料傳來:BTSerial.available()
  • 讀取傳來的資料:BTSerial.read() 

有「read」,當然就可以使用「write」來將資料傳送給 master 端。


master 端程式碼(HC-05 TXD、RXD接在D10、D11)

#include <SoftwareSerial.h>
SoftwareSerial BTSerial(10, 11); // HC-05的TXD,RXD腳位
void setup() {
  BTSerial.begin(115200);
  //稍等一秒後再送資料給遠方
  delay(1000);
  BTSerial.write("^^ I Love You ^^");
}
void loop()
{
  //
}

這裡只簡單的用「write」來送出字串給遠端的 HC-05,想接收遠端送來的資料,當然就使用「read」囉!


哈~將 LCD  裝在之前 3D printer 做的履帶車上,用手機遙控,開到老婆面前後,再打出字幕,不賴吧!討了老婆歡心之後,應該可以提高對我老是花很多時間在研究如何「玩耍」的耐受度吧?!

相關文章




56 則留言:

  1. 最後使用LCD放閃的大絕招我要向雄哥學習 ^_^
    這樣以後玩耍時就不會老是被罵亂花錢了 :P

    回覆刪除
    回覆
    1. Wei ming :
      為了我們「美好的未來」,這是一定要的啦!!

      刪除
  2. 請問雄哥 能用2個HC-06互連傳資料嗎~

    回覆刪除
    回覆
    1. slave 和 slave 則無法通訊, 而 HC-06 不像 HC-05 可以自己設定它要當 master 還是 salve, 所以, 如果您是買了一個 master 的 HC-06 和一個 slave 的 HC-06 , 那它們就可以互連傳資料。

      刪除
  3. 不好意思,想請問假如兩塊hc05型號不同,會影響其溝通嗎?

    回覆刪除
    回覆
    1. 您好:
      我測試時,兩塊都是 HC-05, 不過,是不同廠商的貨,配置亦不同,您指的是這種情形嗎?照說,只要板子跑相同協定,應該可以通訊才對,不然,就不用制定通訊協定了。可能還是試過才知道,個人只用過幾塊而已,純憑猜測。

      刪除
  4. 你好 可否提供你的LCD library是那個版本,我網路嘗試了幾個都無法與你的程式匹配,另外在請教 我如果使用2004
    是否改成 LiquidCrystal_I2C lcd(0x27,20,4); 就可以了呢?
    謝謝你

    回覆刪除
    回覆
    1. chingying cheng 您好:
      因為是直接用商家給的參考資料, 並不知道它的版本為何。
      真不好意思, 我是第一次用 LCD, 細節的部份並沒有深入研究, 建議您還是搜尋一下別人的解說資料, 可能較清楚。

      刪除
  5. 作者已經移除這則留言。

    回覆刪除
  6. 您好
    非常感謝你提供這麼有用的資料,國內網站我找了很多都沒有您的詳細。
    我也是今天剛買了兩塊HC-05來玩玩看
    有研究一下如何傳數值~ 確實蠻充實的
    -----------------------------------------------------
    如果是用一般的LCD模組 記得改成lcd.print(char(BTSerial.read()));
    char才能正常顯示喔~
    大家不要吝嗇多多分享自己實作的經驗吧~

    回覆刪除
  7. 您好,我可不可以在 另一塊版子上裝設RC522

    然後把讀取的結果( 1或2) 也就是正確或錯誤

    單純這兩個訊息回傳到主要的MEGA2560

    因為我的RC522會距離原本的版子2.2米

    用8PIN的排線過去,線太長訊號回不來。

    回覆刪除
    回覆
    1. 或者是有沒有其他的解呢?

      刪除
    2. 您好:
      我沒用過 RC522,可不可以這麼做,您試試看就可以知道結果了呀!玩這種東西最大的樂趣不就是動手。祝您成功!

      刪除
  8. 您好
    非常感謝你提供這麼有用的資料,對我受用無窮!!!

    但我現在遇到一個問題是:

    我有HC05與HC06各ㄧ個,我讓HC05當master讓他連上HC06,不過我查到HC06的mac address是30:14:11:28:31:14
    我使用AT+BIND=30,14,11,28,31,14確出現error,想請問我應該怎麼讓我的HC05透過藍牙方式連接上HC06呢?

    麻煩您了,非常感謝!

    回覆刪除
    回覆
    1. 您好:
      看您 mac address 的格式好像不太一樣, 您可能要重新在 HC05 中下「AT+ADDR?」指定再查一下回應的內容,然後才將分隔符號置換為逗號。

      刪除
  9. 哈囉您好:
    謝謝您的回覆,我有在HC05中下AT+ADDR?但這樣不就是HC05的address嗎?但我想要HC05連上HC06,但HC06是不是不能用AT+ADDR?這個command?

    回覆刪除
    回覆
    1. 您好:
      抱歉,我手上並沒有 HC06 可以測試,您可能要自己試試。建議您還是先去將您那兩片的使用說明找出來,應該可以省去很多摸索的時間。

      刪除
  10. 作者已經移除這則留言。

    回覆刪除
  11. 您好,我使用Arduino搭配兩個HC-05做主僕式藍芽通訊,我想將複數筆資料(溫度、濕度、光照度)由slave傳至master,請問我是否能在主端分開資不同料類別的資料? 建議該如何操做呢? 謝謝您!

    回覆刪除
    回覆
    1. 您好:
      個人是認為像這種可以實作的問題, 自己心中有何想法, 去試試看就可以知道結果了。
      通訊的問題, 應該就是一來一往, 編碼、解碼, 編碼、解碼,想傳多長的資料, 只要兩端的協定講好了就可以。

      刪除
  12. 謝謝老師教導, 另問如何再掏寶網購物及付費 謝謝

    回覆刪除
  13. 您好~想請問如果我想利用電腦藍芽傳送資料給hc-05,再藉由hc-05將資料傳送給連接的arduino nano板,讓nano板去執行此資料的程式碼。想請問電腦藍芽傳送給hc-05的資料附檔名要是什麼檔才接收的到????

    回覆刪除
    回覆
    1. 您好:
      HC-05 並不是直接傳檔案, 您必須自己將資料編碼傳出去, 在另一邊則進行反向的解碼, 對 HC-05 而言, 它只知道傳送及接收一堆 0 和 1, 因此和資料的檔名沒有任何關係。

      刪除
  14. 您好~~~
    我想請教您
    將HC-05進入AT時,它的亮燈會兩秒閃爍一次
    然後便可以開始寫AT設定鮑率.地址..等
    但當我將電源拔掉在插上
    便會發現它變回原本的閃爍速度
    這樣一來剛剛所寫進去的資訊還在嗎?

    回覆刪除
    回覆
    1. 您好:
      一般是執行改更改參數的 AT command 後就儲存了。
      其實您可以拔掉後, 重新以查詢的 AT command 觀察就知道了

      刪除
  15. 您好~~ 我想請教您~
    AT command的程式 是需要和傳接送的程式寫一起嗎
    還是可以分開寫 先做完 鮑率與地址後
    在燒入傳送接收得成是進去?

    回覆刪除
    回覆
    1. 您好:
      關於 AT command , 個人只用來設定藍牙模組, 多是透過 console 直接一行行下指令, 設定完就斷線, 讓它回到一般模式。HC-05/06 如果執行的是設定的指令,輸入完畢就自動寫入了, 使用者不用管寫入的部份。至於其它的應用, 因為沒有需求, 我完全沒經驗。

      刪除
  16. 你好~我想請問您,為何無法傳輸

    slave:

    void setup() {
    Serial.begin(9600);
    blue.begin(9600);
    }

    void loop() {
    blue.write(currentHeartrate);
    }

    master:

    void setup() {
    Serial.begin(9600);
    blue.begin(9600);
    }

    void loop() {
    if (blue.available()) {
    val = blue.read();
    Serial.println(val);
    }
    }

    我想詢問邏輯有問題嗎,宣告及符號沒問題編譯有過

    回覆刪除
    回覆
    1. 請問這個問題最後如何解決呢?
      最近遇到一樣的問題

      刪除
  17. 您好,感謝老師的資料,依照資料稍加修改已經可以兩塊板子用藍芽傳輸文字到LCD了,但是每次重開機都會有某些字會亂碼,最後把全部板子程式碼跟藍芽AT的傳輸速率都設為9600,竟然都好了,每次都一字不差。不懂原因,很幸運。

    回覆刪除
  18. 你好~~我想請教您
    AT+UART=115200,0,0
    後面兩個0的意思是什麼?

    回覆刪除
    回覆
    1. 您好:
      三個參數分別為 : baud rate , stop bit, parity
      用 "AT+UART" 或是 AT command 搜尋, 應該可以找到很多說明哦~

      刪除
  19. 請問 我設計好 app invertor 2 的APP, 可以和 3個 HC-05 都配對成功,個別連線控制也可以,現在的問題是要 同時控制3個的話,也就是群控,可以做的到嗎? APP要怎麼選拼塊來改? 謝謝!

    回覆刪除
    回覆
    1. 您好:
      哈~這我沒玩過, 您會了記得來分享一下哦~~

      刪除
  20. 老師您好:
    我是土木系的學生,我最近有使用mma8451加速規與UNO或MEGA板去接上筆電做測試,我若想改成使用HC-05來無線傳輸資料到teraterm這軟體來擷取XYZ軸資料,想請問我的程式碼是否只需把您提供的slave端程式碼稍作修正直接丟入我原本寫的程式內即可?

    回覆刪除
    回覆
    1. 暐力您好:
      我沒用過 Tera Term,不過,我想,應該是差不多。反正 HC-05 接在 Arduino 上,您只要寫到它建立的的通道,由遠端收到的資料,只要能對應的解碼即可。

      刪除
    2. 好的,謝謝老師,我再試試看

      刪除
  21. 老師你好:
    如果想要利用藍芽模組(主端)收集超音波控制LED燈的資料再傳給另一個藍芽模組(從端)要怎麼打程式比較好??

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

    回覆刪除
  23. 老師你好 :
    我想請問,如果是要利用類比搖桿,經由藍芽,操作兩顆伺服馬達,
    我要如何才能讓slave知道說這個Y角度是A伺服馬達,X角度是B伺服馬達?

    回覆刪除
    回覆
    1. 您好:
      您是寫程式的人,可以自己在傳資料時做一下編碼,除了數字,加上文字來識別。另一端則依據規則來解碼即可。基本概念是這樣,實作則端看您怎麼想,其實沒有一定要怎麼做的,試了看結果如何,再慢慢修改成自己想要的功能。

      刪除
  24. 老師您好
    我想請問一下 如果用兩個HC-05 對聯 可使用同一個板子嗎?

    回覆刪除
  25. 老師您好

    方法一 (HC-05 TXD、RXD接在D10、D11):
    HC-05 TXD ----- Arduino D0
    HC-05 RXD ----- Arduino D1

    方法一後方的D10 D11是否打錯了呢? 應為D0 D1

    回覆刪除
  26. 哈哈哈~ 是打錯了, 已修正。
    謝謝提醒 ^_^

    回覆刪除
  27. 老師您好
    如果想利用按鈕讓HC05的Master端發出訊號來控制Slave端的HC05該如何改寫程式碼呢?

    回覆刪除
    回覆
    1. 知道如何讓兩片 HC-05 傳資料以後,您只要在 Slave 端把收到字串做解析,並讓它們對應到你想做的動作指令就可以了。
      網路上很多這樣的範例(包括我的 blog 中),找一下就有得研究囉!加油!

      刪除
  28. 請問我想把三軸感測的數值用hc-05傳到另一個hc-05
    這是master:
    #include
    SoftwareSerial BTSerial(10, 11); // RX | TX
    const uint8_t zAxis = A2;
    const uint8_t yAxis = A1;
    const uint8_t xAxis = A0;

    //Min and Max values after calibration:
    int16_t zLow = 283, zHigh = 419, xHigh = 399, xLow = 264, yHigh = 396, yLow = 260;
    void setup()
    {
    pinMode(9, OUTPUT); // this pin will pull the HC-05 pin 34 (key pin) HIGH to switch module to AT mode
    digitalWrite(9, HIGH);
    Serial.begin(115200);
    Serial.println("Enter AT commands:");
    BTSerial.begin(115200); // HC-05 default speed in AT command more
    }
    void loop()
    {short angleX = map(constrain(analogRead(xAxis), xLow, xHigh),xLow,xHigh,-90,90);
    short angleY = map(constrain(analogRead(yAxis), yLow, yHigh),yLow,yHigh,-90,90);
    short angleZ = map(constrain(analogRead(zAxis), zLow, zHigh),zLow,zHigh,-90,90);

    String dataString = String(angleX);

    dataString +=",";
    dataString += String(angleY);
    dataString +=",";
    dataString += String(angleZ);

    Serial.println(dataString);
    char a=Serial.println(dataString);

    delay(100);

    // Keep reading from Arduino Serial Monitor and send to HC-05
    if (Serial.available())
    BTSerial.write(a);
    delay(100);
    }
    這邊是slave:
    #include
    SoftwareSerial BTSerial(10, 11); // RX | TX
    void setup()
    {Serial.begin(115200);
    BTSerial.begin(115200);
    }
    void loop()
    {
    if (BTSerial.available())
    {Serial.println("Enter AT commands:");
    delay(200);
    }
    Serial.println(BTSerial.read());
    delay(100);
    }
    請問我有哪裡錯了嗎

    回覆刪除
  29. 老師請問hc05可以雙向傳輸嗎?

    回覆刪除
    回覆
    1. 您好,
      不是很明白您的「雙向傳輸」指的是什麼,連線以後,它就像個通道,可以傳輸資料,要接收,要傳送是看程式要怎麼讓兩端動作。
      可不可以怎樣,應該是要查廠商給的規格書,可能會最精準。

      刪除

 
雄::gsyan © 2009. Design by Pocket