บทความนี้กล่าวถึงการใช้ตัวฮาร์ดแวร์ตั้งเวลาหรือไทม์เมอร์ (Timer) ทั้ง 4 ของ ESP32 เพื่อใช้สำหรับการให้โปรแกรมทำงานเมื่อเป็นตามค่าเวลาที่กำหนดไว้ ความแตกต่างระหว่างการใช้ไทม์เมอร์กับการหน่วงเวลา time.sleep()/time.sleep_ms()/time.sleep_us() คือ การหน่วงเวลาคือการวนรอบเพื่อให้หน่วยประมวลผลเสียเวลาไปการวนรอบเพื่อให้ครบกับระยะเวลาที่กำหนด ขณะที่ไทม์เมอร์ใช้หลักการให้ฟังก์ชันทำงานทุกครั้งเมื่อถึงคาบเวลาที่กำหนดไว้ ดังนั้น ขณะที่ไทม์เมอร์ไม่ได้เรียกฟังก์ชันให้ทำงาน หน่วยประมวลผลมีเวลาเหลือหรือค่าว่างงาน (idle time) สำหรับประมวลผลอื่น ๆ ได้ และมีความแตกต่างกับการขัดจังหวะหรืออินเทอร์รัพต์ตรงที่เป็นการขัดจังหวะด้วยตัวตั้งเวลาแทนการขัดจังหวะจากสถานะของขาที่เชื่อมต่อกับวงจรภายนอก

ไทม์เมอร์

ไทม์เมอร์ หรือตัวตั้งเวลาของ ESP32 มีฮาร์แวร์ไทม์เมอร์จำนวน 2 กลุ่ม ในแต่ละกลุ่มประกอบไปด้วยไทม์เมอร์ฮาร์ดแวร์ย่อยอีก 2 ตัว โดยทั้ง 4 เป็นไทม์เมอร์แบบ 64 บิตที่ทำงานแบบ 16 บิต pre-scalars และตัวนับค่าขึ้น/ลงขนาด 64 บิต ที่รองรับการทำงานรีโหลดค่าอัตโนมัติ

การเรียกใช้คลาสไทม์เมอร์สำหรับไมโครคอนโทรลเลอร์ ESP32 ทำด้วยการเรียกใช้คลาส Timer ที่อยู่ภายใต้คลาส machine ดังนี้

from machine import Timer

การสร้างวัตถุตัวตั้งเวลามีรูปแบบของการสร้างดังนี้ โดย หมายเลขไทม์เมอร์ คือตัวเลขลำดับของไทม์เมอร์ที่ต้องการใช้งาน ซึ่งได้แก่ค่า 0, 1, 2 และ 3

วัตถุ = Timer( หมายเลขไทม์เมอร์ )

เมื่อมีวัตถุประเภทไทม์เมอร์ที่พร้อมใช้งานให้กำหนดค่าการทำงานของตัวตั้งเวลานี้ด้วยคำสั่ง init( ) ดังรูปแบบการใช้งานต่อไปนี้

วัตถุ.init( period, mode, callback )

โดยที่

  • period คือ ค่าคาบเวลาการทำงานของตัวตั้งเวลา มีหน่วยเป็นมิลลิวินาที (millisecond)
  • mode คือ โหมดการทำงานของตัวตั้งเวลา ซึ่งมี 2 โหมดทำงานดังนี้
    • Timer.ONE_SHOT สำหรับถูกเรียกทำงานเพียงครั้งเดียว
    • Timer.PERIODIC สำหรับให้เรียกใช้ฟังก์ชัน callback ทุกคาบเวลาที่กำหนด
  • callback คือ ฟังก์ชันที่ถูกเรียกเมื่อไทม์เมอร์ทำงาน

เมื่อต้องการยกเลิกการถือครองตัวตั้งเวลาที่สร้างไว้สามารถกระทำได้ด้วยคำสั่งดังต่อไปนี้

วัตถุ.deinit( )

ตัวอย่างโปรแกรม demoTimer0.py เป็นการให้ลำโพงเปล่งเสียง 1 ครั้งเมื่อครบเวลาที่ตั้งไว้ 2 วินาที โดยเชื่อมต่อลำโพงเข้ากับขา GPIO25 โดยโปรแกรมจะมีเสียงบี๊ป 1 ครั้งถึงแม้มีการหน่วงเวลา 5 วินาที

###########################################
# demoTimer0.py
# (C) 2021, JarutEx
# https://www.jarutex.com
###########################################
from machine import Timer
from machine import Pin
from time import sleep_ms

def beep(x):
    spkPin = Pin( 25, Pin.OUT )
    spkPin.on()
    sleep_ms(50)
    spkPin.off()

try:
    tmr0 = Timer(0)
except:
    print("cannot construct Timer(0)!")
try:
    tmr0.init( period=2000, mode=Timer.ONE_SHOT, callback=beep)
except:
    print("cannot init()!")
sleep_ms(5000)
if (tmr0):
    tmr0.deinit()

ตัวอย่างโปรแกรม demoTimer1.py เป็นการเปลี่ยนรูปแบบของการเปล่งเสียงให้เกิดขึ้นทุก ๆ 2 วินาทีโดยการกำหนดโหมดเป็น Timer.PERIODIC และโปรแกรมมีเสียงบี๊ป 2 ครั้ง คือ ครั้งแรกเมื่อผ่านไป 2 วินาที ครั้งที่ 2 เมื่อเข้าสู่วินาทีที่ 4 หลังจากนั้นอีก 1 วินาทีเป็นสิ้นสุดการหน่วงเวลา 5 วินาที และจบโปรแกรม

###########################################
# demoTimer1.py
# (C) 2021, JarutEx
# https://www.jarutex.com
###########################################
from machine import Timer
from machine import Pin
from time import sleep_ms

def beep(x):
    spkPin = Pin( 25, Pin.OUT )
    spkPin.on()
    sleep_ms(50)
    spkPin.off()

try:
    tmr0 = Timer(0)
except:
    print("cannot construct Timer(0)!")
try:
    tmr0.init( period=2000, mode=Timer.PERIODIC, callback=beep)
except:
    print("cannot init()!")
sleep_ms(5000)
if (tmr0):
    tmr0.deinit()

สรุป

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

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

  1. Espressif. “General Purpose Timer”
  2. Micropython, “Quick Reference for ESP8266”
  3. Micropython. “Quick Reference for ESP32”
  4. Micropython, “class Timer – control hardware timers”

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