กลับไปหน้ารวมไฟล์
using-millis-function-as-an-alternative-to-using-delay-4a74ef.md

ในบทนี้พี่จะพาน้องไปรู้จักกับการใช้ฟังก์ชัน millis() แทน delay() กัน ว่ามันเจ๋งและมีข้อได้เปรียบทางด้านสถาปัตยกรรมยังไงบ้าง

ภาพรวมโปรเจค

แนวคิด "Async-Core" นี้มาแก้ปัญหาหลักของระบบฝังตัวเลยนะตัวดี นั่นก็คือ การหน่วงแบบบล็อกกิ้ง (Blocking Delay) ฟังก์ชัน delay() มันใช้ง่ายก็จริง แต่เวลามันทำงาน มันจะหยุดพอยน์เตอร์การทำงานของ CPU ซะงั้น ทำให้ระบบกลายเป็น "หูหนวก" ไม่รับรู้การขัดจังหวะหรืออินพุตจากภายนอกเลย

โปรเจคนี้จะพาน้องย้ายสถาปัตยกรรมมาใช้ การทำงานหลายงานแบบไม่บล็อก (Non-Blocking Multitasking) ด้วยฟังก์ชัน millis() ทำให้ Arduino ของเราจัดการงานหลายๆ อย่างพร้อมกันได้แบบไม่สะดุด เช่น กะพริบ LED, อ่านเซนเซอร์, และประมวลผลข้อมูลจาก Serial โดยไม่ต้องรอให้งานหนึ่งจบก่อน

ล้วงลึกเทคนิค

  • เจาะลึกฮาร์ดแวร์ Timer:
    • Timer0 Overflow: ภายใน Arduino core มันใช้ Timer0 (ซึ่งเป็นฮาร์ดแวร์ไทเมอร์ 8-bit) ในการเพิ่มค่าให้ตัวนับ 32-bit (unsigned long) ทุกๆ 1 มิลลิวินาที กระบวนการนี้ทำงานผ่าน Interrupt Service Routine (ISR) ที่รันอยู่เบื้องหลัง โดยไม่ขึ้นกับฟังก์ชันหลัก loop() เลย
    • กฎการลบ (ป้องกัน Overflow): หลุมพรางคลาสสิกคือการกลัว "49-day rollover" ที่ตัวนับ 32-bit จะรีเซ็ตกลับไปที่ศูนย์ โปรเจคนี้จะโชว์ความสวยงามทางคณิตศาสตร์ของ (currentTime - startTime >= interval) ให้ดู เพราะพฤติกรรมการลบของ unsigned integer นี่แหละ ที่ทำให้ได้เวลาที่ผ่านไปถูกต้องเสมอ แม้จะเกิด rollover ก็ตาม
  • การจัดการสถานะแบบอะซิงโครนัส:
    • ตรรกะ Finite State Machine (FSM): แทนที่จะเขียนโค้ดแบบเรียงลำดับเป็นเส้นตรง โค้ดจะถูกออกแบบเป็นลูปแบบตรวจจับเหตุการณ์ CPU จะ "ตรวจสอบ" เวลา, ทำงานย่อยๆ ถ้าถึงเวลาที่กำหนด, แล้วก็ไปทำคำสั่งถัดไปทันที วิธีนี้ทำให้ระบบยังคงตอบสนองต่อ อินพุตจากโพเทนชิโอมิเตอร์ หรือ การกดปุ่ม ได้ 100% แม้จะมีตัวจับเวลา LED 5 วินาทีกำลังทำงานอยู่ก็ตาม
  • วิเคราะห์รอบสัญญาณ CPU:
    • กำจัดช่วงรอเปล่า: ใน delay(1000) ทั่วไป CPU จะเสียรอบสัญญาณไป 16,000,000 รอบโดยไม่ได้ทำอะไรเลย แต่กับ Async-Core รอบสัญญาณ 16 ล้านรอบนั้นจะถูกนำไปใช้ประโยชน์ เช่น ตรวจสอบเซนเซอร์, จัดการบัฟเฟอร์ Serial, หรือคำนวณสมการซับซ้อนอื่นๆ ซึ่งเพิ่ม "ความหนาแน่นของความฉลาด" ให้ระบบได้อย่างมีประสิทธิภาพ

วิศวกรรมและการนำไปใช้

  • การออกแบบงานที่ทำงานพร้อมกัน:
    • การนำไปใช้จะสาธิตงานสองงานที่ทำงานพร้อมกัน:
      1. งาน A: กะพริบ LED ด้วยช่วงเวลาคงที่ 1000ms
      2. งาน B: อ่านและพล็อตค่าอะนาล็อกจากโพเทนชิโอมิเตอร์ลง Serial ทุกๆ 10ms
    • การใช้ millis() จะทำให้กราฟบน Serial Plotter เป็นเส้นเรียบแบบเรียลไทม์ ในขณะที่ถ้าใช้ delay(1000) สำหรับ LED กราฟจะ "หยุดนิ่ง" และสูญเสียข้อมูลไปเต็มๆ 1 วินาที
  • แพทเทิร์นการออกแบบซอฟต์แวร์:
    • โปรเจคนี้จะแนะนำ "แพทเทิร์นการตรวจจับ (Polling Pattern)":
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          // Execute non-blocking task here
      }
      
    • แพทเทิร์นนี้คือบล็อกพื้นฐานสำคัญสำหรับระบบปฏิบัติการที่ซับซ้อนและเคอร์เนลของ RTOS เลยนะเออ

สรุปสั้นๆ แต่อัดแน่น

Async-Core นี่แหละคือประตูบานใหญ่สู่โลกของ การพัฒนา Embedded แบบโปร (Professional Embedded Development) เลยนะน้อง! พอเราเชี่ยวชาญเรื่อง Non-Blocking Logic และ Hardware Timer Forensics แล้วเนี่ย จากที่เคยเขียนโค้ดแบบสคริปต์ง่ายๆ ก็จะอัพเลเวลขึ้นมาเป็นวิศวกรที่ออกแบบแอปพลิเคชันที่ทั้งแข็งแรง (robust) และทำงานแบบมัลติเธรดได้ รับรู้สภาพแวดล้อมแบบเรียลไทม์ได้ชัวร์ๆ


Mastery แบบจัดเต็ม: ยึดครอง CPU ผ่านการทำงานแบบ Async และรู้ลึก รู้จริงเรื่อง Timer

อยากเห็นภาพชัดๆ ว่าทำยังไง ตามไปดูในคลิปด้านล่างนี้ได้เลยจ้า รับรองว่าดูจบแล้วทำเป็น!

ข้อมูล Frontmatter ดั้งเดิม

apps:
  - "1x Arduino IDE 2.0 (beta)"
author: "Dziubym"
category: "Lab Stuff"
components:
  - "1x Arduino Nano R3"
  - "1x LED (generic)"
  - "1x Resistor 220 ohm"
  - "1x Rotary potentiometer (generic)"
description: "มาเรียนวิธีใช้ฟังก์ชัน millis() ในโค้ดกันเถอะ วัยรุ่น! จะบอกให้ว่ามันเทพกว่าการใช้ delay() ยังไงบ้าง รับรองว่าทำแล้วตึงๆ งานไหลลื่น ไม่สะดุดแน่นอน จัดไป!"
difficulty: "Easy"
documentationLinks: []
downloadableFiles: []
encryptedPayload: "U2FsdGVkX1+HVuv9+b/eDw/yFG3yBHwOsJDRcb5UmVrsDQJJmDcQS3jwg8P6B2Nnc1eCkCp619SgZsB8w60wRZgFy4/uAT4Kpb/BeQYwMmA="
heroImage: "https://cdn.jsdelivr.net/gh/bigboxthailand/arduino-assets@main/images/projects/using-millis-function-as-an-alternative-to-using-delay-4a74ef_cover.jpg"
lang: "en"
likes: 4
passwordHash: "5741b065aadd2a61545c88cc32e2d48a4086ec916bec34ceb828a89ba0373c6a"
price: 299
seoDescription: "Learn to use the millis() function in Arduino as a non-blocking alternative to delay() for better multitasking and performance."
tags:
  - "millis"
  - "delay"
  - "multitasking"
title: "Using millis() Function as an Alternative to Using Delay"
tools: []
videoLinks:
  - "https://www.youtube.com/embed/dCku8BabPx4"
views: 24544