วันที่ 1 โครงสร้างพื้นฐานและการรับรู้ข้อมูล (Infrastructure & Perception Layer)

IoT คืออะไร ?

IoT ย่อมาจากคำว่า Internet of Things ถ้าแปลตรงตัวคือ “อินเทอร์เน็ตของสรรพสิ่ง” แต่ความหมายจริงๆ ของมันสนุกกว่านั้นมาก

ให้นักศึกษาลองจินตนาการว่า ปกติแล้วสิ่งของรอบตัวเรา (Things) เช่น หลอดไฟ พัดลม ปั๊มน้ำ หรือแปลงผัก มันเป็นสิ่งไม่มีชีวิตที่ “พูดไม่ได้” และ “คิดเองไม่เป็น” เราต้องเดินไปกดสวิตช์หรือลงมือทำด้วยตัวเองมันถึงจะทำงาน

แต่จะเกิดอะไรขึ้น… ถ้าเราจับสิ่งของธรรมดาๆ พวกนี้ มาติด “สมองกล” และเชื่อมต่อ Wi-Fi ให้มัน

สิ่งของเหล่านั้นจะตื่นขึ้นมา “คุยกันเองได้” และ “รายงานสถานะให้เรารู้ได้” ทันที นี่แหละคือหัวใจของ IoT

💡 ตัวอย่าง IoT ในชีวิตจริงที่เราพบบ่อย

  • Smart Farm (ฟาร์มอัจฉริยะ) เซนเซอร์ตรวจจับได้ว่าดินในแปลงผักแห้งเกินไป ระบบจึงสั่งเปิดปั๊มน้ำอัตโนมัติ
  • Smart Home (บ้านอัจฉริยะ) นักศึกษาออกมาจากบ้านแล้วเพิ่งนึกได้ว่าลืมปิดแอร์ ก็แค่หยิบมือถือขึ้นมากดปิดแอร์ผ่านแอปพลิเคชันได้เลย
  • Smart Band (นาฬิกาสุขภาพ) นาฬิกาที่ใส่อยู่คอยวัดอัตราการเต้นของหัวใจ แล้วส่งข้อมูลไปเก็บในมือถือ เพื่อวิเคราะห์สุขภาพของเรา

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


3 โครงสร้างหลักของระบบ IoT (3-Layer Architecture)

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

ให้นึกภาพว่าระบบ IoT ทำงานประสานกันเหมือน “ร่างกายมนุษย์” ซึ่งสามารถแบ่งออกเป็น 3 ส่วนหลักๆ ดังนี้

1. Perception Layer (ชั้นรับรู้ข้อมูล) 🦾

  • เปรียบเสมือน อวัยวะรับสัมผัส และกล้ามเนื้อของร่างกาย
  • หน้าที่หลัก คอยดักจับข้อมูลจากสภาพแวดล้อมรอบตัว และลงมือทำงานตามคำสั่ง
  • อุปกรณ์ในงานจริง
    • ฝ่ายรับรู้ เซนเซอร์วัดความชื้นในดิน เซนเซอร์วัดอุณหภูมิ เซนเซอร์รับแสง
    • ฝ่ายลงมือทำ รีเลย์ (Relay) ปั๊มน้ำ พัดลมระบายอากาศ

2. Network Layer (ชั้นเครือข่ายสื่อสาร) ⚡

  • เปรียบเสมือน ระบบเส้นประสาทที่คอยวิ่งส่งสัญญาณไปทั่วร่างกาย
  • หน้าที่หลัก เป็นสะพานเชื่อม ส่งต่อข้อมูลจากเซนเซอร์ไปหาหน้าจอ และรับคำสั่งจากหน้าจอส่งกลับมาที่อุปกรณ์ควบคุม
  • อุปกรณ์ในงานจริง ตัวบอร์ดไมโครคอนโทรลเลอร์ เช่น บอร์ด ESP32 สัญญาณ Wi-Fi Bluetooth หรือสาย LAN ที่ทำหน้าที่เป็นตัวกลางส่งข้อมูลขึ้นอินเทอร์เน็ต

3. Application Layer (ชั้นประยุกต์ใช้งาน) 🧠

  • เปรียบเสมือน สมองที่ใช้สั่งการ และหน้าจอที่ให้เราสื่อสารกับระบบได้
  • หน้าที่หลัก นำข้อมูลที่ได้มาแสดงผลให้มนุษย์เข้าใจง่ายๆ และเป็นศูนย์กลางให้เรากดปุ่มสั่งงานระบบทั้งหมด
  • อุปกรณ์ในงานจริง แอปพลิเคชันบนมือถือ หน้า Dashboard สรุปข้อมูล

💡 ตัวอย่างขั้นตอนการทำงาน เซนเซอร์อ่านค่าความชื้นดิน (Layer 1) ➡️ ส่งข้อมูลผ่าน Wi-Fi ของบอร์ด (Layer 2) ➡️ ไปโชว์กราฟบนแอปมือถือ (Layer 3)


ทำความรู้จัก บอร์ด ESP32

บอร์ด ESP32 คืออะไร

ESP32 (อี-เอส-พี-สาม-สิบ-สอง) คือ ไมโครคอนโทรลเลอร์ (Microcontroller) เรียกง่ายๆว่า “สมองกลขนาดจิ๋ว” ที่ถูกสร้างขึ้นมาเพื่อควบคุมการทำงานของอุปกรณ์อิเล็กทรอนิกส์ต่างๆ

สิ่งที่ทำให้ ESP32 แตกต่างและล้ำหน้ากว่าบอร์ดรุ่นเก่าๆ คือมัน มี Wi-Fi และ Bluetooth ในตัว ทำให้มันเปรียบเสมือนกุญแจสำคัญที่ทำให้อุปกรณ์ธรรมดาๆสามารถเชื่อมต่ออินเทอร์เน็ตและกลายเป็นอุปกรณ์ IoT (Internet of Things) ได้ทันที

จุดเด่นที่ทำให้ ESP32 ได้รับความนิยม

  • เก่งและเร็ว มีหน่วยประมวลผลแบบ Dual-Core (ทำงานได้ 2 แกนสมองพร้อมกัน) ทำให้ประมวลผลคำสั่งหรือเซนเซอร์หลายตัวได้ลื่นไหล
  • เชื่อมต่อไร้สายได้ทันที ไม่ต้องซื้อโมดูล Wi-Fi หรือ Bluetooth มาต่อเพิ่มให้วุ่นวาย เพราะฝังมาให้แล้วในชิปเดียว
  • ขั้วต่อ (GPIO) หลากหลาย มีขาเสียบสายไฟสำหรับต่อกับเซนเซอร์ มอเตอร์ หลอดไฟได้เยอะมาก รองรับการอ่านค่าทั้งแบบดิจิทัล (Digital) และอนาล็อก (Analog)
  • ประหยัดพลังงาน มีโหมด Deep Sleep ที่กินไฟน้อยมาก เหมาะสำหรับการนำไปทำอุปกรณ์ที่ต้องใช้แบตเตอรี่
  • ราคาคุ้มค่า เมื่อเทียบกับความสามารถระดับนี้ ESP32 ถือว่ามีราคาที่เข้าถึงได้ง่ายมากสำหรับนักศึกษาและนักพัฒนา (ประมาณ 200 บาท)

ESP32 นำไปสร้างโปรเจกต์อะไรได้บ้าง

ด้วยความที่มันต่ออินเทอร์เน็ตได้ การประยุกต์ใช้งานจึงไร้ขีดจำกัด

  • ระบบสมาร์ทฟาร์ม (Smart Farm) นำบอร์ดไปต่อกับเซนเซอร์วัดความชื้นในดินและเซนเซอร์วัดอุณหภูมิ เพื่อประมวลผลและสั่งเปิด-ปิดปั๊มน้ำอัตโนมัติ
  • ระบบควบคุมผ่านแอปพลิเคชัน (Blynk IoT) สร้างระบบรดน้ำต้นไม้อัจฉริยะที่สามารถดูสถานะและกดสั่งการผ่านหน้าจอมือถือได้จากทุกที่บนโลก
  • ระบบแจ้งเตือน (Notification System) ทำระบบตรวจจับผู้บุกรุก และให้บอร์ดส่งข้อความแจ้งเตือนเข้าแอปพลิเคชัน LINE

ส่วนประกอบพื้นฐานบนบอร์ดที่ควรรู้จัก

เมื่อหยิบบอร์ด ESP32 ขึ้นมาดู จะพบกับส่วนประกอบหลักๆ ดังนี้

  1. ชิป ESP32 กล่องสี่เหลี่ยมโลหะตรงกลาง คือหัวใจหลักที่ใช้ประมวลผลและส่งสัญญาณไร้สาย
  2. พอร์ต USB (Micro-USB หรือ Type-C) ใช้สำหรับเสียบสายเชื่อมต่อกับคอมพิวเตอร์เพื่ออัปโหลดโค้ดโปรแกรม และใช้เป็นช่องรับไฟเลี้ยงบอร์ด
  3. ปุ่ม EN (Enable) ใช้สำหรับกดเพื่อรีเซ็ต (Reset) การทำงานของบอร์ด
  4. ปุ่ม BOOT ใช้กดค้างไว้ในบางกรณีที่บอร์ดไม่ยอมรับการอัปโหลดโค้ดจากคอมพิวเตอร์
  5. ขา GPIO (General Purpose Input/Output) ขาเข็มโลหะรอบๆบอร์ด ใช้สำหรับเสียบสายไฟจัมเปอร์ (Jumper) เพื่อรับข้อมูลจากเซนเซอร์ หรือส่งไฟไปสั่งการอุปกรณ์อื่น

เราจะสั่งงาน ESP32 ได้อย่างไร

บอร์ด ESP32 ไม่สามารถคิดเองได้ เราต้องเป็นคนเขียนคำสั่ง (Code) ลงไปให้มัน โดยเครื่องมือที่นิยมใช้กันมากที่สุดในหมู่นักศึกษา คือ Arduino IDE ซึ่งใช้ภาษา C/C++ ในการเขียนคำสั่ง นอกจากนี้ยังรองรับการเขียนด้วยภาษา Python (MicroPython) ด้วย


เตรียมความพร้อมก่อนเริ่มเขียนโค้ด

ขั้นตอนที่ 1 ติดตั้งโปรแกรม Arduino IDE

  1. ไปที่เว็บไซต์ทางการ arduino.cc
  2. เลือกดาวน์โหลดเวอร์ชันล่าสุด แล้วทำการ Install ลงเครื่องตามปกติเหมือนลงโปรแกรมทั่วไป

ขั้นตอนที่ 2 ติดตั้ง Driver สำหรับสื่อสารกับบอร์ด

คอมพิวเตอร์จะคุยกับบอร์ด ESP32 ผ่านสาย USB ได้ ต้องมี Driver ก่อน ซึ่งบอร์ดส่วนใหญ่ในท้องตลาดจะใช้ชิปสื่อสารอยู่ 2 ยี่ห้อ

  1. ชิป CP2102 (Silicon Labs) ส่วนใหญ่บอร์ดจะมีชิปตัวสี่เหลี่ยมจัตุรัสเล็ก ๆ
    1. ดาวน์โหลด CP210x Driver
  2. ชิป CH340 (QinHeng) บอร์ดรุ่นประหยัดมักใช้ชิปตัวสี่เหลี่ยมผืนผ้าขนาดยาว
    1. ดาวน์โหลด CH340 Driver

ขั้นตอนที่ 3 การเพิ่มบอร์ด ESP32 ลงใน Arduino IDE

โปรแกรมเริ่มต้นจะยังไม่รู้จักบอร์ด ESP32 เราต้องไปลงทะเบียนบอร์ดเพิ่มตามขั้นตอนนี้

3.1 เพิ่ม URL ของบอร์ด (Additional Boards Manager URLs)

  1. เปิดโปรแกรม Arduino IDE
  2. ไปที่เมนู File > Preferences
  3. มองหาช่องที่ชื่อว่า Additional Boards Manager URLs
  4. คัดลอกลิงก์ด้านล่างนี้ไปวางในช่องนั้น (หากมีลิงก์อื่นอยู่ก่อนแล้ว ให้กดปุ่มด้านขวาของช่องเพื่อขึ้นบรรทัดใหม่แล้ววางลิงก์เพิ่มเข้าไป)

https//raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

3.2 ติดตั้งบอร์ดผ่าน Boards Manager

  1. ไปที่แถบเครื่องมือด้านซ้าย เลือกไอคอน Boards Manager (หรือไปที่ Tools > Board > Boards Manager…)
  2. ในช่องค้นหา ให้พิมพ์คำว่า “esp32”
  3. เลือกตัวที่พัฒนาโดย Espressif Systems และกดปุ่ม Install
  4. รอจนโปรแกรมดาวน์โหลดและติดตั้งสำเร็จ (อาจใช้เวลา 1-3 นาทีขึ้นอยู่กับความเร็วอินเทอร์เน็ต)

ขั้นตอนที่ 4 การเลือกบอร์ดและพอร์ตก่อนเริ่มงาน

  1. ไปที่เมนู Tools > Board > esp32
  2. เลือกชื่อบอร์ดให้ตรงกับที่เราใช้ (ส่วนใหญ่คือ DOIT ESP32 DEVKIT V1 หรือ ESP32 Dev Module)
  3. ไปที่เมนู Tools > Port
  4. เลือกหมายเลข COM Port เช่น COM3 หรือ COM5

Lab 1 ควบคุมสวิตช์ไฟฟ้า (Relay Module)

https://wokwi.com/projects/461608713858843649

เป้าหมาย เพื่อให้นักศึกษาสามารถเขียนโค้ดควบคุมขา Digital Output ของ ESP32 เพื่อสั่งเปิด-ปิด Relay ซึ่งเปรียบเสมือนสวิตช์อัจฉริยะในฟาร์มของเรา

อุปกรณ์ที่ใช้

  • บอร์ด ESP32
  • Relay Module (1-Channel)
  • สาย Jumper (แบบ M-F)

การต่อวงจร (Wiring Diagram)

ให้นักศึกษาต่อสายสัญญาณระหว่าง ESP32 และ Relay ตามรายละเอียดดังนี้

ขาของ Relayเชื่อมต่อกับ ESP32หน้าที่
VCCVIN (5V จาก USB)จ่ายไฟเลี้ยงให้ขดลวดใน Relay
GNDGNDต่อสายดินร่วมกัน
IN / SignalGPIO 2รับคำสั่ง Digital (0 หรือ 1) จากบอร์ด

ข้อควรระวัง บอร์ด ESP32 ทำงานที่แรงดันไฟฟ้า 3.3V เท่านั้น ห้ามเอาไฟ 5V ป้อนเข้าขา Input อื่น ๆ โดยตรง เพราะบอร์ดอาจพังได้ทันที

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

void setup() {
  // ตั้งค่าขา GPIO 2 ให้ทำหน้าที่เป็น "ขาออก" (Output)
  pinMode(2, OUTPUT); 
}

void loop() {
  // สั่งให้ Relay ทำงาน (เปิดปั๊มน้ำ)
  digitalWrite(2, HIGH); 
  delay(5000);           // หน่วงเวลาให้ปั๊มทำงาน 5 วินาที

  // สั่งให้ Relay หยุดทำงาน (ปิดปั๊มน้ำ)
  digitalWrite(2, LOW);  
  delay(5000);           // หน่วงเวลาให้ปั๊มหยุดพัก 5 วินาที
}

คำอธิบายการทำงาน

  • pinMode(2, OUTPUT) เป็นการบอก ESP32 ว่าเราจะส่งกระแสไฟฟ้าออกที่ขา 2 นะ
  • digitalWrite(2, HIGH) ส่งไฟออกไป (Logic 1) เพื่อกระตุ้นให้ Relay ทำงาน
  • digitalWrite(2, LOW) ตัดไฟ (Logic 0) เพื่อให้ Relay หยุดทำงาน
  • delay(5000) สั่งให้บอร์ดรอ โดยหน่วยเป็นมิลลิวินาที (5000 ms = 5 วินาที)
  • คำสั่ง pinMode(2, OUTPUT)
  • เปรียบเสมือนการตั้งค่าหน้าที่ให้กับขา GPIO ของบอร์ดไมโครคอนโทรลเลอร์ เพื่อเปลี่ยนสถานะจากค่าเริ่มต้นที่เป็นทางรับสัญญาณ (Input) ให้กลายเป็นทางส่งสัญญาณไฟฟ้า (Output) ซึ่งจะไปช่วยเปิดวงจรภายในให้สามารถจ่ายกระแสไฟออกมาได้เพียงพอสำหรับขับอุปกรณ์ภายนอกอย่าง Relay หากเราลืมประกาศคำสั่งนี้ ขาพินจะไม่มีกำลังไฟพอที่จะสั่งให้ Relay ทำงาน แม้ว่าเราจะเขียนโค้ดสั่งให้เป็น HIGH แล้วก็ตาม

💡 โจทย์ท้าทาย (Smart Farm Challenge)

เมื่อนักศึกษาทำ Lab 1 สำเร็จแล้ว ลองจินตนาการว่าหากเราต้องการรดน้ำต้นไม้แบบ “สั้น ๆ แต่บ่อย” ให้นักศึกษาลองแก้โค้ดให้ เปิดปั๊มน้ำ 2 วินาที และปิดพัก 10 วินาที ลองดูว่าต้องเปลี่ยนตัวเลขที่บรรทัดไหนบ้าง

คำแนะนำ สังเกตไฟ LED บนบอร์ด ESP32 จะกระพริบไปพร้อมกับเสียง “แต๊ก” ของ Relay แสดงว่าระบบทำงานถูกต้อง


Lab 2 การอ่านค่าเซนเซอร์ความชื้นดิน (Analog Input)

เป้าหมาย เรียนรู้การรับสัญญาณแบบ Analog เพื่อวัดความชื้นในดิน และทำความเข้าใจระบบการแปลงสัญญาณของ ESP32

ทฤษฎีไอที ADC Resolution คืออะไร

เนื่องจากคอมพิวเตอร์เข้าใจแต่เลข 0 กับ 1 แต่โลกแห่งความเป็นจริงมีความละเอียดมากกว่านั้น

  • ESP32 มีความละเอียดของตัวแปลงสัญญาณ (ADC) อยู่ที่ 12-bit
  • นั่นหมายความว่ามันจะเปลี่ยนแรงดันไฟฟ้าจากเซนเซอร์ให้เป็นตัวเลขดิจิทัลได้ตั้งแต่ 0 ถึง 4095 ระดับครับ

ทำไมต้อง Map ค่าให้เป็น 0-100%

ในงาน IoT การวัดความชื้นดินด้วยบอร์ด ESP32 มีความละเอียดของ ADC อยู่ที่ 12-bit ซึ่งจะแปลงแรงดันไฟฟ้าเป็นตัวเลข 0 ถึง 4095

ความละเอียดแบบ 12-bit สามารถสร้างขั้นบันไดของข้อมูลได้ทั้งหมด 4,096 ระดับ (แต่ในทางคอมพิวเตอร์เราเริ่มนับระดับแรกที่เลข 0 จึงได้เลขสุดท้ายเป็น 4,095 ระดับ)

  • ค่า 4095 หมายถึง ดินแห้งสนิท
  • ค่า 0 หมายถึง ดินเปียกที่สุด
  • ปัญหา ตัวเลข 4095 นั้น อ่านเข้าใจยากสำหรับผู้ใช้งานทั่วไปหรือเกษตรกร การแปลงให้เป็น 0-100% จึงช่วยให้สื่อสารได้เข้าใจง่ายกว่ามาก

อุปกรณ์ที่ใช้

  • บอร์ด ESP32
  • เซนเซอร์ความชื้นดิน (Soil Moisture Sensor)
  • สาย Jumper (แบบ M-F)

การต่อวงจร (Wiring Diagram)

ให้นักศึกษาต่อสายเซนเซอร์เข้ากับบอร์ดตามตารางนี้

ขาของเซนเซอร์เชื่อมต่อกับ ESP32หน้าที่
VCC3.3Vจ่ายไฟเลี้ยงเซนเซอร์ (ห้ามต่อ 5V)
GNDGNDต่อสายดินร่วมกัน
AO (Analog Out)GPIO 34ส่งสัญญาณแรงดันไฟฟ้า (Analog)

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

ดูค่าที่เซนเซอร์อ่านได้ผ่านทาง Serial Monitor

void setup() {
  // เริ่มการสื่อสารกับคอมพิวเตอร์ที่ความเร็ว 115200
  Serial.begin(115200);
}

void loop() {
  // อ่านค่าจากขา Analog 34
  int rawValue = analogRead(34);

  // แปลงค่า 0-4095 ให้เป็น 0-100% เพื่อให้อ่านง่าย
  // สมมติว่า 4095 คือแห้งสนิท และ 0 คือเปียกที่สุด
  int percent = map(rawValue, 4095, 0, 0, 100);

  Serial.print("Raw Value ");
  Serial.print(rawValue);
  Serial.print(" | Moisture ");
  Serial.print(percent);
  Serial.println("%");

  delay(1000); // อ่านค่าทุกๆ 1 วินาที

}

โครงสร้างของฟังก์ชัน map()

ในภาษา C++ ของ Arduino เราใช้ฟังก์ชันสำเร็จรูปที่มีรูปแบบดังนี้

map(value, fromLow, fromHigh, toLow, toHigh)

พารามิเตอร์ความหมาย
valueตัวแปรที่เก็บค่า “ต้นทาง” ที่อ่านได้จากเซนเซอร์
fromLowค่าต่ำสุดของช่วงต้นทาง เช่น 0
fromHighค่าสูงสุดของช่วงต้นทาง เช่น 4095
toLowค่าต่ำสุดของช่วงปลายทางที่เราต้องการ เช่น 0%
toHighค่าสูงสุดของช่วงปลายทางที่เราต้องการ เช่น 100%

ขั้นตอนการทดลอง

  1. เปิด Serial Monitor ไปที่เมนู Tools > Serial Monitor และปรับความเร็วเป็น 115200 baud
  2. สังเกตค่าในอากาศ เมื่อเซนเซอร์แห้ง ค่าตัวเลขดิจิทัล (Raw Value) ควรจะสูงใกล้เคียง 4095
  3. สังเกตค่าในน้ำ ลองนำเซนเซอร์ไปจุ่มในแก้วน้ำ ค่าตัวเลขจะลดต่ำลง

💡 โจทย์ท้าทาย (IT Integration)

ให้นักศึกษานำความรู้จาก Lab 1 มาผสมกับ Lab 2 “เขียนเงื่อนไข If-Else ให้ Relay ทำงาน”

Lab 2.1 ระบบรดน้ำอัตโนมัติ (Basic Auto-Watering)

โจทย์ ให้นักศึกษาเขียนโปรแกรมให้ระบบรดน้ำทำงานเองโดยไม่ต้องใช้คนสั่ง

จุดประสงค์ ฝึกการใช้เงื่อนไข if-else มาควบคุมอุปกรณ์ตามค่าที่อ่านได้จากเซนเซอร์จริง

กำหนดเงื่อนไข

  • หากค่าความชื้นดินที่อ่านได้ ต่ำกว่า 40% ให้สั่งเปิด Relay (ปั๊มน้ำ) ทันที
  • หากค่าความชื้นดิน มากกว่า 80% ให้สั่งปิด Relay เพื่อประหยัดน้ำ

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

//การประกาศตัวแปร เป็นการตั้งชื่อเล่นให้กับขา (Pin) ของบอร์ด ESP32
//int (Integer)ใช้เก็บข้อมูลตัวเลขจำนวนเต็ม
int soilPin = 34;  // ขาอ่านค่าความชื้นดิน 
int relayPin = 2;  // ขาสั่งงาน Relay 

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

void loop() {
  int rawValue = analogRead(soilPin); 
  // แปลงค่า 4095 (แห้ง) - 0 (เปียก) เป็น 0-100% 
  int percent = map(rawValue, 4095, 0, 0, 100); 

  if (percent < 40) { 
    digitalWrite(relayPin, HIGH); // ดินแห้งเกินไป เปิดปั๊ม
    Serial.println("ดินแห้ง กำลังรดน้ำ...");
  } else if (percent > 80) {
    digitalWrite(relayPin, LOW);  // ดินเปียกชุ่มพอแล้ว ปิดปั๊ม
    Serial.println("ดินชุ่มพอแล้ว หยุดรดน้ำ");
  }

  delay(1000); 
}

Lab 2.2 ระบบไฟเตือนสถานะดิน (Visual Status Monitor)

โจทย์ นำไฟ LED (แดง เหลือง เขียว) มาเพิ่ม เพื่อแสดงสถานะความชื้นในดินให้ชัดเจน

จุดประสงค์ ฝึกการจัดการขา Output หลายตัวพร้อมกันตามช่วงข้อมูลที่ซับซ้อนขึ้น

กำหนดเงื่อนไข

  • ไฟสีแดง ติดเมื่อดินแห้งวิกฤต (ความชื้น < 20%) และสั่งเปิดปั๊มน้ำ
  • ไฟสีเหลือง ติดเมื่อความชื้นอยู่ในระดับที่เหมาะสม (20% – 70%) และสั่งปิดปั๊มน้ำ
  • ไฟสีเขียว ติดเมื่อดินเปียกมาก (> 70%) เพื่อเตือนว่าไม่ต้องรดน้ำเพิ่ม

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

int soilPin = 34;
int relayPin = 2;
int ledRed = 25, ledYellow = 26, ledGreen = 27; // กำหนดขา LED

void setup() {
  pinMode(relayPin, OUTPUT);
  pinMode(ledRed, OUTPUT);
  pinMode(ledYellow, OUTPUT);
  pinMode(ledGreen, OUTPUT);
}

void loop() {
  int percent = map(analogRead(soilPin), 4095, 0, 0, 100);

  // ปิดไฟทุกดวงก่อนเพื่อรีเซ็ตสถานะ
  digitalWrite(ledRed, LOW); digitalWrite(ledYellow, LOW); digitalWrite(ledGreen, LOW);

  if (percent < 20) {
    digitalWrite(ledRed, HIGH);   // สถานะวิกฤต
    digitalWrite(relayPin, HIGH); 
  } else if (percent >= 20 && percent <= 70) {
    digitalWrite(ledYellow, HIGH); // สถานะปกติ/เฝ้าระวัง
    digitalWrite(relayPin, LOW);
  } else {
    digitalWrite(ledGreen, HIGH);  // สถานะเปียกมาก
    digitalWrite(relayPin, LOW);
  }
  delay(1000);
}

Lab 2.3 ระบบรดน้ำอัจฉริยะพร้อมเสียงเตือน (Safety Alert System)

โจทย์ เพิ่มระบบเสียงแจ้งเตือนความปลอดภัยให้กับฟาร์มของเรา

จุดประสงค์ ฝึกการบริหารจัดการเวลา (Time Management) ในโค้ด และการใช้สัญญาณเสียงแจ้งเตือนสถานะวิกฤต

กำหนดเงื่อนไข

  • ทำงานคล้าย Lab 2.2 แต่เพิ่ม Buzzer (ลำโพง)
  • หากดินแห้งวิกฤตจนไฟสีแดงติด ให้ส่งเสียงเตือน Buzzer เป็นจังหวะสั้นๆ เพื่อเรียกเจ้าของฟาร์มมาดู
  • แสดงผลค่าความชื้นเป็นตัวเลขออกทาง Serial Monitor ทุกๆ 2 วินาที

ตารางเปรียบเทียบ Active vs Passive Buzzer

หัวข้อเปรียบเทียบActive BuzzerPassive Buzzer
วงจรภายในมีวงจรสร้างความถี่ (Oscillator) ในตัวไม่มี วงจรสร้างความถี่ในตัว
การทำงานป้อนไฟกระแสตรง (DC) แล้วดังทันทีต้องป้อนสัญญาณความถี่ (Square Wave) ถึงจะดัง
เสียงที่ได้เสียงโทนเดียว (มักจะเป็นเสียง Beep แหลมๆ)เปลี่ยนความถี่ได้ (เล่นเป็นเพลง/โน้ตดนตรีได้)
คำสั่งที่ใช้digitalWrite()tone() หรือ PWM
ราคาสูงกว่าเล็กน้อยถูกกว่า

การต่อวงจร (Wiring Diagram)

อุปกรณ์ขาอุปกรณ์ต่อกับ ESP32หน้าที่
เซนเซอร์ดินVCC3.3Vจ่ายไฟให้เซนเซอร์
GNDGNDต่อสายดิน
AOGPIO 34ส่งค่าความชื้นแบบ Analog
RelayVCCVIN (5V)จ่ายไฟเลี้ยงขดลวด
GNDGNDต่อสายดิน
INGPIO 2รับคำสั่งเปิด-ปิดปั๊ม
BuzzerVCC (บวก)GPIO 5รับคำสั่งส่งเสียง (Digital Output)
GND (ลบ)GNDต่อสายดิน

ตัวอย่างโค้ด เมื่อใช้การแจ้งเตือผ่าน Active Buzzer

int soilPin = 34;
int relayPin = 2;
int buzzerPin = 5; // ขาสำหรับ Buzzer
unsigned long lastPrint = 0; // สำหรับตั้งเวลาส่งข้อมูลออก Serial

void setup() {
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  int percent = map(analogRead(soilPin), 4095, 0, 0, 100);

  // เงื่อนไขแจ้งเตือนด้วยเสียงเมื่อดินแห้งวิกฤต
  if (percent < 15) {
    digitalWrite(relayPin, HIGH); // เปิดปั๊มน้ำ
    // ส่งเสียง Beep เป็นจังหวะ
    digitalWrite(buzzerPin, HIGH); delay(100);
    digitalWrite(buzzerPin, LOW); delay(100);
  } else if (percent > 40) {
    digitalWrite(relayPin, LOW); // ปิดปั๊มน้ำ
    digitalWrite(buzzerPin, LOW);
  }

  // ส่งค่าออก Serial Monitor ทุกๆ 2 วินาที (ไม่ใช้ delay หลักเพื่อให้ Buzzer ทำงานต่อเนื่อง)
  if (millis() - lastPrint > 2000) {
    Serial.print("Current Soil Moisture ");
    Serial.print(percent);
    Serial.println("%");
    lastPrint = millis();
  }
}

การหน่วงเวลาแบบไม่หยุดรอ (Non-Blocking Code)

การเขียนโค้ดจับเวลาที่อนุญาตให้สมองกลข้ามไปทำงานอื่นๆต่อได้ทันทีโดยไม่ต้องหยุดค้างรอเวลา

ใช้คำสั่ง millis() เพื่อจับเวลาในส่วนของลูป (Loop) แทนการใช้คำสั่ง delay()

คำอธิบาย

unsigned long (ชนิดของตัวแปร) ปกติเรามักจะคุ้นเคยกับ int แต่การจับเวลาในสมองกลจะนับเป็น “มิลลิวินาที” (1 วินาที = 1,000 มิลลิวินาที) หมายความว่าบอร์ดเปิดทำงานแค่แป๊บเดียว ตัวเลขเวลาก็จะพุ่งขึ้นไปสูงมาก การใช้ unsigned long จึงเปรียบเสมือนการสร้าง “กล่องเก็บของขนาดมหึมาที่เก็บได้เฉพาะเลขบวก” (เก็บค่าได้สูงสุดถึงประมาณ 4 พันล้าน) เพื่อไม่ให้ตัวเลขเวลาล้นกล่องจนโปรแกรมรวน

lastPrint (ชื่อตัวแปร) ตั้งชื่อให้สื่อความหมายว่า แสดงครั้งล่าสุด ทำหน้าที่จำว่า เราส่งข้อมูลออกหน้าจอครั้งล่าสุดตอนเวลาเท่าไหร่

เปรียบเทียบให้เห็นภาพง่ายๆ

การใช้ delay(2000) เหมือนเราสั่งให้ยามเฝ้าประตูว่า พอมองหน้าต่างเสร็จ ให้หลับตาไปเลย 2 วินาที แล้วค่อยตื่นมาเขียนรายงาน ซึ่งระหว่างที่หลับตา ถ้ามีขโมยเดินผ่าน ยามก็จะไม่เห็น = ระบบเตือนภัยรวน

การใช้ millis() ร่วมกับ lastPrint เหมือนแจกนาฬิกาข้อมือให้ยาม แล้วสั่งว่า ให้ลืมตาเฝ้าประตูตลอดเวลาเลยนะ (เสียง Buzzer จึงดังต่อเนื่องได้) แต่ให้คอยเหลือบดูนาฬิกา ถ้าเวลาผ่านไปครบ 2 วินาทีเมื่อไหร่ ให้เขียนรายงานแจ้งเตือน 1 ครั้ง

กลไกการทำงานในโค้ด

  if (millis() - lastPrint > 2000) {  // เอาเวลาปัจจุบันตั้งแล้วลบด้วยเวลาที่แสดงครั้งล่าสุด 
      ...
      lastPrint = millis();           // อัปเดตเวลาแสดงครั้งล่าสุดเป็นเวลาปัจจุบัน เพื่อเริ่มจับเวลาใหม่
  }

บรรทัดนี้คือการเช็คว่า เวลาปัจจุบัน (millis()) ลบกับ เวลาที่แสดงครั้งล่าสุด (lastPrint) มันห่างกันเกิน 2,000 มิลลิวินาที (2 วินาที) หรือยัง ถ้าเกินแล้วก็ให้ส่งค่าความชื้นออกหน้าจอ แล้วทำการจดเวลาปัจจุบันทับลงไปใน lastPrint เพื่อเริ่มจับเวลา 2 วินาทีรอบถัดไป

ตัวอย่างโค้ด เมื่อใช้การแจ้งเตือผ่าน Passive Buzzer (เสียงดนตรี)

// 1. กำหนดโน้ตดนตรี
#define NOTE_C4  262
#define NOTE_D4  294
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_G4  392
#define NOTE_A4  440
#define NOTE_C5  523

// 2. กำหนดขาอุปกรณ์
int soilPin = 34;   // ขาอ่านค่าเซนเซอร์ดิน 
int relayPin = 2;   // ขาสั่งงาน Relay (ปั๊มน้ำ)
int buzzerPin = 5;  // ขาสั่งงาน Passive Buzzer

// 3. ตัวแปรสถานะ
bool isWatering = false; 
int melody[] = { NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4, NOTE_F4, NOTE_E4 }; // ท่อนแยกเพลง
int durations[] = { 4, 8, 4, 4, 4, 2 };

void setup() {
  Serial.begin(115200);
  pinMode(relayPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
}

// ฟังก์ชันสำหรับเล่นเพลง Success
void playSuccessMelody() {
  for (int i = 0; i < 6; i++) {
    int duration = 1000 / durations[i];
    tone(buzzerPin, melody[i], duration);
    delay(duration * 1.30);
    noTone(buzzerPin);
  }
}

void loop() {
  // อ่านค่าและ Map เป็น 0-100%
  int rawValue = analogRead(soilPin); 
  int percent = map(rawValue, 4095, 0, 0, 100); 

  Serial.print("Moisture ");
  Serial.print(percent);
  Serial.println("%");

  // เงื่อนไข 1 ดินแห้งวิกฤต
  if (percent < 15) {
    digitalWrite(relayPin, HIGH); // เปิดปั๊ม
    isWatering = true;
    
    // เสียงเตือน Alert (Beep สั้น)
    tone(buzzerPin, 1000, 100); 
    delay(100);
    noTone(buzzerPin);
  } 
  // เงื่อนไข 2 รดน้ำจนพอใจแล้ว
  else if (percent > 80 && isWatering == true) {
    digitalWrite(relayPin, LOW); // ปิดปั๊ม
    isWatering = false;
    
    Serial.println("รดน้ำสำเร็จ! กำลังเล่นเพลงแสดงความยินดี...");
    playSuccessMelody(); // เล่นเพลง 1 รอบ
  }
  
  delay(500); // หน่วงเวลาเล็กน้อยเพื่อให้ระบบเสถียร
}

💡 สรุปความล้ำที่นักศึกษาจะได้เห็น

  • Lab 2.1 บอร์ดเริ่มมี “ความคิด” ตัดสินใจรดน้ำเองได้
  • Lab 2.2 ระบบสื่อสารกับมนุษย์ผ่าน “แสง” (User Interface พื้นฐาน)
  • Lab 2.3 ระบบมีความปลอดภัยและสื่อสารผ่าน “เสียง” รวมถึงการจัดการเวลาในโค้ด (Time Management) เพื่อเตรียมความพร้อมไปสู่ระบบเครือข่ายในวันถัดไป

Project 1 ระบบเฝ้าระวังโรงเรือน (Smart Monitor)

เป้าหมาย สร้างหน้าจอแสดงผลสถานะอากาศในฟาร์ม โดยใช้ DHT22 วัดอุณหภูมิ/ความชื้น และ OLED แสดงผลผ่านโปรโตคอล I2C

I2C Protocol คืออะไร

I2C (Inter-Integrated Circuit) คือ มาตรฐานการสื่อสารแบบดิจิทัลที่นิยมใช้กันมากที่สุดในงาน IoT เพราะประหยัดสายไฟและใช้งานง่ายมาก โดยใช้สายสัญญาณเพียง 2 เส้น ในการรับ-ส่งข้อมูลระหว่างบอร์ด ESP32 กับอุปกรณ์ต่างๆ เช่น จอ OLED หรือเซนเซอร์อื่นๆ ต่อเข้า Pin เดียวกันได้เลย

สายสัญญาณ 2 เส้นที่เป็นหัวใจหลัก

  • SDA (Serial Data) เปรียบเสมือน “ถนน” ที่ใช้ส่งตัวข้อมูลจดหมายวิ่งไปมา
  • SCL (Serial Clock) เปรียบเสมือน “จังหวะเคาะสัญญาณนาฬิกา” เพื่อคุมจังหวะให้ผู้ส่งและผู้รับทำงานพร้อมกัน (Synchronize)

การต่อใช้งานจริงกับ ESP32

  • SDA ต่อตรงกับขา GPIO 21
  • SCL ต่อตรงกับขา GPIO 22

อุปกรณ์ที่ใช้ใน Project 1 ระบบเฝ้าระวังโรงเรือน

  • บอร์ด ESP32
  • เซนเซอร์ DHT22 (วัดอุณหภูมิและความชื้นอากาศ)
  • จอ OLED Display 0.96″ (I2C)
  • สาย Jumper (M-M และ M-F)

การต่อวงจร (Wiring Diagram)

https://wokwi.com/projects/461653573565557761

ในโปรเจคนี้เราจะใช้ทั้งการสื่อสารแบบสายเดียว (Single Data) และแบบ I2C

อุปกรณ์ขาอุปกรณ์ต่อกับ ESP32หน้าที่
DHT22VCC3.3Vจ่ายไฟเลี้ยงเซนเซอร์
GNDGNDต่อสายดิน
DATAGPIO 4ส่งข้อมูลอุณหภูมิ/ความชื้น
OLED (I2C)VCC3.3Vจ่ายไฟเลี้ยงหน้าจอ
GNDGNDต่อสายดิน
SDAGPIO 21สายรับ-ส่งข้อมูล I2C
SCLGPIO 22สายสัญญาณนาฬิกา I2C

Project นี้ต้องใช้ Library (ไลบรารี)

Library ก็เปรียบเสมือน “พริกแกงสำเร็จรูป”

ลองจินตนาการว่าเราอยากทำ “แกงเขียวหวาน” (โปรเจกต์แสดงผลบนจอ OLED)

  • ถ้าไม่ใช้ Library (ทำเองตั้งแต่ต้น) เราต้องเดินไปเด็ดพริก ปลูกตะไคร้ โขลกน้ำพริกแกงเอง คั้นกะทิเอง ซึ่งใช้เวลานานเป็นวันๆ และอาจจะไม่อร่อย (โค้ด Error)
  • ถ้าใช้ Library (ใช้พริกแกงสำเร็จรูป) มีคนเก่งๆระดับเชฟ (นักพัฒนา) โขลกพริกแกงใส่ซองเตรียมไว้ให้เราแล้ว เราแค่ฉีกซอง เทลงหม้อ ใส่เนื้อสัตว์ (ใส่ข้อมูลของเรา) ก็ได้แกงเขียวหวานที่อร่อยทันทีภายใน 5 นาที

อุปกรณ์อย่างจอ OLED เซนเซอร์วัดอุณหภูมิ หรือแม้แต่การต่อ Wi-Fi นั้นมีการทำงานระดับฮาร์ดแวร์ที่ซับซ้อนมาก หากไม่มี Library เราอาจต้องเขียนโค้ดเป็น พันๆ บรรทัด เพื่อจัดการสัญญาณไฟฟ้าให้ถูกต้อง แต่พอใช้ Library เราเขียนโค้ดแค่ไม่กี่บรรทัดก็ใช้งานได้แล้ว

Library มีหน้าที่ซ่อนความยุ่งยากทางเทคนิคเอาไว้เบื้องหลัง และเปิดให้เราใช้งานผ่านคำสั่งสั้นๆที่เป็นภาษามนุษย์เข้าใจง่าย ทำให้เราเอาเวลาไปโฟกัสที่ไอเดียของโปรเจกต์ได้อย่างเต็มที่

การเตรียม Library

ก่อนเขียนโค้ด ให้นักศึกษาไปที่ Library Manager และติดตั้ง 2 ตัวนี้

  1. DHT sensor library (โดย Adafruit สำหรับ DHT22)
  2. Adafruit SSD1306 (สำหรับจอ OLED)

โค้ดตัวอย่าง Smart Monitor

#include <Wire.h>               // เรียกใช้งาน Library ควบคุมเส้นทางการสื่อสารแบบ I2C
#include <Adafruit_GFX.h>       // เรียกใช้งาน Library จัดการกราฟิก เช่น ขนาดอักษร วาดเส้น
#include <Adafruit_SSD1306.h>   // เรียกใช้งาน Library สำหรับสั่งการหน้าจอ OLED โดยเฉพาะ
#include <DHT.h>                // เรียกใช้งาน Library สำหรับคุยกับเซนเซอร์อุณหภูมิและความชื้น

// ตั้งค่าจอ OLED
#define SCREEN_WIDTH 128        // กำหนดความกว้างของหน้าจอ OLED เป็น 128 พิกเซล
#define SCREEN_HEIGHT 64        // กำหนดความสูงของหน้าจอ OLED เป็น 64 พิกเซล
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // สร้างตัวแปรชื่อ display ควบคุมจอ (ไม่มีขารีเซ็ต = -1)

// ตั้งค่า DHT22
#define DHTPIN 4                // กำหนดให้สายข้อมูลเซนเซอร์ (Data) ต่อกับบอร์ดที่ขา 4
#define DHTTYPE DHT22           // ระบุว่าเราใช้เซนเซอร์รุ่น DHT22
DHT dht(DHTPIN, DHTTYPE);       // สร้างตัวแปรชื่อ dht เตรียมไว้สำหรับดึงค่าเซนเซอร์

void setup() {                  // ฟังก์ชัน setup() ทำงานแค่ "ครั้งเดียว" ตอนเปิดบอร์ด
  Serial.begin(115200);         // เปิดการเชื่อมต่อส่งข้อมูลเข้าคอมพิวเตอร์ที่ความเร็ว 115200
  dht.begin();                  // สั่งให้ตัวเซนเซอร์ DHT เริ่มทำงาน

  // เริ่มต้นหน้าจอ OLED 
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // ตรวจสอบว่าบอร์ดมองเห็นจอ OLED ที่ Address 0x3C หรือไม่
    Serial.println(F("SSD1306 allocation failed")); // ถ้าไม่เจอจอ ให้พิมพ์แจ้ง Error บนคอมพิวเตอร์
    for(;;);                                        // สั่งให้บอร์ดหยุดทำงานค้างไว้ตรงนี้ ไม่ต้องทำอย่างอื่นต่อ
  }
  display.clearDisplay();       // สั่งล้างหน้าจอให้ดำสนิท เผื่อมีจุดสีค้างจากรอบก่อน
  display.setTextColor(WHITE);  // ตั้งค่าให้แสดงตัวอักษรเป็นสีสว่าง
}

void loop() {                   // ฟังก์ชัน loop() ทำงานวนซ้ำไปเรื่อยๆตลอดเวลาที่เปิดเครื่อง
  float h = dht.readHumidity();    // อ่านค่าความชื้นมาเก็บในตัวแปร h (ใช้ float เพราะมีทศนิยม)
  float t = dht.readTemperature(); // อ่านค่าอุณหภูมิมาเก็บในตัวแปร t (ใช้ float เพราะมีทศนิยม)

  if (isnan(h) || isnan(t)) {      // ตรวจสอบว่าค่า h หรือ t ออกมาสำเร็จไหม
    Serial.println("Failed to read from DHT sensor!"); // ถ้าไม่สำเร็จ ให้พิมพ์แจ้งเตือนบนคอมพิวเตอร์
    return;                        // สั่งให้จบการทำงานรอบนี้ทันที เพื่อกลับไปเริ่มบรรทัดบนสุดของ loop ใหม่
  }

  // ส่วนของการจัดรูปแบบแสดงผลบนหน้าจอ OLED
  display.clearDisplay();          // ล้างกระดานหน้าจอให้ว่างเปล่าก่อนเริ่มเขียนรอบใหม่
  display.setCursor(0, 0);         // เอาเคอเซอร์ไปจ่อที่พิกัด X:0, Y:0 (มุมซ้ายบนสุดของจอ)
  display.setTextSize(1);          // กำหนดขนาดตัวอักษรเป็นไซส์ 1 (ขนาดเล็ก)
  display.println("SMART FARM MONITOR"); // แสดงข้อความ SMART FARM MONITOR
  
  display.setTextSize(2);          // เปลี่ยนขนาดตัวอักษรเป็นไซส์ 2 (ใหญ่ขึ้นมาหน่อย)
  display.setCursor(0, 20);        // ย้ายเคอเซอร์ลงมาที่พิกัด X:0, Y:20
  display.print("T "); display.print(t); display.println(" C"); // แสดงตัว T ตามด้วยค่าอุณหภูมิ และตัว C
  
  display.setCursor(0, 45);        // ย้ายเคอเซอร์ลงมาอีกที่พิกัด X:0, Y:45
  display.print("H "); display.print(h); display.println(" %"); // แสดงตัว H ตามด้วยค่าความชื้น และ %

  // Challenge ถ้าอุณหภูมิเกิน 35C ให้แจ้งเตือน
  if(t > 35.0) {                   // ตรวจสอบเงื่อนไข ถ้าอุณหภูมิ (t) มีค่ามากกว่า 35.0 องศา
    display.setTextSize(1);        // ปรับขนาดอักษรกลับมาไซส์ 1
    display.setCursor(85, 10);     // ย้ายเคอเซอร์ไปพิกัด X:85, Y:10 แถวมุมขวาบน
    display.print("HOT!");         // แสดงคำเตือนว่า HOT!
  }

  display.display();               // สำคัญมาก นำสิ่งที่เราจัดเตรียมไว้ทั้งหมดข้างต้น ส่งไปแสดงบนจอภาพจริงๆ
  delay(2000);                     // สั่งให้บอร์ดหยุดรอ 2 วินาที เพื่อให้พอดีกับที่เซนเซอร์ DHT22 อัปเดตค่ารอบใหม่
}

ภารกิจที่ 1 ปรับแต่งหน้าจอตามใจฉัน

เป้าหมาย ให้นักศึกษาเข้าใจการทำงานของคำสั่งจัดการข้อความและพิกัด (X, Y) บนหน้าจอ OLED

  • โจทย์ 1.1 เปลี่ยนข้อความหัวกระดานจาก "SMART FARM MONITOR" เป็นชื่อโปรเจกต์ของตัวเอง เช่น "SPTC GREENHOUSE"
  • โจทย์ 1.2 ปัจจุบันตัวอักษร T (อุณหภูมิ) และ H (ความชื้น) อยู่ชิดขอบซ้ายเกินไป ให้นักศึกษาขยับข้อความทั้ง 2 บรรทัด ให้เข้ามาตรงกลางจอมากขึ้น

💡 คำใบ้สำหรับนักศึกษา ลองหาคำสั่ง display.setCursor(X, Y); แล้วปรับแก้ตัวเลขแกน X แนวนอน (หน้าจอเรากว้าง 128 พิกเซล)

ภารกิจที่ 2 เพิ่มระบบแจ้งเตือนความชื้น

เป้าหมาย ฝึกการเขียนเงื่อนไข if และการจัดวาง Layout บนหน้าจอไม่ให้ตัวหนังสือทับกัน

  • โจทย์ ปัจจุบันระบบมีการแจ้งเตือนคำว่า "HOT!" เมื่ออุณหภูมิเกิน 35 องศาแล้ว ให้นักศึกษาเพิ่มระบบแจ้งเตือนความชื้นด้วย โดย “ถ้าความชื้น (h) ต่ำกว่า 40% ให้แสดงคำว่า “DRY!” (ดินแห้ง) ที่มุมขวาล่างของหน้าจอ”

💡 คำใบ้สำหรับนักศึกษา คัดลอกโครงสร้างของบล็อก if(t > 35.0) { ... } มาเป็นต้นแบบได้เลย แล้วเปลี่ยนตัวแปรเป็น h พร้อมกับปรับพิกัด setCursor ให้ไปอยู่มุมขวาล่างของหน้าจอ เพื่อไม่ให้ทับกับคำว่า HOT!

การสร้างภาพเคลื่อนไหว (Animation) บนจอ OLED

หลักการ “สมุดมุมกระดาษ” (Flipbook)

ให้นักศึกษาลองนึกถึงตอนเด็กๆที่เราวาดรูปการ์ตูนไว้ที่มุมสมุดหลายๆหน้า โดยแต่ละหน้าขยับแขนขาตัวการ์ตูนทีละนิด แล้วใช้นิ้วกรีดหน้ากระดาษอย่างรวดเร็ว ตาของเราจะมองเห็นตัวการ์ตูนนั้นขยับได้

บอร์ด ESP32 และหน้าจอ OLED ก็ใช้หลักการเดียวกันเป๊ะเลยครับ เรียกว่า การสร้างแอนิเมชันแบบ “เฟรมต่อเฟรม” (Frame by Frame) โดยมีหัวใจสำคัญอยู่ 4 ขั้นตอนที่ต้องทำวนลูปซ้ำๆ

  1. ลบกระดาน (Clear) ลบภาพเก่าทิ้งให้หมด
  2. วาดรูปใหม่ (Draw) วาดภาพเดิม แต่เปลี่ยนตำแหน่ง (พิกัด X หรือ Y) ไปนิดหน่อย
  3. โชว์ภาพ (Display) สั่งให้หน้าจอแสดงภาพที่เพิ่งวาดเสร็จ
  4. พักสายตา (Delay) หน่วงเวลาแป๊บเดียว เพื่อให้สมองคนเราจับภาพได้ทัน ก่อนจะกลับไปข้อ 1 ใหม่

สร้างหน้าจอ Loading Bar เท่

ให้นักศึกษานำโค้ดชุดนี้ ไปวางไว้ในฟังก์ชัน setup() แนะนำให้วางไว้ใต้ส่วน “เริ่มต้นหน้าจอ OLED”

  display.clearDisplay();       // ล้างหน้าจอให้สะอาดก่อน
  
  // 1. พิมพ์ข้อความชื่อโปรเจกต์
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(15, 20);    // กะระยะให้อยู่กึ่งกลางจอ
  display.print("SPTC GREENHOUSE");

  // 2. วาด "กรอบเปล่า" ของหลอดโหลดข้อมูล
  // รูปแบบ drawRect(แกน X, แกน Y, ความกว้าง, ความสูง, สี)
  display.drawRect(14, 40, 100, 10, WHITE); 
  display.display();            // สั่งแสดงผลกรอบเปล่าขึ้นจอก่อน

  // 3. วาด "แถบสีทึบ" ให้ค่อยๆ วิ่งจนเต็มกรอบ
  // ใช้ลูป for ให้นับเลข 0 ถึง 100 เก็บไว้ในตัวแปร i
  for (int i = 0; i <= 100; i++) {
    // ให้ความกว้างของสี่เหลี่ยมทึบ เพิ่มขึ้นตามค่า i
    display.fillRect(14, 40, i, 10, WHITE); 
    display.display();          // อัปเดตหน้าจอทุกครั้งที่ขยับ 1 พิกเซล
    delay(20);                  // หน่วงเวลา 20 มิลลิวินาที (ยิ่งค่าน้อย หลอดยิ่งวิ่งเร็ว)
  }

  // 4. โหลดเสร็จแล้ว ค้างหน้าจอไว้ 1 วินาทีให้คนดูทัน แล้วเคลียร์ทิ้ง
  delay(1000);
  display.clearDisplay();
  // ---------------------------------------------------

การนำไปประยุกต์ใช้กับ Smart Farm

นักศึกษาสามารถนำเทคนิคการทำแอนิเมชันนี้ ไปทำให้หน้าจอระบบสมาร์ทฟาร์มของเราดูมีความเป็นมืออาชีพ (Professional) มากขึ้นได้ เช่น

  • ตอนที่ปั๊มน้ำทำงาน ทำแอนิเมชันรูปหยดน้ำร่วงลงมาบนพื้นดิน
  • ตอนที่พัดลมทำงาน ใช้วิธีสลับรูปวาดใบพัดลม 2 รูปสลับกันไปมาอย่างรวดเร็ว (รูปกากบาท X สลับกับรูปเครื่องหมายบวก +) จะดูเหมือนพัดลมกำลังหมุนอยู่จริงๆ
  • ตอนที่ระบบมีปัญหา ทำแอนิเมชันกรอบสี่เหลี่ยมเตือนภัยกะพริบขยายใหญ่แล้วหดลง

สอนโดย อาจารย์นุ/ครูนุ (ภานุพงศ์ สะและหมัด)

ติดต่อ Line ID : salae44476

Scroll to Top