# 高二下自主學習計畫---遠端寵物飼料餵食器 ## 目錄 [TOC] ## 動機 在高一探究與實作的課程中,我們有研究可以藍芽控制的寵物飼料餵食器,不過由於藍芽接收範圍有限之原因,因此不能夠完全實現能夠在美國遠端台灣的餵食器的想法。因此這次的自主學習,我們決定要實現此想法,並且改善裝置的設計。 ## 預計功能 * 能夠在國外也能用手機定時餵食家中寵物 ## 實踐想法 **這次計畫預計的想法是:前端網頁送出選擇時間後經由後端去計算多久之後執行,最後透過Arduino的HTTPCLIENT程式庫去讀取最後計算出來所需的時間讓馬達在時間到後運作。** 為了達成遠端的功能,勢必不能只依靠無線WI-FI和藍芽,因此我想到可以上傳project到IoT雲平台上,因此我使用了Heroku這個支持多種程式語言的雲平台當作這次架設網頁的Server端。這也是我第一次接觸到要設計後端程式運作,由於之前有學過一點點python,所以這次是使用Flask去架設後端程式網頁。 ## 程式架構 **以下先附上這次的程式碼:** **HTML網頁程式碼如下:** ```htmlembedded= <!DOCTYPE html> <head> <h1>遠端控制飼育機器</h1> <!--for python flask--> <script type="text/javascript" src="{{ url_for('static' , filename='js/jquery.js')}}"></script> <script type="text/javascript" src="{{ url_for('static' , filename='js/jquery-ui.js')}}"></script> <script type="text/javascript" src="{{ url_for('static' , filename='js/jquery-ui-sliderAccess.js')}}"></script> <script type="text/javascript" src="{{ url_for('static' , filename='js/jquery-ui-timepicker-addon.js')}}"></script> </head> <body> <!--Form--> <div id='modes'> <form id='myform' method="POST" action='' autocomplete="off"> <div id='FeedTime'> <label for='select-FeedTime'>FeedTime</label> <input type='text' name='select-FeedTime' id='select-FeedTime'> </div> <div id='WaterTime'> <label for='select-WaterTime'>WaterTime</label> <input type='text' name='select-WaterTime' id='select-WaterTime'> </div> </div> <input type="submit" id="submit" value="Send"> </form> </div> <!--for HTML--> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/jquery-ui.js"></script> <script type="text/javascript" src="/static/js/jquery-ui-sliderAccess.js"></script> <script type="text/javascript" src="/static/js/jquery-ui-timepicker-addon.js"></script> <link rel="stylesheet" href="/static/css/jquery-ui.min.css"> <link rel="stylesheet" href="/static/css/jquery-ui-timepicker-addon.css"> <!--datetimepickerLaunch--> <script> jQuery('#select-FeedTime').datetimepicker({dateFormat:'yy.mm.dd', timeFormat:'HH:mm', defaultDate:''}); </script> <script> jQuery('#select-WaterTime').datetimepicker({dateFormat:'yy.mm.dd', timeFormat:'HH:mm', defaultDate:''}); </script> </body> ``` **PYTHON程式碼如下:** ```python= from flask import Flask,request,url_for,render_template,redirect from datetime import datetime,timezone,timedelta import time app = Flask(__name__) @app.route("/timetest") def Time_cmp(): ty = timezone(timedelta(hours =+8)) datetimeNow = datetime.now(ty).strftime('%Y.%m.%d %H:%M') return datetimeNow @app.route("/") def home(): global work work="FALSE" return "Hello Heroku." @app.route("/htmltest", methods=["POST","GET"]) def htmltest(): if request.method == "POST": WaterTime = request.form['select-WaterTime'] FeedTime =request.form['select-FeedTime'] print("Feed",FeedTime,"Water",WaterTime) if FeedTime != '': global A A = Feed(FeedTime) work = "TRUE" return redirect(url_for("FEEDING")) else: global B B = WATER(WaterTime) work = "TRUE" return redirect(url_for("WATERING")) else: return render_template("index.html") @app.route("/FEEDING") def FEEDING(): return A @app.route("/WATERING") def FEEDING(): return B @app.route("/WORK") def WORK(): reset() return work def reset(): time.sleep(1) work= "FALSE" return work def Feed(selectFeedTime): ty = timezone(timedelta(hours =+8)) datetimeNow = datetime.now(ty).strftime('%Y.%m.%d %H:%M:%S') datetimeNow = datetime.now().strptime(datetimeNow , '%Y.%m.%d %H:%M:%S') selectFeedTime = datetime.strptime(selectFeedTime , '%Y.%m.%d %H:%M') timeGapFeed = selectFeedTime - datetimeNow timeGapFeedSecond = str(timeGapFeed.total_seconds()) return timeGapFeedSecond def Feed(selectWaterTime): ty = timezone(timedelta(hours =+8)) datetimeNow = datetime.now(ty).strftime('%Y.%m.%d %H:%M:%S') datetimeNow = datetime.now().strptime(datetimeNow , '%Y.%m.%d %H:%M:%S') selectFeedTime = datetime.strptime(selectFeedTime , '%Y.%m.%d %H:%M') timeGapWater = selectWaterTime - datetimeNow timeGapWaterSecond = str(timeGapWater.total_seconds()) return timeGapWaterSecond if __name__ == "__main__": app.run(debug=True) ``` **Arduino程式碼如下:** ```Arduino= #include <WiFi.h> #include <HTTPClient.h> #include <Servo.h> char severName[] = "feed-your-pet-anywhere-omg.herokuapp.com"; const char* ssid = "******"; const char* pass = "******"; const char* headerKeys[] = {"Referer","Cookie"}; Servo myservo; int pos=0; #define USE_SERIAL Serial void setup() { myservo.attach(9); Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid,pass); Serial.println(""); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Wi-Fi ready..."); } void loop(){ if((WiFi.status()== WL_CONNECTED)){ httpclient(); } } void httpclient(){ HTTPClient feedcheck; feedcheck.begin("http://feed-your-pet-anywhere-omg.herokuapp.com/FEEDING"); int httpCode = feedcheck.GET(); USE_SERIAL.print(httpCode); USE_SERIAL.print("\n"); if(httpCode == HTTP_CODE_OK) { String payload1 = feedcheck.getString(); int FEED=payload1.toInt(); for(int t=FEED;t<0;t=t-1){ if(t==0){ Serial.print("ENDFEED"); for(pos = 0; pos < 180; pos += 1) { myservo.write(pos); delay(15); } for(pos = 180; pos>=1; pos-=1) { myservo.write(pos); delay(15); } } } Serial.print("Sever response playload:"); Serial.print(payload1); Serial.print("\n"); } else { USE_SERIAL.print("Error Response Code:" ); USE_SERIAL.print(httpCode); } feedcheck.end(); } ``` ## 運行截圖 ![](https://i.imgur.com/tmj8Ifl.png) ![](https://i.imgur.com/pv38lPD.png) ![](https://i.imgur.com/bQl8a3Z.png) ## 遭遇困難 & 解決辦法 ### HTML內部的Input time 無法選擇日期 HTML中的`input type="time"`只能選擇幾點幾分而不能選擇哪一天,為了能更精確選擇日期,查詢網路過後,發現可以使用額外的Javascript套件Datetimepicker,就能夠選擇日期了。 ### Arduino判斷運作條件的方法 一開始的時候計畫要讓Arduino偵測網址,在python上面計時,時間到即跳轉頁面,Arduino偵測到後即運作。結果因為頁面是預先寫好的Arduino在偵測時就會直接偵測到計時完成的頁面而不停運作。 為了能實踐時間到才運作的想法,因此改成讓Arduino偵測要過多久才運作,並且將計時移動到Arduino端來進行,如此一來就能正常運行。 ## 未來可改進之處 ### 能夠餵飼料和倒水同時進行 當初在寫Arudino端偵測網頁時,一直找不到原因可以讓Arduino同時偵測飼料和倒水的頁面成功,導致一次只能選擇兩者之一進行,只能夠分開選兩次時間,如果能一次選擇兩個的時間能讓使用效果更好。 ### 網頁介面 之後可以學習CSS的寫法,讓網頁介面整個看起來更美觀一些。 ## 心得 這次自主學習整個程式都是由我來負責,其他人則負責製作裝置,因此我也感覺自己身負重任,畢竟缺少了程式整個都不能運作。不過很可惜的是當時因為疫情爆發而被迫線上教學,當時程式並還沒debug完,後來回學校後發現裝置被誤丟掉了,也因此沒有搭配過裝置運作。 不過這次的自主學習對我來說還是很好的一次學習經驗,這也是我第一次接觸到網頁的程式設計,我覺得非常有趣而javacript對html的擴˙充性也讓我再次讚嘆程式真的是無極限,甚麼都能做的互相搭配做出來。 ## 參考資料 [發布網站到Heroku - iT 邦幫忙](https://ithelp.ithome.com.tw/articles/10196129) [HttpClient - Arduino Reference](https://www.arduino.cc/reference/en/libraries/httpclient/) [Arduino库教程-Bridge-HTTP Client - 创客智造](https://www.ncnynl.com/archives/201608/539.html) [Python Flask 入門指南: 輕量級網頁框架教學](https://devs.tw/post/448) [W3School-HTML Element Reference](https://www.w3schools.com/tags/default.asp)