ดิว.นินจา

ดิว.นินจา

Wednesday, February 14, 2018

พัฒนาระบบควบคุมบน ESP32 โดยไลบรารี FreeRTOS

ในบทความก่อนหน้านี้ได้กล่าวแนะนำไลบรารี FreeRTOS ที่มาพร้อมกับ Arduino Core ของ ESP32 โดยเน้นประเด็นสำคัญคือการกำหนดคอร์ประมวลผลให้กับทาสก์ เพื่อให้สามารถใช้ทรัพยากรฮาร์ดแวร์ของ ESP32 ได้อย่างมีประสิทธิภาพ เพราะการเขียนโปรแกรมโดยปกติบน Arduino IDE คอร์หมายเลข 0 จะไม่ถูกใช้งาน ข้อได้เปรียบจากการใช้ ESP32 ที่เหนือกว่า ESP8266 จะยังไม่ชัดเจนตราบเท่าที่เราไม่สามารถใช้ประโยชน์จากฮาร์ดแวร์ทั้งหมดอย่างเต็มที่ สำหรับโครงงานพื้นฐานเช่นอ่านข้อมูลจากเซนเซอร์และแสดงผลผ่านอินเทอร์เน็ต คงไม่มีความจำเป็นที่ต้องใช้ ESP32 และ FreeRTOS แต่ผู้อ่านที่ติดตามเรื่องราวจากบล็อกนี้คงทราบว่างานควบคุมอุตสาหกรรมจะมีความซับซ้อนมากกว่า โดยเฉพาะตัวควบคุมป้อนกลับเช่น PID จะต้องการคาบเวลาในการประมวลผลที่คงที่และเป็นอิสระจากงานอื่น งานควบคุมสมรรถนะสูงต้องการอัตราการสุ่มที่เร็วขึ้น ดังนั้นคำสั่งในลูปควบคุมจะต้องมีเพียงเท่าที่จำเป็น งานอื่นเช่นส่วนรับคำสั่ง การส่งข้อมูลออกพอร์ตอนุกรม จอแสดงผล หรืออินเทอร์เน็ตควรถูกแยกออกจากลูป ลักษณะการทำงานเรียลไทม์แบบหลายเทรด (multithread) นี้เองทำให้การใช้ FreeRTOS มีความเหมาะสมอย่างยิ่ง นอกจากนั้นยังเป็นไลบรารีที่ใช้งานง่ายและเอื้ออำนวยต่อการจัดการและการบำรุงรักษาซอฟต์แวร์

ยกตัวอย่างโครงสร้างเดิมของโครงสร้างตัวควบคุมที่ตั้งชื่อว่า IoFC (Internet of Feedback Controllers) ที่อัลกอริทึมควบคุมอยู่ในฟังก์ชันไทเมอร์ ส่วนงานอื่นทีเหลือใส่ไว้ใน loop() ทั้งหมด ซึ่งคาบเวลารวมถูกกำหนดโดยฟังก์ชัน delay() ข้อด้อยคือการจะเขียนโค้ดให้แต่ละส่วนทำงานตามคาบเวลาต่างกันจะต้องใช้ตัวแปรค่านับช่วย ยกตัวอย่างการเชื่อมต่อ NETPIE loop() จะต้องเรียก microgear.loop() ทุกรอบเพื่อรักษาการเชื่อมต่อไว้ ขณะที่การส่งข้อมูลให้กับ Freeboard และ Feed จะกระทำด้วยอัตราที่ต่ำกว่า หากมีการรับคำสั่งจากผู้ใช้ ส่งข้อมูลให้กับพอร์ตอนุกรม หรือจอแสดงผลด้วยอัตราที่ต่างกันก็ยิ่งทำให้ต้องเพิ่มตัวแปรนับค่า การจะทำให้บางฟังก์ชันไม่ทำงานต้องอาศัยตัวแปรแฟล็ก (flags) ทำให้โปรแกรมมีความยุ่งเหยิงและส่งผลต่อการจัดการและบำรุงรักษาซอฟต์แวร์

การปรับปรุงโครงสร้างโดยอาศัยไลบรารี FreeRTOS แต่ละส่วนของงานจะถูกสร้างเป็นทาสก์ เช่น ทาสก์อัลกอริทึมควบคุม ทาสก์รับคำสั่ง ทาสก์สำหรับ NETPIE โดยแต่ละทาสก์ทำงานตามคาบเวลาที่ตั้งไว้ (และสามารถเปลี่ยนได้โดยง่ายขณะทำงาน) หากไม่มีการใช้งานในส่วนใดก็สั่งให้ทาสก์นั้นหยุดทำงาน (suspend) เมื่อต้องการใช้ก็สั่งให้เริ่มทำงานใหม่ (resume) นอกจากนั้นยังสามารถใช้แถวคอยเป็นบัฟเฟอร์สำหรับการส่งข้อมูลจำนวนมาก

ในต้นฉบับหนังสือ ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266 และ ESP32" ที่อยู่ระหว่างจัดทำ (ความหนาปัจจุบัน 187 หน้า A4) ผู้เขียนได้เพิ่มเติมเนื้อหาเกี่ยวกับระบบเรียลไทม์และ FreeRTOS โดยเฉพาะในบทที่ 11 ที่กล่าวถึงการใช้งานทาสก์ แถวคอย และการจัดการทรัพยากรโดย FreeRTOS ณ ปัจจุบันหนังสือไม่มีวางขาย แต่จะมอบให้กับผู้เข้าฝึกอบรม "IoT สำหรับงานควบคุมอุตสาหกรรมโดย ESP32 และ NETPIE" พร้อมฮาร์ดแวร์ LOLIN32 บอร์ด LAG3 และตัวอย่างโปรแกรม

ลงทะเบียนฝึกอบรม : เสาร์ 24 กุมภาพันธ์ 2561

สำหรับหนังสือวางแผนไว้ว่าในช่วงหลังของปีหากเขียนได้จำนวนหน้าที่เหมาะสมจะลองส่งให้สำนักพิมพ์ ม.เกษตรศาสตร์ พิจารณา (ช่วงนี้การพัฒนาซอฟต์แวร์ของ ESP32 บางส่วนยังมีการเปลี่ยนแปลงทำให้ต้องแก้ไขต้นฉบับอย่างสม่ำเสมอ)

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


11.7 ตัวควบคุมที่ออกแบบใหม่โดยใช้ฟังก์ชันของ FreeRTOS

เนื้อหาที่กล่าวมาตั้งแต่ต้นของบทนี้ได้กล่าวแนะนำฟังก์ชันสำคัญของ FreeRTOS ที่สามารถประยุกต์ใช้ในงานควบคุมอุตสาหกรรม ในส่วนนี้จะปรับปรุงตัวควบคุมพลานต์ LAG3 เดิมที่พัฒนาในบทที่ 6 – 7 ให้มีสมรรถนะสูงขึ้น โดยออกแบบโครงสร้างตามตาราง 11.1

ทาสก์ คอร์ คาบเวลา ความสำคัญ หน้าที่
0 0 10 ms 4 อัลกอริทึมควบคุม
1 1 10 ms 3 อ่านข้อมูลจากแถวคอย (ถ้ามี) ส่งพอร์ตอนุกรม
2 1 100 ms 2 ส่งข้อมูลให้ OLED
3 1 100 ms 2 ปรับสี RGB LED
4 1 300 ms 2 รับคำสั่งจากผู้ใช้
5 1 1 s 1 ส่งข้อมูลให้ NETPIE Freeboard
6 1 15 s 1 ส่งข้อมูลให้ NETPIE Feed
loop() 1 100 ms - เรียก microgear.loop() เพื่อรักษาการเชื่อมต่อ NETPIE

ตาราง 11.1 โครงสร้างตัวควบคุมที่ออกแบบใหม่

องค์ประกอบของไลบรารี FreeRTOS ที่ใช้งาน

  • ฟังก์ชันสร้างทาสก์แบบกำหนดคอร์ได้ xTaskCreatePinnedToCore() โดยทาสก์ 0 ที่เป็นอัลกอริทึมควบคุมจะมีความสำคัญสูงสุด ประมวลผลบนคอร์ 0 เพียงทาสก์เดียว ใช้ฟังก์ชัน vTaskDelayUntil() เพื่อกำหนดคาบเวลาทำงานที่แน่นอน สำหรับทาสก์ 2, 3 จะสร้างและลบตามคำสั่งใช้งาน OLED และ RGB LED
  • สร้างแถวคอย 2 ตัว เพื่อรับข้อมูล y, u จากทาสก์ 0 และส่งออกพอร์ตอนุกรมโดยทาสก์ 1 เหตุผลที่ใช้แถวคอยเพื่อลดภาระในทาส 0 ให้เหลือแต่อัลกอริทึมควบคุมเท่านั้น (จากการวัดเวลาที่ใช้ในการส่งค่า r,y,u ออกพอร์ตอนุกรมจะมีค่าประมาณ 120 ไมโครวินาที ส่วนการเขียนข้อมูล 1 ค่าให้แถวคอยใช้เวลาเพียง 3 ไมโครวินาที) หากไม่มีข้อมูลในแถวคอย ทาสก์ 1 จะบล็อก
  • มีการปกป้องส่วนวิกฤต หรือใช้มิวเท็กซ์ เมื่อเข้าถึงตัวแปรหรือทรัพยากรที่ใช้ร่วมกัน หรือที่ต้องทำให้เสร็จโดยไม่มีการขัดจังหวะ ตัวอย่างเช่นการอัพเดทค่าสัมประสิทธิ์ตัวควบคุม

ลักษณะเด่นของโครงสร้างใหม่ที่ใช้ไลบรารี FreeRTOS

  1. องค์ประกอบของโปรแกรมถูกแยกเป็นทาสก์ที่ทำงานตามคาบเวลาที่กำหนด ทำให้มีความยืดหยุ่นมากขึ้น เช่นสมมุติว่าไม่ต้องการใช้จอ OLED ก็เพียงสั่งหยุดการทำงานของทาสก์ที่เป็นตัวส่งข้อมูลให้กับจอ
  2. อัลกอริทึมควบคุมที่มีความสำคัญสูงสุดทำงานบนคอร์ 0 เพียงทาสก์เดียว ช่วยเพิ่มสมรรถนะการควบคุมและทำให้การทำงานของระบบรวมมีประสิทธิภาพมากขึ้น
  3. สร้างทาสก์สำหรับส่งข้อมูลจำนวนมากผ่านพอร์ตอนุกรม โดยดึงข้อมูลจากแถวคอยที่เชื่อมต่อกับอัลกอริทึมควบคุม ช่วยลดภาระการสื่อสารข้อมูลจากตัวควบคุม
  4. การปรับแต่งคาบเวลาของแต่ละทาสก์ขณะทำงานโดยคำสั่งสามารถทำได้ง่ายและเป็นอิสระต่อกัน

โปรแกรมทั้งหมดรวมอยู่ในไฟล์ lag3_freertos.ino โดยทาสก์หมายเลข 1 - 6 จะถูกสร้างตามที่กำหนดไว้ในตาราง 11.1 แต่ละทาสก์จะมีแฮนเดิล xTask1h, …, xTask6h ทำให้สามารถใช้คำสั่ง vTaskSuspend() และ vTaskResume() เพื่อหยุดหรือเริ่มการทำงานใหม่ได้ตามต้องการ ตัวอย่างเช่นหากผู้ใช้ไม่ต้องการรับส่งข้อมูลผ่าน NETPIE ใช้คำสั่งผ่านพอร์ตอนุกรม

netpie=off

ทาสก์หมายเลข 5 และ 6 จะถูกสั่งให้หยุดทำงาน ทำให้ไม่มีการส่งข้อมูลให้กับทั้ง NETPIE Freeboard และ Feed แต่หากใช้คำสั่ง netpiefeed=off ทาสก์หมายเลข 6 ที่ส่งข้อมูลให้ Feed จะถูกหยุดทำงานเพียงทาสก์เดียว ส่วนคำสั่ง oled, rgbled ใช้สำหรับ ปิด/เปิด การทำงานของจอ OLED และ RGB LED

การตั้งค่าคาบเวลาของทาสก์ 0 - 6 ใช้คำสั่ง t0ms - t6ms ตามลำดับ ตัวอย่างเช่น

t0ms=5

เป็นการกำหนดคาบเวลาของอัลกอริทึมควบคุมเท่ากับ 5 มิลลิวินาที ค่าน้อยสุดที่สามารถกำหนดคาบเวลาสำหรับ FreeRTOS คือ 1 มิลลิวินาที หากต้องการค่าน้อยกว่านี้ต้องไปแก้ในไลบรารี ซึ่งไม่แนะนำเพราะอาจมีผลกระทบกับฟังก์ชันอื่นๆ เนื่องจากค่าคาบเวลาของติ๊กถูกใช้เป็นเสมือนสัญญาณนาฬิกาของระบบรวม ในงานอุตสาหกรรมทั่วไป ระบบควบคุมที่ต้องการอัตราการสุ่มที่สูงกว่า 1 KHz ไม่พบเห็นบ่อย ซึ่งหากจำเป็นต้องใช้แบนด์วิดท์สูงขนาดนั้นแนะนำให้อิมพลิเมนต์ตัวควบคุมบนตัวประมวลผลสนับสนุน โดยติดต่อสื่อสารกับ ESP32 ผ่าน SPI, I2C หรือพอร์ตอนุกรม

สังเกตว่าโดยโครงสร้างของทาสก์จากโปรแกรม lag3_freertos.ino อัลกอริทึมควบคุมจะถูกกำหนดให้มีคาบเวลาที่แน่นอนจากการเรียกใช้ฟังก์ชัน vTaskDelayUntil() เพื่อให้ตัวควบคุมทำงานได้อย่างถูกต้อง แตกต่างจากทาสก์อื่นที่คาบเวลาถูกกำหนดโดย vTaskDelay() ซึ่งจะได้ค่าคาบเวลาโดยประมาณเท่านั้น

ผลการรับส่งข้อมูลกับ NETPIE Feed และ Freeboard แสดงในรูปที่ 11.9 ทุกส่วนประกอบสามารทำงานได้อย่างถูกต้อง ในมุมของผู้ใช้งานอาจไม่เห็นความแตกต่างจากโปรแกรมเดิมที่ไม่ใช้ไลบรารี FreeRTOS แต่สมรรถนะของระบบรวมถูกปรับปรุงให้ใช้ฮาร์ดแวร์ของ ESP32 ได้อย่างมีประสิทธิภาพ ความยืดหยุ่นในการใช้งานเพิ่มขึ้น และมีโครงสร้างที่เป็นระบบ เอื้ออำนวยต่อการบำรุงรักษาซอฟต์แวร์ในภายหลัง

รูปที่ 11.9 การรับส่งข้อมูลกับ NETPIE Feed และ Freeboard จากโปรแกรม lag3_freertos.ino

จุดหนึ่งที่ยังต้องมีการปรับปรุงคือ สัมประสิทธิ์ของตัวควบคุมเชิงเส้นที่ถูกเขียนเป็นค่าคงที่ในโปรแกรม หากมีการปรับค่าคาบเวลาตัวควบคุมแตกต่างไปจากค่าที่ใช้ในการแปลงเป็นระบบดีสครีต จะทำให้อัลกอริทึมไม่ใช่ตัวแทนของตัวควบคุมที่ออกแบบไว้ ในทางปฏิบัติต้องหาวิธีที่จะโหลดสัมประสิทธิ์ใหม่ออนไลน์ได้โดยคำสั่ง หรือวิธีที่ดีกว่าคือหาสมการของสัมประสิทธิ์ในรูปของค่าคาบเวลา ทำให้สามารถคำนวณสัมประสิทธิ์ใหม่ได้ทุกครั้งที่มีการเปลี่ยนคาบเวลาแบบเดียวกันที่ใช้ในอัลกอริทึม PID แนวทางในการอิมพลิเมนต์จะได้นำเสนอในภาคผนวก C

ดาวน์โหลด lag3_freertos.ino

ลงทะเบียนฝึกอบรม : เสาร์ 24 กุมภาพันธ์ 2561

No comments:

Post a Comment

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

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