Arduino 配合 HC05藍牙模組 無線控制

最近打算製作一些無線的工具,方便遙距控制一些裝置,通報訊息

HC05模組

外觀
見下文
HC05模組 的正面

見下文
CSR 的 BC417藍牙晶片

見下文
Spansion 的 記憶體晶片

見下文
HC05模組 的背面
部分 HC05模組 會提供連接到 BC417藍牙晶片 刷新用的SPI引腳,可以變更 BC417藍牙晶片 的功能

引腳
編號引腳方向功能
1EN輸入低電壓或不接電 為 資料模式 ;高電壓 為 指令模式
2VCC電源,接受 3.6V 至 6V
3GND接地
4TXD輸出UART 發送訊號引腳
5RXD輸入UART 接收訊號引腳
6STATE輸出回應HC05狀態:
每100毫秒反覆輸出高低電壓時為資料模式
每2秒反覆輸出高低電壓時為指令模式

資料模式

藍牙裝置的 資料模式 是使用 UART通訊協定 傳送及接收訊號
線路原型
見下文
HC05模組 雖然有6支引腳,但如果執行資料模式,只需要使用4支引腳便可以與 HC05模組 通訊
VCC 及 GND 接通電路,及接駁 UART通訊協定 的 TXD 及 RXD 到微控制器

實際線路
見下文
閣下可能會發現在下將 Arduino Nano 連接 HC05模組,不是使用原生的 TX 及 RX 引腳
原因是 Arduino Nano 的 TX 及 RX 引腳只能在 從機狀態 才能使用
當 Arduino Nano 透過 USB 連接到 電腦 時,屬於 主機狀態,因此不能使用 TX 及 RX 引腳連接 從機 傳送及接收訊號

見下文
HC05模組啟動時,便會發射藍牙訊號,讓藍牙主機搜尋及連接
LED指示燈 會以 100毫秒 速度閃動

見下文
在下連接 七段顯示器 作簡單測試

使用 Android 測試
Android 裝置通常都內建藍牙功能,連接方法亦比較簡單,因此使用 Android 測試

見下文
HC05模組 使用 藍牙2.0 ,只要 Android 能夠搜尋到藍牙訊號,即可連接
在下使用 Serial Bluetooth Terminal ,讓 Android 向 HC05模組 傳送 序列訊號
但 iOS 只可以與具備 藍牙低功耗 (Bluetooth Low Energy (BLE)) 連接
然而 HC05模組沒有 BLE功能,因此暫時無法使用 iOS 測試

見下文
開啟 Android 的 藍牙工具,搜尋 HC模組 的名稱

見下文
見下文
選擇 HC-05 後,HC05模組 需要輸入密碼才能配對
預設的 HC05模組 使用 0000 1234 為配對密碼

見下文
開啟 Serial Bluetooth Terminal 到 選單 Devices

見下文
選擇 HC-05

見下文
HC-05 連接後,會顯示綠色標示

見下文
回到 Serial Bluetooth Terminal 的 Terminal 會顯示
Connecting to HC-05 ...
Connected

見下文
Serial Bluetooth Terminal 可以自訂訊號按鈕,方便操作

見下文
透過 Android 向 HC05模組 傳送訊號,控制 七段顯示器 顯示十六進制數值

操作前,還要將 Sketch 上載到 Arduino Nano 才有效果
HC05模組 的資料模式預設以 9600鮑率運作,因此都要以 9600鮑率的速度 傳送及接收訊號
另外由於 Arduino Nano 原本的 UART引腳 只能作為 從機使用
因此使用 Arduino 預設的 SoftwareSerial.h 函式庫作為主機 傳送及接收 UART訊號
#include <SoftwareSerial.h>

SoftwareSerial myBlue = SoftwareSerial(3, 2);

const byte VCC_PIN = 12;
const byte GND_PINS[] = {8, 7, 6, 5, 4, 9, 10, 11};
const byte SEGMENTS[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x80};

void setup() {
	myBlue.begin(9600);
	pinMode(VCC_PIN, OUTPUT);
	digitalWrite(VCC_PIN, HIGH);
	for (byte i = 0; i < sizeof(GND_PINS) / sizeof(byte); i++) {
		pinMode(GND_PINS[i], OUTPUT);
		digitalWrite(GND_PINS[i], HIGH);
	}
}

void loop() {
	while (myBlue.available()) {
		byte b = myBlue.read();
		if ('0' <= b && b <= '9') {
			for (byte i = 0; i < sizeof(GND_PINS) / sizeof(byte); i++) {
				digitalWrite(GND_PINS[i], ((SEGMENTS[b - '0'] ^ 0xFF) & (1 << i)) > 0);
			}
		} else if ('A' <= b && b <= 'F') {
			for (byte i = 0; i < sizeof(GND_PINS) / sizeof(byte); i++) {
				digitalWrite(GND_PINS[i], ((SEGMENTS[b - 'A' + 10] ^ 0xFF) & (1 << i)) > 0);
			}
		} else if ('a' <= b && b <= 'f') {
			for (byte i = 0; i < sizeof(GND_PINS) / sizeof(byte); i++) {
				digitalWrite(GND_PINS[i], ((SEGMENTS[b - 'a' + 10] ^ 0xFF) & (1 << i)) > 0);
			}
		} else if (b == ' ') {
			for (byte i = 0; i < sizeof(GND_PINS) / sizeof(byte); i++) {
				digitalWrite(GND_PINS[i], ((SEGMENTS[16] ^ 0xFF) & (1 << i)) > 0);
			}
		}
	}
}
使用 Minicom 測試
Minicom 是一個數據機通訊軟件,可以向序列裝置傳送訊號
由於普遍 Linux發行版 沒有預裝 Minicom ,需要在 Terminal 輸入
sudo apt install minicom

在此下載及安裝 Minicom

見下文
由於 藍牙裝置 有 類別 區分,但 HC05模組 屬於 未分類 (Uncategory)
因此,即使已經與 HC05模組 配對,但控制版面會顯示開關按鈕無法按動

見下文
雖然 HC05模組 屬於未分類,但仍然可以使用 射頻通訊 (Radio frequency communication (RFCOMM)) 的方法傳送序列訊
由於系統預設未必會包含 射頻通訊裝置,因此需要使用 rfcomm指令 建立 射頻通訊裝置 的 裝置檔案
在 Terminal 輸入
sudo rfcomm bind hci0 <Bluetooth-MAC-Address>

<Bluetooth-MAC-Address> 為 藍牙裝置的地址
由於需要在 /dev 目錄建立 RFCOMM裝置檔案,因此必須使用 sudo 或 root帳戶 才能執行操作

見下文
輸入
minicom -con -b 9600 -D /dev/rfcomm0

-con 使用分類顏色顯示資料,可以不使用
-b 9600 設定 9600鮑率 連接藍牙裝置,預設 115200
-D /dev/rfcomm0 設定 射頻裝置 的位置 為 /dev/rfcomm0 ,預設 /dev/modem

見下文
連接後,控制版面會發現 HC05模組 原本在控制版面無法按動開關 顯示已連接
但仍然無法按動開關

見下文
見下文
雖然 Minicom 還有更新,但 Minicom 仍然使用相對比較舊的操作方法,而且操作不太直觀
執行 Minicom 後,會發現所有按鍵都沒有反應,需要先按 Ctrl+A 後再按 Z 開啟說明選單才了解操作方法
執行基本訊號傳送,需要先啟用 local Echo (Ctrl+A 後按 E) ,才能夠在 Minicom 中直接傳送訊號

見下文
在電腦經 藍牙序列通訊 傳送訊號

測試時會發現,HC05模組 接收的速度時快時慢
主要因為 HC05模組 的 工作週期 相比現今的藍牙裝置太慢,顯得有明顯的延遲
不過作為學習或測試用途,並沒有太大問題

指令模式

指令模式 可以向藍牙模組 傳送設定指令,更改藍牙模組部分設定值
閣下可能會發現 Minicom 的示範中, HC05模組 的名稱是 MyBlue 而不是 HC-05
是因為使用 AT指令 來設定藍牙裝置的資料
由於 HC05 並不支援所有 AT指令,亦並非所有指令都需要使用
因此在下只列出部分常用的指令,閣下有興趣可以自行尋找 AT指令 的清單

AT指令
指令回應功能
AT
OK
測試指令
AT+RESET
OK
重新啟動
AT+ORGL
OK
OK
OK
回復原始設定
AT+VERSION?
+VERSION:<data>
OK
顯示版本
<data> 為版本
  • 格式為 VER-YYYYMMDD
AT+ADDR?
+ADDR:<data>
OK
顯示地址
<data> 為 Mac地址
  • 但接收到 AT 的格式為 NNNN:NN:NNNNNN
AT+NAME?
+NAME:<data>
OK
顯示名稱
<data> 為名稱
AT+NAME=<data>
OK
設定名稱
<data> 為名稱, 最長22個位元組字元
  • Unicode字元會以3位元組計算
AT+PSWD?
+PSWD:<data>
OK
顯示密碼
<data> 為密碼
AT+PSWD=<data>
OK
設定密碼
<data> 為密碼, 必須4個位元組字元
  • Unicode字元會以3位元組計算
AT+CMODE?
+CMODE: <data>
OK
顯示連接模式
<data> 為連接模式的類型
AT+CMODE=<data>
OK
設定連接模式
<data> 為連接模式的類型
  • 0 為 指定模式,只能讓指定地址連接
  • 1 為 任意模式,可以讓任意裝置連接
  • 2 為 回環模式,只傳回訊號
AT+ROLE?
+ROLE:<data>
OK
顯示角色模式
<data> 為角色模式的類型
AT+ROLE=<data>
OK 
設定角色模式
<data> 為角色模式的類型
  • 0 為 被動模式,裝置接收訊號
  • 1 為 主動模式,裝置傳送訊號
  • 2 為 回環模式,只傳回訊號
AT+UART?
+UART:<data1>,<data2>,<data3>
OK
顯示資料模式的UART
<data1> 為 鮑率
<data2> 為 停止位元
<data3> 為 校驗位元
AT+UART=<data1>,<data2>,<data3>
OK 
設定資料模式的UART
<data1> 為 鮑率
  • 4800
  • 9600
  • 19200
  • 38400
  • 57600
  • 115200
  • 230400
  • 460800
  • 921600
  • 1382400
<data2> 為 停止位元
  • 0 為 1位元
  • 1 為 2位元
<data3> 為 校驗位元
  • 0 為 不校驗
  • 1 為 單數校驗
  • 2 為 雙數校驗
AT+STATE?
+STATE:<data>
OK
顯示狀態
<data> 為顯示狀態
  • INITIALIZED 為 初始化狀態
  • READY 為 準備連接狀態
  • PAIRABLE 為 可配對狀態
  • PAIRED 為 已配對狀態
  • INQUIRING 為 查詢狀態
  • CONNECTING 為 正在連接狀態
  • CONNECTED 為 已連接狀態
  • DISCONNECTED 為 中斷連接狀態
  • NUKNOW 為 未知狀態
當中
  • AT+NAME
  • AT+PSWD
  • AT+ROLE
  • AT+CMODE

會比較常用
接駁線路
見下文
見下文
基本上與資料模式相同,只是將 EN引腳 連接到高電壓

使用序列監視器傳送 AT指令
現今的電腦已經絕少具備 D-Sub 9 介面
Arduino IDE 的 序列監視器 (Serial Monitor) 可以透過 Arduino 顯示裝置的序列訊號,還能夠將序列訊號傳送到裝置
不需要特殊裝置,而且 Arduino IDE 是跨平台軟件,可以非常簡單地在任何平台監視序列訊號

見下文
進入指令模式時,LED 會每 2秒 閃動

將 Sketch 上載到 Arduino Nano HC05模組 的指令模式以 38400鮑率運作
#include <SoftwareSerial.h>

const byte RX_PIN = 3;
const byte TX_PIN = 2;

SoftwareSerial myBlue = SoftwareSerial(RX_PIN, TX_PIN);

void setup() {
	myBlue.begin(38400);
	Serial.begin(9600);
}

void loop() {
	while (Serial.available()) {
		char c = Serial.read();
		Serial.print(c);
		myBlue.write(c);
	}
	while (myBlue.available()) {
		char c = myBlue.read();
		Serial.write(c);
	}
}

見下文
上載 Sketch 後,開啟 Arduino IDE 的 序列監視器 (Serial Monitor)

見下文
由於 AT指令 是以 回車 (Carriage Return (CR)) 換行 (Line Feed (LF))
如果需要透過 序列監視器 傳送訊號,先將 結束字符 設定為 Both NL & CR

見下文
序列監視器 可以在文字爛位輸入 AT指令 後按 ENTER鍵 或按 Send按鈕 向 HC05模組 傳送訊號

見下文
在 序列監視器 輸入
AT 

測試
如果 HC05模組 正常運作,會傳回
OK 

給微控調器

見下文
輸入
AT+NAME?

傳回
+NAME:<藍牙名稱>
OK

表示藍牙名稱
及輸入
AT+PSWD?

傳回
+PSWD:<配對密碼>
OK

表示配對密碼

見下文
輸入
AT+NAME=<藍牙名稱>

傳回
OK 

表示藍牙名稱設定成功
及輸入
AT+PSWD=<配對密碼>

傳回
OK 

表示配對密碼設定成功

見下文
搜尋藍牙裝置 時會發現 更新藍牙名稱 後的 HC05模組
但主機未必會即時顯示新名稱,有時需要連接後才會更新

見下文
見下文
輸入 更新後的配對密碼
(雖然配對密碼已經更新,但提示內容仍然顯示 0000 及 1234)

補充資料

復原後的設定
見下文
閣下可能會發現網上有些教學會使用 按鈕 啟動 HC05模組 的指令模式,但在下卻沒有提及 HC05模組 上的按鈕
原來 HC05模組 的 指令模式,還區分 簡化指令模式 (Mini AT Mode) 完整指令模式 (Full AT Mode)
簡化指令模式 只能執行很少 AT指令 ,但在下無法啟動 HC05模組 的 簡化指令模式
因此沒有考慮使用 簡化指令模式

HC05模組 的指令模式是以 38400鮑率運作,而示範指 序列監視器 要設定為 38400鮑率
但 序列監視器 設定為 38400鮑率,與 SoftwareSerial.h 的 38400鮑率 沒有關係
因此在下並沒有 序列監視器設定為 38400鮑率

另外,在下測試 HC05模組 回復原始設定 指令,發現回復後無法搜尋 HC05模組
網上資料指要將 AT+CLASS 設定為 1 ,但在下的 HC05模組 無法修改 CLASS ,仍然顯示 0x1F00
可能是在下的 HC05模組 與 網上說明的 HC05模組 不完全相同導致
在下查詢 藍牙的 裝置類別 (Class of Device (CoD))

主類別位元次類別位元十六進制主類別次類別
1211109876543210
00000000000000x0000雜項沒有
00001000000000x0100電腦未分類電腦
00001000001000x0104電腦桌上電腦
00001000010000x0108電腦伺服器電腦
00001000011000x010C電腦手提電腦
00001000100000x0110電腦迷你電腦
00001000101000x0114電腦掌上電腦
00001000110000x0118電腦穿戴電腦
00001000111000x011C電腦平板電腦
00010000000000x0200電話未分類電話
00010000001000x0204電話蜂巢式電話
00010000010000x0208電話無線電話
00010000011000x020C電話智能電話
00010000100000x0210電話數據機
00010000101000x0214電話綜合服務數碼網絡
00011000000000x0300網絡裝置完全使用
00011001000000x0320網絡裝置1%~17%使用
00011010000000x0340網絡裝置17%~33%使用
00011011000000x0360網絡裝置33%~50%使用
00011100000000x0380網絡裝置50%~67%使用
00011101000000x03A0網絡裝置67%~83%使用
00011110000000x03C0網絡裝置83%~99%使用
00011111000000x03E0網絡裝置完全不使用
00100000000000x0400影音裝置未分類影音裝置
00100000001000x0404影音裝置穿戴式耳筒
00100000010000x0408影音裝置免手持式裝置
00100000011000x040C影音裝置<保留>
00100000100000x0410影音裝置麥克風
00100000101000x0414影音裝置擴音機
00100000110000x0418影音裝置耳筒
00100000111000x041C影音裝置攜帶式音響
00100001000000x0420影音裝置汽車音響
00100001001000x0424影音裝置數碼視訊轉換器
00100001010000x0428影音裝置高品質音響
00100001011000x042C影音裝置錄影機
00100001100000x0430影音裝置影像鏡頭
00100001101000x0434影音裝置攝影機
00100001110000x0438影音裝置影像監視器
00100001111000x043C影音裝置影像顯示器及擴音機
00100010000000x0440影音裝置影像會議
00100010001000x0444影音裝置<保留>
00100010010000x0448影音裝置遊戲及玩具
00101000000000x0500周邊裝置未分類周邊裝置
00101000001000x0504周邊裝置遊戲控制桿
00101000010000x0508周邊裝置遊戲控制器
00101000011000x050C周邊裝置遙控器
00101000100000x0510周邊裝置感應裝置
00101000101000x0514周邊裝置繪圖板
00101000110000x0518周邊裝置讀卡器
00101000111000x051C周邊裝置數碼筆
00101001000000x0520周邊裝置手持式掃描器
00101001001000x0524周邊裝置手勢輸入裝置
00101010000000x0540周邊裝置鍵盤
00101100000000x0580周邊裝置浮點裝置
00101110000000x05C0周邊裝置複合鍵盤及浮點裝置
00110000100000x0610成像裝置顯示器
00110001000000x0620成像裝置相機
00110010000000x0640成像裝置掃描器
00110100000000x0680成像裝置印表機
00111000001000x0704穿戴裝置手錶
00111000010000x0708穿戴裝置傳呼機
00111000011000x070C穿戴裝置外套
00111000100000x0710穿戴裝置頭盔
00111000101000x0714穿戴裝置眼鏡
01000000001000x0804玩具機械人
01000000010000x0808玩具汽車
01000000011000x080C玩具公仔
01000000100000x0810玩具控制器
01000000101000x0814玩具遊戲
01001000000000x0900健康裝置未定義健康裝置
01001000001000x0904健康裝置血壓監測器
01001000010000x0908健康裝置溫度計
01001000011000x090C健康裝置重量計
01001000100000x0910健康裝置血糖計
01001000101000x0914健康裝置血氧飽和儀
01001000110000x0918健康裝置脈搏監測器
01001000111000x091C健康裝置健康資料顯示器
01001001000000x0920健康裝置計步器
01001001001000x0924健康裝置身體成份分析儀
01001001010000x0928健康裝置峰值呼氣監測器
01001001011000x092C健康裝置藥物監測器
01001001100000x0930健康裝置膝關節置換器
01001001101000x0934健康裝置腳踝置換器
01001001110000x0938健康裝置通用健康管理器
01001001111000x093C健康裝置個人行動裝置
11111000000000x1F00未分類沒有

根據現存的 裝置類別 顯示,暫時不存在 1 的類別
因此在下繼續閱讀 AT指令表 嘗試自行解決問題,最後在下將 AT+CMODE 設定為 1
AT+CMODE=1

才能讓 Android 搜尋到 HC05模組

除了解裝置類別,還有 裝置服務 (Service of Device (SoD))
SoD位元CoD位元(共13位元)服務名稱
2322212019181716151413第12至0位元
00000000001*可見度
00000001000*定位服務
00000010000*網絡服務
00000100000*渲染服務
00001000000*擷取服務
00010000000*傳輸服務
00100000000*音訊服務
01000000000*通話服務
10000000000*資訊服務

修改名稱問題
見下文
還有,當 HC05模組 回復原始設定 後,藍牙裝置的名稱,並非 HC-05 而是 H-C-2010-06-01OK
但其實最後的 OK 是 HC05模組 傳送正確的訊息,因此實際的預設名稱是 H-C-2010-06-01

見下文
嘗試在電腦連接 HC05模組 ,發現顯示連接藍牙裝置時的名稱出現斷行

見下文
在下被預設名字提示,發現 HC05模組 修改的名稱後的 OK 會在新行顯示,在下估計是因為行尾的 CR 及 LF 導致
因此將 結束字符 更改為 No line ending 後,再傳送 AT+NAME=MyBlue

見下文
發現 AT+NAME=MyBlue 是能夠正確傳送指令

見下文
連接藍牙裝置時的名稱沒有斷行,亦即是設定 藍牙裝置的名稱是不需要使用 CF 及 LF 為結束字元
減去 CF 及 LF ,即是藍牙裝置名稱最長是24個位元組字元

總結

見下文
HC05模組 是一種常見的 藍牙模組,網絡上有很多示範資料,但在下發現很多示範都是搬字過紙
官方的文件都沒有說明清楚修改名藍牙裝置名稱的正確方式
普遍網上的資料都是使用 Android 為示範效果,而在 Android 中,藍牙裝置的名稱不會顯示 CR 及 LF (或轉換成 空格字元 顯示)
大部分資料都是將內容複製、貼上或將只是轉載內容,根本沒有正式地查證及親自研究
包括恢復原始設定後,要使用 AT+CMODE=1 來解決的方法,在下在網上找不到相關資料(亦可能是在下無法正確搜尋關鍵內容)
更加不要期望會提供經由電腦的序列裝置與藍牙裝置通訊的示範

參考資料