Mais conteúdo relacionado Semelhante a 期末專題報告書 (20) 期末專題報告書1. 1
防疫送餐車
Food Delivery
專題組別: (請勾選)
☒電路與系統 ☐電子與材料 ☐電腦與通訊模組課程
授課老師:戴政祺教授、林志隆教授
組員學號、姓名:
職稱 學號 姓名 email
組長 F94089032 劉永勝 f94089032@gs.ncku.edu.tw
組員一 E24099025 李宇洋 ppalee1217@gmail.com
組員二 E24099059 陳旭祺 chenneil90121@gmail.com
2. 2
摘要
基於 ESP32、Heroku、Arduino mega 2560 開發的送餐服務系統。應用於防疫旅
館的送餐車,主要控制板為 ESP32,執行送餐之基本程序,提供提示語音、
OLED 顯示即時資訊、房卡辨識、秤重防運送時被偷吃等服務。消費者可使用
line bot 與指定網頁進行點餐,ESP32 作為 HTTP client,每隔一段時間會向
Heroku 的 server 發送請求,詢問是否有人點餐。當有人點餐後,將會取得訂單
資料,如果要移動車體至指定房號時,ESP32 會與 Arduino mega 2560 進行藍芽
傳輸。
關鍵字
物聯網、智慧居家、line bot、ESP32、Heroku、送餐服務
Abstract
A food delivery service system based on ESP32, Heroku, and Arduino mega 2560,
which is used in quarantine hotels. The microcontroller is ESP32, which deals with
the operating procedures of food delivery and provides many services including voice
prompt, OLED displaying real-time information, room card recognition, weighing to
prevent being stolen during transportation, etc. Consumers order food from the Line
bot and the website. The ESP32 acts as an HTTP client to send HTTP requests to
Heroku's server at regular intervals to ask if anyone has ordered food. When someone
orders food, ESP32 will get the order information. If the car needs to be moved to the
designated room, the ESP32 will send messages to Arduino mega 2560 by Bluetooth.
Keywords
IoT, Home automation, line bot, ESP32 Heroku, food delivery
3. 3
目錄
前言................................................................................................................4
原理分析與系統架構設計 1 - 使用材料 ....................................................4
1. 開發版............................................................................................................4
2. 模組................................................................................................................4
3. 車體................................................................................................................6
4. 後端架構........................................................................................................7
原理分析與系統架構設計 2 - 原理說明 ....................................................9
1. 系統架構與使用者的交互體驗....................................................................9
2. 循跡與房號編碼..........................................................................................10
3. ESP32 與各個模組之間的通訊..................................................................11
4. 後端技術......................................................................................................14
計畫成果 1 - 成果發表 ..............................................................................18
計畫成果 2 - 產品設計 ..............................................................................18
計畫成果 3 - 功能描述 ..............................................................................19
1. 簡述..............................................................................................................19
2. 正常流程......................................................................................................19
3. 異常處理......................................................................................................24
結論..............................................................................................................25
1. 劉永勝..........................................................................................................25
2. 李宇洋..........................................................................................................26
3. 陳旭祺..........................................................................................................26
4. 4
⚫ 前言
新冠疫情肆虐全球,大減餐廳的內用生意,而外送訂餐儼然已成為生活常態,
而各外送平台為了避免外送時造成的接觸感染,提出了無接觸外送 - Foodpanda
在領取商品時,外送員與消費者保持 1 公尺以上的距離。而 Uber eat 採用線上
支付或是放在門口。
但同時無接觸外送也引發了某些問題 - 放在門把上、放在地上、被偷走、使用
非實體支付遭重複扣款,因此以此問題為出發點,我們想實現全自動的防疫送
餐車,讓消費者不需要直接與外送員面對面取餐,減少染疫風險。
⚫ 原理分析與系統架構設計 1 - 使用材料
1. 開發版
A) 車體開發板 Arduino Mega 2560
Arduino Mega 2560 開發板比起 Arduino Uno 開發板擁有更多的 GPIO,包括 15
個 PWM、54 個 Digital I/O,符合我們車體需要 3 個控制馬達 L298N 的要求。
B) 車上模組開發板 NodeMCU-32s
NodeMCU-32s 開發版使用 ESP32 晶片,有以下功能符合我們的需求
⚫ 內建 Wi-Fi,可與架在 Heroku 的 server 連線。
⚫ 內建藍芽,可與 Arduino Mega 2560 板連線。
⚫ 擁有更大的記憶體(Flash 4-32 MB),可以跑更大的程式。
⚫ 留給使用者彈性大,可根據需求修改分區表。
⚫ 支援動態配置,可以直接操作記憶體的 heap 區。
⚫ 價格便宜、性價比高,NodeMCU-32s 開發板網路價為台幣 190 元。
2. 模組
A) 車體開發板 Arduino Mega 2560
功能 模組 通訊
驅動馬達轉動車輪 控制馬達 L298N 3 條(1 條 PWM)2 組
與 NodeMCU-32s 開發
版連線
藍芽模組 HC-05 UART 2 條
自動掀蓋機(optional) 控制馬達 L298N 3 條(1 條 PWM)
5 路循跡感測器
(optional)
紅外線感測器
TCRT5000
OUT1~5
註 1 : 考量到實際場地的不平,需要反覆調參數測試,因此在最終版的 demo
中,並未實裝 5 路循跡感測器的功能。
5. 5
註 2 : 自動掀蓋機因為板子無法燒錄的硬體問題,因此在最終版的 demo 中,改
為使用者手動開啟。
B) 車上模組開發板 NodeMCU-32s
功能 模組 通訊
在車上顯示即時資訊
黃藍雙色 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 條
註 3 : NodeMCU-32s 有內建藍芽功能,但由於 ESP32 的 http client 與藍芽功能
共用同一條天線,所以 http client 與藍芽不能同時開啟,因此我們使用額外的藍
芽模組 HC-05 來解決這個問題。
⚫ 房卡(RFID),上面標示文字即為房號與登入系統的密碼
7. 7
4. 後端架構
A) Heroku
雲端運算平台,支援多程式語言功能,提供使用者雲端解決方案服務。可以想
像為使用者放置在網路上的一台電腦中的 compiler,替使用者進行上傳 code 的
執行,並且不同於使用者在自己電腦執行(本地端),而是可以透過 Https 協定進
行網路連線與傳輸。
Heroku 在使用上會與 Git 搭配,每次進行版本更新都需要利用 Git Push 來
Deploy 最新的版本,好處是在進行版本控制非常方便,當需要回溯程式碼時直
接使用 Heroku 的 Rollback 功能即可實現。
在此次專題為我們提供後端程式(Node.js)在其伺服器上運行的功能,除此之外
也透過其與 Line Messaging API 的 Webhook 功能讓我們能方便使用創建好的
Line bot。
B) MongoDB / MongoDB Atlas
資料庫管理系統,提供使用者雲端儲存資料的服務,可以透過與指定資料庫進
行連線,並對資料進行 Find、Update、Delete、Create 等動作以及衍伸的多種功
能。
此外也有提供 MongoDB Compass 這款應用程式,與原本的 MongoDB Shell 相
同的點是一樣可以對資料庫直接進行操作,不同的點是 MongoDB Compass 提
供了人性化的使用者 UI 介面,在對資料操作方面更為方便。
在此次專題為我們提供使用者資料、歷史訂單資料、房間資訊的儲存,以及查
找比對資料和更新資料等功能。
8. 8
C) Line Messaging API
聊天機器人,Line 公司提供創作者建立聊天機器人頻道的服務,可以透過在後
端撰寫的程式碼以及在 Line 創作頁面的設定來與使用者進行互動。
透過提供頻道的 CHANNEL_SECRET、CHANNEL_SECRET、
CHANNEL_ACCESS_TOKEN 便可以簡單地與 Heroku 進行連接,進而使用其
Webhook 功能,以達到與使用者傳輸訊息的功能。
在此次專題為我們提供與使用者進行交換訊息的前端功能。
D) React
前端開發框架,協助開發者對前端進行高效率、高性能的開發,可以透過其較
輕易地組建複雜且龐大的前端應用程式,且其組件化開發模式可以透過類似於
物件的方式重複使用組件讓開發效率提升、開發難度降低。
在此次專題為我們前端點餐網頁撰寫所使用的工具。
9. 9
E) Node.js
JavaScript 引擎,用來直接編譯撰寫的 javascript 檔案,並且可以透過 Node.js
引入很多易於使用與開發的模組及套件。
在此次專題為我們後端執行、編譯程式碼以及透過其引入多個開發套件,例
如:Express.js、LineBot 等。
⚫ 原理分析與系統架構設計 2 - 原理說明
1. 系統架構與使用者的交互體驗
10. 10
2. 循跡與房號編碼
A) 循跡
紅外線感測器 TCRT5000 由 5 對紅外光二極體和高靈敏光電晶體組成。紅外光
照射在黑色物體上時,光線被吸收,則該燈號輸出 logic low。照射在其他顏色
之物體,紅外光皆會反射,則該燈號輸出 logic high。
實作中使用中間三個紅外線(OUT2、OUT3、OUT4)作為循跡判斷。下方表格為
對應燈號之車體修正結果。
OUT2 OUT3 OUT4 判斷結果
1 0 1 車體前進
1 0 0 車體向右修正
0 0 1 車體向左修正
B) 房號編碼
紅外線感測器 TCRT5000 由 5 個邏輯燈號組成,其輸出結果最多為25
= 32種可
能。扣除直線之輸出為 11011 不能作為房號,剩餘 31 種組合皆可做為房號編碼
使用。本次實作選用三個編碼做為房號,分別為 11000、10001、00011,下表
為房號所對應之編碼圖示。
11. 11
房號 編碼 循跡圖示
h 11000
j 10001
j 00011
註 4 : 考量到實際場地的不平,需要反覆調參數測試,因此在最終版的 demo
中,並未實裝循跡與房號編碼的功能。
3. ESP32 與各個模組之間的通訊
ESP32(NodeMCU-32s)每隔 3 秒會訪問路徑/Update 的,在未收到訂單時,會回
傳 0,而當使用者在網頁中送出訂單後,server 會將/Update 的數字改為 1,而
當 ESP32 再次訪問時,/Update 的數字就會變為 0,因此 ESP32 可以知道目前
收到一筆訂單,並訪問 server 的路徑/Order,獲得以下 json 數據。
{
"menu": [1, 2, 0, 0, 0, 3, 1, 8, 33, 0],
"room": "h",
"rfid": [0, 9, 10, 5],
}
ESP32 使用 ArduinoJson.h 函式庫進行 json 解析,獲得 10 項商品的數量、房號
位置、對應 RFID 的 UID。
12. 12
template <typename T>
class Queue {
struct Node {
T room_number;
int menu[10];
int UID[4];
Node *next;
long waiting_time;
};
Node *head;
Node *tail;
int qsize;
long start_time;
public:
Queue() {
head = NULL;
tail = NULL;
qsize = 0;
}
...
void put(int (&menu)[10], const T &room_number, int
(&UID)[4]) {
Node *newNode = new Node;
if (qsize) {
tail->next = newNode;
newNode->room_number = room_number;
for (int i = 0; i < 10; i++)
newNode->menu[i] = menu[i];
for (int i = 0; i < 4; i++)
newNode->UID[i] = UID[i];
newNode->waiting_time = millis();
newNode->next = NULL;
tail = newNode;
} else {
head = tail = newNode;
newNode->room_number = room_number;
for (int i = 0; i < 10; i++)
newNode->menu[i] = menu[i];
13. 13
for (int i = 0; i < 4; i++)
newNode->UID[i] = UID[i];
newNode->waiting_time = millis();
newNode->next = NULL;
}
qsize++;
}
}
將解析得到的資訊調用自定義 queue 的成員函數 put,加進隊列(enqueue)。
// 宣告UART接口1
HardwareSerial SerialBT(1);
// HC-05
SerialBT.begin(38400, SERIAL_8N1, 27, 13); // Serial的TX,RX
//車輛移動到h, j, k的位置
SerialBT.write(queue.room_number());
當後場人員送完餐點後,從 queue 中讀取房號,並寫入 ESP32 的藍芽模組,假
設 queue.room_number()的返回值是 h,會傳給 Arduino mega 2560 板子 h,使其
移動到 h 的位置。
if (SerialBT.available()) {
char completed = SerialBT.read();
if (completed == '1') {
notice_status("/Arrived"); // notice line
state = 2;
return;
}
}
當 ESP32 收到 Arduino mega 2560 板子回傳的藍芽資訊 1 時,代表指派給車體
移動的任務完成,接下來 ESP32 會進入下一個 state,處理消費者付款的手續。
其中也會訪問一次 server 的路徑/Arrived,讓 server 能告知使用者物流的狀態。
14. 14
4. 後端技術
A) 與 Line bot 間的通訊
const linebot = require('linebot');
const bot = linebot({
channelId : process.env.CHANNEL_ID,
channelSecret : process.env.CHANNEL_SECRET,
channelAccessToken : process.env.CHANNEL_ACCESS_TOKEN
});
const linebotParser = bot.parser();
app.post('/linewebhook', linebotParser);
透過引入 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 則是上面我們自行設定
的傳輸通道。
bot.on('follow',function (event) {
client.getProfile(event.source.userId)
.then((profile) => {
UserID=event.source.userId;
UserName=profile.displayName;
});
bot.on('message',async function (event) {
client.getProfile(event.source.userId)
.then((profile) => {
UserID=event.source.userId;
UserName=profile.displayName;
15. 15
});
app.listen(process.env.PORT || 80, function(){
console.log('Linebot Running');
});
上面為實際使用其 API 的情況,此次專題只有使用 Follow(加入好友)與
Message(發送訊息)兩種情況。下面則為 Line bot 指定的聆聽通道(port)為 80。
B) 與資料庫間的通訊
const mongoose = require('mongoose');
//使用者 Schema => 以使用者 ID 做判定
const UserSchema = new mongoose.Schema({
UserID: String, //用作查找使用者的依據 => 利用 UserID(目前
發言者)查找
UserName: String, //使用者名稱
totalmoney: Number, //此使用者所有訂單消費
room: String, //此使用者居住房號 => 若登出要消除
Isorder: Boolean, //確認使用者是否有送出訂單
orderNUM: Number, //記錄此使用者擁有的訂單數
})
//歷史訂單 Schema => 以使用者的 ID 做判定
const HistorySchema = new mongoose.Schema({
UserID: String, //用作查找訂單的依據=>利用 OrderUserID(目
前發出訂單者)查找
orderNUM: Number, //記錄此筆訂單是此使用者第幾筆
order: [Number], //訂單內容
money: Number, //單筆訂單之價格
orderstatus: String, // finished / working / canceled
RFIDWrong: Number,//此筆訂單 RFID 錯誤次數
})
//房間資訊 Schema => 以房號做判定
const RooomSchema = new mongoose.Schema({
Islogin: Boolean, //記錄此房號是否有登入 => 若登出要消除
CurrentUserID: String, //紀錄目前此房號的房客 => 若登出要
消除
CurrentUserName: String,//紀錄目前此房號的房客 => 若登出要消
除
room: String, //房號
pass: String, //密碼
RFID: [Number], //UID
16. 16
})
const User = mongoose.model("User", UserSchema);
const historyOrder = mongoose.model("Historyorder",
HistorySchema);
const Room = mongoose.model("Room", RooomSchema);
透過引入 mongoose 套件以方便我們在 Node.js 上直接對資料庫進行操作而非還
需要透過 MongoDB Shell 建立資料庫,其 API 使用方式與原本 MongoDB 語法
類似,需要先建立一個 Schema(類似 class)並在裡面定義各項 Property(利用 json
格式進行儲存),之後再進行物件實體化為一個 Model(類似 object)。
let userdata =
await User.findOne({ UserID: OrderUserID, UserName:
OrderUserName })
每個 Model 底下都有可以用來查找、更新、刪除與創建資料的 member
function,使用方式可以參照 Mongoose 官方文件。
C) 與 ESP32 間的通訊
const express = require('express')
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/Canceled', async function (req, res) {
bot.push(OrderUserID, OrderUserName +
'您好,因為您的訂單出現錯誤n 所以我們已經取消此筆訂單n 造
成您的困擾非常抱歉!');
GetCanceled();
res.send();
})
app.post('/Menu', jsonParser, async function (req, res)
{...})
透過引入 express 框架讓我們可以更簡單的架設伺服器,如上也同樣需要使用
body-parser 來進行訊息解析。在一般伺服器的架構中通常只會遇到兩種請求方
式:get 與 post 的形式,而 get 又更為常用,因此此次專題使用到的是 get。其
會搭配有一個我們自訂義的 route,主要是與 ESP32 溝通好後互相設定一樣的
route,當有任何事件觸發時即訪問特定的 URL,並且伺服器端接受到 req(請求)
後會根據情況返回對應的 res(回應),藉此就可以達到伺服器端與 ESP32 的通
訊。
17. 17
D) 前端點餐網頁架設
import React, { useState } from "react";
const addHandler = (index, amount) => {
setProduct((prev) => {
let newProduct = [...prev];
newProduct[index] += amount;
return newProduct;
});
};
const totalPriceHandler = (price) => {
setTotal((previousTotal) => previousTotal + price);
};
const resetHandler = () => {
setTotal(0);
setProduct([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
setShow(false);
};
const confirmHandler = () => {
setShow(false);
};
const submitHandler = () => {
console.log(Product);
setShow(true);
};
const closeHandler = () => {
setShow(false);
};
const sendHandler = () => {
setShow(false);
axios.post("https://indoor-foodie.herokuapp.com/Menu", {
product: Product,
total: total,
});
};
18. 18
透過引入 React 框架方便我們進行前端菜單網頁開發,可以看到上面有好幾個
Handler 組成的組件,在對應不同情況觸發不同的功能(e.g.:點選按鈕後新增餐
點;點選按鈕後跑出下拉數目條;點選按鈕後提交餐點),並且可以看到最後面
透過 axios 套件與原本後端伺服器上的一個 route 連接,再透過 post 傳遞餐點資
料,完成了方便使用者點餐的菜單。
⚫ 計畫成果 1 - 成果發表
demo 影片連結 程式原碼
⚫ 計畫成果 2 - 產品設計
概念圖 Line 的圖文選單 點餐網址介面
19. 19
⚫ 計畫成果 3 - 功能描述
1. 簡述
完成送餐流程如下,依序為
1. Line上點餐
2. 後場確認餐點後送出
3. (車輛前往指定房號...)
4. 送達指定房號並由消費者完成取餐手續
5. (車輛返回起始點...)
6. 重複步驟1,繼續下一筆訂單
另外還有以下 5 個異常處理的狀況。
1. 運送途中食物重量異常減少
2. 消費者未遵照正常手續直接取餐
3. 消費者使用房卡(RFID)感應錯誤超過3次
4. 後場人員在一開始即取消訂單
5. 消費者逾時未取餐
2. 正常流程
A) 消費者使用 Line 介面並導向指定網頁點餐
Line 介面 內容描述 Line 介面 內容描述
1. 加入"防疫
送餐車"Line
好友
2. 登入系統
(輸入房號與
密碼)
24. 24
Line 介面 內容描述 Line 介面 內容描述
餐點抵達目
的地消費者
通知
完成訂單消
費者通知
E) (車輛返回起始點…)
F) 重複步驟 1,繼續下一筆訂單
3. 異常處理
Line/車體介面 狀況 異常處理
運送途中食物
重量異常減少
停車,提示語
音並於 4 秒撥
放警報聲
消費者未遵照
正常手續直接
取餐
提示語音並於
5 秒撥放警報
聲
27. 27
D) 熟悉常見模組使用
如模組列表,我也額外測試 GPS 定位模組 GY-NEO6MV2,幾乎是大部分
Arduino 能玩的模組都學會如何使用。以 DFPlayer 為例,它是一個 wav,mp3 解
碼器,需要將要撥放的歌曲按照指定格式存進容量 32GB 以下的 microSD 卡,
並且外接功率 3W 以下的外放喇叭才能撥放聲音,它的通訊是使用 UART 協
定,由 MCU 透過寫入要撥放哪一首歌曲、要暫停撥放的指令;而 MCU 透過
DFPlayer 的 TX 接口接受目前 DFPlayer 模組的狀態,包括現在是否有歌曲這在
撥放、音量多少、microSD 是否有正確讀取等狀態。
E) 如何清楚並簡潔地介紹我們的產品
在第二次報告時,教授的回饋是不清楚我們的產品內容,因此在最後一次報告
時,我梳理了一下如何清楚並在短時間內介紹我們的商品,分為以下 3 點:
1. 選用影片呈現,可以透過剪輯的手法,將我們要呈現的內容壓在一定時間
內表達。
2. 不要一股腦兒所有東西都呈現給別人看,因此在影片demo時分為正常流程
與異常處理,一開始正常流程先跑完一遍所有的送餐程序,讓別人熟悉我們
的送餐流程後,之後才做異常處理的分支,介紹我們系統是如何反應各個突
發狀況。
3. 不要加入無意義的影片CG特效,而是專注於實際的內容,在影片方面我的
大方向就是條列是介紹我們的流程,現在影片播到哪裡,就列出當下是哪一
個送餐步驟。