บทความนี้กล่าวถึงการคอมไพล์ (build) และใช้งาน MicroPython สำหรับไมโครคอนโทรลเลอร์ esp32-s2 ที่เป็นบอร์ด TTGO ESP32-S2 V1.1 หรือ TTGO ESP32-S2-WOOR V1.1 ซึ่งมีพอร์ต USB แบบ Type-C ที่รองรับการทำงานผ่าน CH340C และแบบ OTG ด้วยการใช้ดิปสวิตช์ดังภาพที่ 1 ทำให้สามารถใช้ MicroPython ได้ เนื่องจากการโปรแกรมชิพใช้การโปรแกรมผ่านทางวงจรของ CH340 และการใช้งานภาษาไพธอนจะต้องอาศัยพอร์ตที่ทำงานแบบ OTG
TTGO ESP32-S2 V1.1
TTGO ESP32-S2 V1.1 มีคุณสมบัติเป็นดังนี้
- ใช้ชิพเซ็ต espressif-esp32-s2
- หน่วยความจำแฟลช ขนาด 4MB
- หน่วยความจำ SRAM ขนาด 320KB
- หน่วยความจำ SPIRAM ขนาด 8MB
- ปุ่ม
- Power Switch
- Reset button
- Boot button
- Customize
- DPI Switch
- ช่องอ่านการ์ด microSD
- โมดูล USB-to-TTL ใช้ชิพ CH340C
- XTal บนบอร์ด 32.768KHz
- แรงดันที่รองรับ 2.7V-3.6V
- ช่วงอุณหภูมิที่ทำงานได้ -40℃ ~ +85℃
- มีวงจรเชื่อมต่อแบตเตอรีภายนอก
- รองรับแหล่งจ่ายไฟจากพอร์ต USB ที่แรงดัน 5V กระแส 1A
- กระแสสำหรับชาร์จแบตเตอรี 500mA
- แบตเตอรีที่ใช้งานได้ต้องเป็นแรงดันในช่วง 3.7-4.2V
- สามารถต่อสายอากาศภายนอกได้
ขั้นตอน
ก่อนจะคอมไพล์ผู้อ่านจะต้องมีชุด ESP-IDF ก่อนซึ่งสามารถอ่านได้จากบทความก่อนหน้านี้ หรือจากตัวอย่างการคอมไพล์สำหรับ ESP32 ผ่านทาง WSL เมื่อมีคอมไพล์เลอร์ติดตั้งในระบบเป็นที่เรียบร้อยก็มาสู่ ขั้นตอนการคอมไพล์ MicroPython เป็นดังนี้
ดาวน์โหลด
ให้ดาวน์โหลดไฟล์ต้นฉบับของ MicroPython จาก github ด้วยคำสั่งต่อไปนี้
git clone --recurse-submodules https://github.com/micropython/micropython.git
ตัวอย่างผลลัพธ์ของการทำงานเป็นดังภาพที่ 2
เมื่อดาวน์โหลดเป็นที่เรียบร้อยให้ใช้คำสั่งย้ายเข้าไปในโฟลเดอร์ของ micropython ดังนี้
cd ~/micropython
คอมไพล์ mpy-cross
ตัวคอมไพล์ภาษาไพธอนของ MicroPython หรือ mpy-cross ให้เป็นไบต์โค้ดที่มีนามสกุลเป็น .mpy ซึ่งมีประโยชน์ในแง่ของการทำให้โค้ดนั้นมีขนาดเล็กลงสะดวกต่อการนำไปใช้เนื่องจากประหยัดพื้นที่ของรอม/แรม และไม่ต้องประมวลผลขณะที่เรียกทำงาน นอกจากนี้ ในการคอมไพล์ MicroPython เองก็ต้องใช้ตัว mpy-cross ด้วยเช่นกัน ดังนั้น สิ่งที่ต้องทำในขัเนตอนที่ 2 คือ คอมไพล์ mpy-cross เพื่อเป็นเครื่องมือสำหรับคอมไพล์ MicroPython ต่ออีกชั้นหนึ่ง โดยเข้าไปที่ mpy-xxx หลังจากนั้นสั่ง make ดังนี้
cd mpy-cross
make clean
make
เมื่อคอมไพล์เสร็จจะพบไฟล์ชื่อ mpy-cross
คอมไพล์ submodules ของ esp32
เมื่อมี mpy-cross แล้ว ขั้นตอนต่อไปคือสร้างไลบรารีที่จะถูกเรียกใช้ด้วย esp32-s2 โดยเข้าไปที่ ports ของ ESP32 ดังนี้
cd ~/micropython/ports/esp32
หลังจากนั้นสั่งคอมไพล์ด้วยคำสั่งดังต่อไปนี้
make clean
make submodules
คอมไพล์ MicroPython
คำสั่งสำหรับคอมไพล์ MicroPython เพื่อใช้กับ ESP32-S2 คือ กำหนดให้บอร์ดที่ใช้งานเป็น ESP32_S2_WROVER ดังนี้
make BOARD=ESP32_S2_WROVER
เมื่อการคอมไพล์เสร็จสิ้นโดยไม่เกิดข้อผิดพลาดเกี่ยวกับ ESP-IDF หรือลืม mpy-cross จะได้โฟลเดอร์ชื่อ xxx
อัพโหลด
เมื่อคอมไพล์เรียบร้อย ขั้นตอนต่อไปคืออัพโหลดเข้าบอร์ด ซึ่งต้องตรวจสอบการตั้งค่าของสวิตช์ให้เป็นดังภาพที่ 3 หลังจากนั้นสั่งงานดังนี้
~/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../esp-idf/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after no_reset --chip esp32s2 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x1000 build-ESP32_S2_WROVER/bootloader/bootloader.bin 0x8000 build-ESP32_S2_WROVER/partition_table/partition-table.bin 0x10000 build-ESP32_S2_WROVER/micropython.bin
โดยให้เปลี่ยน (PORT) เป็นไดเร็กทีรีของพอร์ต เช่น /dev/ttyUSB0 เป็นต้น
การใช้งาน
เมื่ออัพโหลดเฟิร์มแวร์เป็นที่เรียบร้อย ให้เปลี่ยนโหมดเป็น OTG โดยการเลื่อนสวิตช์ให้เป็นดังภาพที่ 4
ทดสอบการทำงาน
หลังจากเปลี่ยนโหมดเป็น OTG ตามภาพที่ 4 ให้จ่ายไฟเข้าบอร์ด หลังจากนั้นเข้าโปรแกรม thonny และเปลี่ยนบอร์ดเป็น ESP32 ด้วยการเข้าเมนู Run และเลือก Select interpreter… ตามภาพที่ ภาพที่ 5 และหลังจากนั้นเลือกใช้บอร์ดเป็น Micropython (ESP32) และพอร์ตสื่อสารดังภาพที่ 6
เมื่อคลิกที่ปุ่ม OK และการตั้งค่าถูกต้องจะเป็นหน้าจอเหมือนกับภาพที่ 6
ตัวอย่างโปรแกรมอ่านข้อมูลของบอร์ด TTGO ESP32-S2 V1.1 และทดลองหาค่าจำนวนเฉพาะเขียนได้ดังนี้
##################################################################################
# coreInfo
# JarutEx (https://www.jarutex.com)
##################################################################################
import gc
import os
import sys
import time as tm
import machine as mc
##################################################################################
# system setting
##################################################################################
gc.enable()
gc.collect()
mc.freq(240000000)
##################################################################################
# show_hw_info()
##################################################################################
def show_hw_info():
uname = os.uname()
mem_total = gc.mem_alloc()+gc.mem_free()
free_percent = "("+str((gc.mem_free())/mem_total*100.0)+"%)"
alloc_percent = "("+str((gc.mem_alloc())/mem_total*100.0)+"%)"
stat = os.statvfs('/flash')
block_size = stat[0]
total_blocks = stat[2]
free_blocks = stat[3]
rom_total = (total_blocks * block_size)/1024
rom_free = (free_blocks * block_size)/1024
rom_usage = (rom_total-rom_free)
rfree_percent = "("+str(rom_free/rom_total*100.0)+"%)"
rusage_percent = "("+str(rom_usage/rom_total*100.0)+"%)"
print("ID ............:",mc.unique_id())
print("Platform ......:",sys.platform)
print("Version .......:",sys.version)
print("Memory")
print(" total ......:",mem_total/1024,"KB")
print(" usage ......:",gc.mem_alloc()/1024,"KB",alloc_percent)
print(" free .......:",gc.mem_free()/1024,"KB",free_percent)
print("ROM")
print(" total ......:", rom_total,"KB" )
print(" usage ......:", rom_usage,"KB",rfree_percent )
print(" Free .......:", rom_free,"KB",rusage_percent )
print("system name ...:",uname.sysname)
print("node name .....:",uname.nodename)
print("release .......:",uname.release)
print("version .......:",uname.version)
print("machine .......:",uname.machine)
print("Frequency .....:",mc.freq())
##################################################################################
# is_prime()
##################################################################################
def is_prime(x):
i = 2
while (i < x):
if x%i == 0:
return False
i = i+1
if (i == x):
return True
return False
##################################################################################
# test_prime_number()
##################################################################################
def test_prime_number(maxN):
counter = 0
t0 = tm.ticks_ms()
for n in range(2, maxN):
if is_prime(n):
counter+=1
t1 = tm.ticks_ms()
print("Found {} in {} msecs.".format(counter,abs(t1-t0)))
##################################################################################
# main program
##################################################################################
try:
show_hw_info()
test_prime_number(2000)
except KeyboardInterrupt:
pass
print("end of program")
ตัวอย่างผลลัพธ์ของการทำงานเป็นดังภาพที่ 8
สรุป
จากบทความนี้จะพบว่าการสร้าง MicroPython เพื่อใช้กับไมโครคอนโทรลเลอร์ ESP32-S2 นั้นมีขั้นตอนเหมือนกับ ESP32 แต่จุดที่แตกต่างคือขั้นตอนของการสลับโหมดทำงานของพอร์ต USB ตามเงื่อนไขดังนี้
- การติดตั้ง MicroPython จะต้องเป็นโหมด USB
- การใช้งาน MicroPython จะต้องเป็นโหมด OTG
ส่วนหลักภาษาเขียนโปรแกรมยังคงเป็นภาษาไพธอนเหมือนกับ ESP32 และ สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ
ท่านใดต้องการพูดคุยสามารถคอมเมนท์ได้เลยครับ
แหล่งอ้างอิง
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-10-17, 2021-12-30