一、簡介
這個單元著重在將之前所學到的內容做整合,並且應用到工業類的主題。讓我們試想一個場景,傳統工廠對於物料分類,大多仰賴人工搬運。當貨物、料件運送至指定地點後,再由倉儲人員開堆高機出來搬貨,依照類別存放在指定層架。
想想看,其中是不是有能自動化的部份呢?像是在一個倉庫內會有很多區域,每個區域都存放著不同的東西,若是能架一臺機器手臂於指定位置,那麼人員只要將屬於這間倉庫的料件置於門口,是否就能讓手臂自動幫我們分門別類地放好呢?當然,這還需要讓手臂看得見是什麼貨物才行。
接下來就讓我們來設計一個,影像辨識後能讓手臂幫我們搬運物件的專題。藉由 Pixel:bit 的 ESP32 與攝影鏡頭,並搭配 Edge Impulse,可以完成影像辨識貨物分類。另外,我們還需要一個機器手臂,手臂控制的部份可以交給 ATmega328p,但為了讓手臂的馬達方便連接,還需要準備一塊適合的擴充板。接著就剩下用來辨識的貨物了,這就自己 DIY 設計吧!
二、所需設備
可以選擇自己手邊有的機器手臂或是擴充板,設計出屬於自己的操作場景。接下來的教學內容,我們會使用下列設備做示範:
1. Pixel:bit x1
2. Micro USB to USB Type-A數據傳輸線 x1
3. meArm 迷你機械手臂 x1
4. SG90 9G伺服馬達 180度 x4
5. MbitBot 多功能板 x1
6. 聚合物鋰電池-1000mAh 3.7V x1
7. 固定板或是製作貨物的材料(自行 DIY)
三、規劃流程
將任務分工後我們知道,ESP32 負責辨識與顯示,ATmega328p 負責手臂控制。詳細動作流程規劃如下圖所示,以顏色區分工作權責,藍色區塊為 ATmega328p,紅色區塊則是 ESP32。
我們以按下 Pixel:bit 上面的按鈕來啟動辨識任務,按鈕是由 ATmega328p 控制。當 ATmega328p 讀取到按下按鈕的動作,會立即發送請求訊號給 ESP32,當 ESP32 收到請求訊號後,將啟動拍攝與辨識功能,並將結果顯示在螢幕上,同時回傳結果給 ATmega328p。收到結果的 ATmega328p,經比對結果後控制手臂夾取貨物並搬移至指定區域。
四、確認目標
我們在網路上找到兩張圖片,做為讓 Pixel:bit 辨識的目標。分別是左側的「寶特瓶」與右側的「廚餘」。大家可以依照自己的喜好選擇要辨識的目標。
將圖片印出來後,黏在裁切的厚紙板或木板上,將其製作成小牌子,牌子末端設計 T 型結構,以便手臂方便夾取,也讓牌子在移動的過程中不易脫落。
五、訓練模型
整個流程最重要的一環,就是要能夠辨識物品,這樣才能呼叫機器手臂將東西搬運到指定地點。在教學單元(五)與教學單元(六),我們已經學會如何訓練一個模型。從使用 Pixel:bit 拍攝照片蒐集資料,上傳至 Edge Impulse 線上平台,並透過平台服務訓練與評估模型。
1. 資料蒐集
請依照教學單元(五)的教學步驟,使用 Pixel:bit 蒐集「寶特瓶」與「廚餘」的照片資料,蒐集的照片越多越好,最好是不同角度或是不同位置的圖片。
小知識
資料蒐集的正確性會大大影響訓練出來的模型,請確保同類別的資料沒有參雜其他照片,例如蒐集的寶特瓶資料內,不應該參雜廚餘的資料,或是別的圖像資料。
每個種類的資料數量平不平均,也是一個影響模型準確性的重點,請儘量讓每個種類可以蒐集到等量的資料,例如寶特瓶蒐集到的資料大約是 100 張,請讓廚餘的資料也接近 100 張。最忌諱的就是數量相差過大,像是寶特瓶的資料是 123 張,廚餘的資料只有 10 張。
2. 資料上傳
將蒐集到的照片全數上傳至 Edge Impulse ,步驟可參照教學單元(六),我們將寶特瓶的資料標籤設定為「bottle」,廚餘的資料標籤則是「food」。請依照您找到的圖片,設定自己能理解的標籤名稱。
設定圖片裁切大小,請選擇「96 x 96」,並確認「Output features」是不是我們要辨識的兩個類別。
3. 設定訓練參數並訓練
設定訓練次數的部份我們設定「200次」,模型的選擇是用預設的「MobileNetV1 96×96 0.1」。
完成上述設定後即可開始訓練模型,下圖是訓練後的結果,準確度有 97% 還不錯。
接著同樣參照教學單元(六)的內容,將訓練好的模型編譯成 Arduino library,再將模型儲存到自己的電腦。
六、建置模擬場域
請自行組裝 meArm 機器手臂,接線方式請參考下方兩張圖。
請依照上圖伺服馬達對應的編號,連接到擴充板「MbitBot」上,並順勢將電池也接上去。
可以自行裁切厚紙板或木板,並用麥克筆自己畫出區域,前提是手臂夾爪要能到的了的地方喔!請大家自行發揮。
我們使用雷切機製作了一片有 A、B 區與擺放區的木板,並用螺絲、螺帽與銅柱將各部件都固定,最後將 Pixel:bit 插上,完成圖如下所示:
七、範例程式下載
若之前已下載過範例程式,即可在之前下載的資料夾中找到「07_Arm_control」。如果還沒下載,請點選連結,進到網頁看到「Code」按鈕,點選後選擇「Download ZIP」就能將檔案整個下載下來。
解壓縮後,這個單元的範例程式,就放在資料夾名稱為「07_Arm_control」裡。
八、程式解析
既然硬體已經配置好了,範例程式也有了,就讓我們看看 ESP32 與 ATmega328p 的程式分別做了什麼吧!若是您的硬體配置與教學範例的不同,也能透過範例程式,修改成適合自己的方式。
1. ATmega328p 程式
在 ATmega328p 這邊,被分配到的任務有幾項,第一項是偵測按鈕 B 是否被按下,一旦被按下,則需馬上傳送「開始辨識指令」給 ESP32。第二項任務則是接收 ESP32 傳送過來的「辨識結果」,並依照結果派送任務給機器手臂。
經由 UART 讓 ESP32 與 ATmega328p 互相溝通,這個我們在教學單元(二)已經學過了。所以傳送「開始辨識指令」與接收「辨識結果」,對我們來說已不是什麼難事,比較困難的是控制機器手臂。
每個機器手臂的控制方式各有不同,有的直接操控驅動板控制每顆馬達,有的內含控制板,並有自己的控制指令。馬達的使用也不相同,常見的馬達種類分為兩種,分別是「伺服馬達」與「步進馬達」。
我們選擇的「meArm」是使用伺服馬達,操控方式是透過連接的 MbitBot 擴充板,上面的 PWM IC 來控制。
a. 安裝 PWM IC 程式庫
為了能控制伺服馬達,請開啟 Arduino IDE 的「程式庫管理員」,並於搜尋欄位內輸入「Adafruit PWM Servo Driver」,找到這個程式庫並安裝,如下圖所示:
b. 馬達控制步驟
請從這個單元的範例程式內開啟「servo_control」資料夾,並打開程式,完整程式如下圖所示:
除了基本的匯入相關程式庫、參數設定與初始化之外,讓我們來看看馬達控制的部分。
「pwm.writeMicroseconds」程式會依照括號內的參數,去控制指定的馬達轉動,第一個參數是「連接馬達的編號」,第二個參數則是控制馬達的「microseconds」。MbitBot 擴充板上可以連接 8 個伺服馬達(編號是 S1~S8),對應到的程式編號是 0~7,也就是說要控制 S8 的馬達的話,在程式內要填上「7」。而 microseconds 會影響轉動角度,就一般而言會轉換成角度比較直覺,所以透過 Arduino 內建的「map」方法,將我們輸入的 0~180 度的角度參數轉換成 500~2400 微秒。
上圖的程式會讓 meArm 的四個馬達分別轉動到下表對應的位置:
c. 記錄手臂動作參數
因為在組裝 meArm 的過程中,伺服馬達初始轉角可能不太相同,所以需要針對自己的手臂,來找到各個動作下的馬達轉動參數。
以我們建置的硬體為例,為了讓手臂在夾取與放置的過程中能順利,共可切分為 12 個動作。以下表所示,透過控制馬達轉動角度的程式,找到適合的手臂位置。
這個步驟最為繁瑣,請依照自己的手臂找到對應的角度,並記錄下來。
d. 修改並上傳程式
請打開「pixel_pro_mini」這個資料夾,這個是完整的控制程式。我們直接挑重點看,在「loop()」區塊內有兩個「if」,第一個 if 是用來接收從 ESP32 來的辨識結果,並依照收到的辨識結果,執行特定的動作。若是收到的結果是「A」,就執行「class_box(1)」,如果是「B」則執行「class_box(2)」。
第二個 if 則是偵測「按鈕B」是否被按下,若按下則傳送開始辨識指令「I」給 ESP32。
剛剛有提到的「class_box()」,是我們依照填入的結果去執行手臂移動流程的函式,如果是填入[1],也就是「class_box(1)」則執行放置貨物到 A 區的一系列動作,如果是「class_box(2)」則執行放置貨物到 B 區的一系列動作。
請大家依照自己找到的對應角度,填入每個「servoList」內。修改完後即可將程式上傳至Pixel:bit 的 ATmega328p。
2. ESP32 程式
a. 安裝訓練好的模型程式庫
在「訓練模型」的階段,我們在 Edge Impulse 將訓練好的模型,編譯成 Arduino library 並下載下來,接著需要將其匯入 Arduino IDE。
b. 修改並上傳程式
打開「pixel_esp32cam」這個資料夾,這是 ESP32 從接收辨識指令,接著推論結果,並回傳結果給 ATmega328p 的程式。
第一步要修改匯入的程式庫名稱,每個人在 Edge Impulse 命名專案時的名稱可能不同,請在下圖方框的對應位置內填入,自己下載下來的模型 library 名稱。
接著讓我們來看一下關鍵的程式碼,在「loop()」區塊內,只要收到從 ATmega328p 傳送過來的訊息「I」,就會透過程式讓顯示螢幕顯示倒數 3 秒的效果,在這段時間中,操作者可以拿取要辨識的圖片擺在鏡頭前,當讀秒結束,會呼叫推論的程式「inference()」。
在 inference() 函式內,主要就是將攝影機擷取到的資料,做一些轉換,並經由另一個函式「classify()」得出推論結果。若您仔細查看 classify() 內的程式,可以發現那個得到結果的程式,會將最終結果存放在「result」,如下圖所示:
「result」存放的資料包含每個類別的名稱,還有對於這次的推論結果,各類別符合的百分比。得到結果後我們透過 Pixel:bit 正面的顯示螢幕將結果顯示出來。
接著透過下方的程式檢查哪個類別的分數最高,若是第一類的百分比較高,變數「higher」將等於 0,若是第二類則變數「higher」將等於 1。
得出最高分的類別後,接著顯示倒數 3 秒的資訊,主要是讓操作者有時間將要搬運的貨物放在搬運區。倒數完畢後將依照最高分的類別,傳送要搬運的區域訊息給 ATmega328p。
以上就是針對較重要的程式說明,最後將程式燒錄到 Pixel:bit 的 ESP32。
九、運作展示
依照我們所撰寫的步驟,按下按鈕B後,ATmega328p 會傳送訊息給 ESP32,ESP32 辨識完畢後會顯示在畫面上,並回傳結果給 ATmega328p,最後再由 ATmega328p 控制手臂完成搬運任務。
十、結論
這個單元教大家在明白使用 Edge Impulse 訓練模型,以及 ESP32 和 ATmega328p 通訊後,依照設定的主題,額外加上機器手臂的控制,並整合所有功能。當然不是只有機器手臂可以這樣用,大家也可以思考看看,還有沒有能適用圖像辨識的場景,並用手上的 Pixel:bit 練習看看。本次教學就到這邊結束,若是對於訓練模型、UART 通訊還不太熟悉的朋友,可以再回去看看之前的教學單元。我們下個教學單元見!
若您有 Pixel:Bit 研習的需求,歡迎填寫表單,日後有相關課程資訊將在第一時間通知您!