← กลับหน้าบทความ

MicroPython คืออะไร

MicroPython คืออะไร แล้ว Python ไปรันอยู่บนไมโครคอนโทรลเลอร์ได้ยังไง?

ถ้าพูดถึง Python หลายคนน่าจะนึกถึงการเขียนโปรแกรมบนคอมพิวเตอร์ เปิดไฟล์ .py ขึ้นมาแล้วสั่งรัน หรือไม่ก็ใช้ Python ทำงานพวก Web, Automation, Data หรือ AI ซึ่งทั้งหมดนี้เรากำลังรัน Python อยู่บนเครื่องที่มีระบบปฏิบัติการ มี RAM หลาย GB มีพื้นที่เก็บข้อมูลเหลือเฟือ และมี CPU ที่แรงเกินพอสำหรับงานทั่วไป

แต่ถ้าเราเอาทุกอย่างนั้นออกไปล่ะ?

ไม่มี Windows ไม่มี Linux ไม่มี SSD ไม่มี RAM หลาย GB เหลือเพียงไมโครคอนโทรลเลอร์ตัวเล็ก ๆ อย่าง ESP32 ที่มีหน่วยความจำอยู่เพียงนิดเดียวเมื่อเทียบกับคอมพิวเตอร์ แต่เรากลับสามารถเสียบสาย USB เปิดโปรแกรมขึ้นมา แล้วพิมพ์โค้ด Python ลงไปได้

print("Hello World")

แล้วมันก็ทำงาน

คำถามคือ Python เข้าไปอยู่ในไมโครคอนโทรลเลอร์ได้ยังไง?

เพราะถ้าเราย้อนกลับไปดู Arduino ที่พูดถึงกันก่อนหน้านี้ เวลาเราเขียน C/C++ แล้วกด Upload สิ่งที่เกิดขึ้นไม่ได้หมายความว่า ATmega328P หรือ ESP32 สามารถอ่านภาษา C++ ได้ ตัว Compiler จะเป็นคนแปลงโปรแกรมของเราให้กลายเป็น Machine Code ก่อน จากนั้นจึงนำโปรแกรมที่ได้ไปใส่ลงใน Flash ของไมโครคอนโทรลเลอร์ เมื่อเปิดเครื่อง CPU จึงสามารถนำคำสั่งเหล่านั้นไปทำงานได้

แต่ MicroPython มีวิธีคิดที่ต่างออกไปเล็กน้อย

MicroPython ไม่ใช่ Python ที่ถูกย่อไฟล์ให้เล็กลง

ชื่อ MicroPython อาจทำให้เข้าใจได้ง่าย ๆ ว่า มันคงเป็น Python ตัวเดิมที่ถูกตัดบางอย่างออกจนมีขนาดเล็กพอจะใส่ลงในไมโครคอนโทรลเลอร์

ความจริงไม่ใช่แบบนั้นเสียทีเดียว

MicroPython เป็น implementation ของภาษา Python ที่ถูกสร้างขึ้นใหม่โดยมีเป้าหมายตั้งแต่ต้นว่าจะต้องสามารถทำงานบนไมโครคอนโทรลเลอร์และระบบที่มีทรัพยากรจำกัดได้ ดังนั้นหลายอย่างจึงถูกออกแบบโดยคิดถึงเรื่อง RAM, Flash และความสามารถของ Hardware ตั้งแต่แรก

สิ่งที่เราเอาไปใส่ใน ESP32 จึงไม่ได้มีแค่ไฟล์ Python ที่เราเขียน แต่มี MicroPython Firmware อยู่ใน Flash ของไมโครคอนโทรลเลอร์ด้วย

Firmware ตัวนี้เป็นส่วนสำคัญ เพราะมันทำหน้าที่เป็นสภาพแวดล้อมสำหรับรันโปรแกรม Python ของเรา และยังเตรียมสิ่งที่จำเป็นสำหรับการเข้าถึง Hardware เอาไว้ให้ด้วย

นั่นเป็นเหตุผลว่าทำไมหลังจาก Flash MicroPython ลงในบอร์ดแล้ว เราจึงสามารถพิมพ์อะไรแบบนี้ได้

>>> 1 + 1
2

โดยไม่ต้อง Compile โปรแกรมใหม่แล้ว Upload ทั้งโปรเจกต์ทุกครั้งเหมือนวิธีที่เราคุ้นเคยจาก Arduino

ตรงนี้เองที่ทำให้การใช้งาน MicroPython ให้ความรู้สึกต่างออกไปพอสมควร

ไมโครคอนโทรลเลอร์ไม่ได้เข้าใจ Python

ถึงเราจะพิมพ์ Python ลงไปได้ ก็ไม่ได้หมายความว่า CPU ของ ESP32 อยู่ดี ๆ จะอ่าน Python ออก

CPU ยังคงเข้าใจคำสั่งของมันเหมือนเดิม

สิ่งที่เพิ่มเข้ามาคือ MicroPython ที่อยู่ระหว่างโค้ดของเรากับ Hardware

ลองนึกภาพง่าย ๆ ว่าเราพิมพ์

led.value(1)

สำหรับคนเขียนโปรแกรม ความหมายของมันค่อนข้างชัด เราต้องการให้ขาที่กำหนดเอาไว้เป็น HIGH

แต่ CPU ไม่รู้จักคำว่า led และไม่ได้รู้ว่า .value(1) หมายถึงอะไร MicroPython ต้องจัดการโค้ดของเรา แล้วสุดท้ายจึงไปเรียกส่วนที่เกี่ยวข้องกับ Hardware ของไมโครคอนโทรลเลอร์อีกที

แนวคิดตรงนี้จริง ๆ แล้วไม่ได้ห่างจาก Arduino มากอย่างที่คิด

ใน Arduino เราอาจเขียน

digitalWrite(2, HIGH);

ส่วนใน MicroPython เราอาจเขียน

from machine import Pin

led = Pin(2, Pin.OUT)
led.value(1)

ผลลัพธ์สุดท้ายคือขา GPIO เปลี่ยนสถานะเหมือนกัน แต่เส้นทางจากโค้ดที่เราเขียนไปจนถึง Hardware นั้นต่างกัน

และความต่างตรงนี้เป็นหนึ่งในเหตุผลที่ทำให้ MicroPython ใช้งานสะดวกมาก แต่ก็ไม่ได้หมายความว่ามันจะเหมาะกับทุกงาน

machine มาจากไหน?

ถ้าเคยเขียน Python บนคอมพิวเตอร์ แล้วมาเห็นโค้ด MicroPython ครั้งแรก สิ่งหนึ่งที่น่าจะสะดุดตาคือ

from machine import Pin

ถ้าลองเอาบรรทัดนี้ไปเปิด Python ปกติบนคอมพิวเตอร์ ส่วนใหญ่ก็จะใช้ไม่ได้ เพราะ Python บนคอมพิวเตอร์ไม่ได้มี GPIO ของ ESP32 ให้ควบคุม

machine เป็น Module ที่ MicroPython เตรียมไว้สำหรับเข้าถึง Hardware ของไมโครคอนโทรลเลอร์ ไม่ว่าจะเป็น GPIO, ADC, PWM, UART, SPI, I2C หรือส่วนอื่น ๆ ที่บอร์ดนั้นรองรับ

อย่างการสร้าง Output หนึ่งขา เราสามารถเขียนได้ว่า

led = Pin(2, Pin.OUT)

จากนั้นจะเปิด

led.value(1)

หรือปิด

led.value(0)

ก็ได้

ถ้ามองจากคนที่เคยใช้ Arduino มาก่อน มันก็คือแนวคิดเดียวกับ pinMode() และ digitalWrite() เพียงแต่ API และวิธีเขียนต่างกัน

แต่สิ่งที่น่าสนใจของ MicroPython ยังไม่ใช่แค่ Syntax ที่อ่านง่ายกว่า

เขียนแล้วลองได้เลย

สิ่งหนึ่งที่ทำให้ MicroPython สนุกมากเวลาใช้กับไมโครคอนโทรลเลอร์คือ REPL หรือ Read-Evaluate-Print Loop

หลังจากเชื่อมต่อกับบอร์ด เราสามารถคุยกับ MicroPython ได้โดยตรง

สมมติเราพิมพ์

>>> from machine import Pin
>>> led = Pin(2, Pin.OUT)
>>> led.value(1)

ไฟติด

จากนั้นพิมพ์

>>> led.value(0)

ไฟดับ

เราไม่จำเป็นต้องสร้างโปรเจกต์ เขียน setup() เขียน loop() Compile แล้ว Upload ใหม่เพียงเพื่อทดลองว่าขานี้เปิดได้หรือเปล่า

ตรงนี้มีประโยชน์มากเวลาเรากำลังทดลอง Hardware เพราะเราสามารถลองสั่ง GPIO อ่าน Sensor หรือเช็กค่าบางอย่างได้ทันที แล้วดูผลตรงนั้นเลย

มันทำให้เส้นแบ่งระหว่าง "เขียนโปรแกรม" กับ "ทดลองวงจร" บางลงไปเยอะ

แต่ความสะดวกนี้ก็มาพร้อมกับสิ่งที่ต้องแลก

ถ้ามันง่ายขนาดนี้ แล้วทำไมเราไม่ใช้ MicroPython กับทุกอย่าง?

นี่น่าจะเป็นคำถามที่ควรถามมากกว่า "MicroPython ดีกว่า Arduino ไหม"

เพราะจริง ๆ แล้วสองอย่างนี้ไม่ได้มีคำตอบว่าอะไรดีกว่ากันแบบตรง ๆ

MicroPython ทำให้เราเขียนและทดลองโปรแกรมได้เร็ว อ่านโค้ดง่าย และเหมาะมากกับงานที่ต้องการพัฒนาอะไรขึ้นมาโดยไม่อยากเสียเวลากับรายละเอียดระดับล่างมากเกินไป โดยเฉพาะบอร์ดอย่าง ESP32 หรือ RP2040 ที่มีทรัพยากรมากพอให้เราทำอะไรได้ค่อนข้างเยอะ

แต่เราก็ต้องไม่ลืมว่า MicroPython เองกำลังทำงานอยู่บนไมโครคอนโทรลเลอร์อีกชั้นหนึ่ง

RAM ยังมีจำกัด

Flash ยังมีจำกัด

CPU ก็ยังมีความเร็วเท่าเดิม

และระหว่าง Python หนึ่งบรรทัดที่เราเขียน กับคำสั่งที่ CPU ทำงานจริง ยังมี MicroPython อยู่ตรงกลาง

ลองกลับมาดูคำสั่งง่าย ๆ อีกครั้ง

led.value(1)

เรารู้ว่าผลสุดท้ายคือ GPIO เป็น HIGH

แต่คำถามคือ ตั้งแต่เราสั่ง .value(1) จนกระทั่งขา GPIO เปลี่ยนสถานะ MicroPython ต้องทำอะไรไปบ้าง?

แล้วถ้าเราเอาคำสั่งนี้ไปเทียบกับการเขียน Register โดยตรงเหมือนที่เราทำกับ Arduino ก่อนหน้านี้ มันจะช้ากว่ากันแค่ไหน?

หรือถ้าโปรแกรมของเราใช้ RAM ไปเรื่อย ๆ จากการสร้าง Object แล้ว Object ที่เราไม่ได้ใช้หายไปไหน ในเมื่อไมโครคอนโทรลเลอร์ไม่มี RAM เหลือเฟือเหมือนคอมพิวเตอร์?

ที่สำคัญกว่านั้น ถ้าวันหนึ่ง MicroPython กำลังจัดการหน่วยความจำอยู่ แต่ในเวลาเดียวกัน Hardware ของเราต้องตอบสนองภายในเวลาที่แน่นอน จะเกิดอะไรขึ้น?

ตรงนี้เองที่ทำให้ MicroPython เริ่มน่าสนใจมากกว่าการเป็นแค่ "Python สำหรับบอร์ดเล็ก ๆ"

เพราะยิ่งเราใช้มัน เราจะยิ่งเจอคำถามเดียวกับที่เคยเจอตอนใช้ Arduino

ความง่ายที่เราเห็นอยู่ข้างบน กำลังซ่อนอะไรเอาไว้ข้างล่างบ้าง?