กลับไปหน้ารวมไฟล์
implementing-a-heart-beat-in-your-code-e7b613.md

Heart Beat คืออะไรวะ?

Heart Beat ก็คือ 'ชีพจร' ที่โปรแกรมเราสร้างขึ้นมาให้เต้นตามความถี่ที่เราตั้งไว้ มันช่วยบอกเราว่าโค้ดหรือแอปพลิเคชันหลักของเรายังทำงานปกติดีอยู่หรือเปล่า โดยปกติแล้ว (แต่ไม่เสมอไปนะ) เราจะแสดง Heart Beat ผ่านการกะพริบของไฟอินดิเคเตอร์ เช่น LED นั่นแหละ ตราบใดที่ไฟยังกะพริบอยู่ ('ยังเต้นอยู่') เราก็รู้ว่าโค้ดยังรันอยู่ แต่ถ้ามันหยุดนิ่งล่ะก็... ถึงเวลาต้องลุย debug แล้วล่ะน้อง

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

Heart Beat เนี่ย ต้องมีโค้ดกับชิ้นส่วนอะไรบ้าง?

การทำให้ Heart Beat มันมองเห็นได้เนี่ย ประกอบด้วย 2 ส่วนหลัก:

1. ชิ้นส่วนฮาร์ดแวร์ ที่จะแสดงผลให้เห็นว่า Heart Beat ยังเต้นอยู่ และ
2. ซอฟต์แวร์หรือโค้ด ที่จะมาควบคุมฮาร์ดแวร์ตัวนั้น

แต่เพื่อให้ชีวิตง่ายแบบสุดๆ Heart Beat ที่เราจะพูดถึงในบทความนี้ ไม่ต้องใช้ ชิ้นส่วนฮาร์ดแวร์อื่นใดเพิ่มเติมเลยนอกจากบอร์ดไมโครคอนโทรลเลอร์ที่เข้ากับ Arduino ได้ เพราะเราจะใช้ LED ในตัวที่มาพร้อมกับบอร์ดพวกนี้อยู่แล้ว บอร์ดส่วนใหญ่จะมี LED ในตัว (ใช้ชื่อว่า 'LED_BUILTIN') ติดอยู่ที่ดิจิตอลพิน 13 ซึ่งเราสามารถสั่งงานได้โดยตรง เพราะฉะนั้น แค่ใช้ฟีเจอร์นี้ เราก็ไม่ต้องหาซื้อหรือต่อสายอะไรเพิ่มอีกแล้ว สบายปากเลย งานเราก็จะเหลือแค่โฟกัสที่โค้ดของ Heart Beat เท่านั้น

ซอฟต์แวร์/โค้ดของ Heart Beat

โค้ด Heart Beat สามารถแบ่งออกได้เป็น 4 ส่วน:

1. การประกาศหรือกำหนดค่าตัวแปรต่างๆ ที่จำเป็นต้องใช้,
2. การประกาศฟังก์ชัน heart_beat(),
3. การตั้งค่าเริ่มต้นของ Heart Beat, และ
4. การเรียกใช้ Heart Beat ในตำแหน่งที่ต้องการในโค้ดของเรา

โค้ด Heart Beat ถูกออกแบบมาเป็นฟังก์ชันแบบ non-blocking (ฟังก์ชัน 'heart_beat()') และเราสามารถเอาไปใส่ไว้ที่ไหนในโค้ดก็ได้ แม้แต่หลายๆ ที่พร้อมกันก็ยังได้ แต่ขั้นต่ำสุดนะ ถ้าเราออกแบบลูปหลักให้รันซ้ำๆ การเรียกใช้ heart_beat() ควรจะปรากฏอยู่ในส่วนนี้ด้วย เช่น วางไว้ตอนเริ่มต้นของ loop() เลยก็ได้

มาแยกย่อยดูแต่ละส่วนของโค้ด Heart Beat กันดีกว่า

1. การประกาศ และ การกำหนดค่า

#define heart_beat_pin   LED_BUILTIN  // digital pin for heart beat LED
long unsigned heart_beat_freq = 1000; // time(milliseconds) of heart beat frequency
long unsigned heart_beat_on_off_time; // the time the LED is on and off - 1/2 frequency
long unsigned last_heart_beat_time; // time in milliseconds of last heart beat status change
bool heart_beat_status = HIGH; // current status of heart beat, start high

เราสามารถปรับแต่งโค้ด Heart Beat ให้เหมาะกับความต้องการได้ โดยการแก้ไขค่าที่ประกาศไว้ด้านบนนี่แหละ ตามนี้:

ใช้ LED ในตัวหรือ LED ภายนอก - ถ้าเราไม่อยากใช้ LED ในตัวของบอร์ด ให้ไปเปลี่ยนค่าของ 'heart_beat_pin' เป็นเลขดิจิตอลพินที่เราต่อ LED ภายนอกไว้แทน แต่ถ้าใช้แบบ default โค้ดก็จะใช้ LED ในตัวที่พิน 13 (ซึ่งรู้จักในชื่อ LED_BUILTIN) อยู่แล้ว ทำให้เราไม่ต้องเสียเวลาต่อสายหรือหาอะไรมาเพิ่มเลย สบายๆ
ปรับความถี่การเต้นของ Heart Beat - เราสามารถตั้งความถี่ที่ Heart Beat จะเต้นได้ โดยการกำหนดค่าตัวแปร 'heart_beat_freq' เป็นจำนวนมิลลิวินาทีที่ต้องการ จำไว้ว่า เวลาที่ LED จะติดและดับนั้น จะเป็นครึ่งหนึ่งของความถี่ที่เราตั้งไว้ ตัวอย่างเช่น ถ้าเราตั้งความถี่ไว้ที่ 1 Hz หรือ 1000 มิลลิวินาที LED ของ Heart Beat ก็จะติดอยู่ 500 มิลลิวินาที และดับ 500 มิลลิวินาที หรือก็คือครึ่งวินาทีต่อครึ่งวินาทีนั่นเอง

ตัวแปรอื่นๆ ทั้งหมดถูกใช้ภายในโค้ดการเต้นของหัวใจ (heart beat) โดยตรง ไม่สามารถกำหนดค่าเองได้

2. ฟังก์ชัน heart_beat()

เพื่อให้เรื่องง่ายเข้าไว้ โค้ดหัวใจเต้นถูกออกแบบมาเป็นฟังก์ชันแบบไม่บล็อกกิ้ง (non-blocking) เรียบง่าย ไม่มีพิธีรีตอง ชื่อว่า 'heart_beat' มันไม่มีพารามิเตอร์ และเป็นประเภท void

ฟังก์ชันหน้าตาแบบนี้:

//
// Function handles the heart beat cycle.
// May be called from anywhere, but at least every main loop cycle.
//
void heart_beat() {
if (millis() - last_heart_beat_time >= heart_beat_on_off_time) {
// time to swap status of the heart beat LED and update it
last_heart_beat_time = millis();
heart_beat_status = !heart_beat_status; // invert current heart beat status value
digitalWrite(heart_beat_pin, heart_beat_status); // update LED with new status
}
}

แค่เอาไปแปะในโค้ดของน้องตรงไหนก็ได้ที่เหมาะสม และต้องมั่นใจว่าเรียกใช้มันอย่างน้อยในส่วน main loop นะจ๊ะ

3. การตั้งค่า Heart Beat

โค้ดหัวใจเต้นจะถูกตั้งค่าเริ่มต้นภายในฟังก์ชัน setup() แบบนี้:

 // setup heart beat
pinMode(heart_beat_pin, OUTPUT);
heart_beat_on_off_time = heart_beat_freq / 2; // LED is on and off at 1/2 frequency time
// end of heart beat setup

ตรงนี้ไม่มีอะไรให้ผู้ใช้ปลายทางอย่างน้องต้องทำหรือแก้ไข แค่ต้องแน่ใจว่าโค้ดนี้อยู่ในฟังก์ชัน setup() เท่านั้นเอง วางใจรุ่นพี่ได้เลย

4. การเรียกใช้ Heart Beat

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

ตัวอย่างใน main loop ก็ประมาณนี้:

void loop() {
heart_beat();
// add your other code here...
}

รายละเอียดทางเทคนิคเพิ่มเติม

การออกแบบเฟิร์มแวร์แบบไม่บล็อกกิ้ง (Non-Blocking)

"Heartbeat" ในระบบเอมเบดเด็ดเป็นตัวบ่งชี้สถานะและดีบั๊กที่สำคัญมาก

  • เทคนิค Millis(): โปรเจคนี้แสดงให้เห็นวิธีหลีกเลี่ยงการใช้ฟังก์ชัน delay() โดยการใช้ millis() ทำให้ Arduino สามารถกะพริบ LED หรือส่งข้อความ Serial ในช่วงเวลาที่กำหนด (เช่น ทุก 1000ms) โดยไม่ต้องหยุดการทำงานของลอจิกหลักของแอปพลิเคชัน
  • การตรวจสอบสถานะ: ถ้า LED Heartbeat หยุดกะพริบ มันจะให้สัญญาณภาพทันทีว่าไมโครคอนโทรลเลอร์อาจค้างหรือติดอยู่ในลูปอนันต์แล้ว

ประโยชน์ในการนำไปใช้

  • การวินิจฉัยตัวเอง: โค้ดนี้สามารถขยายได้เพื่อเปลี่ยนความถี่การเต้นของหัวใจตามสถานะของระบบ (เช่น กะพริบเร็วเมื่อมี Error, กะพริบช้าเมื่อ Normal)
  • วอตช์ด็อกไทเมอร์: ลอจิกนี้มักเป็นก้าวแรกสู่การใช้วอตช์ด็อกไทเมอร์ (WDT) แบบฮาร์ดแวร์ ซึ่งสามารถรีเซ็ต Arduino อัตโนมัติได้หากสัญญาณหัวใจเต้นหายไปนานเกินไป

แค่นั้นแหละ! เก็บเทคนิคนี้ไว้ใกล้ตัวและใส่มันลงในสเก็ตช์ของน้องเป็นฟีเจอร์มาตรฐานไปเลย สู้งานนะน้อง!

อ่านเพิ่มเติม

น้องอาจจะพบว่าผลงานอื่นๆ จากผู้เขียนคนเดียวกันนี้น่าสนใจและมีประโยชน์:

  • A Music & Lights Workbench ออกแบบมาเพื่อแนะนำผู้ที่ใหม่กับการเขียนโปรแกรมคอมพิวเตอร์ โดยใช้คำสั่งง่ายๆ ที่ให้เอฟเฟกต์เจ๋งๆ แนวทางการสอนเป็นแบบพี่สอนน้อง
  • **ez_SIPO8_lib** - ไลบรารีตัวนี้จัดไปวัยรุ่น! มันช่วยให้เราจัดการ IC 74HC595 (Serial-In/Parallel-Out) ได้แบบอิสระ ทั้งแบบเดี่ยวและแบบต่อกันเป็นทอดๆ (cascaded) ไปจนถึง 255 ตัว (หรือก็คือ 2040 ขา output นั่นแหละ) งานใหญ่แค่ไหนก็สู้ได้
  • **ez_switch_lib** - ไลบรารีสำหรับสวิตช์แบบจัดเต็ม ใช้ได้กับสวิตช์เกือบทุกประเภทและวงจรเกือบทุกแบบ พร้อมฟีเจอร์เด็ดๆ ที่ทำให้ชีวิตง่ายขึ้นอีกนิด
  • **เข้าใจและใช้ปุ่มกด (Button Switches) อย่างเซียน** - ปุ่มกดนี่ดูง่ายแต่ดันมีมุกซ่อนไว้เพียบ! บทความนี้จะพาน้องๆ ลงลึกทุกเรื่อง ตั้งแต่การต่อวงจร วิธีอ่านค่า ไปจนถึงการจัดการกับปัญหาเด้งของสัญญาณ (debouncing) รับรองว่าเข้าใจกระจ่าง
  • **ปุ่มกดแบบใช้ Interrupt** - มาเล่นของสูงกัน! ตัวอย่างการเชื่อมโยงปุ่มกดเข้ากับ External Interrupt ของ Arduino ให้ระบบตอบสนองไวแบบทันใจ
  • **อ่านค่าสวิตช์แบบ Toggle ให้แม่นยำ** - สวิตช์แบบโยกขึ้น-ลงนี่อ่านค่าให้ถูกต้องและน่าเชื่อถือได้ยังไง มาดูเคล็ดลับกัน
  • **เกมปุ่มกดกับไฟ LED** - มาเบรกจากเรื่องซีเรียสด้วยโปรเจกต์สนุกๆ ใช้ปุ่มกดและไฟ LED ทำเกมง่ายๆ เล่นแก้เครียด
  • **จัดการ External Interrupts แบบโปร** - เฟรมเวิร์กเจ๋งๆ สำหรับจัดการ Interrupt หลายๆ ตัวพร้อมกันแบบ asynchronous ตั้งค่าคุณสมบัติต่างกันได้ตามใจ และเพิ่มโค้ดสำหรับประมวลผลหลัง Interrupt ได้สบายๆ
  • **ระบบแจ้งเตือนตามเวลาแบบโปรแกรมได้** - เฟรมเวิร์กสำหรับตั้งเวลาแจ้งเตือนแบบ asynchronous ทั้งแบบนับเวลาผ่านไป (elapsed) และแบบตามเวลาจริง (real-time) ตั้งกี่ครั้งก็ได้ ตั้งแต่ไม่ถึงวินาทีไปจนถึงหลายชั่วโมง
  • ข้อมูล Frontmatter ดั้งเดิม

    apps:
      - "1x Arduino IDE"
    author: "ronbentley1"
    category: ""
    components:
      - "1x Arduino UNO"
    description: "วิธีเทพๆ ง่ายๆ ในการเพิ่มไฟกระพริบเป็นจังหวะเหมือนหัวใจเต้นในโค้ด Arduino ของเรา ไว้โชว์ให้รู้ว่างานของเรายังรันอยู่ จัดไปแบบงานง่ายแต่หล่อ!"
    difficulty: "Easy"
    documentationLinks: []
    downloadableFiles:
      - "https://projects.arduinocontent.cc/b7089037-030f-4e10-9ab9-554474e09258.ino"
      - "https://projects.arduinocontent.cc/b7089037-030f-4e10-9ab9-554474e09258.ino"
    encryptedPayload: "U2FsdGVkX18YYfaLie9cF+UzLElKXLSNnvYRDQZZEMopOjV3VJVz9Df68PSbNtL61Shi+sleQjoxtF8bCTZmptgSzImxN8cgCLIRdi7Wges="
    heroImage: "https://cdn.jsdelivr.net/gh/bigboxthailand/arduino-assets@main/images/projects/implementing-a-heart-beat-in-your-code-e7b613_cover.jpg"
    lang: "en"
    likes: 0
    passwordHash: "f35bdc0424d97a34a495b2d1ee1d199da3017c6fa22b35ff6d7eb6f9e9db8dfe"
    price: 79
    seoDescription: "Learn how to add a Heart Beat indicator to your Arduino sketches to show that your code is alive and running correctly."
    tags:
      - "hear beat"
      - "heart_beat"
      - "indicator"
    title: "ใส่ Heart Beat ในโค้ดให้ตึงๆ รู้ปะว่ายังไม่ตาย!"
    tools: []
    videoLinks: []
    views: 6450