(photo)
實作上, 當以XBEE通訊時,NXT是使用S4的Hi-Speed port,Arduino則使用Serial port。
而當藍芽通訊時,NXT使用的是COMM Module功能,Arduino的藍芽模組(BluetoothBee)雖然也是透過Serial port,但必須符合NXT的封包交換規範。(DFRobot Bluetooth)
LEGO對於NXT通訊建立有NXT Communication protocol來定義它的功能,在階層(layer)上適用於有線(USB)與無線(Bluetooth)兩種方式,而主要的用途類型有:
● System Command:用於上傳/下載檔案以及刪除內存於NXT Flash的檔案。
對於上述這些通訊類型,在protocol中制訂有各個功能的封包格式,使用時,需要遵循定義的規範才能正確執行。
詳細規格可以參考官方的技術文件(Lego Bluetooth Developer Kit)。
配對 與 建立連結
由於本次Arduino所使用的藍芽模組其Bluetooth stack功能很陽春,因此,在與NXT通訊時只能作為Slave,而由NXT擔任Master來起始連結。
首先須進行的是NXT與Arduino藍芽裝置的配對與認證,完成之後會在NXT的Bluetooth→My contacts中建立名單:
(NXT My contacts)
配對之後,即可以由NXT的Bluetooth→My contacts→Select→Connect再選擇1~3 Connection來進行連結。
而若NXT有安裝NBC/NXC enhanced firmware,就可直接由NXC程式來建立連結。
(參考『使用NXC在程式中建立藍芽連結的方式』)
由於本次Arduino所使用的藍芽模組其Bluetooth stack功能很陽春,因此,在與NXT通訊時只能作為Slave,而由NXT擔任Master來起始連結。
首先須進行的是NXT與Arduino藍芽裝置的配對與認證,完成之後會在NXT的Bluetooth→My contacts中建立名單:
(NXT My contacts)
配對之後,即可以由NXT的Bluetooth→My contacts→Select→Connect再選擇1~3 Connection來進行連結。
而若NXT有安裝NBC/NXC enhanced firmware,就可直接由NXC程式來建立連結。
(參考『使用NXC在程式中建立藍芽連結的方式』)
NXT Message Command訊息交換指令
在NXT Communication Protocol的Direct command中,Message Command是定義交換字串資料的指令,含:MessageWrite與MessageRead兩個指令,都是以NXT信箱作為傳送與接收訊息的標的。
接下來,即會使用MessageWrite來分別進行:
(1)由NXT傳送字串資料給Arduino 以及
(2)反向由NXT接收來自Arduino所傳送資料等雙向的藍芽通訊。
對於NXT,無論(1)傳送或(2)接收,都有現成的NXC API可以使用。但對於Arduino,則在(1)接收時,需要自行解析封包內容,在(2)傳送時,則需建構指令封包。至於MessageWrite指令的封包格式為:
Byte 0 (Command Type):0x80 (為Direct command,且不須回覆訊息)Byte 1 (Command byte):0x09 (指令碼)
Byte 2 (Inbox number):信箱代號(0 – 9)Byte 3 (Message size):傳送的字串長度,含結尾null code
Byte 4 – N (Message data):傳送的字串資料,結尾須加上null code此外,為了改善NXT藍芽通訊的效率,在指令封包前還須加上兩個byte的封包長度資料,其中Low byte在前,High byte在後。
(1)由NXT傳送字串資料給Arduino 以及
(2)反向由NXT接收來自Arduino所傳送資料等雙向的藍芽通訊。
對於NXT,無論(1)傳送或(2)接收,都有現成的NXC API可以使用。但對於Arduino,則在(1)接收時,需要自行解析封包內容,在(2)傳送時,則需建構指令封包。至於MessageWrite指令的封包格式為:
Byte 0 (Command Type):0x80 (為Direct command,且不須回覆訊息)Byte 1 (Command byte):0x09 (指令碼)
Byte 2 (Inbox number):信箱代號(0 – 9)Byte 3 (Message size):傳送的字串長度,含結尾null code
Byte 4 – N (Message data):傳送的字串資料,結尾須加上null code此外,為了改善NXT藍芽通訊的效率,在指令封包前還須加上兩個byte的封包長度資料,其中Low byte在前,High byte在後。
(1)由NXT傳送至Arduino:
NXC的MessageWrite API為:
SendRemoteString (connection, mailBoxNo, sendStringValue) 當NXT呼叫上述的API傳送〝(99)_Hello_Arduino〞字串至Arduino時,Arduino會以Serial.read()接收並解析讀取的封包內容如下:(Msg_Fm_NXT)
(NXT_SendTo_Arduino_BT_01)
(2)接收來自Arduino傳送的字串:NXC的MessageWrite API為:
SendRemoteString (connection, mailBoxNo, sendStringValue) 當NXT呼叫上述的API傳送〝(99)_Hello_Arduino〞字串至Arduino時,Arduino會以Serial.read()接收並解析讀取的封包內容如下:(Msg_Fm_NXT)
(NXT_SendTo_Arduino_BT_01)
Arduino要先建構傳送至NXT的MessageWrite封包:
char replyMsg[16]={'H','e','l','l','o',' ','N','X','T',' ','(',' ',' ',' ',')','\0'};
int sendCountIndex, sendPacketSize;
void build_MESSAGEWRITE_packet()
{
for(int xii=0; xii
replyBuf[0] = 0x14; // Length byte LSB, total packet is 20 bytes
replyBuf[1] = 0x00; // Length byte MSB
replyBuf[2] = 0x80; // Byte 0: command type
replyBuf[3] = 0x09; // Byte 1: command
replyBuf[4] = 0x00; // Byte 2: Inbox number(0 - 9)
replyBuf[5] = 0x10; // Byte 3: Message Size, includes the null termination byte
for(int xii=0; xii<16; xii++) replyBuf[xii+6] = replyMsg[xii];
sendCountIndex = 18;
sendPacketSize = word(replyBuf[1], replyBuf[0]);
}再以Serial.write()逐個字元透過藍芽傳送至NXT。
至於NXT則呼叫以下API接收資料:
ReceiveRemoteString (mailBoxNo, isRemove, receiveStringValue)。
(Msg_Fm_Arduino)
(NXT_ReceiveFrom_Arduino_BT_01)
※NXC及Arduino程式碼:(連結)
你好,想請教有關NXT(NXC)及Arduino利用藍芽做資料傳輸的問題。
回覆刪除若我Arduino端使用HC-05做資料傳輸,NXT成功傳輸資料給Arduino,現在我希望Arduino回傳資料給NXT。請問就NXT藍芽端需要哪種資料型態及方法他才能讀取?
你好,
刪除由 Arduino 透過 藍芽傳輸給 NXT 的資料需要符合 NXT MessageWrite 的封包格式, 格式內容如下:
Byte 0 與 byte 1 為封包總長度 LSB+MSB
Byte 2 為 0x80 (Direct command)
Byte 3 為 0x09 (MessageWrite)
Byte 4 為 Mail box number(0 - 9)
Byte 5 為 訊息長度, 含最後的 null code
Byte 6 - N 為訊息(最後要加 Null code)
NXC 使用 :
ReceiveRemoteString(Mail box number, TRUE, 訊息字串) 函式 接收, 資料會存放在 訊息字串中
你好,不好意思有幾個問題想再請教您...
刪除問題一:
就Arduino而言若我要傳MessageWrite的格式封包我是否能依序利用write()來將封包格式傳送出去?比如說:
I2CBT.begin(9600);
I2CBT.write(Byte 0);
I2CBT.write(byte 1);
I2CBT.write(byte 2);
I2CBT.write(byte 3);
I2CBT.write(byte 4); …
問題二:
在NXT MessageWrite 的格式中…
Byte 0 與 byte 1 為封包總長度 LSB+MSB
LSB及MSB的大小定義意取決於程式中的哪?還是說他就和Byte 5的訊息長度一致?
Byte 2 為 0x80 (Direct command)
Direct command 指的是指令碼?在這0x80是指?
Byte 3 為 0x09 (MessageWrite)
這也是指令碼嗎?還是有另外的功能?
Byte 4 為 Mail box number(0 - 9)
Mail box是需要有特定的位置,還是說不需要?
還是說需要再NXC中的ReceiveRemoteString (mailBoxNo, I sRemove, receiveStringValue)中的mailBoxNo一致?
你好, 以下是關於所提問題的回覆:
刪除問題一:
Arduino是透過 Serial.write() 函式, 一次一個byte將封包資料傳送給 藍芽模組再傳送出去, 你所舉的例子中, 是否使用
#define Serial I2CBT 重新定義過, 若是的話就沒錯
問題二:
NXT 的通訊協定中為了解決它本身藍芽模組與ARM處理器之間時間差延誤的問題,所以規範了資料封包的格式:
Byte 0, Byte 1: 總封包長度, 但不包含 Byte0 與 Byte1
Byte 2: Command type, 代表指令類型,
其中 0x80 是指Direct command 且不需要回覆的指令類型, 像MessageWrite 就是屬於這種類型的指令
Byte 3: 0x09 是MessgaeWrite 的指令碼, 當NXT收到並解析後才會知道這個資料封包是一個郵件, 也才能夠使用 ReceiveRemoteString() 函式去讀取信箱內容
Byte 4: 是指此封郵件是傳送到NXT那一個信箱號碼(0 - 9)
Byte 5: 是指整個郵件內容的長度, 包含最後一個byte 的 null
Byte 6 - Byte N: 傳送的郵件內容, 最後一個 byte 必須是 null(0x00)
所以,
Byte 5 的值就是 N-6+1
Byte 0 與 Byte 1 的總封包長度是: N-1
至於 ReceiveRemoteString(Mail box number, TRUE, 訊息字串) 函式中的 Mail Box number 引數需要與 Byte4 指定的值一樣
你可以再測試看看, 若還有問題, 歡迎提出討論