[TH] An Interrupt in MicroPython

บทความนี้อธิบายหลักการทำการขัดจังหวะหรืออินเทอร์รัพต์ (Interrupt) และการดักการเกิดการขัดจังหวะด้วย MicroPython โดยทดลองกับ ESP8266 และ ESP32 เพื่อเป็นแนวทางในการเขียนโปรแกรมตอบสนองการเกิดเหตุการณ์จากภายนอกโดยไม่ต้องรอให้งานที่ทำอยู่นั้นทำเสร็จก่อน

ภาพที่ 1 การทดลองตรวจจับระยะด้วยการดักการขัดจังหวะ

การขัดจังหวะ

โดยปกติการเขียนโปรแกรมเพื่อใช้ในงานระบบสมองกลฝังตัวหรือตรวจจับการทำงาน เช่น การตรวจสอบสิ่งปกติที่เข้ามาใกล้ (ภาพที่ 1) เมื่อเขียนผังของการทำงานจะเป็นดังภาพที่ 2 คือ มีการวนรอบเพื่อให้การทำงานทำซ้ำไม่รู้จบ และในการวนรอบแต่ละรอบทำการตรวจสอบสิ่งผิดปกติ ถ้าพบจะรายงานให้ทราบ แต่ถ้าไม่พบหรือรายงานเสร็จแล้วจะหน่วงเวลา 1 วินาทีเพื่อรอรอบการทำงานรอบถัดไป ทั้งนี้จะพบว่าระหว่างเวลา 1 วินาทีที่รอนั้นอาจจะเกิดสิ่งผิดปกติขึ้นได้โดยที่ระบบไม่พบเนื่องจากอยู่ในช่วงของคำสั่งการหน่วงเวลา และถึงแใ่จะนำคำสั่งหน่วงเวลาออกไป แต่เมื่อเพิ่มการทำงานอื่น ๆ เข้าไประบบจะต้องรอการตรวจสอบก่อนเสมอจึงจะไปทำงานอื่น ดังนั้น จะทำอย่างไรให้โปรแกรมหรือระบบทำงานปกติไป และเมื่อเกิดการพบสิ่งผิดปกติค่อยทำการเตือน เพื่อลดช่วงของการไม่พร้อมตรวจสอบสิ่งปกติและไม่ต้องเสียเวลาการตรวจสอบสถานะในทุกวงรอบการทำงาน

ภาพที่ 2 การทำงานแบบตรวจจับเอง

ในภาพที่ 3 จะพบว่า เมื่อกำหนดให้มีการดักการขัดจังหวะจะทำให้วงรอบของการทำงานไม่ต้องตรวจสอบสถานะของความผิดปกติ แต่ทำการออกแบบระบบให้มีการส่งสัญญาณขัดจังหวะให้กับหน่วยประมวลผลทราบจะทำให้เมื่อเกิดการขัดจังหวะเกิดขึ้น หน่วยประมวลผลจะหยุดคำสั่งที่ทำงานอยู่และไปทำการานงาน เมื่อทำเสร็จจึงกลับมาทำงานที่ค้างไว้

ภาพที่ 3 การตรวจจับด้วยการดักการขัดจังหวะ

คำสั่ง

คำสั่งในการกำหนดการดักการขัดจังหวะใน Micropython กระทำโดยสร้างฟังก์ชันเรียกกลับ (callback function) ขึ้นมาเพื่อให้ถูกเรียกใช้เมื่อเกิดการขัดจังหวะ โดยรูปแบบของฟังก์ชันที่สร้างขึ้นเป็นดังนี้

def ชื่อฟังก์ชัน( pin ):
global interrupt_pin
interrupt_pin = pin
สิ่งที่ทำเมื่อเกิดการขัดจังหวะ

คำสั่งกำหนดการดักการขัดจังหวะจากสัญญาณของขา GPIO ต้องกระทำ 2 ขั้นตอน ดังนี้

  1. สร้างตัวแปรสำหรับเข้าถึงขารับสัญญาณขัดจังหวะ โดยกำหนดหน้าที่ของขาเป็น Pin.IN
  2. ใช้คำสั่ง irq() ตามรูปแบบต่อไปนี้

ตัวแปรขา.irq( trigger=ช่วงเวลาของการขัดจังหวะ, handler=ฟังก์ชันตอนสนองการขัดจังหวะ)

ช่วงเวลาของการดักการขัดจังหวะ

เนื่องจากสัญญาณดิจิทัลมีสถานะของสัญญาณ 4 แบบ คือ ช่วงที่ยังคงเป็น 0 ช่วงที่ยังคงเป็น 1 และช่วงที่มีการเปลี่ยนแปลงค่าจาก 0 ไป 1 และจาก 1 ไป 0 ดังภาพที่ 4

ภาพที่ 4 ช่วงเวลาของการขัดจังหวะ

MicroPython รองรับการดักสัญญาณขัดจังหวะได้ 3 ประเภท คือ

  1. Pin.IRQ_RISING สำหรับการดักช่วงของการเกิดเปลี่ยนแปลงระดับจาก 0 ไปเป็น 1
  2. Pin.IRQ_FALLING สำหรับการดักช่วงของการเปลี่ยนระดับจาก 1 ไปเป็น 0
  3. 3 สำหรับดักทั้ง 2 ช่วง

ตัวอย่างโปรแกรม

ตัวอย่างโปรแกรมต่อไปนี้เป็นการตรวจสอบระยะการเข้าใกล้ของวัตถุ ถ้าอยู่ใกล้วัตถุจะเกิดการขัดจังหวะและแสดงข้อความ Alert!!! โดยภาคเซ็นเซอร์ที่ใช้เป็น IR Reflect โดยต่อขา Vcc เข้ากับ 3V3, GND เข้ากับ GND และขา OUT เข้ากับ D1

ภาพที่ 5 ไฟสถานะเมื่อวัตถุอยู่ไกล
ภาพที่ 6 ไฟสถานะเมื่อวัตถุอยู่ใกล้
import machine as mc
alertPin = mc.Pin(5, mc.Pin.IN) # D1

def alert_interrupt(pin):
    global interrupt_pin
    interrupt_pin = pin
    print("Alert!!!")

if __name__=="__main__":
    alertPin.irq(trigger=mc.Pin.IRQ_RISING, handler=alert_interrupt)
    while True:
        pass

สรุป

จากบทความนี้หวังว่าคงเป็นแนวทางสำหรับการเขียนโปรแกรมของผู้อ่านให้สามารถเขียนโปรแกรมแบบดักการขัดจังหวะด้วยภาษาไพธอนบนระบบ MicroPython ซึ่งมีหลักการคือ ออกแบบวงจรให้นำเข้าข้อมูลเป็น 0 หรือ 1 หลังจากนั้นสร้างฟังก์ชันตอนสนองการเปลี่ยนแปลงค่าจาก 0 ไป 1 หรือจาก 1 ไป 0 หรือทั้ง 2 กรณีเพื่อให้ฟังก์ชันตอบสนองการขัดจังหวะทำงาน ซึ่งทำให้หน่วยประมวลผลมีเวลาไปทำคำสั่งอื่น ๆ โดยไม่ต้องเสียเวลาตรวจสอบในทุกวงรอบการทำงาน สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ

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