ดิว.นินจา

ดิว.นินจา

Thursday, May 10, 2018

การจำลองฟังก์ชันถ่ายโอนของพลานต์บน ESP32

เว็บนี้ได้นำเสนอการพัฒนาตัวควบคุมป้อนกลับบน ESP32 มาสักช่วงระยะเวลาหนึ่ง โดยมากตัวอย่างในบทความก่อนหน้านี้จะอาศัยบอร์ด LAG3-ESP32 ซึ่งผู้ที่เคยฝึกอบรมกับเราจะได้รับไปพร้อมกับบอร์ด WEMOS LOLIN32 ทำให้สามารถทดลองตามไปได้ เป็นปัญหาสำหรับผู้ไม่มีบอร์ดและไม่มีเวลาบัดกรีวงจรอิเล็กทรอนิกส์บนบอร์ดอเนกประสงค์ บทความนี้จึงนำเสนอการจำลองพลานต์ LAG3 บน ESP32 ที่ให้ผลตอบสนองเช่นเดียวกับที่ได้จากวงจรอิเล็กทรอนิกส์โดยไม่ต้องใช้อุปกรณ์ใดเพิ่มเติมนอกจากบอร์ด ESP32 จากบริษัทใดก็ได้ที่ผู้อ่านมีอยู่ วิธีการนี้สามารถใช้จำลองพลานต์ใดๆ ที่บรรยายในรูปฟังก์ชันถ่ายโอน มีประโยชน์อย่างยิ่งในกรณีที่ต้องการพัฒนาทั้งตัวควบคุมและพลานต์ไปพร้อมกัน

หมายเหตุ : เนื้อหาด้านล่างนี้คัดลอกจากหนังสือ "ระบบควบคุมและอินเทอร์เน็ตเชื่อมต่อสรรพสิ่ง" ซึ่งอยู่ระหว่างจัดทำต้นฉบับ

วิธีการฮาร์ดแวร์ในวง

ในการพัฒนาและทดสอบระบบควบคุมฝังตัวที่มีความซับซ้อน แนวทางหนึ่งที่นิยมใช้รู้จักกันในชื่อ ฮาร์ดแวร์ในวง (Hardware-in-the-loop) หรือเรียกโดยย่อว่า HIL วิธีการนี้จะใช้ตัวแทนโมเดลทางคณิตศาสตร์ของ พลานต์ในการจำลองการทำงาน โดยตัวควบคุมหรือระบบอื่นๆ ที่ต่อเชื่อมจะทำงานร่วมกับพลานต์จำลองนี้ อุตสาหกรรมหลายประเภทประสบความสำเร็จในการใช้ HIL ช่วยในการพัฒนา ตัวอย่างหนึ่งคืออุตสาหกรรมยานยนต์ ในรถยนต์ปัจจุบันประกอบด้วยระบบสมองกลฝังตัวจำนวนมากติดต่อสื่อสารกัน โดยแบ่งเป็นระบบย่อย เช่นระบบต้านการล็อกของเบรค ระบบจ่ายเชื้อเพลิง สรุปข้อดีของการใช้ HIL ได้ดังนี้

  • ในการทดสอบเบื้องต้นกับพลานต์จริงที่มีราคาสูง หรือเปราะบาง ความผิดพลาดในระบบอาจทำให้เกิดความเสียหาย จึงเหมาะสมที่จะทดสอบโดย HIL จนมั่นใจเสียก่อน
  • งานบางประเภทต้องการทดสอบด้วยแรงหรืออินพุตที่มีขนาดสูงเกินค่าปกติ ซึ่งอาจเกิดความเสียหายได้หากใช้พลานต์จริง หรือในบางกรณีต้องการศึกษาโครงสร้างภายในของพลานต์ขณะที่เกิดความเสียหาย การใช้อุปกรณ์และชิ้นส่วนของพลานต์จริงจะมีค่าใช้จ่ายที่สูงกว่า หรืออาจเกิดอันตรายต่อผู้ทดสอบ
  • ในการออกแบบและพัฒนาผลิตภัณฑ์ใหม่ พลานต์กับตัวควบคุมอาจจะถูกสร้างและมีการแก้ไขไปพร้อมกัน การใช้ HIL จะมีความยืดหยุ่น และช่วยลดระยะเวลาในการพัฒนา

การจำลองฟังก์ชันถ่ายโอนของพลานต์

ในหัวข้อนี้จะกล่าวเฉพาะกรณีที่พลานต์มีโมเดลทางคณิตศาสตร์ที่บรรยายในรูปฟังก์ชันถ่ายโอน ซึ่งใช้หลักการเดียวกันกับการอิมพลิเมนต์ตัวควบคุม คือการแปลงจากระบบเวลาต่อเนื่องเป็นดีสครีตโดยวิธีการประมาณค่า 3 แบบ ในที่นี้จะเลือกใช้วิธีแปลงเชิงเส้นคู่ โดยยกตัวอย่างระบบถังน้ำ 3 ระดับ

เพื่อแสดงให้เห็นถึงความยืดหยุ่นในการใช้พลานต์จำลอง สมมุติว่าต้องการสร้างโมเดลจำลองของพลานต์ถังน้ำ 3 ระดับ ที่ค่าอัตราขยาย KL และเวลาการหน่วง τi, i= 1,2,3 เป็นตัวแปร

โดย

พิจารณาแต่ละพจน์ย่อย (2) ตัวอย่างเช่น P1(s) แทนค่าความสัมพันธ์ของการแปลงเชิงเส้นคู่

และจัดรูปใหม่ จะได้เป็น

ใช้วิธีการเดียวกันเพื่อหาฟังก์ชันถ่ายโอน P2(z) และ P3(z) เพื่อให้สอดคล้องกับการกำหนดสถานะระบบในส่วนต้อนของบทนี้ กำหนดอินพุตและเอาต์พุตของแต่ละภาคดังนี้

สามารถแสดงได้โดยง่ายว่า (5) - (7) แปลงเป็นระบบสมการผลต่างในโดเมนเวลาได้เท่ากับ

โดยมีค่าสัมประสิทธิ์เป็นดังนี้

และค่าเอาต์พุตเท่ากับ

สมการ (8) - (11) อยู่ในรูปที่อิมพลิเมนต์เป็นอัลกอริทึมได้โดยง่าย ในกรณีใช้ ESP32 ควรสร้างทาสก์เฉพาะสำหรับจำลองพลานต์แยกจากตัวควบคุม จะทำให้บริหารจัดการโค้ดได้ง่ายกว่าใส่ไว้ในลูปเดียวกัน และยังสามารถเลือกคาบเวลาที่ต่างกันได้ด้วย การเข้าถึงตัวแปรที่นิยามเป็นอินพุต สถานะ และเอาต์พุต อาจใช้วิธีป้องกันส่วนวิกฤต เช่นการใช้มิวเท็กซ์ เพื่อมิให้เกิดปัญหาการอ่านค่าก่อนตัวแปรจะถูกเขียนแล้วเสร็จ

ตัวอย่าง : ทดลองแก้ไขโปรแกรมเดิมที่ใช้บอร์ด LAG3-ESP32 และโครงสร้าง FreeRTOS โดยเพิ่มทาสก์ใหม่สำหรับอัลกอริทึมจำลองพลานต์ตามสมการ (8) - (10) ตั้งค่าพารามิเตอร์ KL, และ τi, i= 1,2,3 เท่ากับ 1 ทั้งหมดเพื่อสามารถเปรียบเทียบผลตอบสนองกับการใช้วงจรอิเล็กทรอนิกส์ โปรแกรมส่วนที่เพิ่มประกอบด้วยนิยามตัวแปรเป็นโครงสร้างข้อมูล


struct PlantSim
{
  float T;      // sampling period
  float Tau1,Tau2, Tau3;    // lag parameters
  float K;                  // overall gain
  float a11, a21, a31, b11,b21,b31;   // coefficients
  float x1_1,x1_0, x2_1, x2_0, x3_1, x3_0;       // states
  float u0, u1;           // input (from controller output)
  bool ulim;          // input limit flag
};
struct PlantSim PSim;   // create instance

ฟังก์ชันการคำนวณค่าสัมประสิทธิ์และตั้งค่าเริ่มต้น


void PSim_init(void) 
{
  float Tau1_T, Tau2_T, Tau3_T;
  PSim.T = 0.01;      //sampling period (sec)
  PSim.ulim = 1;      // input limit OFF/ON
  PSim.Tau1 = 1;
  PSim.Tau2 = 1;
  PSim.Tau3 = 1; 
  PSim.K = 1;
  Tau1_T = PSim.Tau1*PSim.T;
  Tau2_T = PSim.Tau2*PSim.T;
  Tau3_T = PSim.Tau3*PSim.T;
  PSim.a11 = (2 - Tau1_T)/(2 + Tau1_T);
  PSim.a21 = (2 - Tau2_T)/(2 + Tau2_T);
  PSim.a31 = (2 - Tau3_T)/(2 + Tau3_T);
   PSim.b11 = PSim.T/(2+Tau1_T);
  PSim.b21 = PSim.T/(2+Tau2_T);  
  PSim.b31 = PSim.T/(2+Tau3_T);  
  PSim.x3_0 = 0; // initialize states to zero
  PSim.x2_0 = 0;
  PSim.x1_0 = 0;
  PSim.x3_1 = 0;
  PSim.x2_1 = 0;
  PSim.x1_1 = 0;
}

ทาสก์สำหรับจำลองพลานต์เขียนได้ดังนี้


void Task7( void * parameter)
{
  float px1, px2, px3;
  TickType_t xLastWakeTime;
  xLastWakeTime = xTaskGetTickCount();
  //float ylocal, ulocal;
  for(;;)
  {
             PSim.u1 = PSim.u0;  // update plant states and input
    PSim.x3_1 = PSim.x3_0;
    PSim.x2_1 = PSim.x2_0;
    PSim.x1_1 = PSim.x1_0;
    px1 = PSim.a11*PSim.x1_1 + PSim.b11*(PSim.u0 + PSim.u1);
    px2 = PSim.a21*PSim.x2_1 + PSim.b21*(PSim.x1_0 + PSim.x1_1);
    px3 = PSim.a31*PSim.x3_1 + PSim.b31*(PSim.x2_0 + PSim.x2_1);
    taskENTER_CRITICAL(&myMutex);
    PSim.x1_0 = px1;
    PSim.x2_0 = px2;
    PSim.x3_0 = px3;
    taskEXIT_CRITICAL(&myMutex);   
    vTaskDelayUntil(&xLastWakeTime, T7ticks);  // set period 
  }
  vTaskDelete(NULL);
}

และถูกสร้างให้ทำงานบนคอร์หมายเลข 1 โดยคำสั่ง


xTaskCreatePinnedToCore(Task7, "PSimTask", 10000, NULL, 1, &xTask7h, 1);

สังเกตว่าจะใช้กลไกในการปกป้องส่วนวิกฤตก่อนการเขียนข้อมูลลงบนตัวแปรที่ตัวควบคุมอ่าน ในส่วนของ cmdInt() สามารถใช้คำสั่งเพื่อเลือกใฃ้พลานต์จำลองหรือวงจรอิเล็กทอนิกส์ภายนอกได้โดยกำหนดค่าให้กับตัวแปร plantsim และถ้าเลือกใช้วงจรภายนอก ทาสก์ที่จำลองพลานต์จะถูกแขวนไม่ให้ทำงาน สำหรับส่วนตัวควบคุมจะเพิ่มเงื่อนไขในการเลือกรับอินพุตและส่งเอาต์พุตจากการจำลองหรือจากภายนอก ตัวอย่างเช่นการส่งเอาต์พุตจากตัวควบคุมจะถูกเลือกโดยตัวแปร plantsim ดังนี้


    if (plantsim)   {
      if (PSim.ulim)  {
        taskENTER_CRITICAL(&myMutex);
        PSim.u0 = u0lim;
        taskEXIT_CRITICAL(&myMutex);        
      }
      else  {
        taskENTER_CRITICAL(&myMutex);
        PSim.u0 = u0;
        taskEXIT_CRITICAL(&myMutex);     
      }
    }
    else   {
      // send output to both DAC1 and PWM16
      ledcWrite(PWMch, pwmval);
      dacval = pwmval>>4; //int(pwmval/8);
      dacWrite(DAC1, dacval);
    }

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

ดาวน์โหลดโปรแกรม lag3_freertos_plantsim.zip

No comments:

Post a Comment

แนะนำหนังสือ “ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266”

ปัจจุบันเมื่อกล่าวถึงอุปกรณ์ IoT (Internet of Things) คงมีน้อยคนที่จะไม่รู้จัก ในยุคที่การเข้าถึงอินเทอร์เน็ตเป็นกิจวัตรประจำวันของมนุษย์เ...