🧩 1. Timer (ตัวจับเวลา)
Timer (ตัวจับเวลา) คือวงจรภายในไมโครคอนโทรลเลอร์ที่ทำหน้าที่ “นับเวลา” อย่างต่อเนื่อง สามารถตั้งให้ “เรียกฟังก์ชันอัตโนมัติ” หรือ “สร้างสัญญาณ” ได้โดยไม่ต้องใช้
delay()
🕓 ตัวอย่างการใช้งานจริง
- กระพริบไฟ LED แบบไม่หยุดโปรแกรม
- วัดความถี่สัญญาณ
- สร้างคลื่นเสียง (Tone, Buzzer)
- สร้างสัญญาณ PWM
- ตั้งเวลาเรียก Interrupt เป็นช่วง ๆ
⚙️ 2. Timer vs Delay
| หัวข้อ | delay() | Timer |
|---|---|---|
| การทำงาน | หยุดโปรแกรมชั่วคราว | ทำงานเบื้องหลัง |
| ความแม่นยำ | ระดับมิลลิวินาที | ระดับไมโครวินาที |
| ทำอย่างอื่นระหว่างรอ | ❌ ไม่ได้ | ✅ ได้ |
| ใช้งานกับ Interrupt | ❌ ไม่ได้ | ✅ ได้ |
| เหมาะกับ | งานทั่วไป | งานควบคุมแบบ Real-Time |
🔹 3. การใช้ Timer เบื้องต้น (แนวคิด)
ใน Arduino และ ESP32 มี Hardware Timer หลายตัว ซึ่งทำงานแยกจาก CPU โดยตรง — หมายความว่า “ไมโครคอนโทรลเลอร์สามารถทำงานอื่นไปพร้อมกันได้”
🔹 4. Timer บน Arduino (UNO, Mega, Nano)
Arduino UNO มี Timer 3 ตัวในชิป ATmega328P:
| Timer | ความละเอียด | หน้าที่หลัก |
|---|---|---|
| Timer0 | 8-bit | ใช้กับ millis(), micros() |
| Timer1 | 16-bit | ใช้งาน PWM, Servo, หรือ Tone |
| Timer2 | 8-bit | PWM เพิ่มเติม |
แต่ในระดับพื้นฐาน Arduino ใช้คำสั่งง่าย ๆ ผ่านฟังก์ชัน เช่น millis(), micros(), tone(), noTone() หรือใช้ไลบรารี เช่น TimerOne, TimerThree เพื่อเรียก Interrupt อัตโนมัติ
🔹 5. การใช้ Timer แบบ Software (millis())
ฟังก์ชัน millis() คืนค่าเวลาที่ MCU ทำงานไปแล้ว (หน่วยมิลลิวินาที) สามารถใช้แทน delay() ได้โดยไม่หยุดโปรแกรม
📘 ตัวอย่าง: กระพริบไฟ LED โดยไม่ใช้ delay
const int led = 2;
unsigned long previous = 0;
const int interval = 1000; // 1 วินาที
void setup() {
pinMode(led, OUTPUT);
}
void loop() {
unsigned long current = millis();
if (current - previous >= interval) {
previous = current;
digitalWrite(led, !digitalRead(led));
}
}
✅ โปรแกรมยังสามารถทำอย่างอื่นได้ระหว่างรอเวลา
🔹 6. ฟังก์ชันที่เกี่ยวกับเวลาใน Arduino
| ฟังก์ชัน | หน่วย | ความหมาย |
|---|---|---|
delay(ms) | มิลลิวินาที | หน่วงเวลาทั้งโปรแกรม |
delayMicroseconds(us) | ไมโครวินาที | หน่วงสั้นระดับไมโคร |
millis() | มิลลิวินาที | เวลาที่ผ่านไปตั้งแต่เริ่มทำงาน |
micros() | ไมโครวินาที | เวลาที่ผ่านไปละเอียดกว่า millis |
yield() | – | ให้ระบบภายในทำงานระหว่างรอ (ESP32/ESP8266) |
🔹 7. Timer Interrupt (Arduino UNO)
สามารถใช้ไลบรารี TimerOne เพื่อเรียกฟังก์ชันอัตโนมัติเป็นระยะ
📘 ตัวอย่าง:
#include <TimerOne.h>
void blinkLED() {
digitalWrite(2, !digitalRead(2));
}
void setup() {
pinMode(2, OUTPUT);
Timer1.initialize(1000000); // 1,000,000 µs = 1 วินาที
Timer1.attachInterrupt(blinkLED);
}
void loop() {
// โค้ดหลักทำงานได้อิสระ
}
LED จะกระพริบทุก 1 วินาที โดยไม่ใช้
delay()
🔹 8. Timer ใน ESP32 (Hardware Timer)
ESP32 มี 4 Hardware Timers (0–3) แต่ละตัวมีความละเอียดสูง (64-bit) และสามารถเรียก ISR ได้ตามเวลาที่กำหนด
📘 ตัวอย่าง:
hw_timer_t *timer = NULL;
void IRAM_ATTR onTimer() {
digitalWrite(2, !digitalRead(2));
}
void setup() {
pinMode(2, OUTPUT);
timer = timerBegin(0, 80, true); // Timer0, Prescaler=80 → 1µs
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true); // เรียกทุก 1,000,000µs = 1s
timerAlarmEnable(timer);
}
void loop() {
// ทำงานอื่นต่อได้
}
💡 ใช้ได้พร้อมกันหลาย Timer เช่น Timer0 สำหรับ LED, Timer1 สำหรับ Sensor
🔹 9. การตั้งค่า Timer ESP32
| ฟังก์ชัน | ความหมาย |
|---|---|
timerBegin(timer, prescaler, countUp) | สร้าง Timer (0–3) |
timerAttachInterrupt() | ผูก ISR กับ Timer |
timerAlarmWrite(timer, time, autoReload) | ตั้งค่าเวลาเรียกซ้ำ |
timerAlarmEnable() / Disable() | เปิด/ปิด Timer |
timerWrite(timer, 0) | รีเซ็ต Timer |
🔹 10. การสร้างสัญญาณ PWM ขั้นสูง
PWM (Pulse Width Modulation) คือการส่งคลื่นสี่เหลี่ยมสลับ HIGH/LOW โดยควบคุม “อัตราส่วนเวลา HIGH” หรือ “Duty Cycle (%)”
| ค่าที่ส่ง | Duty Cycle | ความหมาย |
|---|---|---|
| 0 | 0% | 0V (ปิดสนิท) |
| 128 | 50% | ครึ่งแรงดัน |
| 255 | 100% | เต็มแรงดัน |
🔹 11. PWM ใน Arduino
Arduino ใช้คำสั่ง:
analogWrite(pin, value);
📘 ตัวอย่าง:
analogWrite(9, 128); // สร้างคลื่น 50% duty cycle
ความถี่ PWM ~490Hz (ปกติ) หรือ 980Hz (บางขา)
🔹 12. PWM ใน ESP32 (แบบละเอียด)
ESP32 มีระบบ PWM ที่ยืดหยุ่นมาก (เรียกว่า LEDC)
ledcSetup(channel, freq, resolution_bits);
ledcAttachPin(pin, channel);
ledcWrite(channel, duty);
📘 ตัวอย่าง:
const int led = 2;
void setup() {
ledcSetup(0, 5000, 8); // Channel 0, 5kHz, 8-bit
ledcAttachPin(led, 0);
}
void loop() {
for (int i = 0; i <= 255; i++) {
ledcWrite(0, i); // เพิ่มความสว่าง LED
delay(5);
}
for (int i = 255; i >= 0; i--) {
ledcWrite(0, i);
delay(5);
}
}
ใช้ได้หลาย Channel (สูงสุด 16 ช่อง) และตั้งความถี่ต่างกันได้แต่ละขา!
🔹 13. การสร้างเสียงด้วย PWM (Buzzer / Tone)
📘 Arduino:
tone(8, 1000); // ส่งเสียง 1kHz
delay(500);
noTone(8);
📘 ESP32 (แบบแม่นยำกว่า):
const int buzzer = 25;
void setup() {
ledcSetup(1, 1000, 8);
ledcAttachPin(buzzer, 1);
ledcWriteTone(1, 1000);
}
🔹 14. PWM ควบคุมความเร็วมอเตอร์
ใช้ค่า Duty Cycle เพื่อปรับแรงดันเฉลี่ยให้มอเตอร์หมุนเร็ว–ช้าได้
📘 ตัวอย่าง:
int motorPin = 14;
void setup() {
ledcSetup(0, 20000, 8); // 20kHz (ลดเสียง)
ledcAttachPin(motorPin, 0);
}
void loop() {
ledcWrite(0, 128); // ครึ่งแรงดัน = หมุนปานกลาง
}
📚 15. แบบฝึกหัด
1️⃣ ใช้ millis() กระพริบไฟ LED โดยไม่ใช้ delay()
2️⃣ เขียนโปรแกรมใช้ Timer Interrupt ให้เรียกฟังก์ชันทุก 500ms
3️⃣ ใช้ PWM ควบคุมความสว่าง LED แบบ Fade In–Out
4️⃣ ใช้ PWM ควบคุมความเร็วพัดลมหรือมอเตอร์ DC
5️⃣ ทดลองตั้งค่าความถี่ PWM ต่างกัน (1kHz, 5kHz, 20kHz) แล้วสังเกตเสียงจาก Buzzer
🧾 16. สรุปแนวคิดสำคัญ
| หัวข้อ | อธิบาย |
|---|---|
| Timer | ตัวนับเวลาภายใน MCU ทำงานอัตโนมัติ |
| millis() / micros() | ใช้วัดเวลาโดยไม่หยุดโปรแกรม |
| Timer Interrupt | เรียก ISR ตามเวลาที่ตั้งไว้ |
| PWM | สร้างแรงดันจำลองโดยควบคุม Duty Cycle |
| analogWrite() | ควบคุม PWM ใน Arduino |
| ledcWrite() | ควบคุม PWM ใน ESP32 (หลายช่อง, หลายความถี่) |
| tone() / noTone() | สร้างเสียงด้วย PWM |
| ใช้ Timer กับ ISR | สำหรับงาน Real-Time เช่น Sensor หรือ Motor |
🧠 สรุปภาพรวมความสัมพันธ์
┌──────────────────────┐
│ Timer Hardware │
│ (นับเวลาอัตโนมัติ) │
└─────────┬────────────┘
│
┌─────────┴──────┐
│ │
┌────▼─────┐ ┌────▼─────┐
│ Timer ISR │ │ PWM Unit │
│ เรียกฟังก์ชันเมื่อครบเวลา│ สร้างคลื่น PWM │
└──────────┘ └──────────┘
