Simple Temperature Control by using Fuzzy Logic Control Based on Arduino [EP1]

บทความนี้เป็นการควบคุมอุณหภูมิแบบฟัซซี่ลอจิก (Fuzzy Logic Control : FLC) โดยใช้บอร์ด Arduino UNO และจำลองการทำงานบนเว็บไซต์ www.tinkercad.com อุปกรณ์เซนเซอร์อุณหภูมิทางด้านอินพุตจะใช้ตัวต้านทานปรับค่า (Variable Resistor : VR) แทนเซนเซอร์จริงเพื่อสังเกตการทำงาน ในส่วนสัญญาณเอาต์พุตจะเป็นพัลซ์วิดธ์มอดูเลตชั่นที่ได้จากการประมวลผลแบบฟัซซี่ลอจิก เพื่อควบคุมการทำงานของพัดลมในการปรับต่าอุณหภูมิที่เหมาะสม

ระบบควบคุมแบบ Fuzzy logic โดยทั่วไปประกอบด้วย 4 ส่วนหลัก ได้แก่
Fuzzification (การทำให้เป็นฟัซซี) : เป็นกระบวนการแปลงข้อมูลที่เป็นค่าจริง (Crisp value) เช่น อุณหภูมิ 25 องศาเซลเซียส ให้เป็นข้อมูลแบบฟัซซี (Fuzzy value) โดยใช้ฟังก์ชันสมาชิกภาพ (Membership function) ซึ่งเป็นกราฟที่แสดงระดับความเป็นสมาชิกของค่าหนึ่งๆ ในกลุ่มคำศัพท์ทางภาษา (Linguistic terms) เช่น “อุณหภูมิ” จะถูกแปลงเป็น “เย็น” “สบาย” หรือ “ร้อน” โดยแต่ละคำจะมีค่าสมาชิกภาพตั้งแต่ 0 ถึง 1
Knowledge Base (ฐานความรู้) : เป็นส่วนที่เก็บกฎและเงื่อนไขการควบคุมที่อยู่ในรูปของ “ถ้า-แล้ว” (IF-THEN rules) โดยกฎเหล่านี้จะมาจากผู้เชี่ยวชาญหรือการทดลอง เช่น “ถ้าอุณหภูมิ ร้อน และความชื้น สูง แล้วให้ เพิ่ม ความเร็วพัดลม” กฎเหล่านี้จะใช้ในการตัดสินใจและให้ผลลัพธ์ที่เหมาะสม
Inference (การอนุมาน) : เป็นส่วนที่ใช้กฎจาก Knowledge Base มาประมวลผลข้อมูลฟัซซีที่ได้จาก Fuzzification โดยจะนำค่าสมาชิกภาพของข้อมูลเข้าแต่ละตัวมาประมวลผลร่วมกันตามกฎ IF-THEN เพื่อหาค่าสมาชิกภาพของผลลัพธ์ที่เป็นฟัซซี เช่น หากข้อมูลเข้า “อุณหภูมิ” มีค่าสมาชิกภาพ 0.8 ในกลุ่ม “ร้อน” และ “ความชื้น” มีค่าสมาชิกภาพ 0.6 ในกลุ่ม “สูง” การอนุมานจะใช้ค่าเหล่านี้เพื่อกำหนดค่าสมาชิกภาพของผลลัพธ์ “ความเร็วพัดลม” ในกลุ่ม “เพิ่ม”
Defuzzification (การทำให้ไม่เป็นฟัซซี) : เป็นขั้นตอนสุดท้ายที่แปลงผลลัพธ์ที่เป็นข้อมูลฟัซซีจากกระบวนการ Inference ให้กลับเป็นค่าที่เป็นตัวเลขหรือค่าจริง (Crisp value) อีกครั้ง เช่น ผลลัพธ์ที่ได้จากการอนุมานคือ “ความเร็วพัดลม” มีค่าสมาชิกภาพสูงในกลุ่ม “เพิ่ม” กระบวนการ Defuzzification จะแปลงสิ่งนี้ให้เป็นค่าที่ใช้งานได้จริง เช่น ความเร็วพัดลมเท่ากับ 1200 รอบต่อนาที โดยมีหลายวิธีในการแปลง เช่น วิธี Centroid (หาจุดศูนย์กลางของพื้นที่ใต้กราฟ) หรือวิธี Mean of Maxima (หาค่าเฉลี่ยของค่าที่ให้ค่าสมาชิกภาพสูงสุด)
// Define linguistic terms and their corresponding membership functions // Example: For input 'temperature' with terms 'Cold', 'Warm', 'Hot' float cold_mf(float temp) { if (temp <= 10) return 1.0; if (temp > 10 && temp < 20) return (20 - temp)/10.0; return 0.0; } float warm_mf(float temp) { if (temp >= 15 && temp <= 25) return 1.0; if (temp > 10 && temp < 15) return (temp - 10)/5.0; if (temp > 25 && temp < 30) return (30 - temp)/5.0; return 0.0; } float hot_mf(float temp) { if (temp >= 30) return 1.0; if (temp > 20 && temp < 30) return (temp - 20)/10.0; return 0.0; } // Define fuzzy rules // Example: If temperature is Cold, then fan speed is Low // If temperature is Warm, then fan speed is Medium // If temperature is Hot, then fan speed is High // Function for fuzzy inference (Mamdani-type example) float infer_fan_speed(float cold_val, float warm_val, float hot_val) { // Assuming output terms for fan speed: Low, Medium, High // For simplicity, we'll use a weighted average for defuzzification // This is a simplified representation and may need adjustment based on specific defuzzification method float low_output = cold_val; // If cold, fan speed is low float medium_output = warm_val; // If warm, fan speed is medium float high_output = hot_val; // If hot, fan speed is high // Defuzzification (Centroid method simplified for illustration) // In a real application, you'd define output membership functions and calculate centroid // Avoid division by zero float defuzzified_value = (low_output*0+medium_output*50+high_output*100)/(low_output+medium_output+high_output+0.001); return defuzzified_value; } void setup() { Serial.begin(9600); } void loop() { // 1. Fuzzification: Read sensor input and determine membership values float current_temperature = analogRead(A0); // Read temperature from analog pin A0 // float current_temperature = random(0,1023); // Map sensor reading to temperature range (e.g., 0-40°C) current_temperature = map(current_temperature, 0, 1023, 0, 40); float cold_membership = cold_mf(current_temperature); float warm_membership = warm_mf(current_temperature); float hot_membership = hot_mf(current_temperature); Serial.print("Temperature: "); Serial.print(current_temperature); Serial.print(", [Cold: "); Serial.print(cold_membership); Serial.print(" | Warm: "); Serial.print(warm_membership); Serial.print(" | Hot: "); Serial.print(hot_membership); Serial.println("] "); // 2. Fuzzy Inference: Apply fuzzy rules float fan_speed_output = infer_fan_speed(cold_membership, warm_membership, hot_membership); // 3. Defuzzification: Convert fuzzy output to a crisp value int crisp_fan_speed = (int)fan_speed_output; // Convert to integer for controlling a device Serial.print("Calculated Fan Speed (Crisp): "); Serial.print(crisp_fan_speed); Serial.println(" %"); Serial.println(""); // Control your output device (e.g., set PWM for fan speed) // analogWrite(PWM_PIN, crisp_fan_speed); delay(1000); // Delay for demonstration }
โปรแกรมการทำงานที่แสดงข้างบนสามารถอธิบายพอสังเขปคือ ในส่วนแรกจะเป็นกลุ่มของฟังก์ชั่นการทำงานเกี่ยวกับสมาชิกของข้อมูลอินพุต (Membership function) ที่คำสั่ง float cold_mf(float temp), float warm_mf(float temp) และ float warm_mf(float temp) ถัดลงมาที่ฟังก์ชั่น float infer_fan_speed(float cold_val, float warm_val, float hot_val) จะทำหน้าที่ประมวลผลข้อมูลฟัซซีที่ได้จาก Fuzzification ถัดลงมาจะเป็นคำสั่งการประกาศการใช้ค่าตัวแปรในการประมวลผล คือ float low_output = cold_val, float medium_output = warm_val และ float high_output = hot_val ถัดลงมาจะเป็นการคำนวณผลลัพธ์ด้วยคำสั่ง float defuzzified_value = (low_output*0+medium_output*50+high_output*100)/(low_output+medium_output+high_output+0.001) เพื่อแปลงผลลัพธ์ข้อมูลฟัซซีให้เป็นตัวเลขหรือค่าจริง
จากนั้นในส่วนของฟังก์ชั่น void setup() จะกำหนดการสื่อสารผ่านพอร์ตอนุกรม Serial.begin(9600); ไว้ที่ 9600 และถัดลงมาที่ฟังก์ชั่น void setup() จะใช้คำสั่ง float current_temperature = analogRead(A0); ในการอ่านค่าแรงดันอินพิตที่ขา A0 จากนั้นจะใช้คำสั่ง current_temperature = map(current_temperature, 0, 1023, 0, 40); เพื่อเปลี่ยนค่าที่อ่านได้ 0-1023 ให้อยู่ในช่วง 0-40 (หมายถึงช่วงอุณหภูมิ 0-40°C) ต่อมาจะเป็นการเรียกฟังก์ชั่น float cold_membership = cold_mf(current_temperature);, float warm_membership = warm_mf(current_temperature); และ float hot_membership = hot_mf(current_temperature); แล้วให้นำต่าที่ได้จากฟังก์ชั่นมาแสดงผลผ่านพอร์ตอนุกรมด้วยคำสั่ง Serial.print(“Temperature: “); ตามลำดับ ต่อมาจะเป็นการเรียกฟังก์ชั่น float fan_speed_output = infer_fan_speed(cold_membership, warm_membership, hot_membership); เพื่อให้ได้ค่าจากกระบวนการ fuzzy inference สุดท้ายจะเป็นฟังก์ชั่นการ Defuzzification เพื่อให้เป็นตัวเลขหรือค่าจริงในการควบคุมโหลด และแสดงผลที่ได้ผ่านพอร์ตอนุกรมอีกครั้งด้วยคำสั่ง Serial.print(“Calculated Fan Speed (Crisp): “); ตามลำดับ

ในรูปที่ 2 แสดงอุปกรณ์ที่ใช้ในการจำลองการควบคุมแบบฟัซซี่ลอจิก ซึ่งประกอบด้วยบอร์ดประมวลผล Arduino UNO, ตัวต้านทานปรับค่าสำหรับปรับค่าแรงดันในช่วง 0-5V (เป็นค่าอินพุตให้กับระบบฟัซซี่ลอจิก) เพื่อใช้จำลองค่าอุณหภูมิให้อยู่ในช่วง 0-40°C, และโวลต์มิเตอร์แสดงค่าแรงดันที่ได้จากการปรับค่าความต้านทานเพื่อป้อนเข้ามายังขา A0 ในส่วนของผลลัพธ์ (ค่าเอาต์พุตของระบบฟัซซี่ลอจิก) จะให้แสดงผลมายังหน้าต่าง Serial Monitor ของโปรแกรมจำลองการทำงาน

รูปที่ 3 แสดงผลการทดลองการทำงานที่ 1 เมื่อปรับแรงดันไปยังขา A0 เท่ากับ 1.5V จากนั้นสังเกตค่าอุณหภูมิที่ได้จะเท่ากับ 12°C ทำให้ได้ค่า Membership function คือ Cold = 0.80 , Warm = 0.40 และ Hot = 0.00 ตามลำดับ (ในกรอบสีเขียว) และการทำงานทางด้านเอาต์พุตจะเท่ากับ 16% (ในส่วน 16 % หมายถึงถ้าใช้พัดลมเป็นโหลดจะให้มอเตอร์ทำงานที่ 16% ของความเร็วสูงสุด) เพื่อปรับอุณหภูมิให้ได้เหมาะสม

รูปที่ 4 แสดงผลการทดลองการทำงานที่ 2 เมื่อปรับแรงดันไปยังขา A0 เท่ากับ 2.5V สังเกตค่าอุณหภูมิที่ได้จะเท่ากับ 19°C ทำให้ได้ค่า Membership function คือ Cold = 0.10 , Warm = 1.00 และ Hot = 0.00 ตามลำดับ (ในกรอบสีส้ม) และการทำงานทางด้านเอาต์พุตจะเท่ากับ 45% (ในส่วน 45 % หมายถึงถ้าใช้พัดลมเป็นโหลดจะให้มอเตอร์ทำงานที่ 45% ของความเร็วสูงสุด) เพื่อปรับอุณหภูมิให้ได้เหมาะสม

รูปที่ 5 แสดงผลการทดลองการทำงานที่ 3 เมื่อปรับแรงดันไปยังขา A0 เท่ากับ 4.5V สังเกตค่าอุณหภูมิที่ได้จะเท่ากับ 35°C ทำให้ได้ค่า Membership function คือ Cold = 0.00 , Warm = 0.00 และ Hot = 1.00 ตามลำดับ (ในกรอบสีน้ำเงิน) และการทำงานทางด้านเอาต์พุตจะเท่ากับ 99% (ในส่วน 99 % หมายถึงถ้าใช้พัดลมเป็นโหลดจะให้มอเตอร์ทำงานที่ 99% ของความเร็วสูงสุด) เพื่อปรับอุณหภูมิให้ลดลงตามที่เหมาะสม
ในบทความนี้เป็นการจำลองการทำงานเพื่อควบคุมอุณหภูมิด้วยการควบคุมแบบฟัซซี่ลอจิก (Fuzzy Logic Control : FLC) และใช้บอร์ด Arduino UNO ในการประมวลผล ด้วยการเขียนโปรแกรมควบคุมที่ไม่ซับซ้อนมากนักและเป็นความรู้พื้นฐานในการทดลองด้วยการใช้ตัวควบคุมแบบฟัซซี่ลอจิก ทั้งนี้การเขียนโค้ดโปรแกรมสำหรับการควบคุมแบบฟัซซี่ลอจิกเราสามารถใช้ไลบารี่ที่มีผู้พัฒนาและแชร์ไว้ในเว็บไซต์ต่างๆ สำหรับการเรียนรู้และพัฒนาโครงงานต่างๆ ได้รวดเร็วยิ่งขึ้น
Reference
- https://en.wikipedia.org/wiki/Fuzzy_control_system
- https://forum.arduino.cc/t/how-make-fuzzy-logic-coding-for-arduino-uno/282381/4
- https://github.com/alvesoaj/eFLL
- https://github.com/amimaro/FuzzyLibrary
- https://www.microjpm.com/products/ad52300/
- https://www.tinkercad.com/dashboard
- https://www.circuitbasics.com/arduino-thermistor-temperature-sensor-tutorial/
- https://gemini.google.com/
- https://copilot.microsoft.com