สวัสดีครับนักศึกษาทุกคน ในบทที่แล้วเราเชื่อมต่อ ESP32 เข้ากับ Blynk Server ได้แล้ว (เห็นสถานะ Online) แต่มันยังทำอะไรไม่ได้เลยนอกจากโชว์ว่าต่อเน็ตติด

วันนี้เราจะมาทำให้มัน “มีชีวิต” กันครับ โดยเราจะเรียนรู้ 2 คำสั่งสำคัญที่สุดของ Blynk คือ:

  1. BLYNK_WRITE: เมื่อเรากดปุ่มในมือถือ -> บอร์ดจะทำอะไร? (App to Board)
  2. Blynk.virtualWrite: เมื่อบอร์ดอ่านค่าเซนเซอร์ได้ -> ส่งขึ้นไปโชว์บนมือถืออย่างไร? (Board to App)

และที่สำคัญ เราจะมาเรียนรู้วิธีแก้ปัญหา “Blynk หลุดบ่อย” ด้วยการใช้ Software Timer แทน delay() กันครับ


1. รู้จักกับ “Virtual Pin” (ตัวแปรสมมติ)

ในบทที่แล้วเราสร้าง Datastream ชื่อ V0 ไปแล้ว คำว่า V (Virtual) หรือ “ขาเสมือน” คือช่องทางส่งข้อมูลพิเศษที่ Blynk สร้างขึ้นมาให้เราคุยกัน

  • แทนที่เราจะสั่งงานขา GPIO 23 โดยตรง เราจะสั่งผ่าน V0
  • จากนั้นเราค่อยเขียนโค้ดบอกบอร์ดว่า “ถ้ามีคำสั่งมาที่ V0 ให้ไปเปิดไฟที่ขา 23 นะ”
  • วิธีนี้ทำให้เรายืดหยุ่นมาก จะเอา V0 ไปสั่งเปิดไฟ, สั่งหมุนมอเตอร์ หรือสั่ง Reset บอร์ดก็ได้ ตามแต่ใจเรากำหนด

2. ส่วนที่ 1: สั่งงานจากมือถือ (App -> Board)

เราจะใช้ฟังก์ชันพิเศษที่อยู่นอก loop() ชื่อว่า BLYNK_WRITE(Vpin) ครับ

หลักการ: เมื่อมีการกดปุ่ม V0 บนมือถือ ฟังก์ชันนี้จะถูกเรียกใช้งานทันที (เหมือน Interrupt)

C++
// เมื่อมีการเปลี่ยนแปลงค่าที่ V0 (กดปุ่มบนแอพ)
BLYNK_WRITE(V0) {
  int pinValue = param.asInt(); // รับค่าที่ส่งมา (0 หรือ 1)
  
  if (pinValue == 1) {
    digitalWrite(23, HIGH); // สั่งเปิดไฟ
    Serial.println("Turn ON");
  } else {
    digitalWrite(23, LOW);  // สั่งปิดไฟ
    Serial.println("Turn OFF");
  }
}

3. ส่วนที่ 2: ส่งค่าขึ้นมือถือ (Board -> App) และกับดักของ delay

ถ้าเราอยากส่งค่าอุณหภูมิขึ้นไปโชว์ เราใช้คำสั่ง Blynk.virtualWrite(V1, temperature); ได้เลย แต่…

ห้าม! เอาคำสั่งนี้ไปใส่ใน void loop พร้อม delay() เด็ดขาด!

ทำไม? เพราะ Blynk.run() ใน loop ต้องการทำงานตลอดเวลาเพื่อรักษาการเชื่อมต่อ ถ้าเราใส่ delay(2000) บอร์ดจะหยุดทำงานไป 2 วินาที ทำให้ Blynk Server คิดว่าบอร์ดตาย (Offline) และตัดการเชื่อมต่อทันที (Connection Lost)

ทางแก้: ใช้ BlynkTimer เราจะใช้ตัวช่วยที่ชื่อ BlynkTimer มานับเวลาแทนครับ เช่น “ให้ทำงานทุกๆ 1 วินาที” โดยไม่ไปขวางการทำงานหลัก


4. ปฏิบัติการ: ระบบ Smart Home จำลอง

เราจะรวมทุกอย่างเข้าด้วยกัน:

  1. ปุ่มบนมือถือ (V0): สั่งเปิด-ปิด LED (ที่ขา 23)
  2. เกจบนมือถือ (V1): แสดงค่าจำลอง (Random) หรือค่าจาก Potentiometer

การเตรียม App (Blynk Console):

  1. เพิ่ม Datastream V1 (Data Type: Integer, Min: 0, Max: 100)
  2. ใน Dashboard บนมือถือ ลาก Gauge (เกจวัด) มาวาง เลือก Datastream เป็น V1

โค้ดโปรแกรมฉบับสมบูรณ์:

C++
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"      // **แก้ไขเป็นของตัวเอง**
#define BLYNK_TEMPLATE_NAME "ESP32 Smart Home"
#define BLYNK_AUTH_TOKEN "YourAuthToken"    // **แก้ไขเป็นของตัวเอง**

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char ssid[] = "YOUR_WIFI_NAME"; // **แก้ไข**
char pass[] = "YOUR_WIFI_PASS"; // **แก้ไข**

BlynkTimer timer; // ประกาศตัวแปร Timer

const int ledPin = 23; // ขา LED

// ฟังก์ชันนี้จะถูกเรียกทุกๆ 1 วินาที (ตามที่เราตั้งไว้ข้างล่าง)
void myTimerEvent() {
  // จำลองค่าเซนเซอร์ (สุ่มเลข 0-100)
  // ในงานจริง ให้เอาค่าจาก dht.readTemperature() หรือ analogRead() มาใส่แทน
  int sensorVal = random(0, 100); 
  
  // ส่งค่าไปที่ V1 บนแอป
  Blynk.virtualWrite(V1, sensorVal);
  
  Serial.print("Sending Data: ");
  Serial.println(sensorVal);
}

// รับคำสั่งจากปุ่ม V0
BLYNK_WRITE(V0) {
  int p = param.asInt();
  digitalWrite(ledPin, p); // เขียนค่า 0 หรือ 1 ลงขา LED โดยตรงได้เลย
}

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);

  // ตั้งเวลา: ให้เรียกฟังก์ชัน myTimerEvent ทุกๆ 1000ms (1 วินาที)
  timer.setInterval(1000L, myTimerEvent);
}

void loop() {
  Blynk.run(); // ห้ามลบ! ห้ามมี delay ใน loop!
  timer.run(); // สั่งให้ Timer ทำงาน
}

5. ดูผลลัพธ์

  1. Upload โค้ด
  2. เปิดแอป Blynk ในมือถือ
  3. กดปุ่ม V0: ไฟ LED ที่บอร์ดต้องติด/ดับ ตามมือเรากด (Latency ต่ำมาก กดปุ๊บติดปั๊บ)
  4. ดูที่ Gauge V1: เข็มวัดต้องขยับเปลี่ยนค่าทุกๆ 1 วินาที ตามเลขที่สุ่มได้

สรุปท้ายบท

วันนี้เราได้ก้าวข้ามขีดจำกัดสำคัญที่สุดของการเขียนโปรแกรม IoT คือ “Multitasking” (การทำงานหลายอย่างพร้อมกัน) โดยใช้ BlynkTimer ทำให้เราสามารถส่งข้อมูลเซนเซอร์ขึ้นไปโชว์ได้เรื่อยๆ โดยที่ยังกดปุ่มสั่งงาน LED ได้อย่างลื่นไหล ไม่หน่วง ไม่หลุดครับ

ภารกิจต่อไป: ตอนนี้เราควบคุมผ่านมือถือได้แล้ว แต่… ถ้าเราเปิดไฟทิ้งไว้แล้วเน็ตหลุดล่ะ? หรือไฟดับแล้วติดใหม่? ระบบจะจำค่าเดิมได้ไหม? บทความหน้าเราจะมาเรียนรู้เรื่อง “Automation & Notification” บน Blynk (การแจ้งเตือนเข้ามือถือเมื่อค่าเกินกำหนด) กันครับ


หมายเหตุ:

  • เรื่อง BlynkTimer เป็นเรื่องที่เด็ก ปวส. มักจะงงในตอนแรก แต่ถ้าเขาเข้าใจแล้ว มันจะเป็นพื้นฐานที่ดีมากในการเขียนโปรแกรมแบบ Non-blocking ในอนาคตครับ
  • ย้ำ นักศึกษาเรื่อง Template ID อีกครั้งครับ ถ้าไม่แก้ โค้ดจะ Compile ผ่านแต่ต่อ Server ไม่ได้ครับ