บทความนี้กล่าวถึงการใช้ Ticker กับไมโครคอนโทรลเลอร์ ESP8266 เพื่อสร้างการขัดจังหวะจากสัญญาณนาฬิกา แทนการหน่วงเวลาด้วย delay() ทำให้ระยะเวลาที่ต้องเสียจากการวนรอบด้วย delay() ถูกใช้ไปทำอย่างอื่น และสร้างประสิทธิภาพต่อซอฟต์แวร์ที่พัฒนา
การใช้งาน Ticker
Ticker เป็นไลบรารีของ esp8266 ที่พัฒนามาตั้งแต่ปี ค.ศ. 2014 โดย Ivan Grokhotkov ซึ่งเป็นการเปิดความสามารถของเฟรมเวิร์ก Arduino ให้เข้าถึงการใช้ os_timer เพื่อตั้งเวลาให้เรียกฟังก์ชัน callback ที่กำหนดไว้เมื่อครบระยะเวลาที่ต้องการ โดยการใช้งานต้องเรียกใช้ไฟล์ส่วนหัว Ticker.h ดังนี้
#include <Ticker.h>
เมื่อนำเข้าไฟล์ส่วนหัว Ticker เรียบร้อย ขั้นตอนต่อไปคือสร้างวัตถุประเภทตัวตั้งเวลาที่สร้างจากคลาส Ticker ดังนี้
Ticker วัตถุ;
การใช้งานวัตถุที่เป็นตัวตั้งเวลาจะต้องกำหนดระยะเวลาของการตั้งเวลาในหน่วยวินาที (ใช้ข้อมูลแบบตัวเลขทศนิยม) และระบุฟังก์ชันที่จะถูกเรียกใช้เมื่อครบระยะเวลาที่กำหนดดังรูปแบบต่อไปนี้
วัตถุ.attach( เวลาหน่วยวินาที, ฟังก์ชันเรียกกลับ)
หรือถ้าต้องการตั้งค่าเป็นหน่วยมิลลิวินาทีให้เปลี่ยนการใช้งานเป็นฟังก์ชัน attach_ms() แทน attach() ดังรูปแบบต่อไปนี้
วัตถุ.attach_ms( เวลาหน่วยมิลลิวินาที, ฟังก์ชันเรียกกลับ )
สำหรับการเรียกฟังก์ชันที่กำหนดแบบเพียงครั้งเดียวสามารถเปลี่ยนเป็นใช้ once() หรือ once_ms() ตามรูปแบบการใช้งานดังนี้
วัตถุ.once( เวลาในหน่วยวินาที, ฟังก์ชันเรียกกลับ )
วัตถุ.once_ms( เวลาในหน่วยมิลลินาที, ฟังก์ชันเรียกกลับ )
ถ้าต้องการตรวจสอบสถานะการทำงานของวัตถุตั้งเวลาที่สร้างไว้ให้ใช้คำสั่ง active() ในการตรวจสอบสถานะดังนี้ และได้คำตอบเป็น true หรือ false
สถานะ = วัตถุ.active()
ในกรณีที่ใช้ attach() หรือ attach_ms() และต้องการหยุดการเรียกซ้ำสามารถทำได้ด้วยการยกเลิกการผนวกฟังก์ชันเข้ากับตัวตั้งเวลาด้วยคำสั่ง detach() ดังนี้
วัตถุ.detach()
นอกจากนี้ กรณีที่ต้องการสร้างพารามิเตอร์ส่งไปให้ฟังก์ชันตอบกลับต้องใช้ std::bind() เป็นตัวช่วย เช่นตัวอย่างต่อไปนี้
void func( int id ) {
Serial.println( id );
}
...
วัตถุ.attach_ms(500, std::bind( func, 10 ));
...
ตัวอย่างโปรแกรม
จากโค้ดตัวอย่างด้านล่างนี้เป็นการใช้วิธีหน่วงเวลาของคำสั่ง delay() เพื่อสั่งให้หลอดแอลอีดีบนบอร์ด NodeMCU ติดและดับสลับกันทุก 500ms (โดยประมาณ)
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, LOW);
delay(500);
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
}
เมื่อเขียนใหม่ด้วยการใช้ Ticker ซึ่งมีขั้นตอนของการเขียน 3 ส่วนหลัก คือ ส่วนของการสร้างวัตถุตั้งเวลาทำงานประเภท Ticker การสร้างฟังก์ชันตอบสนอง และการผนวกฟังก์ชันเข้ากับวัตถุตั้งเวลาทำงาน ดังโค้ดต่อไปนี้
#include <Ticker.h>
Ticker tm500ms;
void myToggle() {
int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
tm500ms.attach(0.5, myToggle);
}
void loop() {
}
เมื่อสังเกตหลักการทำงานของทั้ง 2 โปรแกรมจะพบว่า โปรแกรมแรกนั้นสั่งเปิด (หรือปิด) แล้วหน่วงเวลาไป 500 มิลลิวินาที หลังจากนั้น สั่งปิด (หรือเปิด) แล้วหน่วงเวลาอีก 500 มิลลิวินาที จึงทำให้เวลาที่ใช้ไปจริง ๆ เกิน 1 วินาที แต่ในโปรแกรมที่ 2 เมื่อใช้ Ticker จะเกิดการทำงานทุก 500 มิลลิวินาที หมายความว่าเมื่อครบเวลาที่ตั้งไว้โปรแกรมจะทำการอ่านสถานะของขา LED_BUILTIN และกลับค่าเพื่อส่งผลให้หลอดสลับการติดหรือดับ แล้วสิ้นสุดการทำงาน และเมื่อครบ 500 มิลลิวินาทีอีกครั้งจะทำการสลับผลการติดหรือดับอีกครั้ง ดังนั้น การเขียนในแบบที่ 2 มีผลให้ 1 วินาที หรือใกล้เคียง 1 วินาทีจะเกิดการติดและดับ 1 วงรอบ ส่งผลให้ในเวลาที่เหลืออยู่นั้นสามารถเขียนโปรแกรมให้ทำงานอื่นได้ เพราะเมื่อครบเวลาที่ตั้งไว้จะหยุดงานที่ทำอยู่และกลับไปตอบสนองการสั่งเปิด/ปิด แต่ในวิธีแรกนั้นต้องเสียเวลาในการ delay()
สรุป
จากบทความนี้จะพบว่า Ticker รองรับการทำงานในเรื่องของการตั้งเวลา โดยรองรับทั้งการตั้งเวลาให้ทำทุกเวลาที่กำหนด และสามารถยกเลิกการทำงานในภายหลังได้ กับตั้งเวลาเพื่อให้เรียกใช้งานเพียงครั้งเดียว ซึ่งเมื่อนำไปประยุกต์กับการใช้งานในลักษณะของการตั้งเวลาให้ไมโครคอนโทรลเลอร์เก็บค่าจาก DHT11 ในทุก 1 นาที จะทำให้สามารถเก็บฐานข้อมูลอุณหภูมิและความชื้นที่ละเอียดเป็นทุก 1 นาทีได้ด้วย หรือประยุกต์เป็นตัวนาฬิกาได้เช่นกันซึ่งทั้งหมดนี้ขึ้นอยู่กับประสบการ์และการนำไปประยุกต์ใช้ สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ
แหล่งอ้างอิง
- Github: esp8266/Arduino/Libraries/Ticker
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-08-12, 2021-11-22