final-project
demo影片連結 | 程式原碼 |
---|---|
新冠疫情肆虐全球,大減餐廳的內用生意,而外送訂餐儼然已成為生活常態,而各外送平台為了避免外送時造成的接觸感染,提出了無接觸外送 - Foodpanda在領取商品時,外送員與消費者保持1公尺以上的距離。而Uber eat採用線上支付或是放在門口。
但同時無接觸外送也引發了某些問題 - 放在門把上、放在地上、被偷走、使用非實體支付遭重複扣款,因此以此問題為出發點,我們想實現全自動的防疫送餐車,讓消費者不需要直接與外送員面對面取餐,減少染疫風險。
Arduino Mega 2560開發板比起Arduino Uno開發板擁有更多的GPIO,包括15個PWM、54個Digital I/O,符合我們車體需要3個控制馬達L298N
的要求。
NodeMCU-32s開發版使用ESP32晶片,有以下功能符合我們的需求
功能 | 模組 | 通訊 |
---|---|---|
驅動馬達轉動車輪 | 控制馬達L298N |
3條(1條PWM)2組 |
與NodeMCU-32s開發版連線 | 藍芽模組HC-05 |
UART 2條 |
自動掀蓋機(optional) | 控制馬達L298N |
3條(1條PWM) |
5路循跡感測器(optional) | 紅外線感測器TCRT5000 |
OUT1~5 |
考量到實際場地的不平,需要反覆調參數測試,因此在最終版的demo中,並未實裝5路循跡感測器的功能。
自動掀蓋機因為板子無法燒錄的硬體問題,因此在最終版的demo中,改為使用者手動開啟。
功能 | 模組 | 通訊 |
---|---|---|
在車上顯示即時資訊 | 黃藍雙色 SSD1306 0.96吋 OLED |
I2C 共用 |
操作OLED面板 | 遊戲搖杆、按鈕 | OUT1,2、訊號線1條 |
在車上秤重,防止運送時的突發狀況(實際demo用手機當作食物去測重) | 秤重模組HX711 |
I2C 共用 |
個別房卡辨識 | RFID模組MFRC-522 、房卡(RFID) |
I2C 共用(UART、I2C、SPI皆可) |
播放相應提示聲音 | wav,mp3解碼器DFPlayer 、MicroSD卡、喇叭 |
UART 2條 |
播放相應提示聲音2 | 無源蜂鳴器 | 訊號線1條 |
與Arduino Mega 2560開發版連線 | 藍芽模組HC-05 |
UART 2條 |
NodeMCU-32s有內建藍芽功能,但由於ESP32的http client與藍芽功能共用同一條天線,所以http client與藍芽不能同時開啟,因此我們使用額外的藍芽模組
HC-05
來解決這個問題。
使用汶諺學長以前專題的車體。
輪子是使用麥克納姆輪,實現全向移動,適用於轉動空間較小的地點。
雲端運算平台,支援多程式語言功能,提供使用者雲端解決方案服務。可以想像為使用者放置在網路上的一台電腦中的compiler,替使用者進行上傳code的執行,並且不同於使用者在自己電腦執行(本地端),而是可以透過Https協定進行網路連線與傳輸。
Heroku在使用上會與Git搭配,每次進行版本更新都需要利用Git Push來Deploy最新的版本,好處是在進行版本控制非常方便,當需要回溯程式碼時直接使用Heroku的Rollback功能即可實現。
在此次專題為我們提供後端程式(Node.js)在其伺服器上運行的功能,除此之外也透過其與Line Messaging API的Webhook功能讓我們能方便使用創建好的Line bot。
資料庫管理系統,提供使用者雲端儲存資料的服務,可以透過與指定資料庫進行連線,並對資料進行Find、Update、Delete、Create等動作以及衍伸的多種功能。
此外也有提供MongoDB Compass這款應用程式,與原本的MongoDB Shell相同的點是一樣可以對資料庫直接進行操作,不同的點是MongoDB Compass提供了人性化的使用者UI介面,在對資料操作方面更為方便。
在此次專題為我們提供使用者資料、歷史訂單資料、房間資訊的儲存,以及查找比對資料和更新資料等功能。
聊天機器人,Line公司提供創作者建立聊天機器人頻道的服務,可以透過在後端撰寫的程式碼以及在Line創作頁面的設定來與使用者進行互動。
透過提供頻道的CHANNEL_SECRET
、CHANNEL_SECRET
、CHANNEL_ACCESS_TOKEN
便可以簡單地與Heroku進行連接,進而使用其Webhook功能,以達到與使用者傳輸訊息的功能。
在此次專題為我們提供與使用者進行交換訊息的前端功能。
前端開發框架,協助開發者對前端進行高效率、高性能的開發,可以透過其較輕易地組建複雜且龐大的前端應用程式,且其組件化開發模式可以透過類似於物件的方式重複使用組件讓開發效率提升、開發難度降低。
在此次專題為我們前端點餐網頁撰寫所使用的工具。
JavaScript引擎,用來直接編譯撰寫的javascript檔案,並且可以透過Node.js引入很多易於使用與開發的模組及套件。
在此次專題為我們後端執行、編譯程式碼以及透過其引入多個開發套件,例如:Express.js
、LineBot
等。
概念圖 | Line的圖文選單 | 點餐網址介面 |
---|---|---|
完成送餐流程如下,依序為
另外還有以下5個異常處理的狀況。
Line介面 | 內容描述 | Line介面 | 內容描述 |
---|---|---|---|
1. 加入"防疫送餐車"Line好友 | 2. 登入系統(輸入房號與密碼) | ||
3. 選擇"我要點餐"的圖文選單 | 4. 導入指定網址點餐 | ||
5. 計算消費金額並送出 | 6. 餐點發送後會實時通知目前的物流狀況、按"歷史定單"的圖文選單可以查詢所有訂單(包括目前這筆)的狀態 |
車體介面 | 內容描述 |
---|---|
未收到訂單 |
車體介面 | 內容描述 |
---|---|
1. 收到新訂單的通知(蜂鳴器+語音提示) | |
2. (當後場備妥餐點後…) | |
3. 使用遊戲搖桿選擇"delivery"選單 | |
4. 放餐點夾在防疫蓋與秤重模組之間 | |
5. 按下按鈕(enter鍵) | |
6. 五秒發車並計算食物重量 |
Line介面 | 內容描述 |
---|---|
發車後消費者通知 |
車體介面 | 內容描述 |
---|---|
OLED顯示餐點公克數 |
車體介面 | 內容描述 |
---|---|
1. 送達目的地並宣讀購買項目與數量 | |
2. 房卡感應 | |
3. 拿取餐點並完成交易 |
Line介面 | 內容描述 | Line介面 | 內容描述 |
---|---|---|---|
餐點抵達目的地消費者通知 | 完成訂單消費者通知 |
Line/車體介面 | 狀況 | 異常處理 |
---|---|---|
運送途中食物重量異常減少 | 停車,提示語音並於4秒撥放警報聲 | |
消費者未遵照正常手續直接取餐 | 提示語音並於5秒撥放警報聲 | |
消費者使用房卡(RFID)感應錯誤超過3次 | 此筆訂單取消 | |
後場人員在一開始即取消訂單 | 取消該筆訂單 | |
消費者逾時未取餐 | 取消該筆訂單 |
紅外線感測器TCRT5000
由5對紅外光二極體和高靈敏光電晶體組成。紅外光照射在黑色物體上時,光線被吸收,則該燈號輸出logic low。照射在其他顏色之物體,紅外光皆會反射,則該燈號輸出logic high。
實作中使用中間三個紅外線(OUT2、OUT3、OUT4)作為循跡判斷。下方表格為對應燈號之車體修正結果。
OUT2 | OUT3 | OUT4 | 判斷結果 |
---|---|---|---|
1 | 0 | 1 | 車體前進 |
1 | 0 | 0 | 車體向右修正 |
0 | 0 | 1 | 車體向左修正 |
紅外線感測器TCRT5000
由5個邏輯燈號組成,其輸出結果最多為種可能。扣除直線之輸出為11011不能作為房號,剩餘31種組合皆可做為房號編碼使用。本次實作選用三個編碼做為房號,分別為11000、10001、00011,下表為房號所對應之編碼圖示。
房號 | 編碼 | 循跡圖示 |
---|---|---|
h |
11000 | |
j |
10001 | |
k |
00011 |
考量到實際場地的不平,需要反覆調參數測試,因此在最終版的demo中,並未實裝循跡與房號編碼的功能。
ESP32(NodeMCU-32s)每隔3秒會訪問路徑/Update
的,在未收到訂單時,會回傳0
,而當使用者在網頁中送出訂單後,server會將/Update
的數字改為1
,而當ESP32再次訪問時,/Update
的數字就會變為0
,因此ESP32可以知道目前收到一筆訂單,並訪問server的路徑/Order
,獲得以下json
數據。
ESP32使用ArduinoJson.h
函式庫進行json
解析,獲得10項商品的數量、房號位置、對應RFID的UID。
將解析得到的資訊調用自定義queue
的成員函數put
,加進隊列(enqueue)。
當後場人員送完餐點後,從queue
中讀取房號,並寫入ESP32的藍芽模組,假設queue.room_number()
的返回值是h
,會傳給Arduino mega 2560板子h
,使其移動到h
的位置。
當ESP32收到Arduino mega 2560板子回傳的藍芽資訊1
時,代表指派給車體移動的任務完成,接下來ESP32會進入下一個state
,處理消費者付款的手續。其中也會訪問一次server的路徑/Arrived
,讓server能告知使用者物流的狀態。
透過引入linebot
套件來使用其API,並且因為已經在Heroku的設定上與要使用的Line bot頻道進行掛勾,因此在使用上非常方便,只需使用環境變數在雲端執行時便會自己抓取設定好的頻道資訊。
在最後兩行引入body-parser
套件來協助解析Line bot傳輸的body,由於我們在傳輸時是使用URL上的Route
,因此需要在Line開發頁面上設定好URL網址作為事先約定好的傳輸通道,以我們的為例是https://indoor-foodie.herokuapp.com/linewebhook
,其中indoor-foodie.herokuapp.com
是由Heroku提供,而/linewebhook
則是上面我們自行設定的傳輸通道。
上面為實際使用其API的情況,此次專題只有使用Follow(加入好友)與Message(發送訊息)兩種情況。下面則為Line bot指定的聆聽通道(port)為80。
透過引入mongoose
套件以方便我們在Node.js上直接對資料庫進行操作而非還需要透過MongoDB Shell建立資料庫,其API使用方式與原本MongoDB語法類似,需要先建立一個Schema(類似class)並在裡面定義各項Property(利用json
格式進行儲存),之後再進行物件實體化為一個Model(類似object)。
每個Model底下都有可以用來查找、更新、刪除與創建資料的member function,使用方式可以參照Mongoose官方文件。
透過引入express
框架讓我們可以更簡單的架設伺服器,如上也同樣需要使用body-parser
來進行訊息解析。在一般伺服器的架構中通常只會遇到兩種請求方式:get
與post
的形式,而get
又更為常用,因此此次專題使用到的是get
。其會搭配有一個我們自訂義的route
,主要是與ESP32溝通好後互相設定一樣的route
,當有任何事件觸發時即訪問特定的URL,並且伺服器端接受到req
(請求)後會根據情況返回對應的res
(回應),藉此就可以達到伺服器端與ESP32的通訊。
透過引入React
框架方便我們進行前端菜單網頁開發,可以看到上面有好幾個Handler組成的組件,在對應不同情況觸發不同的功能(e.g.:點選按鈕後新增餐點;點選按鈕後跑出下拉數目條;點選按鈕後提交餐點),並且可以看到最後面透過axios
套件與原本後端伺服器上的一個route連接,再透過post
傳遞餐點資料,完成了方便使用者點餐的菜單。
這次的專題我們的主題雖然是防疫送餐車,但實際上我們從點餐、出餐、送餐、取餐、結帳,整個流程都進行了整合。點餐部分為了使消費者能接收即時資訊,使用了Line作為餐點物流通知,也使用圖像介面之網頁選單,讓顧客能簡易的進行餐點的數量選擇。送餐過程中,重量感測模組會時刻紀錄餐點重量,以確保餐點在運送過程之狀況,並用Line與消費者通知餐點之即時訊息。藉由循跡模組抵達指定房號後,顧客藉由房卡感應,確認餐點送達,並提取餐點。
此次專題實作是一個很新的體驗,實際動手去把之前學過的模組應用出來,又要透過專題的不同需求自己去學習如何使用另外的一些模組、後端技術等等,那也因為這樣我們確實做出了一個算是非常完善的系統,從點餐的使用者介面,到送餐的使用者操作流程、整個送餐車系統的優化,以及最後送餐完畢自走車自行返回的功能等,可以說算是一個滿意的專題作品。
這次我們專題內容或許不是什麼新奇的創意,但我重點擺在學會使用別人寫好的工具去實現自己想完成的系統,從學期初,不會用MCU去控制LED亮暗,到期末做出一個完整、像樣的系統,雖然很花時間,但同時我也學到了很多知識。
json
格式與跟mega 2560的藍芽傳輸字串格式,因此我們彼此之間不需要知道對方具體的實踐內容,只需要知道傳輸接口的規則,如此才能增加我們的工作效率,就再需要反覆無意義的討論了。json
格式文檔。analogWrite()
,但在使用Arduino框架的ESP32上需要完成以下3個步驟:
ledcSetup(LEDChannel, freq, resolution)
ledcAttachPin(ledPin, LEDChannel)
ledcWrite(LEDChannel, dutyCycle)
GY-NEO6MV2
,幾乎是大部分Arduino能玩的模組都學會如何使用。以DFPlayer為例,它是一個wav,mp3解碼器,需要將要撥放的歌曲按照指定格式存進容量32GB以下的microSD卡,並且外接功率3W以下的外放喇叭才能撥放聲音,它的通訊是使用UART協定,由MCU透過寫入要撥放哪一首歌曲、要暫停撥放的指令;而MCU透過DFPlayer的TX接口接受目前DFPlayer模組的狀態,包括現在是否有歌曲這在撥放、音量多少、microSD是否有正確讀取等狀態。