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

ในตอนสุดท้ายของการควบคุมอุณหภูมิแบบฟัซซี่ลอจิก (Fuzzy Logic Control : FLC) โดยใช้บอร์ด Arduino UNO ครั้งนี้ จะเป็นอีกตัวอย่างหนึ่งของการควบคุมอุณหภูมิด้วยการกำหนดค่า Setpoint ที่ชัดเจนเช่น ต้องการอุณหภูมิที่ 20°C หรือ 25°C และนำค่า Error และ DeltaError เป็นสัญญาณอินพุตฟัซซี่ลอจิก (อินพุต 2 ส่วน) สำหรับควบคุมการทำงานของระบบและใช้ไลบารี่ฟัซซี่ลอจิก <Fuzzy.h> ในการเขียนโปรแกรม สำหรับสัญญาณเอาต์พุตจะใช้เพียง 1 ช่องในลักษณะของพัลซ์วิดธ์มอดูเลตชั่นเพื่อให้เห็นผลที่เกิดขึ้น หรือจะนำไปใช้ในการควบคุมพัดลมหรือคอมเพลสเซอร์ได้ตามต้องการ

Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 1 ลักษณะการต่ออุปกรณ์สำหรับทดลอง

Download Arduino Library Fuzzy logic Control

Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 2 วงจรที่ใช้ในการทดลองการควบคุมแบบฟัซซี่ลอจิก

ในรูปที่ 1 และรูปที่ 2 แสดงลักษณะการต่ออุปกรณ์สำหรับทดลองและวงจรที่ใช้ในการทดลองการควบคุมแบบฟัซซี่ลอจิก โดยในการทดลองครั้งนี้จะใช้ตัวต้านทานปรับค่า (Variable Resistor : VR) เพื่อทดสอบการทำงานแทนค่าเซนเซอร์อุณหภูมิที่อ่านได้ในส่วนของอินพุตฟัซซี่ลอจิก ในส่วนเอาต์พุตจะส่งเป็นสัญญาณพัลซ์วิดธ์มอดูเลตชั่นที่ขา D9 และต่อแอลอีดีเพื่อสังเกตผลที่ได้จากการทำงาน

// Arduino_advanced_sample_V6

#include <Fuzzy.h>

int  setpoint = 20; // (20°C)
int  Error = 0;
int  DeltaError = 0;
int  previousError = 0;
int  PWMoutput = 0; // PWM value (0-255)

Fuzzy *fuzzy = new Fuzzy();  // Fuzzy 

// FuzzyInput1
FuzzySet *error_NB = new FuzzySet(-40, -40, -20, -5);
FuzzySet *error_Z = new FuzzySet(-10, 0, 0, 10);
FuzzySet *error_PS = new FuzzySet(5, 20, 40, 40); 

// FuzzyInput2
FuzzySet *deltaError_NS = new FuzzySet(-40, -30, -20,-5);
FuzzySet *deltaError_Z = new FuzzySet(-10, 0, 0, 10); 
FuzzySet *deltaError_PS = new FuzzySet(5, 20, 40, 40); 

// FuzzyOutput
FuzzySet *slowOutput = new FuzzySet(-5, -5, -2, -2);
FuzzySet *normalOutput = new FuzzySet(-1, 0, 0, 1);
FuzzySet *quickOutput = new FuzzySet(2, 2, 5, 5);

void setup()
{  
  Serial.begin(9600); // Set the Serial output
  pinMode(9,OUTPUT);  // PWM Pin
  
  // Every setup must occur in the function setup()
  // FuzzyInput1
  FuzzyInput *error = new FuzzyInput(1);
  error->addFuzzySet(error_NB);
  error->addFuzzySet(error_Z);
  error->addFuzzySet(error_PS);
  fuzzy->addFuzzyInput(error);

  // FuzzyInput2
  FuzzyInput *deltaError = new FuzzyInput(2);  
  deltaError->addFuzzySet(deltaError_NS);
  deltaError->addFuzzySet(deltaError_Z);
  deltaError->addFuzzySet(deltaError_PS);
  fuzzy->addFuzzyInput(deltaError);

  // FuzzyOutput
  FuzzyOutput *speedOutput = new FuzzyOutput(1);
  speedOutput->addFuzzySet(slowOutput);
  speedOutput->addFuzzySet(normalOutput);
  speedOutput->addFuzzySet(quickOutput);
  fuzzy->addFuzzyOutput(speedOutput);
    
//---- Building FuzzyRule (1)-----------------------------
  FuzzyRuleAntecedent *iferror_NBAnddeltaError_NS = new FuzzyRuleAntecedent();
  iferror_NBAnddeltaError_NS->joinWithAND(error_NB, deltaError_NS);

  FuzzyRuleConsequent *thenSpeedSlow = new FuzzyRuleConsequent();
  thenSpeedSlow->addOutput(slowOutput);

  FuzzyRule *fuzzyRule1 = new FuzzyRule(1,iferror_NBAnddeltaError_NS, thenSpeedSlow);
  fuzzy->addFuzzyRule(fuzzyRule1);  
   
//---- Building FuzzyRule (2)-----------------------------
  FuzzyRuleAntecedent *iferror_ZAnddeltaError_Z = new FuzzyRuleAntecedent();
  iferror_ZAnddeltaError_Z->joinWithAND(error_Z, deltaError_Z);

  FuzzyRuleConsequent *thenSpeednormal = new FuzzyRuleConsequent();
  thenSpeednormal->addOutput(normalOutput);

  FuzzyRule *fuzzyRule2 = new FuzzyRule(2,iferror_ZAnddeltaError_Z, thenSpeednormal);
  fuzzy->addFuzzyRule(fuzzyRule2);

//---- Building FuzzyRule (3)-----------------------------
  FuzzyRuleAntecedent *iferror_PSAnddeltaError_PS = new FuzzyRuleAntecedent();
  iferror_PSAnddeltaError_PS->joinWithAND(error_PS, deltaError_PS);

  FuzzyRuleConsequent *thenSpeedquick = new FuzzyRuleConsequent();
  thenSpeedquick->addOutput(quickOutput);

  FuzzyRule *fuzzyRule3 = new FuzzyRule(3,iferror_PSAnddeltaError_PS, thenSpeedquick);
  fuzzy->addFuzzyRule(fuzzyRule3);  

  // Add more rules to cover all combinations for better control
  // ...
}

void loop()
{
  int Readtemp1 = analogRead(A1); // Read temperature pin A1 
  int currentTemp = map(Readtemp1, 0, 1023, 0, 40);  // Map temperature range (0-40°C) 
  
  Error = setpoint - currentTemp;   // setpoint = 20 
  DeltaError = Error - previousError;
  previousError = Error;
 
  Serial.println(" ");
  Serial.print(" Error = ");  // Error
  Serial.print(Error);
  Serial.print(", DeltaError = "); // DeltaError
  Serial.println(DeltaError);
 
  fuzzy->setInput(1,Error);
  fuzzy->setInput(2,DeltaError);

  fuzzy->fuzzify();

  Serial.print(" Error: error_NB-> ");
  Serial.print(error_NB->getPertinence());
  Serial.print(", error_Z-> ");
  Serial.print(error_Z->getPertinence());
  Serial.print(", error_PS-> ");
  Serial.println(error_PS->getPertinence());
 
  Serial.print(" DeltaError: deltaError_NS-> ");
  Serial.print(deltaError_NS->getPertinence());
  Serial.print(", deltaError_Z-> ");
  Serial.print(deltaError_Z->getPertinence());
  Serial.print(", deltaError_PS-> ");
  Serial.println(deltaError_PS->getPertinence());

  int output1 = fuzzy->defuzzify(1); 
  
  Serial.print(" Result: ");
  Serial.print(output1); 

  PWMoutput += output1;
  PWMoutput = constrain(PWMoutput, 0, 255); // Ensure PWM is within range
  analogWrite(9,PWMoutput); 
  
  Serial.print(", PWMoutput : ");
  Serial.println(PWMoutput);   
  delay(1000);
}

โปรแกรม Arduino สำหรับประมวลผลแบบฟัซซี่ลอจิกจะแบ่งออกเป็น 3 ส่วนคือ ในส่วนแรกที่คำสั่ง #include <Fuzzy.h> จะทำหน้าที่ประกาศใช้งานฟังก์ชั่นไลบารี่ฟัซซี่ลอจิก ถัดลงมาจะเป็นการกำหนดค่า FuzzyINPUT, FuzzyOUTPUT (ซึ่งจะต่างกับ EP4 เล็กน้อย) ส่วนที่สอง void setup() ที่หน้าที่กำหนดอัตราการสื่อสารของพอร์ตอนุกรมเท่ากับ 9600, FuzzyRule และการกำหนดความกว้างของสัญญาณพัลซ์วิดธ์มอดูเลตชั่นที่ขา D9 ด้วยคำสั่ง analogWrite(9,output); ส่วนที่สาม void loop() จะทำหน้าที่รับค่าสัญญาณอินพุตด้วยคำสั่ง int Readtemp1 = analogRead(A1); จากนั้นจะใช้คำสั่ง int input = map(Readtemp, 0, 1023, 0, 40); เพื่อเปลี่ยนค่าที่อ่านได้ 0-1023 ให้อยู่ในช่วง 0-40 (หมายถึงช่วงอุณหภูมิ 0-40°C) และแสดงผลด้วยคำสั่ง Serial.print(input); จากนั้นจะเป็นคำสั่ง Error = setpoint – currentTemp; DeltaError = Error – previousError; previousError = Error; เพื่อให้ได้ค่า Error และ DeltaError สำหรับอินพุต fuzzy->setInput(1,Error); fuzzy->setInput(2,DeltaError); ในการประมวลผล ด้วยคำสั่ง fuzzy->fuzzify(); และให้แสดงผลที่เกิดขึ้นด้วยคำสั่ง Serial.print(Error:); , Serial.print(deltaError:); ต่อมาที่คำสั่ง int output1 = fuzzy->defuzzify(1); ซึ่งจะได้ค่าเอาต์พุตออกมาที่ตัวแปร output1 เพื่อกำหนดสัญญาณพัลซ์วิดธ์มอดูเลตชั่นที่ขา D9 ด้วยคำสั่ง PWMoutput += output1; PWMoutput = constrain(PWMoutput, 0, 255); และ analogWrite(9,PWMoutput); ตามลำดับ

ในการทดลองนี้จะกำหนด FuzzyRule ไว้เพียง 3 ส่วนคือ

สำหรับการกำหนดกฏของฟัซซี่ลอจิกที่ตำแหน่ง Building FuzzyRule1, 2 และ 3 ในตัวอย่างนี้ ผู้ออกแบบระบบควบคุมจะต้องทดลองปรับให้ระบบการทำงานเป็นไปตามที่ต้องการ (เช่นเดียวกับ EP4) โดยสามารถปรับตัวเลขภายในหรือเพิ่มจำนวน FuzzyINPUT, FuzzyOUTPUT และกฏของฟัซซี่ลอจิก FuzzyRule ให้เหมาะสมกับระบบที่ต้องการควบคุมนั้นๆ ได้

Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 3 เมื่อทดลองปรับ VR ให้ Error = 20, DeltaError = 0 จะได้ Result = 0 และ PWM = 0%
Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 4 เมื่อทดลองปรับ VR ให้ Error = 18, DeltaError = 11 จะได้ Result = 3 และ PWM = 21%
Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 5 เมื่อทดลองปรับ VR ให้ Error = 0, DeltaError = 0 จะได้ Result = 0 และ PWM = 28%
Simple Temperature Control by using Fuzzy Logic Control Based on Arduino
รูปที่ 6 เมื่อทดลองปรับ VR ให้ Error = -18, DeltaError = -17 จะได้ Result = -3 และ PWM = 19%

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

Reference

  1. https://en.wikipedia.org/wiki/Fuzzy_control_system
  2. https://forum.arduino.cc/t/how-make-fuzzy-logic-coding-for-arduino-uno/282381/4
  3. https://github.com/alvesoaj/eFLL
  4. https://github.com/amimaro/FuzzyLibrary
  5. https://fuzzylite.com/
  6. https://fuzzylite.com/downloads/FuzzyLite-Libraries.pdf
  7. https://www.microjpm.com/products/ad52300/
  8. https://c1555f5ec9.clvaw-cdnwnd.com/34662fcf1f1e607c561442431023ac8e/200010020-73ac173ac3/AD52300%20uJPM%20Datasheet.PDF
  9. https://www.tinkercad.com/dashboard
  10. https://www.circuitbasics.com/arduino-thermistor-temperature-sensor-tutorial/
  11. https://gemini.google.com/
  12. https://copilot.microsoft.com