這篇文章將會接續上一篇「影像辨識機械手臂(Part 1)」。
教學原文參考:影像辨識機械手臂
既然硬體已經配置好了,範例程式也有了,就讓我們看看 ESP32 與 ATmega328p 的程式分別做了什麼吧!若是您的硬體配置與教學範例的不同,也能透過範例程式,修改成適合自己的方式。
在 ATmega328p 這邊,被分配到的任務有幾項,第一項是偵測按鈕 B 是否被按下,一旦被按下,則需馬上傳送「開始辨識指令」給 ESP32。第二項任務則是接收 ESP32 傳送過來的「辨識結果」,並依照結果派送任務給機器手臂。
經由 UART 讓 ESP32 與 ATmega328p 互相溝通,這個我們在教學單元(二)已經學過了。所以傳送「開始辨識指令」與接收「辨識結果」,對我們來說已不是什麼難事,比較困難的是控制機器手臂。
每個機器手臂的控制方式各有不同,有的直接操控驅動板控制每顆馬達,有的內含控制板,並有自己的控制指令。馬達的使用也不相同,常見的馬達種類分為兩種,分別是「伺服馬達」與「步進馬達」。
我們選擇的「meArm」是使用伺服馬達,操控方式是透過連接的 MbitBot 擴充板,上面的 PWM IC 來控制。
為了能控制伺服馬達,請開啟 Arduino IDE 的「程式庫管理員」,並於搜尋欄位內輸入「Adafruit PWM Servo Driver」,找到這個程式庫並安裝,如下圖所示:
請從這個單元的範例程式內開啟「servo_control」資料夾,並打開程式,完整程式如下圖所示:
除了基本的匯入相關程式庫、參數設定與初始化之外,讓我們來看看馬達控制的部分。
「pwm.writeMicroseconds」程式會依照括號內的參數,去控制指定的馬達轉動,第一個參數是「連接馬達的編號」,第二個參數則是控制馬達的「microseconds」。MbitBot 擴充板上可以連接 8 個伺服馬達(編號是 S1~S8),對應到的程式編號是 0~7,也就是說要控制 S8 的馬達的話,在程式內要填上「7」。而 microseconds 會影響轉動角度,就一般而言會轉換成角度比較直覺,所以透過Arduino 內建的「map」方法,將我們輸入的 0~180 度的角度參數轉換成 500~2400 微秒。
上圖的程式會讓 meArm 的四個馬達分別轉動到下表對應的位置:
因為在組裝 meArm 的過程中,伺服馬達初始轉角可能不太相同,所以需要針對自己的手臂,來找到各個動作下的馬達轉動參數。
以我們建置的硬體為例,為了讓手臂在夾取與放置的過程中能順利,共可切分為 12 個動作。以下表所示,透過控制馬達轉動角度的程式,找到適合的手臂位置。
這個步驟最為繁瑣,請依照自己的手臂找到對應的角度,並記錄下來。
請打開「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。
在「訓練模型」的階段,我們在 Edge Impulse 將訓練好的模型,編譯成 Arduino library 並下載下來,接著需要將其匯入 Arduino IDE。
打開「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 通訊還不太熟悉的朋友,可以再回去看看之前的教學單元。