教材目錄:
一、 WiFiBoy OK:ESP32規格介紹
二、 OK:ESP32 快速使用指引
三、 操作介面和積木簡介
四、 韌體更新、程式上傳和燒錄
五、 OK:ESP32 積木實作
六、 MicroPython實作
七、 WiFiBoy Module 模組指令概述
八、 OK:ESP32線路圖
新竹縣成功國中 康文耀 老師 編輯 參考資料:玩學運算科技股份有限公司 賴溱君 總經理 提供
一、WiFiBoy OK:ESP32規格介紹
「OK:ESP32」是由國內玩學運算科技股份有限公司設計,該公司另有WiFiBoy Arcade 和WiFiBoy FPGA等產品,WiFiBoy Arcade可參考拙作「深入淺出用MakeCode Arcade 玩程式設計第一次就上手」 http://gg.gg/13c7vo
規格說明:
二、 OK:ESP32 快速使用指引(玩學運算科技股份有限公司提供)
1. 請先在您的電腦上安裝 CP210x
Win10:https://www.silabs.com/documents/public/software/CP210x_Universal_Windows_Driver.zip
macOS: https://www.silabs.com/documents/public/software/Mac_OSX_VCP_Driver.zip
2. 下載 WiFiBoy Python Playground 開發環境
Win64:https://wifiboy.org/ptp105t-x64.zip
macOS:https://wifiboy.club/assets/uploads/files/ptp-102t-macos.zip
Win64執⾏ 「PythonPlayground-ptp102t-x64 / ptp.exe」程式
3. 以 MicroUSB 線連接您的 OK:ESP32 到電腦的 USB
會看到藍色的充電燈亮起。(充滿電後就會自動熄滅)
在 WiFiBoy Python Playground 的右上角選擇 USB。
4. 下載 OK:ESP32 MicroPython 範例集
https://wifiboy.org/okesp32-examples.zip
切換左側 編輯器選擇按鈕,
以「 CODE 」文字模式載入範例程式。
按「RUN」將程式送到開發板執行。(程式在迴圈中 Ctrl-C 可中斷程式,恢復USB連線)
右側為 REPL Terminal 互動指令介面,可以直接輸入 MicroPython 指令。
請在游標變成「白色實心方塊」時輸入指令。
5. MicroPython WiFiBoy Module 說明書
https://wifiboy.club/assets/uploads/files/ok-esp32-python-module-reference-v1.01t.pdf
6. 如果想要使用 Arduiono IDE ,請安裝 Arduino IDE 與 ESP32 Extension Kit
https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md
7. 相關參考文件
更新 MicroPython 韌體:
https://wifiboy.org/okesp-mp119-4m.zip (參考第四單元)
OK:ESP32 腳位與規格說明書 :
https://wifiboy.club/assets/uploads/files/okesp-specification.pdf
8. 112青少年組全國賽題目含材料表評分表試題及說明.pdf
三、操作介面和積木簡介
Win64執⾏ 「PythonPlayground-ptp105t-x64 / ptp.exe」程式
使用上面WifiBoy 網頁韌體更新,可更新 V2-2.04 或 V3-1.18版本(競賽建議版本),如果無法更新成功,則需使用以下樂鑫原廠更新方式:
下載OK:ESP32韌體 https://wifiboy.org/files/okesp-mp118.zip
開啟 https://www.espressif.com/en/support/download/other-tools 網址,勾選並下載 「Flash Download Tools」韌體更新程式。
解壓縮後執行「flash_download_tool_3.9.4.exe」
1. 選擇「ESP32」按下「OK」(圖一)
2. 選擇COM Port,按下「ERASE」(圖二),清除韌體
3. 下載解壓縮韌體檔案後,選擇 okesp-mp119-4m.bin
4. BAUD請改選:921600(圖二)
5. 選擇韌體檔案路徑及位址(圖三)
6. 勾選檔案路徑確認選擇,並按下「開始」
4-2 USB連線
OK:ESP32連接USB後開機
4-3 上傳程式(暫存於OK:ESP32)
請先完成以下程式
完成後點選 上方「RUN」圖示,上傳程式碼,如需重新上傳,需先點「RESET」。
4-4 燒錄程式(存檔於OK:ESP32)
燒錄程式檔名如為「main.py」則按下RESET或是開機後,會自動執行,如需再次連線操作,必須先按「Ctrl+C」中斷程式執行,才可使用視窗右下「開發板檔案管理」 圖示,刪除「main.py」檔案。
五、 OK:ESP32 積木實作
範例一: 開機後螢幕顯示「Hello world」(黃色文字,大小2),按下「A」鍵更換螢幕背景顏色(黑色←→白色)
範例二: 續上題,按下「B」鍵蜂鳴器發出 440Hz 之聲音,工作週期為 50%,放開按鍵時 停止發出聲音。
範例三: 於 LCM (20,20)位置顯示 X=n,n 開機預設數值為「0」,黑底白字,字體 「5」,大小 「1」,當按下「U」鍵時n + 1,當按下「D」鍵時n - 1。
範例四: 請依RGB LED接路圖,當按下「L」鍵時點亮紅色LED,當按下「U」鍵時點亮綠色LED,當按下「R」鍵時點亮藍色LED,當按下「D」鍵時,RGB LED全部熄滅。
範例五: 續上題,當按下「A」鍵時RGB LED 依序變換顏色,順序如下:黑-紅-綠-藍-黃-紫-白-黑……循環。
範例六: 請依七段顯示器接路圖,當按下「A」鍵,七段顯示器全部熄滅,當按下「B」鍵,七段顯示器全部點亮。
範例七: 續上題,按下「U」鍵時七段顯示器值+ 1,按下「D」鍵時七段顯示器值+ 1,顯示範圍0~9。
範例八: 續上題,開機後七段顯示器自動倒數,使其可以每隔 0.5 秒變換 9-8-7-6-5-4-3-2-1-0,最後停在 0,並同步將數字顯示於螢幕上。
範例九:偵測IO2腳位數位信號,並將HI-LOW訊號繪製於螢幕上
六、 MicroPython實作
Python 是一個簡潔易讀的語言,學習者幾乎可以立刻上手,也適用於大量的商業應用上,Python 是個直譯式語言,不需要編譯與連結。
MicroPython是執行在微控制器硬體之上的系統程式,MicroPython 除了留有 Python 的許多迷你化的標準函式庫,也有例如 machine、network 等硬體相關的專屬函式庫控制硬體相關功能。
MicroPython 主要偵測兩個檔案。一是 boot.py,開機時執行,可以在此執行一些系統設定;二是 main.py,跑完 boot.py 就來執行它,所以通常裡面是無限迴圈。
REPL 全名為「 Read-Eval-Print Loop 」讀取-求值-輸出循環,是一種簡單的交互式的編輯環境;藉由用戶輸入事件、表達式或是運算式,再由電腦進行處理運算,接著輸出給用戶,如此循環下去,啟動直譯器(連線)後將出現提示符 「>>>」。
Python陳述式的段落以縮排為區隔而非括號;不需要宣告變數和引數,寫在「#」後面的文字,都會變成註解。
#主程式前面不能有空格
while True: #冒號後面為程式區段,同一區段的程式碼縮排需相同
Pin(16, Pin.OUT).value(1)
sleep(1)
Pin(16, Pin.OUT).value(0)
sleep(1)
使用Thonny Python IDE編寫MicroPython程式
Thonny設定與wifiBoy OK:ESP32連接
注意:以下兩個程式僅能有一個程式與設備連線
燒錄練習
使用WiFiBoy Python Playground編輯積木程式後,轉成MicroPython並複製至Thonny,然後燒錄至OK:ESP32
MicroPython程式
import machine
pin = machine.Pin(17,3).value(1)
while True:
if(wb.getkey()==1):
wb.cls((0x00f8))
try:
if snd:
snd.deinit()
except:
pass
snd=machine.PWM(machine.Pin(25, 3))
snd.freq(440)
if(wb.getkey()==2):
wb.cls((0x6036))
snd.duty(0)
範例1: 讓OK:ESP32背面LED閃爍,直到按下按鍵
import time #載入時間函式
from machine import * #載入所有設備函式
led = Pin(16,3) #指定第16隻腳為數位輸出
while wb.getkey()==0: #循環直到按下按鍵
led.value(1-led.value()) #0、1切換
time.sleep(0.5) #延遲0.5秒
範例2: 將按鍵編碼顯示於螢幕上
#按鍵編碼: A=1 B=2 R=4 L=8 D=16 U=32 Menu-64
wb.colors(wb.YELLOW, wb.BLACK)
wb.cls();
while True:
key=wb.getkey()
wb.str("%03d"%(key),10,10,2,2)
範例3: 按A數字加1、按B數字減1,並將數字顯示於螢幕上
n=0
wb.colors(wb.YELLOW, wb.BLACK)
wb.cls();
while True:
key=wb.getkey()
if key==1: # A Key to decrease intensity
n++;
elif key==2: # B Key to increase intensity
n--;
wb.str("%03d"%(n),10,10,2,2)
time.sleep(0.1)
範例4: 隨機畫線或方塊
wb.cls() #清除螢幕
while True:
k=wb.getkey() #讀取按鍵值
if k==1:
color = wb.rand(65536)
x0=wb.rand(128)
y0=wb.rand(128)
x1=wb.rand(128)
y1=wb.rand(128)
wb.line(x0,y0,x1,y1,color,1)
else:
wb.box(wb.rand(128),wb.rand(128),16,16,wb.rand(65536))
範例5:伺服馬達(pin25)
https://jimirobot.tw/esp32-micropython-tutorial-pwm-control-202/
from machine import Pin,PWM
import time
sg_pin=PWM(Pin(25),freq=50,duty=0) #duty range 0-1023
d_0=(int)(1023*0.025) #0.5ms # [(2.4ms-0.5ms)/180]*伺服角度+0.5ms = 0.025
d_30=(int)(1023*0.04) #0.81ms
d_60=(int)(1023*0.056) #1.13ms
d_90=(int)(1023*0.0725) #1.45ms
d_120=(int)(1023*0.088) #1.77ms
d_150=(int)(1023*0.104) #2.08ms
d_180=(int)(1023*0.12) #2.4ms
de_map=[d_0, d_30, d_60,d_90, d_120, d_150,d_180]
wb.cls(0)
wb.str(str('PWM Control'),20,20,1,1)
# sg_pin.duty(de_map[x]) #指定伺服馬達角度x=0~6
while 1: #依序旋轉伺服馬達(0-30-60-90-120-150-180)
for i in de_map:
sg_pin.duty(i)
time.sleep(1)
範例6: 偵測並計算IO2脈波寬度及頻率
import utime
from machine import *
pinIn = Pin(2,1) #訊號輸入腳位IO2
HL=0; oldHL=0
now_time=0; old_time=0;
show_time=utime.ticks_us()
time_H=0; time_L=0
count=0
wb.cls(); wb.colors(wb.YELLOW,0)
while True:
HL=pinIn.value()
if HL!=oldHL: #當H->L 或是 L->H時,計算時間
if HL==1:
time_L=utime.ticks_us()-old_time #現在時間-剛才變化時的時間
else:
time_H=utime.ticks_us()-old_time
old_time=utime.ticks_us()
oldHL=HL #記錄時間
if utime.ticks_diff(utime.ticks_us(),show_time)>=2000000:
show_time=utime.ticks_us()
wb.cls()
wb.str("tH= %f ms"%(time_H/1000),16,5,2,1) #顯示Hi時間
wb.str("tL= %f ms"%(time_L/1000),16,20,2,1) #顯示Low時間
try:T=1/(time_H+time_L)*1000000 #換算頻率,使用try避免除以0的錯誤
except:T=0
wb.str("f = %f Hz"%(T),16,40,2,1)
count=1-count;
if count==0: #顯示兩次清除一次
time_H=time_L=0
count=0
競賽檔案: 111青少年技能競賽提供之燒錄檔案(偵測IO2頻率1-10Hz、IO26電壓值)
import machine
import utime
# 設定IO2腳位為輸入腳
input_pin = machine.Pin(2, machine.Pin.IN)
# 設定IO26腳位為類比輸入腳
adc_pin = machine.ADC(machine.Pin(26))
# 設定ADC為3.3V範圍
adc_pin.atten(machine.ADC.ATTN_11DB)
# 設定ADC為12BIT精度
adc_pin.width(machine.ADC.WIDTH_12BIT)
# 初始化各種變數初始值
last_time = utime.ticks_us()
current_time = 0
# 訊號週期計數變數
high_time = 0
# 顯示或是ADC轉換切換變數
count_show = 0
# IO2正負緣偵測變數
input_value = 0
last_input_value = 0
# 計算ADC的最大值和參考電壓設定
last_time_adc = utime.ticks_us()
max_adc = 2 ** 12 - 1 # 12位元的ADC最大值
ref_voltage = 3.3 # 參考電壓3.3V
# 計算頻率用變數
frequency = 0
# 清除螢幕
wb.cls()
while True:
# 讀取輸入IO2狀態
last_input_value = input_value
input_value = input_pin.value()
# 如果檢測到IO2從高電位變為低電立時,開始記錄時間,並將count_show設為1
current_time = utime.ticks_us()
if input_value == 0 and last_input_value == 1 and count_show == 0:
last_time = utime.ticks_us()
count_show = 1
else:
# 如果檢測到IO2從高電位變為低電立時,並count_show為1時,計算週期長度,並計算頻率
if input_value == 0 and last_input_value == 1 and count_show == 1:
high_time = utime.ticks_diff(current_time, last_time)
count_show = 0
frequency = 1/(float(high_time)/1000000.0)
# 每一秒讀取ADC並顯示電壓值,如一直沒有IO2輸入則每二秒讀取一次
if (utime.ticks_diff(current_time, last_time_adc) > 1000000 and count_show == 1) or utime.ticks_diff(current_time, last_time_adc) > 2000000:
# 讀取ADC並轉換為電壓
last_time_adc = utime.ticks_us()
adc_value = adc_pin.read_uv()
voltage = adc_value/1000000.0
# 顯示頻率和電壓值
wb.cls()
wb.str('Frequency: %.2f Hz' % frequency, 8, 0, 3, 1)
wb.str('Voltage: %.2f V' % voltage, 8, 16, 3, 1)
簡化版本 (偵測IO2頻率1-10Hz)
import machine
import utime
# 設定IO2腳位為輸入腳
input_pin = machine.Pin(2, machine.Pin.IN)
# 初始化各種變數初始值
last_time = utime.ticks_us()
last_time_dip = utime.ticks_us()
current_time = 0
high_time = 0 # 訊號週期計數變數
count_show = 0 # 顯示變數
# IO2正負緣偵測變數
input_value = 0
last_input_value = 0
frequency = 0 # 計算頻率用變數
wb.cls() # 清除螢幕
while True:
# 讀取輸入IO2狀態
last_input_value = input_value
input_value = input_pin.value()
# 如果檢測到IO2從高電位變為低電位時,開始記錄時間,並將count_show設為1
current_time = utime.ticks_us()
if input_value == 0 and last_input_value == 1 and count_show == 0:
last_time = utime.ticks_us()
count_show = 1
else:
# 如果檢測到IO2從高電位變為低電位時,並count_show為1時,計算週期長度,並計算頻率
if input_value == 0 and last_input_value == 1 and count_show == 1:
high_time = utime.ticks_diff(current_time, last_time)
count_show = 0
frequency = 1/(float(high_time)/1000000.0)
#每二秒顯示一次頻率
if utime.ticks_diff(current_time, last_time_dip) > 2000000:
last_time_dip = utime.ticks_us()
# 顯示頻率和電壓值
wb.cls()
wb.str('Frequency: %.2f Hz' % frequency, 8, 0, 3, 1)
OK:ESP32 MicroPython 範例集
https://wifiboy.club/assets/uploads/files/ok-esp32-python-example-pack-v1.1.zip
檔 案 名 稱 範 例 功 能
ok-esp32-1a2b-ai-game-example.py A2B遊戲範例
ok-esp32-bounce-ball-example.py 方塊左右移動範例
ok-esp32-deepsleep-test-example.py 切換省電模式範例
ok-esp32-eat-apple-game-example.py 吃蘋果遊戲範例
ok-esp32-galaxian-45line-game-example 小蜜蜂街機遊戲(無聲) 範例
ok-esp32-galaxian-snd-game-example.py 小蜜蜂街機遊戲(有聲) 範例
ok-esp32-lcd-backlight-pwm-example.py 調整LCD背光亮度範例
ok-esp32-led-gpio-example.py 內建LED閃爍範例
ok-esp32-maze-gen-example.py 迷宮產生範例
ok-esp32-ntp-time-example.py NTP網路時間
ok-esp32-pacman-clone-example.py 小精靈遊戲範例1
ok-esp32-pacman-clone-example2.py 小精靈遊戲範例2
ok-esp32-pwm-sound-example.py 產生聲音範例
ok-esp32-simon-game-example.py 西蒙記憶遊戲範例
ok-esp32-simon-game2-example.py 西蒙記憶遊戲2範例
ok-esp32-supermario2-theme-melody-example.py 超級馬里歐旋律範例
ok-esp32-tetris-game.py 俄羅斯方塊遊戲範例
ok-esp32-tone-engine-example.py 小蜜蜂旋律範例
ok-esp32-ultrasonic-piano-example.py 超音波感測器範例
ok-esp32-wifi-web-server-io-status-example.py 網頁伺服器顯示IO狀態範例
七、WiFiBoy Module 模組指令概述
八、OK:ESP32線路圖