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://fuzzylite.com/
- https://fuzzylite.com/downloads/FuzzyLite-Libraries.pdf
- 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