第 12 章 遙控機(jī)器人

2018-02-24 15:51 更新

作者介紹

Liz Looney

{%}

Liz Looney是本書(shū)的合著者之一。她是谷歌的軟件工程師,也是谷歌“機(jī)器人工作小組”(Robotics Task Force)的成員,作為App Inventor團(tuán)隊(duì)的初創(chuàng)成員,她領(lǐng)導(dǎo)了樂(lè)高頭腦風(fēng)暴機(jī)器人(LEGO MINDSTORMS)組件的開(kāi)發(fā)工作。Liz Looney是一位卓越的軟件工程師,有著超過(guò)25年的從業(yè)經(jīng)歷,曾先后在Borland、Oracle及Google公司工作。

本章將創(chuàng)建一個(gè)應(yīng)用,將Android手機(jī)變成LEGO MINDSTORMS NXT 機(jī)器人的遙控器。應(yīng)用中用按鈕來(lái)控制機(jī)器人前后移動(dòng)、左右轉(zhuǎn)動(dòng)和停止,如果機(jī)器人遇到障礙物,它還會(huì)自動(dòng)停止。應(yīng)用中使用具有藍(lán)牙功能的手機(jī)與機(jī)器人通信。

LEGO MINDSTORMS機(jī)器人不只是玩具,更是教具。After-school program 使用機(jī)器人來(lái)教小學(xué)和初中的孩子們掌握解決問(wèn)題的能力,并引導(dǎo)他們了解工程和計(jì)算機(jī)編程。NXT機(jī)器人也用于FIRST LEGO League 機(jī)器人競(jìng)賽,這項(xiàng)比賽允許9-14歲的孩子參加。

{%}

NXT可編程機(jī)器人套件中有一個(gè)“NXT智能積木”主單元,它可以控制三個(gè)電機(jī)及四個(gè)輸入傳感器。你可以用樂(lè)高的構(gòu)造元件、齒輪、車輪、電機(jī)和傳感器來(lái)組裝機(jī)器人。該套件自帶的軟件可以對(duì)機(jī)器人進(jìn)行編程,但現(xiàn)在我們將用App Inventor來(lái)創(chuàng)建Android應(yīng)用,通過(guò)藍(lán)牙連接來(lái)控制NXT機(jī)器人。

應(yīng)用中參與協(xié)作的機(jī)器人具有超聲波傳感器以及用于移動(dòng)的車輪,如Shooterbot 機(jī)器人。圖中所示,這款機(jī)器人通常是人們利用LEGO MINDSTORMS NXT 2.0套件建造的第一個(gè)機(jī)器人。它的左車輪與輸出端口C相連,右車輪與輸出端口B相連,顏色傳感器與輸入端口3相連,超聲波傳感器與輸入端口4相連。

學(xué)習(xí)要點(diǎn)

本章用到了以下組件和概念:

  • BluetoothClient組件:用于建立Android設(shè)備與NXT機(jī)器人之間的藍(lán)牙連接;

  • ListPicker組件:為用戶提供機(jī)器人選擇列表,選中后開(kāi)始建立機(jī)器人到Android的連接;

  • NxtDrive組件:用于驅(qū)動(dòng)機(jī)器人的輪子;

  • NxtUltrasonicSensor組件:利用機(jī)器人的超聲波傳感器探測(cè)障礙物;

  • Notifier組件:顯示錯(cuò)誤消息。

準(zhǔn)備開(kāi)始

本章的應(yīng)用需要Android 2.0或以上版本。此外,出于安全原因,藍(lán)牙設(shè)備必須首先配對(duì)才能彼此連通。在開(kāi)始構(gòu)建應(yīng)用之前,需要按以下步驟使Android設(shè)備與NXT機(jī)器人配對(duì):

1. 在NXT上單擊向右箭頭,直到顯示“Bluetooth”,然后按下橙色方塊;

2. 點(diǎn)擊向右的箭頭,直到顯示“Visibility”,然后按下橙色方塊;

3. 如果“Visibility”值已設(shè)定為可見(jiàn),繼續(xù)步驟4;如果不可見(jiàn),請(qǐng)單擊向左或向右箭頭設(shè)置其值為可見(jiàn);

4. 在Android設(shè)備上,進(jìn)入設(shè)置→無(wú)線與網(wǎng)絡(luò);

5. 確保打開(kāi)藍(lán)牙功能;

6. 點(diǎn)擊“藍(lán)牙”;

7. 在“可用設(shè)備”中查找名為“NXT”的設(shè)備;

8. 如果機(jī)器人名字下顯示“已配對(duì)但未連接”字樣,則配對(duì)成功!否則,繼續(xù)執(zhí)行步驟9;

9. 如果機(jī)器人名字下顯示“與此設(shè)備配對(duì)”,則點(diǎn)擊它;

10. 在NXT上,要求輸入密碼,按下橙色方塊接受1234為密碼;

11. 在Android上,也會(huì)要求輸入PIN碼,輸入1234,然后按確定;

12. 現(xiàn)在應(yīng)該看到“已配對(duì)但未連接?!?,說(shuō)明配對(duì)成功!

 注意:如果你曾經(jīng)修改過(guò)機(jī)器人的名字,則尋找機(jī)器人現(xiàn)在的名字,而非“NXT”。

連接到App Inventor網(wǎng)站,創(chuàng)建新項(xiàng)目“NXTRemoteControl”,將設(shè)置屏幕的標(biāo)題為“遙控機(jī)器人”,并連接測(cè)試手機(jī)。

設(shè)計(jì)組件

在這個(gè)應(yīng)用中,我們需要分別創(chuàng)建可見(jiàn)組件及不可見(jiàn)組件,并分別定義它們的行為。

不可見(jiàn)組件

在創(chuàng)建用戶界面之前,先來(lái)創(chuàng)建表12-1中的不可見(jiàn)組件,如圖12-1所示,用來(lái)控制NXT。

表12-1 NXT“機(jī)器人遙控”應(yīng)用中的不可見(jiàn)組件

組件類型 面板中分組 命名 作用
BluetoothClient Connectivity BluetoothClient1 建立Android與NXT的連接
NxtDrive LEGO? MINDSTORMS? NxtDrive1 驅(qū)動(dòng)機(jī)器人的輪
NxtUltrasonicSensor LEGO? MINDSTORMS? NxtUltrasonicSensor1 檢測(cè)障礙物
Notifier User Interface Notifier1 顯示錯(cuò)誤信息

{%}

圖 12-1 在組件設(shè)計(jì)器底部顯示的不可見(jiàn)組件

按以下方式設(shè)置組件的屬性:

1. 設(shè)置NxtDrive1及NxtUltrasonicSensor1的BluetoothClient屬性為 BluetoothClient1;(說(shuō)明輪子的驅(qū)動(dòng)與障礙物的偵測(cè)都需要依賴藍(lán)牙通信——譯者注)

2. 勾選NxtUltrasonicSensor1的BelowRangeEventEnabled屬性(近距離偵測(cè)障礙物功能可用);

3. 設(shè)置NxtDrive1的DriveMotors屬性

  • 如果機(jī)器人的左輪電機(jī)與輸出端口C連接,右輪電機(jī)與輸出端口B連接,則保持默認(rèn)設(shè)置“CB”;

  • 如果機(jī)器人的配置與上述不同,則將DriveMotors屬性設(shè)置為兩個(gè)字母的文本,其中第一個(gè)字母是連接左輪電機(jī)的輸出端口,第二個(gè)字母是連接右輪電機(jī)的輸出端口。

4. 設(shè)置NxtUltrasonicSensor1的SensorPort屬性

  • 如果機(jī)器人的超聲波傳感器與輸入端口4連接,則保持默認(rèn)值“4”;

  • 如果機(jī)器人的配置與上述不同,則將SensorPort設(shè)置為與超聲波傳感器連接的輸入端口。

可視組件

現(xiàn)在創(chuàng)建用戶界面組件,如圖12-2所示。

{%}

圖 12-2 組件設(shè)計(jì)器中的應(yīng)用

建立藍(lán)牙連接時(shí),Android設(shè)備需要訪問(wèn)NXT機(jī)器人具有唯一性的藍(lán)牙地址,但藍(lán)牙地址由8個(gè)用冒號(hào)分隔的2位數(shù)的十六進(jìn)制數(shù)(二進(jìn)制數(shù)的另一種表示方式)組成,輸入起來(lái)異常麻煩,而且每次運(yùn)行應(yīng)用都要在手機(jī)上輸入該地址。為了減少麻煩,使用ListPicker來(lái)顯示已經(jīng)與手機(jī)配對(duì)的機(jī)器人列表(列表項(xiàng)的值為機(jī)器人的名稱及藍(lán)牙地址),并從中選擇一個(gè)。

使用按鍵來(lái)驅(qū)動(dòng)機(jī)器人的前進(jìn)、后退、左右轉(zhuǎn)動(dòng)、停止和斷開(kāi)連接,使用VerticalArrangement來(lái)放置除ListPicker以外的所有組件,用HorizontalArrangement來(lái)放置左右轉(zhuǎn)向及停車按鈕。

按照表12-2中列出的組件來(lái)創(chuàng)建圖12-2所示的用戶界面。

表12-2 NXT機(jī)器人控制器應(yīng)用中的可見(jiàn)組件

組件類型 面板中分組 命名 作用
ListPicker User Interface ConnectListPicker 選擇要連接的機(jī)器人
VerticalArrangement layout VerticalArrangement1 布局容器,容納除ListPicker之外的組件
Button User Interface ForwardButton 前進(jìn)
HorizonalArrangement layout HorizonalArrangement1 布局容器,容納左轉(zhuǎn)、右轉(zhuǎn)、停止按鈕
Button User Interface LeftButton 左轉(zhuǎn)
Button User Interface StopButton 停止
Button User Interface RightButton 右轉(zhuǎn)
Button User Interface BackwardButton 后退
Button User Interface DisconnectButton 與NXT斷開(kāi)連

按照?qǐng)D12-2所示來(lái)設(shè)置可視組件布局:將LeftButton、StopButton和RightButton放在HorizontalArrangement1中,將ForwardButton、HorizontalArrangement1、BackwardButton和DisconnectButton放在VerticalArrangement1中。 按下列方式設(shè)置組件屬性:

1. 取消勾選Screen1的Scrollable屬性(滾屏功能);

2. 設(shè)置ConnectListPicker和DisconnectButton的寬度為“Fill parent”;

3. 設(shè)置VerticalArrangement1、ForwardButton、HorizontalArrangement1、LeftButton、StopButton、RightButton及BackwardButton的Width與Height為“Fill parent”;

4. 設(shè)置ConnectListPicker的Text屬性為“連接”;

5. 設(shè)置ForwardButton的Text屬性為“∧”;

6. 設(shè)置LeftButton的Text屬性為“<”;

7. 設(shè)置StopButton的Text屬性為“—”;

8. 設(shè)置RightButton的Text屬性為“>”;

9. 設(shè)置BackwardButton的Text屬性為“∨”;

10. 設(shè)置DisconnectButton的Text屬性為“斷開(kāi)連接”;

11. 設(shè)置ConnectListPicker和DisconnectButton的FontSize屬性為30;

12. 設(shè)置ForwardButton、LeftButton、StopButton、RightButton及BackwardButton的FontSize屬性為40。

在這類應(yīng)用中,當(dāng)手機(jī)與NXT建立藍(lán)牙連接之前,應(yīng)該隱藏用戶的操作界面,為此取消勾選VerticalArrangement1的Visible屬性。不要擔(dān)心,當(dāng)NXT連通后,將重新顯示用戶界面。

為組件添加行為

本節(jié)將編程來(lái)設(shè)置應(yīng)用的行為,包括:

  • 用戶從列表中選擇機(jī)器人,并與之建立連接;

  • 斷開(kāi)機(jī)器人與應(yīng)用的連接;

  • 使用控制按鈕來(lái)操控機(jī)器人;

  • 在機(jī)器人偵測(cè)到障礙物時(shí),讓它停下來(lái)。

連接到NXT機(jī)器人

添加第一個(gè)行為:連接到NXT。點(diǎn)擊 ConnectListPicker將顯示已配對(duì)的機(jī)器人列表,選中一個(gè),將在應(yīng)用與機(jī)器人之間建立藍(lán)牙連接。

顯示機(jī)器人列表

使用ConnectListPicker組件來(lái)顯示機(jī)器人列表。ListPicker的外表像按鈕,被點(diǎn)擊后則顯示列表項(xiàng),并允許進(jìn)行單選。

使用BluetoothClient1.AddressesAndNames塊來(lái)提供列表,列表項(xiàng)是已經(jīng)與Android設(shè)備配對(duì)的藍(lán)牙設(shè)備的名稱及地址。由于NXT已經(jīng)將輪驅(qū)動(dòng)及超聲波組件的BluetoothClient屬性設(shè)定為BluetoothClient1,因此AddressesAndNames屬性列表中的設(shè)備會(huì)自動(dòng)限定為這類機(jī)器人,其他類型的藍(lán)牙設(shè)備(如耳機(jī))將不會(huì)出現(xiàn)在列表中。表12-3列出了所需要的塊。

表12-3 在應(yīng)用中添加ListPicker列表所需要的塊

塊的類型 所在抽屜 作用
ConnectListPicker.BeforePicking ConnectListPicker 當(dāng)ConnectListPicker被點(diǎn)擊時(shí),觸發(fā)該事件
set ConnectListPicker.Elements to ConnectListPicker 為ConnectListPicker設(shè)置可供選擇的列表項(xiàng)

塊的作用

點(diǎn)擊ConnectListPicker將觸發(fā)ConnectListPicker.BeforePicking事件,并顯示可選項(xiàng)列表。將ConnectListPicker.Elements屬性設(shè)置為 BluetoothClient1.AddressesAndNames塊,來(lái)設(shè)定可選項(xiàng);ConnectListPicker將顯示已經(jīng)與Android設(shè)備配對(duì)的機(jī)器人列表。

{%}

圖 12-3 顯示機(jī)器人列表

 測(cè)試:在手機(jī)上點(diǎn)擊“連接”,看看會(huì)發(fā)生什么,你會(huì)看到所有已經(jīng)與手機(jī)配對(duì)的機(jī)器人列表。

如果只見(jiàn)黑屏,說(shuō)明手機(jī)尚未與任何機(jī)器人配對(duì);如果見(jiàn)到其他藍(lán)牙設(shè)備,如藍(lán)牙耳機(jī),說(shuō)明 NxtDrive1與 NxtUltrasonicSensor1的BluetoothClient屬性設(shè)置有誤。

建立藍(lán)牙連接

從列表中選擇一個(gè)機(jī)器人,應(yīng)用將通過(guò)藍(lán)牙與機(jī)器人連接。如果連接成功,用戶界面將發(fā)生變化:隱藏ConnectListPicker,并顯示用戶界面的其余部分。如果機(jī)器人開(kāi)關(guān)沒(méi)有打開(kāi),則連接失敗,會(huì)彈出錯(cuò)誤信息。

使用call BluetoothClient1.Connect塊與機(jī)器人進(jìn)行連接。ConnectListPicker.Selection屬性提供了選中機(jī)器人的地址和名稱信息。

使用ifelse塊來(lái)測(cè)試連接是否成功。ifelse塊需要連接三個(gè)不同的塊:“if”、“then”及“else”?!癷f”與BluetoothClient1.Connect塊連接,“then”區(qū)域放置連接成功時(shí)要執(zhí)行的塊;“else”區(qū)域放置連接失敗時(shí)要執(zhí)行的塊。

如果連接成功,使用Visible屬性來(lái)隱藏 ConnectListPicker并顯示VerticalArrangement1(其中放置了除ConnectListPicker之外的所有組件)。如果連接失敗,則使用Notifier1.ShowAlert塊來(lái)顯示錯(cuò)誤信息。表12-4列出了設(shè)置上述行為所需的塊。

表12-4與機(jī)器人建立藍(lán)牙連接所需的塊

塊的類型 所在抽屜 作用
ConnectListPicker.AfterPicking ConnectListPicker 當(dāng)從ConnectListPicker選中一個(gè)機(jī)器人時(shí)觸發(fā)
ifelse Control 檢驗(yàn)藍(lán)牙連接是否成功
call BluetoothClient1.Connect BluetoothClient1 連接到機(jī)器人
ConnectListPicker.Selection ConnectListPicker 選中的機(jī)器人的地址及名稱
set ConnectListPicker.Visible to ConnectListPicker 隱藏ConnectListPicker按鈕
false Logic 插入set ConnectListPicker.Visible to塊
set VerticalArrangement1.Visible to VerticalArrangement 顯示“連接”按鈕之外的所有組件
true Logic 插入set VerticalArrangement1.Visible to塊
Notifier1.ShowAlert Notifier1 用來(lái)彈出錯(cuò)誤信息
“無(wú)法建立藍(lán)牙連接?!?/td> Text 錯(cuò)誤信息。

塊的作用

選中機(jī)器人后將觸發(fā)ConnectListPicker.AfterPicking事件,見(jiàn)圖12-4,BluetoothClient1.Connect塊用于建立與機(jī)器人之間的藍(lán)牙連接。如果連接成功,執(zhí)行“then”塊:隱藏ConnectListPicker按鈕并顯示VerticalArrangement1內(nèi)的所有組件,即,設(shè)置ConnectListPicker.Visible屬性為false,設(shè)置VerticalArrangement1.Visible屬性為true。如果連接失敗,執(zhí)行“else”塊:用Notifier1.ShowAlert塊彈出錯(cuò)誤信息。

{%}

圖 12-4 建立藍(lán)牙連接

與NXT斷開(kāi)連接

讓Android設(shè)備與NXT機(jī)器人連接著實(shí)讓人興奮,不過(guò)“斷開(kāi)連接”是我們下面要添加的行為,這樣便于對(duì)連接與斷開(kāi)進(jìn)行連續(xù)測(cè)試。

當(dāng)點(diǎn)擊DisconnectButton時(shí),應(yīng)用將關(guān)閉藍(lán)牙連接,用戶界面將發(fā)生變化:ConnectListPicker按鈕將重新出現(xiàn),而用戶界面上的其余組件將被隱藏。

表12-5列出了構(gòu)建BluetoothClient1.Disconnect(斷開(kāi)藍(lán)牙連接)所需的塊。設(shè)置Visible屬性來(lái)顯示 ConnectListPicker按鈕并隱藏VerticalArrangement1中包含的所有組件。

表12-5 與機(jī)器人斷開(kāi)連接所需的塊

塊的類型 所在抽屜 作用
DisconnectButton.Click DisconnectButton 當(dāng)點(diǎn)擊DisconnectButton時(shí)觸發(fā)該事件
BluetoothClient1.Disconnect BluetoothClient1 斷開(kāi)與機(jī)器人的藍(lán)牙連接
set ConnectListPicker.Visible to ConnectListPicker 顯示ConnectListPicker(“連接”按鈕)
true Logic 插入set ConnectListPicker.Visible to塊
set VerticalArrangement1.Visible to VerticalArrangement 隱藏用戶界面上的其余組件
false Logic 插入set VerticalArrangement1.Visible to

塊的作用

點(diǎn)擊DisconnectButton將觸發(fā)DisconnectButton.Clicked事件,如圖12-5所示,斷開(kāi)藍(lán)牙連接要用BluetoothClient1.Disconnect塊,之后設(shè)置ConnectListPicker.Visible屬性為true來(lái)顯示 ConnectListPicker,設(shè)置VerticalArrangement1.Visible屬性為false來(lái)隱藏VerticalArrangement1。

{%}

圖 12-5 與機(jī)器人斷開(kāi)連接

 測(cè)試:請(qǐng)確保機(jī)器人已經(jīng)打開(kāi),點(diǎn)擊手機(jī)上的“連接”按鈕,并選擇要連接的機(jī)器人。建立藍(lán)牙連接需要一點(diǎn)時(shí)間。一旦連接成功,用戶界面將顯示機(jī)器人的控制按鈕,以及“斷開(kāi)連接”按鈕。

單擊“斷開(kāi)連接”按鈕:控制機(jī)器人的按鈕會(huì)消失,“連接”按鈕則重新出現(xiàn)。

操控機(jī)器人

下面是真正有趣的部分:添加前進(jìn)、后退、左右轉(zhuǎn)動(dòng)及停止行為。不要忘記“停止”,否則你手中的機(jī)器人會(huì)失去控制!

NxtDrive組件提供了五個(gè)塊,用來(lái)驅(qū)動(dòng)機(jī)器人的電機(jī):

  • MoveForwardIndefinitely塊:驅(qū)動(dòng)兩個(gè)電機(jī)前進(jìn);

  • MoveBackwardIndefinitely塊:驅(qū)動(dòng)兩個(gè)電機(jī)后退;

  • TurnCounterClockwiseIndefinitely塊:驅(qū)動(dòng)機(jī)器人左轉(zhuǎn):讓右側(cè)電機(jī)向前而左側(cè)電機(jī)后退;

  • TurnClockwiseIndefinitely塊:驅(qū)動(dòng)機(jī)器人右轉(zhuǎn):讓左側(cè)電機(jī)向前而右側(cè)電機(jī)后退;

  • Stop將停止電機(jī)。

每個(gè)移動(dòng)及轉(zhuǎn)向塊都有一個(gè)Power參數(shù),需要與數(shù)字塊配合使用,來(lái)設(shè)定機(jī)器人電機(jī)的輸出功率,取值范圍可以從 0到100。但如果設(shè)置的功率太小,電機(jī)會(huì)發(fā)出吱吱聲而不運(yùn)轉(zhuǎn)。在本例中建議使用90(百分比)。表12-6中列出了所需的塊。

表12-6 用于控制機(jī)器人的塊

塊的類型 所在抽屜 作用
ForwardButton.Clic ForwardButton 點(diǎn)擊ForwardButton時(shí)觸
NxtDrive1.MoveForwardIndefinitely NxtDrive1 驅(qū)動(dòng)機(jī)器人前進(jìn)
數(shù)字90 Math 功率值
BackwardButton.Click BackwardButton 點(diǎn)擊BackwardButton時(shí)觸發(fā)
NxtDrive1.MoveBackwardIndefinitely NxtDrive1 驅(qū)動(dòng)機(jī)器人后退
數(shù)字90 Math 功率值
LeftButton.Click LeftButton 點(diǎn)擊LeftButton時(shí)觸發(fā)
NxtDrive1.TurnCounterClockwiseIndefinitely NxtDrive1 驅(qū)動(dòng)機(jī)器人逆時(shí)針轉(zhuǎn)動(dòng)
數(shù)字90 Math 功率值
RightButton.Click RightButton 點(diǎn)擊RightButton時(shí)觸發(fā)
NxtDrive1.TurnClockwiseIndefinitely NxtDrive1 驅(qū)動(dòng)機(jī)器人順時(shí)針轉(zhuǎn)動(dòng)
數(shù)字90 Math 功率值
StopButton.Click StopButton 點(diǎn)擊StopButton時(shí)觸發(fā)
NxtDrive1.Stop NxtDrive1 讓機(jī)器人停止

塊的作用

如圖12-6所示,點(diǎn)擊ForwardButton按鈕時(shí)觸發(fā)ForwardButton.Clicked事件,此時(shí)調(diào)用NxtDrive1.MoveForwardIndefinitely塊,讓機(jī)器人以90%的功率前進(jìn),其余按鈕的事件處理程序與此類似,并以相同的功率驅(qū)動(dòng)機(jī)器人后退及左右轉(zhuǎn)動(dòng)。點(diǎn)擊StopButton時(shí)觸發(fā)StopButton.Clicked事件,調(diào)用NxtDrive1.Stop塊讓機(jī)器人停止運(yùn)動(dòng)。

{%}

圖 12-6 操控機(jī)器人

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)