# 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/)