[TH] ลองเล่น Cytron Maker Pi PICO ด้วย CircuitPython

บทความนี้เป็นการแนะนำบอร์ด Maker Pi PICO ของ Cytron (ภาพที่ 1) ที่ติดตั้งไมโครคอนโทรเลอร์ Raspberry Pi PICO พร้อมทั้งบอร์ดขยายการใช้งานที่มีอุปกรณ์พื้นฐานที่จำเป็นต่อการฝึกฝนเขียนโปรแกรมและใช้งานจริง เช่น หลอดแอลอีดี ช่องอ่านการ์ดหน่วยความจำ (micro SD-Card) หรือ ลำโพง เป็นต้น ซึ่งนอกเหนือจากการแนะนำบอร์ดแล้ว บทความนี้กล่าวถึงการติดตั้งและใช้งาน CircuitPython  ซึ่งเป็นไพธอนที่นำ  MicroPython มาปรับปรุงเพื่อใช้งานกับอุปกรณ์ของ Adafruite และของบริษัทอื่น ๆ ส่วนผู้ที่วนใจบทความที่ใช้กับ MicroPython ทางทีมงานขอแนะนำให้ศึกษาจากเว็บของอาจารย์ดร.เรวัต ศิริโภคาภิรมย์ ต่อไปนี้ซึ่งมีรายละเอียดที่ครบครันกว่าพวกเรามาก

  1. MicroPython for RP2040 Pico
  2. RPi Pico RP2040 Code Examples
  3. PIO Programming
  4. PIO Signaling and Measurement
  5. นอกจากนี้มีบทความส่วนของ CircuitPython ด้วยเช่นกันในบทความ CircuitPython for Pico RP2040
ภาพที่ 1 บอร์ด Maker Pi PICO

บอร์ด Maker Pi PICO

บอร์ด Maker Pi PICO ของ Cytron ประกอบไปด้วย 2 ส่วน คือ

  1. ตัวบอร์ดไมโครคอนโทรลเลอร์ Raspberry Pi Pico (ดังภาพที่2)
  2. บอร์ดขยายพอร์ตของบอร์ดไมโครคอนโทรลเลอร์ Raspberry Pi Pico
ภาพที่ 2 ส่วนของบอร์ดไมโครคอนโทรลเลอร์ Raspberry Pi Pico

บนตัวบอร์ขยายมีสวิตช์ RUN ดังภาพที่ 3 สำหรับใช้กดเมื่อต้องการให้เริ่มรันโปรแกรมใหม่ หรือทำการรีเซ็ตระบบใหม่ ซึ่งมีประโยชน์เวลาต้องการอัพโหลดโปรแกรมเข้าบอร์ด โดยปกติต้องถอดสายและเสียบใหม่ แต่ด้วยการมีปุ่มนี้ทำให้สามารถกดปุ่ม BOOT0 บนบอร์ดไมโครคอนโทรลเลอร์ค้างไว้ แล้วกดปุ่ม RUN เพื่อเริ่มทำงานใหม่เข้าโหมดโปรแกรมชิพ

ภาพที่ 3 ปุ่ม RUN

นอกจากสวิตช์ RUN ยังมีสวิตช์สำหรับให้ใช้งานโดยเชื่อมต่อกับ GP20, GP21 และ GP22 ดังภาพที่ 4 โดยแต่ละปุ่มเป็นแบบ Active Low เนื่องจากต่อวงจร Pull-up เอาไว้

ภาพที่ 4 User Switch

ส่วนที่พวกเราชอบมากที่สุดคือ การมีคอนเน็กเตอร์สำหรับ  ESP-01 อยู่บนบอร์ด ดังภาพที่ 5 ซึ่งสื่อสารผ่านทาง UART2 ด้วยขาGP17 และ GP16

ภาพที่ 5 ช่องเสียบโมดูล ESP-01 หรือ ESP-01s

ส่วนถัดมาคือปลอดแอลอีดีแบบ RGB ที่ต่ออยู่กับขา GP28 ดังภาพที่ 6 ทำให้สามารถเขียนโปรแกรมสั่งเปิดหรือปิดหลอดแอลอีดี โดยกำหนดค่าสีของการแสดงผลได้

ภาพที่ 6 RGB LED

ทางด้านล่างของบอร์ดมีลำโพงแบบบัซเซอร์มาให้ พร้อมสวิตช์เปิด/ปิดการทำงานของลำโพงดังภาพที่ 7 โดยต่ออยู่กับ GP18

ภาพที่ 7 ลำโพง

ช่องเสียบหูฟังแบบสเตอริโอดังภาพที่ 8  ที่ต่อเข้ากับขา GP18 และ GP19

ภาพที่ 8 Audio

สุดท้าย คือ มีช่องอ่าน micro SD ติดตั้งมาให้เป็นที่เรียบร้อยดังภาพที่ 9 ซึ่งต่อผ่านบัส SPI ด้วยขา GP10, GP11, GP12, GP13, GP14 และ GP15 ดังรายละเอียดต่อไปนี้

  • GP10 ทำหน้าที่ SCK1 สำหรับส่งสัญญาณนาฬิกาในการสื่อสารระหว่างกัน
  • GP11 ทำหน้าที่  SDO1 หรือ CMD สำหรับส่งข้อมูลออก
  • GP12 ทำหน้าที่ SDI1 หรือ DAT0 สำหรับรับข้อมูลเข้า
  • GP13 ทำหน้าที่ DAT1
  • GP14 ทำหน้าที่ DAT2
  • GP15 ทำหน้าที่ CSn1 หรือ CD/DAT3 สำหรับขา  CS เพื่อใช้เริ่มต้นหรือสิ้นสุดการสื่อสาร
ภาพที่ 9 ช่องอ่านการ์ด micro SD

ติดตั้ง CircuitPython

CircuitPython เป็นไพธอนที่พัฒนาต่อจาก MicroPython ซึ่งสามารถเข้าไปดาวน์โหลดได้จากเว็บ CircuitPython จะแสดงหน้าหลักดังภาพที่  10

จากหน้าหลักให้คลิกที่ตัวเลือก Downloads เพื่อเข้าสู่หน้าดาวน์โหลดโปรแกรมดังภาพที่ 11

ภาพที่ 10 หน้าหลักของ  CircuitPython

จากภาพที่ 11 จะพบว่า ในหน้านี้มีรายการบอร์ดให้เลือกมากมาย หรือถ้าไม่ต้องการเลื่อนเพื่อหาบอร์ดที่ต้องการ ผู้ใช้สามารถพิมพ์ชื่อของบอร์ดที่ใช้งาน และระบบจะทำการค้นหา ถ้าพบหมายความว่าบอร์ดนั้นสามารถใช้  CircuitPython ได้ โดยในที่นี้เลือกบอร์ด  Pico  

ภาพที่ 11 หน้าเว็บดาวน์โหลด

เมื่อคลิกเข้าหน้าของ Pico By Raspberry Pi จะมีรายการรุ่นของ CircuitPython ให้ดาวน์โหลด โดยเวลาที่ผู้เขียนเข้าถึงเป็นรุ่น 7.0.0 ให้คลิกดาวน์โหลดเพื่อดาวน์โหลดไฟล์ .UF2 ดังภาพที่ 11

ภาพที่ 11 หน้าดาวน์โหลดของบอร์ด Pico

เมื่อดาวน์โหลดเก็บไว้ในเครื่องเป็นที่เรียบร้อยให้ทำการรีบูตเข้าโหมดโปรแกรมชิพ ด้วยการกดปุ่ม  BOOTSEL ในภาพที่ 12 แล้วกด Run  หลังจากนั้นปล่อยปุ่ม RUN ตามด้วยปุ่ม BOOTSEL

ภาพที่ 12 ปุ่ม BOOTSEL

เมื่อเข้าโหมดโปรแกรมชิพ ระบบจะแสดงโฟลเดอร์  RPI-RP2 ดังภาพที่ 13 ให้ลากไฟล์ที่ดาวน์โหลดมาไปวางในโฟลเดอร์ดังาภที่  14  เพื่อเป็นการส่งไฟล์ไปให้ไมโครคอนโทรเลอร์เพื่อโปรแกรมตัวเอง

ภาพที่ 12 โฟลเดอร์  RPI-RP2    และไฟล์  CircuitPython ที่ดาวน์โหลดไว้
ภาพที่ 13 ตัวอย่างการลากโปรแกรมไปยังโฟลเดอร์ RPI-RP2

เมื่อลากเสร็จและชิพถูกโปรแกรมเรียบร้อยจะถูกเปลี่ยนเป็นโหมดรันโปรแกรมจะแสดงโฟลเดอร์สำหรับเก็บข้อมูลที่มีพื้นที่ประมาณ 1.0MB ใช้เก็บโปรแกรมหรือข้อมูลดังภาพที่ 14

ภาพที่  14 โฟลเดอร์หลังจากบอร์ดเริ่มทำงาน

ขั้นตอนต่อไปเป็นการใช้ thonny เขียนโปรแกรมเพื่อทดลองหาค่าจำนวนเฉพาะและอ่านข้อมูลเกี่ยวกับบอร์ดมาแสดงผล โดยในโปรแกรม Thonny ให้กำหนดการทำงานเป็น CircuitPython (generic)  และเลือกพอร์ตสื่อสารให้ถูกต้อง ซึ่งปกติพอร์ตสื่อสารของบอร์ดจะชื่อ Pico – CircuitPython.CDC control ดังภาพที่ 15

ภาพที่ 15 หน้าจอกำหนดโหมดทำงานของ Thonny

โค้ดตัวอย่างโปรแกรมเป็นดังนี้ และผลลัพธ์ของการทำงานเป็นดังภาพที่ 16

##################################################################################
# coreInfo
# esp8266/esp32/rp2/stm32f4/stm32f7/micro:bit information
##################################################################################
import gc
import os
import sys
import time

##################################################################################
# system setting
##################################################################################
gc.enable()
gc.collect()

##################################################################################
# function
##################################################################################
def isPrime(x):
    i = 2
    while (i < x):
        if x%i == 0:
            return False
        i = i+1
    if (i == x):
        return True
    return False

def testPrimeNumber(maxN):
    counter = 0
    t0 = time.monotonic_ns()
    for n in range(2, maxN):
        if isPrime(n):
            counter+=1
    t1 = time.monotonic_ns()
    print("Found {} in {} milliseconds.".format(counter,abs(t1-t0)/1000000))


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("Platform ......:",sys.implementation)
    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)

##################################################################################
# main program
##################################################################################
if __name__=='__main__':
    try:
        testPrimeNumber(2000)
        show_hw_info()
    except KeyboardInterrupt:
        pass
    print("end of program")
ภาพที่ 16ตัวอย่างผลลัพธ์การทำงาน

สรุป

จากบทความนี้จะพบว่า ถึงแม้จะเป็นภาษาไพธอนเหมือนกันแต่คลังไลบรารีมีความแตกต่างกัน ดังนั้น ต้องศึกษารายละเอียดการใช้งานเพิ่มเติม แต่อย่างไรก็ดี ถ้าเขียนโปรแกรมด้วยตนเองเป็นหลักจะสามารถนำโค้ดนั้นกลับมาใช้ได้โดยไม่ต้องกังวลเรื่องการขึ้นอยู่กับแพลตฟอร์มการทำงาน เช่นเดียวกับฟังก์ขันการหาค่าจำนวนเฉพาะที่พวกเรานำมาใช้ในตัวอย่างโปรแกรมเป็นต้น ส่วนการใช้งานกับ I/O สามารถอ่านเพิ่มเติมได้จากบทความที่ได้ระบุไว้ข้างต้น และในส่วนของแหล่งอ้างอิง สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ

แหล่งอ้างอิง

  1. CircuitPython for Pico RP2040
  2. CircuitPython documentation v7.0

(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อวันที่ 2021-09-23, 2021-12-13