การหน่วงเวลาใน Arduino และ nodeMCU

ในการเขียนโปรแกรมควบคุม บางทีบางครั้งเราอาจต้องการชะลอ หรือหน่วงเวลาเพื่อให้เป็นไปตามความต้องการของระบบ เช่น ต้องการให้หลอดไฟ ไม่ติดตลอดเวลา แต่ต้องการให้มันติด และดับ วนไป เราก็ใช้วิธีการสั่งให้หลอดไฟ ติดค้าง ไว้ 10 วินาที และสั่งให้ดับไปอีก 10 วินาที วนไปเราก็จะได้ระบบหลอดไฟ ติดและดับ กระพริบวนไปเรื่อย ๆ

ทีนี้เรามาดูกันว่าในระบบหน่วงเวลา เราสามารถหน่วง แบบไหนได้บาง ด้วยคำสั่งใด

millis()

คำสั่ง millis()
เป็นคำสั่งที่ใช้ทำหน้าที่สำหรับอ่านค่าระยะเวลา การเริ่มทำงานของโปรแกรมตั้งแต่เริ่มต้น โดยจะให้ค่าออกมาในหน่วย มิลลิวินาที (Millisecond) ^{[1]} ซึ่งจะสามารถนับช่วงเวลาการทำงานของโปรแกรมได้สูงสุดคือ 49 วัน 9 ชั่วโมง หลังจากนั้นการนำเวลาจะเริ่มวนกลับไปเป็น 0 ใหม่

ตัวอย่างโค้ต millis()

long time ;
void setup()
  {
Serial.begin(9600);
  }
void loop()
  {
time = millis();
Serial.print("เวลาตอนนี้คือ: ");
Serial.println(time);
delay(1000);// หน่วงเวลาไว้ 1000 มิลลิวินาที
  }

millis_basic1.ino (274 Bytes)

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

ตัวอย่างการกระพริบ LED ด้วย millis โค้ตในส่วนนี้จะไม่มีการหยุดเวลาของโปรแกรมเพื่อกระพริบไฟ แต่จะอาศัยการเช็คช่วงเวลาในการทำงานแทนว่า เงื่อนไขทำงานครบตามกำหนดเวลาหรือยัง

const int ledPin =  LED_BUILTIN;
int ledState = LOW;            
unsigned long previousMillis = 0;
const long interval = 1000;           // ช่วงเวลากระพริบ

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    digitalWrite(ledPin, ledState);
  }
}

Output Simulate

2020-10-04_02-56-03

ตัวอย่าง Millis อื่นๆ ที่อาจเจอ จะขออธิบายเพิ่มเติมไว้สักนิด

millis() คืนค่าเวลาปัจจุบันเป็น milli second (1 ส่วน 1000 วินาที)
timeout = millis() เก็บค่าเวลาปัจจุบันไว้ในตัวแปร timeout เป็นการตั้งค่าตั้งต้น
while … ในขณะที่
client.available() == 0 ไม่มีข้อมูลใน object client
if(millis() - timeout > 5000) ถ้าเวลาปัจจุบัน มากกว่าเวลาที่เก็บใน timeout อยู่ 5000 (ก็คือ 5000 milli second, หรือ 5 วินาที)
client.stop() ให้หยุดการทำงาน client เพราะรอนานมากเกินไป
return; ออกจาก function แบบไม่คืนค่า

delay()

คำสั่ง delay()
คำสั่งนี้เรามักจะเห็นใช้กันบ่อย ใช้สำหรับการหน่วงเวลา เพื่อหยุดรอ ที่จะไปทำงานคำสั่งบรรทัดถัดไป โดยมีหน่วยเป็นมิลลิวินาที โดยทั่วไปเราสามารถกำหนดการหน่วงเวลาได้ ตั้งแต่ 1 ถึง 32,767 เท่านั้น

delay(5555);

โค้ตตัวอย่าง

long time ;
void setup()
  {
Serial.begin(9600);
  }
void loop()
  {
time = millis();
Serial.print("เวลาตอนนี้คือ: ");
Serial.println(time);
delay(5555);// หน่วงเวลาไว้ 1000 มิลลิวินาที
  }

แต่ถ้าต้องการกำหนดค่าช่วงเวลาที่กว้างกว่านั้น ให้ใช้ตัวแปรชนิด unsigned long เราสามารถกำหนดค่าการหน่วงเวลาเพิ่มขึ้น ได้ตั้งแต่ 1 ถึง 4,294,967,295 โดยจะต้องใส่ UL ต่อท้ายตัวเลขนั้นด้วย

ตัวอย่างคำสั่ง delay() หน่วย UL

delay(55555UL);

โค้ตตัวอย่าง

long time ;
void setup()
  {
Serial.begin(9600);
  }
void loop()
  {
time = millis();
Serial.print("เวลาตอนนี้คือ: ");
Serial.println(time);
delay(55555UL);// หน่วงเวลาไว้ 1000 มิลลิวินาที
  }

delayMicroseconds()

คำสั่ง delayMicroseconds( \mu s)
คำสั่งนี้ใช้ทำหน้าที หน่วงเวลา โดยจะมีหน่วยเป็น ไมโครวินาที \mu s (Microsecond) ^{[2]} เป็นการหน่วงเวลาในหน่วย 1 ส่วนล้านวินาที จะหน่างเวลาน้อยกว่าคำสั่ง delay() ลงไปอีกมาก ๆ ฟังก์ชันนี้จะเหมาะกับงานที่ต้องการหยุดเวลาสั้น มาก ๆ บนหน่วยเวลาย่าน \mu s เราสามารถกำหนดการหน่วงเวลาได้สูงสุดที่ 16383 \mu s

ตัวอย่างคำสั่ง delayMicroseconds()

delayMicroseconds(1000);

long time ;
void setup()
  {
Serial.begin(9600);
  }
void loop()
  {
time = millis();
Serial.print("เวลาตอนนี้คือ: ");
Serial.println(time);
delayMicroseconds(5000);// หน่วงเวลาไว้ 5000 ไมโครวินาที
  }


[1] มิลลิวินาที (Millisecond) มีค่าเท่ากับ เป็นเวลาใน 1 ส่วน 1000 (0.001 หรือ 10^{-3} หรือ \frac 1{1000} ของหน่วยวินาที
[2] ไมโครวินาที (Microsecond) มีค่าเท่ากับ เป็นเวลาใน 1 ส่วน ล้านวินาที หรือ (0.000001 หรือ 10^{-6} หรือ \frac 1{1000000} ของหน่วยวินาที