Tello with Micro:bitTello 空拍機提供程式控制的功能,除了使用原廠提供的 Scratch 積木外,也可以使用 DroneBlocks 或 Python SDK。在這篇文章中我將介紹如何利用 Micro:bit 這塊板子搭配 Python 程式來控制 Tello。為了簡化製作的難度,我選擇不使用其他額外的 Micro:bit 外接元件,而僅利用控制板本身的輸入功能對 Tello 進行控制。

在實際動手前,我們先一起來想一下要怎麼達成我們的目的。

系統架構一

在 Tello 與 Scratch 的第一次接觸 一文最後,我提到我們可以利用任意的方式對原廠所提供的 node HTTP Server 送出控制指令以對 Tello 進行控制。所以在考慮如何利用 Micro:bit 控制 Tello 時,這是第一時間閃過我腦中預計使用的方式。但是因為 Micro:bit 並沒有內建 TCP/IP 網路功能,無法直接對 node HTTP Server 送出指令,所以必須透過一個轉接的程式。這個轉接程式在收到 Micro:bit 送來的控制指令後,再將指令轉發到 node HTTP Server。至於這個程式怎麼收到 Micro:bit 送來的指令,有兩個可選擇的方式:一是使用藍芽 BLE 功能,另外一個則是使用序列埠 Serial Port 功能。在這個範例裡我選擇了序列埠的傳遞方式,因為序列埠使用上僅須設定一次即可,而不像 BLE 往往需要重複一再設定。此外,序列埠的程式相對來說也較為簡單。唯一的缺點就是使用時 Micro:bit 必須與電腦保持 USB 連線,而無法自由移動。

根據上面的規劃,我們可以畫出如下的架構:

利用 Micro:bit 控制 Tello 架構一

利用 Micro:bit 控制 Tello 架構一

也就是說,在這個架構下的控制流程是

  1. 由 Micro:bit 透過序列埠把控制指令傳送給轉接程式。
  2. 轉接程式透過 HTTP 將控制指令傳送給 node HTTP Server。
  3. node HTTP Server 透過 WiFi 網路將控制指令傳送至 Tello。

轉接程式可以使用任何的程式語言來達成,只要能夠支援序列埠讀寫以及 HTTP 協定即可。

系統架構二

Python 是我第一時間想到用來撰寫轉接程式的程式語言,因為序列埠與 HTTP 協定對 Python 來說都是很容易處理的功能。等等,之前提到 Tello 原廠提供了 Python 的 SDK,也就是說應該可以直接透過 Python 程式控制 Tello,而不需要額外經過 node HTTP Server 的處理。修改過後的架構圖如下:

利用 Micro:bit 控制 Tello 架構二

利用 Micro:bit 控制 Tello 架構二

在這個架構下的控制流程簡化為

  1. 由 Micro:bit 透過序列埠把控制指令傳送給轉接程式。
  2. 轉接程式透過 WiFi 網路將控制指令傳送至 Tello。

雖然在兩種架構下我們都僅需撰寫一支轉接程式與 Micro:bit 程式,但是第二種架構少了 node HTTP Server 較為單純,可以避免ㄧ些不必要的安裝與可能的麻煩,所以我在此選用第二種架構,也就是由轉接程式直接控制 Tello。

Tello Python SDK Out

第二種架構需要使用 Tello Python SDK 對 Tello 進行控制,但是實際看了官方提供的 SDK 後,我才發現那應該不能算是 SDK,而比較像是 Python 的範例程式,解釋了如何利用網路封包來控制 Tello。我們可以選擇照著範例把控制功能移植到我們的轉接程式,不過在此之前,我查到了網路上已經有人提供 Tello 的 Python 控制物件。在試用過後,我決定使用此控制物件來取代官方的 SDK 範例程式。

控制方式

雖然 Tello 的控制指令並不算多 (例如每次只能往單一方向移動),不過要讓 Micro:bit 完全加以對應還是有所困難。所以我規劃了下列的控制方式:

Micro:bit 動作Tello 動作
A+B 鈕起飛/降落
A 鈕左轉
B 鈕右轉
前傾前進
後傾後退
左傾左移
右傾右移
Pin 0上升
Pin 2下降
搖動前翻

我將起飛與降落使用同一個控制方式,之後再利用程式內的變數決定應該對 Tello 送出起飛或降落的控制指令。這個方式雖然節省了一個 Micro:bit 的所需動作,但是卻有可能因為 Tello 自動停飛 (高度太低或墬毀) 而使得變數的數值與實際飛行狀態有所不同。不過就算狀態發生錯誤導致送出不合適的指令,Tello 也不至於產生危險的動作,算是可以接受的取捨。此外,雖然 Tello 可以進行各種方向的翻滾,但礙於 Micro:bit 能支援的輸入方式,所以在此我只保留了往前翻滾的控制方式。

規劃完畢後,接下來就是開始動手進行程式的開發了。

安裝 Micro:bit 序列埠驅動程式

前面提到在這個範例中 Micro:bit 需要透過序列埠將控制指令傳送給轉接程式,因此我們需要在電腦上安裝 Micro:bit 專用的序列埠驅動程式。ARM 原廠提供了序列埠驅動程式安裝的完整說明,在此大致說明如下:

  1. 下載驅動程式安裝檔
  2. 將 Micro:bit 插入電腦的 USB 中。注意插入時不要使用維護模式。
  3. 關閉檔案總管等類似的應用程式,避免程式存取 Micro:bit。
  4. 執行安裝程式。
  5. 安裝成功後,在左下方開始功能輸入 “裝置管理員” 開啟管理程式。
  6. 可在 “連結埠  (COM 和 LPT)” 分類中看到 Micro:bit 所使用的序列埠編號。需要記住此一編號,轉接程式必須使用同一編號才能順利接受來自 Micro:bit 的控制指令。以圖中的例子而言,序列埠編號即為 COM4。

    Micro:bit COM Port

    Micro:bit COM Port

Micro:bit 程式

Micro:bit 程式部份我選擇使用 Block Editor,可以分為幾個部分 (完整程式可以在這裡下載):

Micro:bit 程式第一部分 – 初始化

Micro:bit Tello 控制程式第一部分 - 初始化

Micro:bit Tello 控制程式第一部分 – 初始化

  1. 程式開始時,將程式中會使用到的變數都予以初始化。
  2. flying 變數表示 Tello 的飛行狀態,0 表示靜止中,而 1 則表示飛行中。
  3. pause 表示 Micro:bit 在送出每個指令後的暫停時間,單位為毫秒,也就是千分之一秒。雖然 Tello 可以連續接受多個指令並依序執行,但是因為實際完成各個動作需要一點時間,如果在還沒有執行完畢就送出後續的指令,很容易造成操作的失誤,所以強制 Micro:bit 在接受每個指令之間暫停一段時間。
  4. sensitvity 變數用來控制當 Micro:bit 的傾斜度超過一定範圍後才對 Tello 送出左右飄移或前進後退的控制指令。除非是完全水平的狀態,否則 Micro:bit 加速器的讀取數值都不可能為零。因此需要一個門檻值,以免 Tello 因為一點點的傾斜而隨時進行非必要的移動。
  5. 變數 x,y 分別用來記錄 X 軸與 Y 軸的傾斜程度,而 Micro:bit 三軸加速度器的 X 軸與 Y 軸偵測方向如下圖所示。當 X 軸數值大於 0 時表示向右方傾斜,反之小於 0 則表示向左方傾斜。而當 Y 軸數值大於 0 時表示向後方傾斜 (也就是正面朝向我們),而小於 0 則表示向前方傾斜 (也就是正面遠離我們)。

    Micro:bit 三軸加速度器

    Micro:bit 三軸加速度器

Micro:bit 程式第二部分 – 起飛/降落

 

Micro:bit Tello 控制程式第二部分 - 起飛/降落

Micro:bit Tello 控制程式第二部分 – 起飛/降落

當 A+B 鈕同時被按下時,送出起飛或降落的指令。當目前為靜止狀態時,也就是 flying 變數為 0 時,送出起飛 (takeoff) 指令。而當在飛行狀態時,也就是變數為 1 時,則送出降落 (land) 指令。送出指令後,需改變 flying 變數的數值以記錄目前飛行狀態。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第三部分 – 左轉

Micro:bit Tello 控制程式第三部分 - 左轉

Micro:bit Tello 控制程式第三部分 – 左轉

當 A 鈕被按下且 Tello 處於飛行狀態時,送出左轉 (rotate_ccw) 的指令。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第四部分 – 右轉

Micro:bit Tello 控制程式第四部分 - 右轉

Micro:bit Tello 控制程式第四部分 – 右轉

當 B 鈕被按下且 Tello 處於飛行狀態時,送出右轉 (rotate_cw) 的指令。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第五部分 – 上升

Micro:bit Tello 控制程式第五部分 - 上升

Micro:bit Tello 控制程式第五部分 – 上升

當碰觸 Pin 0 接腳且 Tello 處於飛行狀態時,送出上升 (move_up) 的指令。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第六部分 – 下降

Micro:bit Tello 控制程式第六部分 - 下降

Micro:bit Tello 控制程式第六部分 – 下降

當碰觸 Pin 2 接腳且 Tello 處於飛行狀態時,送出下降 (move_down) 的指令。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第七部分 – 翻滾

Micro:bit Tello 控制程式第七部分 - 翻滾

Micro:bit Tello 控制程式第七部分 – 翻滾

當搖動 Micro:bit 且 Tello 處於飛行狀態時,送出翻滾 (flip) 的指令。之後則在 Micro:bit 螢幕上顯示指令的對應圖示,在暫停一段時間後清除螢幕並接受後續的指令。

Micro:bit 程式第八部分 – 左飄/右飄/前進/後退

Micro:bit Tello 控制程式第八部分 - 左飄/右飄/前進/後退

Micro:bit Tello 控制程式第八部分 – 左飄/右飄/前進/後退

在這段程式中,我們根據 Micro:bit 在 X、Y 軸的傾斜度來決定 Tello 的左飄、右飄、前進及後退。這是整個 Micro:bit 控制程式中最為複雜的一段功能,但是實際上的概念並不複雜。首先,我們讀取 X 軸與 Y 軸的數值,並分別指定至 x, y 兩個變數中。而由於 Tello 每次只能往一個方向移動,所以我們找出傾斜度較大的方向,並據此送出此一方向的移動指令。不過因為 x, y 數值範圍包含正負數,所以比較時我們必須使用絕對值函數去除負數的影響,這樣才能找出最斜的那個方向。舉例來說,如果 x 為 -520,而 y 為 +400。雖然 +400 大於 -520,但是考慮到實際的傾斜程度,-520 的傾斜度絕對大於 +400。換句話說,-520 的那個 – 號只是用來表示傾斜的方向 (左方),而跟傾斜的程度無關,所以在比較時必須予以移除。因此在這個情況下,程式將會送出左飄 (move_left) 的指令。

Python 程式

  1. 安裝 Python 環境。如果你的電腦已經有 Python 3.x 環境,那麼就不需要重複安裝 Python 環境。否則請先安裝 Python 3.6 64 位元版本,可在此下載安裝檔,選擇 Windows x86-64 executable installer 即可。

    Python 下載連結

    Python 下載連結

  2. 開啟命令列工具。Windows 作業系統下的開啟方式為點選左下角的開始後輸入 cmd 後按下 Enter 鍵即可。

    命令提示字元

    命令提示字元

  3. 安裝 Python 序列埠套件 pyserial,輸入
  4. 創建轉接程式放置目錄。
  5. 切換至轉接程式目錄
  6. 下載 tello 控制物件
  7. 下載完成後解開壓縮檔,並將 tello.py 複製至 C:\microbit-tello-proxy。
  8. 新增 proxy.py,內容如下:
  9. 程式說明如下:
    1. 第 1 行引入序列埠功能所需套件。
    2. 第 2 行引入 tello 控制物件。
    3. 第 5 行定義序列埠編號,請記得將此編號修改為在你電腦上查到的編號。
    4. 第 7 ~ 17 行定義我們所對應支援的控制指令以及所需參數。舉例來說,第 17 行表示我們支援 flip (翻滾) 這個控制指令,而且會以 ‘f’ 這個參數呼叫這個控制指令,也就是往前翻滾。
    5. 第 18 行宣告序列埠控制物件 ser。
    6. 第 19 行宣告 tello 控制物件 drone。
    7. 第 22 行初始化 ser 物件。需注意 115200 為序列埠的速度,此為官方文件所建議,不要任意修改。而 timeout 則是讀寫資料的逾時時間,如有必要可視情況予以修改。
    8. 第 23 行初始化 drone 物件,如無特殊情況應不需進行任何修改。
    9. 第 26 ~ 38 行不斷重複讀取 Micro:bit 送至序列埠的控制指令,並透過 drone 控制物件呼叫相對應的動作控制函數。
    10. 第 26 行每次讀取一行資料,而因為 Micro:bit 每一個控制指令都是獨立的一行資料,所以等於每次讀取一個控制指令。不過因為序列埠傳送的資料為 Byte 格式,所以必須先用 decode 轉為 Python 字串,之後再用 strip 去掉不必要的換行符號。
    11. 第 27 行用來檢查取得的指令是否為正確的指令。一來避免因為 Micro:bit 程式出錯而送出錯誤的指令,另外一方面則因為即使 Micro:bit 未送出任何控制指令,序列埠元件的 readline 仍舊會在 timeout 之後回傳資料,也就是空字串。所以透過這行指令來避免執行空的控制指令。
    12. 第 28 ~ 38 行是一種精簡的寫法。如果拿掉 try catch 的部分,該段程式為

      其實與下面這段程式意思是一樣的

      不過因為共有 11 個控制指令,所以使用後面這種寫法會變成很冗長,所以在此改用雖然較難理解但卻大為精簡的寫法。
    13. 因為 tello 控制物件在指令執行失敗時會回傳一些錯誤的例外,所以在此使用 try catch 包住上面的程式,以便在單一控制指令失敗時仍舊可以繼續處理後續的控制指令。
    14. 第 39 ~ 40 行用來處理當使用者按下 Ctrl-C 中斷程式的情況。
    15. 第 41 ~ 42 行用來處理其他未知的錯誤。
    16. 第 43 ~ 45 行確保程式停止前會正常關閉之前已經開啟的序列埠。
  10. 執行轉接程式

    看到下列訊息表示轉接程式已經正常啟動

連結 Tello

  1. 開啟 Tello。
  2. 將電腦的 WiFi 連線連結至 Tello。你看到的 WiFi 名稱應與畫面上有所不同,因此只要找尋 TELLO 開頭的 WiFi 名稱即可。

    連結 Tello Wifi

    連結 Tello Wifi

  3. 這時候我們就可以利用 Micro:bit 來控制 Tello 了。而且我們可以在 python proxy.py 的視窗畫面中看到相關訊息,包含收到的指令以及執行狀態。如果無法順利控制 Tello,也可以在這裡看到有用的錯誤資訊。

透過一個簡單的 Python 轉接程式,我們就可以使用 Micro:bit 來控制 Tello 空拍機。不過目前這個版本 Micro:bit 使用序列埠與轉接程式進行溝通,導致控制時的機動力降低了許多,如果改用藍芽 BLE 進行溝通就可以自由移動。此外,礙於 Micro:bit 內建輸入方式的數量限制,所以有些控制指令無法順利對應送出。即使像是上升、下降已經對應到 Pin 0 與 Pin 2 的碰觸,也因為動作不易執行而使得操控上有所不便。如果使用附加的控制器,應可達成更好的效果。而透過此方式跟 Scratch 一樣無法取得鏡頭的畫面,所以失去了空拍機的意義。不過 Python 物件支援讀取電池狀態、飛行時間、以及飛行速度等訊息,所以可以提供比 Scratch 更多的應用。最後,我們也可以考慮將控制功能由 Micro:bit 轉移至 Python 轉接程式,讓 Micro:bit 僅提供各種輸入狀態即可。如此一來,就可以利用 Python 程式語言的強大進行更為複雜的控制,也可以透過與 Tello 的直接雙向溝通以達到更為即時且精細的控制。

Facebook 留言
Print Friendly, PDF & Email
Summary
利用 Micro:bit 控制 Tello 空拍機
Article Name
利用 Micro:bit 控制 Tello 空拍機
Description
在這篇文章中我將介紹如何利用 Micro:bit 這塊板子搭配 Python 程式來控制 Tello。為了簡化製作的難度,我選擇不使用其他額外的 Micro:bit 外接元件,而僅利用控制板本身的輸入功能對 Tello 進行控制。
Author
Publisher Name
Everlearn Studio
Publisher Logo