<!-- .slide: data-background="https://i.imgur.com/gJLfldF.jpg" data-background-color="#111111" data-background-opacity="0.2" --> ###### tags: `iot-car` `lab` 返回[物聯網智慧自走車](/s/5c7ggGf0Spqql5Gy31Cqzg) ## 智慧物流 <br> <span style="color:#F9BF45;">自動化搬運系統</span> ###### [點我開啟簡報模式](/@BEExANT-ta/SJSxfhoOF#) ###### <kbd>ESC</kbd> 鍵進入總覽模式 ###### <kbd>&#8592;</kbd> <kbd>&#8593;</kbd> <kbd>&#8595;</kbd> <kbd>&#8594;</kbd> 切換頁面 --- <center><img src="https://i.imgur.com/cB7XLlQ.jpg" width=30%></img></center> 每間大賣場都有自己的物流中心,每天要處理非常大量的貨,而其中的人力成本也是非常可觀,所以各大公司都會發展自己的自動化處理流程。 這單元將搭配[第一套教具的機械手臂](https://hackmd.io/@BEExANT-ta/js-iot/%2Fs%2F9ntHyjh0RBWR2NewpjNQLw),使自走車移動至取貨點時,控制手臂搬貨,再移動至卸貨點等待下一次取貨。 ---- :::info :globe_with_meridians: 參考資源 - [亞馬遜機器人 - 維基百科](https://en.wikipedia.org/wiki/Amazon_Robotics) - [亞馬遜倉庫的「小革命」:服務好機器人,才能讓人類更安全](https://technews.tw/2019/01/25/amazon-built-an-electronic-vest-to-improve-worker-robot-interactions/) ::: --- ## 目標 **在任一車格旁擺放第一套教具的機械手臂作為搬貨點,另外一個車格作為卸貨點,使自走車能移動至搬貨點等待手臂搬貨完畢,再移動至卸貨點等待,重複以上動作至少三次。** --- ## 設計原理 - 網路設定請參考 [遠程控制網路設定](/s/UrpBFetqTfagugoaksoDCg)。 - 手臂遠程控制參考 [傑出的一手! - 遠程手臂控制](/s/s2K5DrGBTXmf8fdqP0l8Hg)。 - 指定顏色車格停車參考 [打造簡易車位辨識系統?! - 指定顏色區域停車](/s/J2S3MJ-vS5KM-0VFDUZDEA)。 - 結合以上實作,定義不同狀態來控制自走車與手臂。 --- ## 流程圖 <center><img src="https://i.imgur.com/g95ZeSo.jpg"></img></center> --- ## 範例程式碼 新增程式檔並命名 ==自動化搬運系統==,將以下程式碼複製貼上程式編輯區執行。 ```javascript= window.state = "初始化"; window.enter_dir = ""; let armTop = 7; let armMiddle = 6; let armBottom = 5; let idle_color = "黃"; let work_color = "綠"; let F = DATA.colorF[3]; let B = DATA.colorB[3]; let L = DATA.colorL[3]; let R = DATA.colorR[3]; let speed = 30; console.log("目前狀態: " + state); if(state == "等待卸貨"){ console.log("卸貨中..."); delay(3000); led_color.set("綠"); delay(300); state = "卸貨完畢"; console.log("卸貨完畢,準備退出卸貨點。"); } if(state == "開始搬貨"){ console.log("搬貨中..."); remote_servo[armTop].set(60); delay(1000); remote_servo[armMiddle].set(30); delay(1000); remote_servo[armBottom].set(30); delay(1000); remote_servo[armMiddle].set(0); delay(1000); remote_servo[armTop].set(0); delay(1000); remote_servo[armMiddle].set(30); delay(1000); remote_servo[armBottom].set(160); delay(1000); remote_servo[armMiddle].set(0); delay(1000); led_color.set("綠"); delay(300); state = "搬貨完畢"; console.log("搬貨完畢,準備退出搬貨點。"); } if(F == idle_color && B == idle_color && L == idle_color && R == idle_color && state == "進入卸貨點") { state = "等待卸貨"; move_stop.set(); delay(300); led_color.set("紅"); } if(F == work_color && B == work_color && L == work_color && R == work_color && state == "進入搬貨點") { state = "開始搬貨"; move_stop.set(); delay(300); led_color.set("紅"); } if(F == "紫") { console.log("前方觸碰邊界,往後方移動"); move_backward.set(speed); } if(B == "紫") { console.log("後方觸碰邊界,往前方移動"); move_forward.set(speed); } if(state == "初始化") { state = "前往搬貨點"; move_forward.set(speed); } if(L == "白" && R == "黑" && (state == "前往搬貨點" || state == "前往卸貨點") ) { console.log("車身向左偏移,向右校正"); move_right.set(speed); delay(500); } if(L == "黑" && R == "白" && (state == "前往搬貨點" || state == "前往卸貨點") ) { console.log("車身向右偏移,向左校正"); move_left.set(speed); delay(500); } if(R == "黑" && L == work_color && state == "前往搬貨點") { state = "進入搬貨點"; enter_dir = "左"; delay(300); move_stop.set(); delay(300); move_left.set(speed); } if(L == "黑" && R == work_color && state == "前往搬貨點") { state = "進入搬貨點"; enter_dir = "右"; delay(300); move_stop.set(); delay(300); move_right.set(speed); } if(R == "黑" && L == idle_color && state == "前往卸貨點") { state = "進入卸貨點"; enter_dir = "左"; move_stop.set(); delay(300); move_left.set(speed); } if(L == "黑" && R == idle_color && state == "前往卸貨點") { state = "進入卸貨點"; enter_dir = "右"; move_stop.set(); delay(300); move_right.set(speed); } if(state == "搬貨完畢") { state = "退出搬貨點"; if(enter_dir == "左"){ move_right.set(speed); } else{ move_left.set(speed); } } if(state == "卸貨完畢") { state = "退出卸貨點"; if(enter_dir == "左"){ move_right.set(speed); } else{ move_left.set(speed); } } if(F == "黑" && B == "黑" && (L == "黑" || R == "黑") && state == "退出搬貨點") { state = "前往卸貨點"; delay(1200); move_forward.set(speed); } if(F == "黑" && B == "黑" && (L == "黑" || R == "黑") && state == "退出卸貨點") { state = "前往搬貨點"; delay(1200); move_forward.set(speed); } ``` --- ## 程式解說 逐行講解程式意義。 ---- ```javascript= window.state = "初始化"; window.enter_dir = ""; ``` - 定義全域變數state,記錄目前模式的變數。 - 定義全域變數enter_dir,記錄進入車格時的方向。 ---- ```javascript= let armTop = 7; let armMiddle = 6; let armBottom = 5; let idle_color = "黃"; let work_color = "綠"; let F = DATA.colorF[3]; let B = DATA.colorB[3]; let L = DATA.colorL[3]; let R = DATA.colorR[3]; let speed = 30; ``` - armTop、armMiddle、armBottom 分別代表控制手臂夾爪、中間、底部的伺服馬達腳位,這裡設定的765會對應到876這三個腳位。 - idle_color與work_color 分別代表卸貨區與搬貨區的顏色。 - F、B、L、R 為四個方向的顏色值。 - speed 為車子移動時的速度。 ---- ```javascript= console.log("目前狀態: " + state); ``` - 每次迴圈皆會顯示目前state中的值。 ---- ```javascript= if(state == "等待卸貨"){ console.log("卸貨中..."); delay(3000); led_color.set("綠"); delay(300); state = "卸貨完畢"; console.log("卸貨完畢,準備退出卸貨點。"); } ``` - 當 state 等於 等待卸貨 時,訊息顯示卸貨中,等待3秒後將led燈設為綠色,設定state為 卸貨完畢。 ---- ```javascript= if(state == "開始搬貨"){ console.log("搬貨中..."); remote_servo[armTop].set(60); delay(1000); remote_servo[armMiddle].set(30); delay(1000); remote_servo[armBottom].set(30); delay(1000); remote_servo[armMiddle].set(0); delay(1000); remote_servo[armTop].set(0); delay(1000); remote_servo[armMiddle].set(30); delay(1000); remote_servo[armBottom].set(160); delay(1000); remote_servo[armMiddle].set(0); delay(1000); led_color.set("綠"); delay(300); state = "搬貨完畢"; console.log("搬貨完畢,準備退出搬貨點。"); } ``` - 當 state 等於 開始搬貨 時,訊息顯示搬貨中,使用remote_servo[].set()發送遠端控制命令,中括號內的值對應到控制伺服馬達的腳位,小括號內的值則為角度。 - 結束後將led設為綠色,state設為 搬貨完畢。 ---- ```javascript= if(F == idle_color && B == idle_color && L == idle_color && R == idle_color && state == "進入卸貨點") { state = "等待卸貨"; move_stop.set(); delay(300); led_color.set("紅"); } if(F == work_color && B == work_color && L == work_color && R == work_color && state == "進入搬貨點") { state = "開始搬貨"; move_stop.set(); delay(300); led_color.set("紅"); } ``` - 當四個方向的顏色皆等於 卸貨區顏色idle_color 時,將state設為 等待卸貨,控制車子停止移動並將led設為紅色。 - 當四個方向的顏色皆等於 搬貨區顏色work_color 時,將state設為 開始搬貨,控制車子停止移動並將led設為紅色。 ---- ```javascript= if(F == "紫") { console.log("前方觸碰邊界,往後方移動"); move_backward.set(speed); } if(B == "紫") { console.log("後方觸碰邊界,往前方移動"); move_forward.set(speed); } ``` - 當前方顏色為紫時,控制車子往反方向移動,反之亦然。 ---- ```javascript= if(state == "初始化") { state = "前往搬貨點"; move_forward.set(speed); } ``` - 一開始state為 初始化 時,將state設為 前往搬貨點,控制車子向前移動。 ---- ```javascript= if(L == "白" && R == "黑" && (state == "前往搬貨點" || state == "前往卸貨點") ) { console.log("車身向左偏移,向右校正"); move_right.set(speed); delay(500); } if(L == "黑" && R == "白" && (state == "前往搬貨點" || state == "前往卸貨點") ) { console.log("車身向右偏移,向左校正"); move_left.set(speed); delay(500); } ``` - 當車子在車道上移動時,其中一方的顏色感測為白色時,控制車子往黑色的方向移動回到車道上。 ---- ```javascript= if(R == "黑" && L == work_color && state == "前往搬貨點") { state = "進入搬貨點"; enter_dir = "左"; delay(300); move_stop.set(); delay(300); move_left.set(speed); } if(L == "黑" && R == work_color && state == "前往搬貨點") { state = "進入搬貨點"; enter_dir = "右"; delay(300); move_stop.set(); delay(300); move_right.set(speed); } ``` - 當state為 前往搬貨點 且 左或右的顏色等於 搬貨區顏色work_color時,將state 設為 進入搬貨點,方向記錄enter_dir 設為進入的方向,控制車子暫停一下後進入車格。 ---- ```javascript= if(R == "黑" && L == idle_color && state == "前往卸貨點") { state = "進入卸貨點"; enter_dir = "左"; move_stop.set(); delay(300); move_left.set(speed); } if(L == "黑" && R == idle_color && state == "前往卸貨點") { state = "進入卸貨點"; enter_dir = "右"; move_stop.set(); delay(300); move_right.set(speed); } ``` - 當state為 前往卸貨點 且 左或右的顏色等於 卸貨區顏色idle_color時,將state 設為 進入卸貨點,方向記錄enter_dir 設為進入的方向,控制車子暫停一下後進入車格。 ---- ```javascript= if(state == "搬貨完畢") { state = "退出搬貨點"; if(enter_dir == "左"){ move_right.set(speed); } else{ move_left.set(speed); } } if(state == "卸貨完畢") { state = "退出卸貨點"; if(enter_dir == "左"){ move_right.set(speed); } else{ move_left.set(speed); } } ``` - 當狀態為 搬貨完畢 時,將state 設為 退出搬貨點,往進入時的反方向移動退出車格。 - 當狀態為 卸貨完畢 時,將state 設為 退出卸貨點,往進入時的反方向移動退出車格。 ---- ```javascript= if(F == "黑" && B == "黑" && (L == "黑" || R == "黑") && state == "退出搬貨點") { state = "前往卸貨點"; delay(1200); move_forward.set(speed); } if(F == "黑" && B == "黑" && (L == "黑" || R == "黑") && state == "退出卸貨點") { state = "前往搬貨點"; delay(1200); move_forward.set(speed); } ``` - 當前後方向且左或右其中一個為黑色 且 state 為 退出搬貨點時,表示車子已從車格退出至車道上,設定1.2秒的延遲使車子能先回到車道中間,這裡delay時間若越長,車子退出車格時的移動距離就會越長,最後再控制向前移動。 --- ## 參數修改 為方便實作,以下會將範例程式中可修改的參數標示出來,進行實作時只需修改對應參數,並觀察結果即可。 :::warning :zap: 詳細內建JS參數參考 - [內建Js參數及功能總覽](/s/wlfjvQBzRPCmJ8LCL3f2Fg) ::: ---- :::success **let idle_color = "黃"; let work_color = "綠";** ::: - idle_color 表示卸貨區車格的顏色,可更換成其他車格的顏色,不可與搬貨區顏色相同。 - work_color 表示搬貨區車格的顏色,可更換成其他車格的顏色,不可與卸貨區顏色相同。 ---- :::success **let armTop = 7; let armMiddle = 6; let armBottom = 5;** ::: - armTop 表示控制手臂夾爪的腳位,設定7表示控制第8個馬達的腳位。 - armMiddle 表示控制手臂中間馬達的腳位,設定6表示控制第7個馬達的腳位。 - armBottom 表示控制手臂底部馬達的腳位,設定5表示控制第6個馬達的腳位。 --- ## 範例影片 {%youtube KBZ87Y4ZDrM %} <a class="btn btn-warning" style="width:100%;color:#333333;" href="/s/5c7ggGf0Spqql5Gy31Cqzg" role="button"> 物聯網智慧自走車 **&#8680;** </a> <a class="btn btn-primary" style="width:100%;" href="/s/rVVZVo_rTg201uLszRsOYg" role="button"> **&#8678;** 自動停車系統 </a>
{"metaMigratedAt":"2023-06-16T15:09:33.689Z","metaMigratedFrom":"YAML","title":"智慧物流 - 自動化搬運系統","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"transitionSpeed\":\"fast\",\"theme\":\"league\"}","contributors":"[{\"id\":\"a1db0c29-d848-4070-be84-9191a2398ca8\",\"add\":14070,\"del\":4312}]"}
    1111 views
   owned this note