# IEYI 上課筆記 ## 8/23 ### 課程內容大綱 * 介紹復健小幫手新架構。 ![](https://i.imgur.com/JYpKMWv.png) * 介紹並安裝 Python 3.9.6 程式語言執行環境。 * 介紹如何使用 Python IDLE,測試執行單行程式碼。 * 介紹如何使用 Ipython,測試執行單行程式碼。 * 可於 PowerShell 中,輸入以下命令,下載 Ipython 工具。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > pip install ipython ``` * 可於 PowerShell 中,輸入以下命令,開啟 Ipython 工具。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > ipython ``` * 可於已開啟的 Ipython 工具中,輸入以下命令,關閉 Ipython 工具。 ```python # 開頭的 In [n]: 不包含在命令中,僅用來表達下方命令的執行環境在 Ipython 中。 In [n]: quit() ``` * 介紹如何使用 Visual Studio Code 編輯器,撰寫多行程式碼。 * 介紹如何使用 PowerShell 命令列工具,執行 Python 程式碼檔案。 * 利用 Python 執行程式檔案前,可以先利用下方命令,查看該檔案是否在目前的目錄中 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > ls ``` ![](https://i.imgur.com/0jlV7eI.png) * 可利用下方命令,讓電腦利用 Python 執行程式檔,其中「[檔案名稱]」區塊,可以自由替換為欲執行之檔案名稱。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > python [檔案名稱].py ``` ![](https://i.imgur.com/1Qm2oeL.png) * 比較不同程式碼編輯工具的優劣差異。 * Python 程式設計: * 認識常用資料型態「String, ```str()```」。 ```python= # 在 Python 中,利用一組雙引號或是單引號包含的文字, # 即被稱為「字串」(即「把一堆文字串接起來表示」)。 print("哈囉大家好~") ``` * 認識常用輸出語法 ```print()```。 ```python= # 在 Python 中,可使用 print() 輸出欲印出的資料。 print("今天天氣真好。") ``` * 打字訓練說明 :::warning 打字速度與程式能力無絕對相關,訓練打字能力只為降低,因打字速度慢或正確率低,導致完成題目或專案進度較慢,進而帶來的挫折感或低成就感。 ::: <iframe width="560" height="315" src="https://www.youtube.com/embed/ZQ_iCBlmGvA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ### 課堂重點紀錄影片 <iframe width="560" height="315" src="https://www.youtube.com/embed/cAuBJowFRWM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ### 回家作業 * 利用 [ztype](https://zty.pe/) 多多練習英文打字。 ## 8/24 ### 課程內容大綱 * 複習 8/23 課程內容(Python 程式撰寫與執行)。 * Python 程式設計: * 認識如何建立變數,並介紹變數的使用時機。 ```python= # 建立一個變數,名稱叫做「num」,被指派了一個資料內容「20」。 num = 20 # 建立一個變數,名稱叫做「name」,被指派了一個資料內容「"lulu"」。 name = "lulu" ``` * 認識字串串接。 ```python= name = "lulu" age = "20" # 字串與字串之間,使用「+」運算子可進行字串串接。 print("我叫" + name + ",我今年" + age + "歲。") ``` * 認識資料型態對於運算上的影響。 ```python= name = "lulu" age = 20 # Error: 不能在字串與數字型態之間,使用「+」運算子進行字串串接。 print("我叫" + name + ",我今年" + age + "歲。") ``` * 認識如何建立格式化字串。 ```python= yyyy = 2021 mm = 8 dd = 24 # 建立一個變數,名稱叫做「fmt」,被指派了一個「格式化字串」的資料內容。 fmt = "{}-{}-{}".format(yyyy, mm, dd) print(fmt) ``` * 認識如何使用流程控制—條件判斷語法 ```if```,以及簡單邏輯運算,並了解「縮排」觀念。 ```python= yyyy = 2021 mm = 8 dd = 24 # 運用縮排表達,某條件成立後,才可執行某段程式碼 if mm > 9 and dd > 9: # 若 mm 為十位數數字,dd 也為十位數數字, # 則變數「fmt」,被指派下方資料內容,無須在數字前補上 0。 fmt = "{}-{}-{}".format(yyyy, mm, dd) if mm > 9 and dd < 10: # 若 mm 為十位數數字,而 dd 為個位數數字, # 則變數「fmt」,被指派下方資料內容,須在數字前補上 0。 fmt = "{}-{}-0{}".format(yyyy, mm, dd) if mm < 10 and dd > 9: # 若 mm 為個位數數字,而 dd 為十位數數字, # 則變數「fmt」,被指派下方資料內容,須在數字前補上 0。 fmt = "{}-0{}-{}".format(yyyy, mm, dd) if mm < 10 and dd < 10: # 若 mm 為個位數數字,dd 也為個位數數字, # 則變數「fmt」,被指派下方資料內容,須在數字前補上 0。 fmt = "{}-0{}-0{}".format(yyyy, mm, dd) print(fmt) ``` * 認識常用輸入語法 ```input()```,以及如何設定提示訊息。 ```python= # 透過 input() 語法,讀取使用者的輸入內容, # 並利用在 () 填入文字,顯示提示文字。 # 但需要注意,input() 讀取完畢使用者的輸入資料後, # 會使用「字串」資料型態來表示該筆資料。 yyyy = input("請輸入年份:") mm = input("請輸入月份:") dd = input("請輸入日期:") if mm > 9 and dd > 9: fmt = "{}-{}-{}".format(yyyy, mm, dd) if mm > 9 and dd < 10: fmt = "{}-{}-0{}".format(yyyy, mm, dd) if mm < 10 and dd > 9: fmt = "{}-0{}-{}".format(yyyy, mm, dd) if mm < 10 and dd < 10: fmt = "{}-0{}-0{}".format(yyyy, mm, dd) print(fmt) ``` * 認識強制轉型觀念。 ```python= # 即「請電腦把讀取到的使用者輸入內容,當作整數(integer)來使用」。 yyyy = int(input("請輸入年份:")) mm = int(input("請輸入月份:")) dd = int(input("請輸入日期:")) if mm > 9 and dd > 9: fmt = "{}-{}-{}".format(yyyy, mm, dd) if mm > 9 and dd < 10: fmt = "{}-{}-0{}".format(yyyy, mm, dd) if mm < 10 and dd > 9: fmt = "{}-0{}-{}".format(yyyy, mm, dd) if mm < 10 and dd < 10: fmt = "{}-0{}-0{}".format(yyyy, mm, dd) print(fmt) ``` * 認識如何使用流程控制—迴圈語法 ```while```,以及簡單邏輯運算。 ```python= yyyy = input("請輸入年份:") mm = input("請輸入月份:") dd = input("請輸入日期:") # 若 yyyy 不為(!=)甚麼都沒有(None),即 yyyy 目前有被指派資料, # 且 mm 不為(!=)甚麼都沒有(None),即 mm 目前有被指派資料, # 且 dd 不為(!=)甚麼都沒有(None),即 dd 目前有被指派資料, # 即執行縮排內的程式碼內容。 while yyyy != None and mm != None and dd != None: if mm > 9 and dd > 9: fmt = "{}-{}-{}".format(yyyy, mm, dd) if mm > 9 and dd < 10: fmt = "{}-{}-0{}".format(yyyy, mm, dd) if mm < 10 and dd > 9: fmt = "{}-0{}-{}".format(yyyy, mm, dd) if mm < 10 and dd < 10: fmt = "{}-0{}-0{}".format(yyyy, mm, dd) print(fmt) yyyy = input("請輸入年份:") mm = input("請輸入月份:") dd = input("請輸入日期:") ``` ### 課堂重點紀錄影片 <iframe width="560" height="315" src="https://www.youtube.com/embed/3TZPOiXFq0E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ### 回家作業 * 利用 [ztype](https://zty.pe/) 多多練習英文打字。 * 嘗試利用 8/23、8/24 所學內容,或上網搜尋相關資料,並想想如何做出一個簡單的聊天程式(命名為「chatbot.py」)。 * 功能要求 * 程式一開始執行後,需要讀取使用者姓名。 * 程式讀取完使用者姓名後,就要不斷接收使用者的輸入文字。 * 程式要根據文字內容,回應使用者合適內容(可以自行設計)。 * 當使用者輸入「```結束```」後,程式就結束執行。 * 提示 * 查查看 ```in``` 語法,在 Python 中如何被使用。 * 查查看 ```if...elif...else``` 語法,在 Python 中如何被使用。 ## 8/30 ### 課程內容大綱 * 複習 8/23、8/24 課程內容。 * 說明 8/24 作業。 * Python 程式設計: * 認識如何匯入模組(```from...import...```)。 * 認識如何進行例外處理(```try...except...```)。 * 認識如何自訂函式(```def...```)。 ### 課堂重點紀錄影片 <iframe width="560" height="315" src="https://www.youtube.com/embed/chO-G6qVy6g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/iNGCq-ZCxr4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ## 8/31 * D1 mini 腳位圖 ![](https://i.imgur.com/CEHrpn1.png) * [下載 esp8266 韌體](https://micropython.org/download/esp8266/) ![](https://i.imgur.com/tSm2KJb.png) * 下載 esp8266 命令列燒錄工具。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > pip install esptool ``` * 執行**清除快閃記憶體**(相當於重新格式化電腦硬碟)。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > esptool.py --port [序列埠名稱] erase_flash ``` ```bash # 範例 > esptool.py --port COM6 erase_flash ``` * 將**燒錄 MicroPython 韌體**至 esp8266 控制板中。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > esptool.py --port [序列埠名稱] --baud [通訊速率] write_flash --flash_size=detect 0 [韌體檔案名稱].bin ``` ```bash # 範例 > esptool.py --port COM6 --baud 460800 write_flash --flash_size=detect 0 D:\Downloads\esp8266-20210618-v1.16.bin ``` * 執行「**暖開機**」(Soft Reset) ```bash # 此處環境為,已經已 Putty 進入 Di mini 控制板的控制畫面 【Ctrl + D】 ``` * [下載 Putty 終端機連線工具](https://www.putty.org/) * 下載 esp8266 命令列程式碼上傳工具(ampy)。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 > pip install adafruit-ampy ``` * 切換至程式碼檔案所在資料夾。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > cd [目的地資料夾路徑] ``` ```bash # 範例 > cd C:\Users\gandolfreddy\Desktop\IEYI_2022 ``` * 透過 ampy 工具於控制板**立即執行(run)程式碼**。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > ampy --port [序列埠名稱] run [--no-output] [程式碼檔案名稱].py ``` ```bash # 範例 - 執行 blink.py 後,命令列會被「凍結」 > ampy --port COM5 run blink.py ``` ```bash # 範例 - 執行 blink.py 後,命令列不會被「凍結」 > ampy --port COM5 run --no-output blink.py ``` * 透過 ampy 工具**上傳(put)程式碼**至控制板。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > ampy --port [序列埠名稱] put [程式碼檔案名稱].py ``` ```bash # 範例 > ampy --port COM5 put blink.py ``` * 透過 ampy 工具**列舉(list)在控制板中的所有程式碼**。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > ampy --port [序列埠名稱] ls ``` ```bash # 範例 > ampy --port COM5 ls ``` * 透過 ampy 工具**得到(get)在控制板中的特定程式碼**。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > ampy --port [序列埠名稱] get blink.py ``` ```bash # 範例 > ampy --port COM5 get blink.py ``` * 透過 ampy 工具**刪除(remove)在控制板中的特定程式碼**。 ```bash # 開頭的 > 不包含在命令中,僅用來表達下方命令的執行環境在 PowerShell 中。 # 格式 > ampy --port [序列埠名稱] rm [程式碼檔案名稱].py ``` ```bash # 範例 > ampy --port COM5 rm blink.py ``` ### Client * boot$.$py ```python= import esp import gc esp.osdebug(None) gc.collect() ``` * main$.$py ```python= # 匯入需要的工具(模組)- Done import gc from machine import Pin import socket from time import sleep # 設定 WiFi 連線(Client --- Server) def connect_wifi_AP(ssid, pwd): import network wlan = network.WLAN(network.STA_IF) wlan.active(False) if not wlan.isconnected(): print("Connect") wlan.active(True) wlan.connect(ssid, pwd) while not wlan.isconnected(): pass print("AP is connected: ", wlan.isconnected()) print("network config: ", wlan.ifconfig()) # 偵測按鈕(Client 開始動作) def socket_client_start(): print("--- Prepare connecting ---") led = Pin(2, Pin.OUT, value=1) # 提示燈號 def prepare_led(): for i in range(8): sleep(0.3) led.value(1) led.value(1) prepare_led() sw = Pin(0, Pin.IN, Pin.PULL_UP) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.connect(("192.168.4.1", 13326)) led.value(0) while True: print("Press Button") while sw.value(): pass if not sw.value(): msg = "toggle" while not sw.value(): pass s.send(msg.encode("utf-8")) reply = s.recv(128) print(str(reply)) gc.collect() except OSError as e: print(e) finally: gc.collect() print("Free RAM: ", gc.mem_free()) s.close() led.value(1) # 編排流程 def start(): connect_wifi_AP("MicroPython-e2ba73", "micropythoN") sw = Pin(0, Pin.IN, Pin.PULL_UP) while sw.value(): pass gc.collect() print("Free RAM: ", gc.mem_free()) socket_client_start() # 正式開始 start() ``` ### Server * boot$.$py ```python= import esp import gc esp.osdebug(None) gc.collect() ``` * main$.$py ```python= # 匯入需要的工具(模組) import gc from machine import Pin import socket from time import sleep # 設定 WiFi(Access Point, AP) def set_wifi_AP(): import network wlan = network.WLAN(network.AP_IF) wlan.active(False) wlan.active(True) print("AP is connected: ", wlan.isconnected()) print("network config", wlan.ifconfig()) # 提示燈號 led = Pin(2, Pin.OUT, value=1) def init_light(): for i in range(10): sleep(0.2) led.value(not led.value()) led.value(1) # Server 運作 def socket_server_start(): signal = Pin(0, Pin.OUT, value=1) HOST = "0.0.0.0" PORT = 13326 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(1) init_light() client, addr = None, None client, addr = s.accept() init_light() while True: msg = client.recv(128).decode("utf-8") reply = "" if msg == "toggle": print("Client's msg received") led.value(0) signal.value(0) reply = b"Led {}".format(led.value()) sleep(1) led.value(1) signal.value(1) client.send(reply) gc.collect() gc.mem_free() except: s.close() if client: client.close() finally: s.close() if client: client.close() gc.collect() gc.mem_free() led.value(1) # 編排流程 def start(): set_wifi_AP() gc.collect() print("Free RAM: ", gc.mem_free()) socket_server_start() # 正式開始 start() ``` ### 新版 Microbit 程式積木 * [點我下載檔案](https://drive.google.com/file/d/1ctQpmL-E9OsBSO7g97JJO2KaCFog6RCX/view?usp=sharing) ![](https://i.imgur.com/79fwhlX.png) ![](https://i.imgur.com/YccKryM.png) ### 實驗影片 <iframe width="560" height="315" src="https://www.youtube.com/embed/gH7xsCFR5F4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> * 伺服器端線路連接圖 ![](https://hackmd.io/_uploads/BJQiuKb6K.png) * 客戶端線路連接圖 ![](https://i.imgur.com/ipg899o.png) ### 課堂重點紀錄影片 <iframe width="560" height="315" src="https://www.youtube.com/embed/72BucdV48Pk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/HTadi6rECIs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ## 作品架構、程式碼解說 <iframe width="560" height="315" src="https://www.youtube.com/embed/RBax3aC4BGg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/4MBvLdY1-wY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/NOL1YBRqa2g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/Sh85iW4_3mA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/UiNOftMT8yc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/lmXn1h-QGaI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/HPHC5Fcak6U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/kVqh8ascs8I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/dwIyxmRILE8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/odBk7y2Vvpw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/D9_REUtfWfE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/BrkDnOYUiaI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ## 參考文件 1. [IEYI 改良版實驗文件](https://hackmd.io/@Gandolfreddy/IEYI_improve) 2. [Line + NodeMCU 實驗](https://hackmd.io/@Gandolfreddy/LineBot_nodemcu) 3. [IEYI手部復健小幫手_相關資訊](https://hackmd.io/IUsZTwSGS4uRWazC4CAL8w) ## 補充工具 * [ztype](https://zty.pe/)