NETPIE Series
ในบทความนี้เราจะปรับปรุงส่วนติดต่อผู้ใช้บน freeboard ที่สร้างไว้ใน บทที่ 6 ของหนังสือ “ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266” ให้เหมาะสมกับการใช้ในงานควบคุมอุตสาหกรรมจริง ตัวควบคุม IoFC ได้ถูกออกแบบให้มีความยืดหยุ่น คือสามารถปรับพารามิเตอร์ได้ทั้งที่หน้างานผ่านพอร์ตอนุกรม และจากระยะไกลโดย NETPIE แต่หน้าควบคุม freeboard จากตัวอย่างที่ 6.4 ในหนังสือยังไม่ได้ออกแบบให้รองรับกรณีมีผู้ปฏิบัติงานทั้ง 2 สถานที่ เพราะหากมีการเปลี่ยนค่าพารามิเตอร์ที่หน้างาน ส่วนควบคุมใน NETPIE จะไม่อัพเดตตาม เราจะมาศึกษาวิธีแก้ปัญหานี้โดยใช้ฟังก์ชัน microgear.publish() และเพิ่มการตั้งค่าใน freeboard widgets
ฮาร์ดแวร์ที่ใช้ทดสอบคือ WEMOS LOLIN32 และรันโปรแกรมจากบทความก่อนหน้านี้คือ “การติดตั้งและแก้ปัญหาไลบรารีสำหรับ ESP32 เพื่อใช้งานกับ Arduino IDE และ NETPIE” ซึ่งจะใช้งานร่วมกับ NETPIE freeboard ในตัวอย่าง 6.4 ในหนังสือได้ เมื่อเข้าหน้า Freeboard จะมีหน้าตาดังแสดงในรูปที่ 1

ในบทความนี้จะไม่กล่าวถึงส่วน gauges และ feed ส่วนบน แต่มุ่งเน้นไปที่ control widgets คือตัว sliders และ toggle switches ในส่วนล่างของ Freeboard สังเกตค่าเริ่มต้นของแต่ละ widgets ซึ่งจะเป็นค่าที่ตั้งไว้ในแต่ละตัว ตัวอย่างเช่นเมื่อเราคลิกที่รูปประแจบน slider ของ Proportional Gain Kp จะเห็นการตั้งค่าในรูปที่ 2 สังเกตว่าค่าเริ่มต้นจะถูกกำหนดไว้ในฟิลด์ INITIAL VALUE ที่ใส่ค่าเท่ากับ 5 ดังนั้นเมื่อเปิดหน้าต่างมาครั้งแรก (หรือเมื่อกด refresh) ค่าจึงถูกตั้งไว้ที่ 5 sliders ตัวอื่นๆ ก็จะทำงานแบบเดียวกัน

ข้อสังเกตอีกจุดหนึ่งก็คือ ในขณะนี้ฟิลด์ AUTO UPDATED VALUE ถูกปล่อยว่างไว้ ซึ่งต่อไปเราจะใช้ฟิลด์นี้ในการปรับค่าของ sliders ให้ตรงกับความเป็นจริง
ดังนั้น เมื่อเปิดหน้าต่างมาครั้งแรก ไม่สามารถรับประกันได้ว่าค่าของ sliders และ toggle switches จะตรงกับค่าจริงในตัวควบคุมขณะนั้น ตรวจสอบง่ายๆ โดยเปิด serial monitor และถามค่าพารามิเตอร์ (โดยพิมพ์ชื่อพารามิเตอร์ที่ต้องการทราบ เช่น kp ในช่องบนสุด) พบว่าค่าจริงเป็นดังที่แสดงในรูปที่ 3 ที่แตกต่างจากค่าใน Freeboard นอกจากนั้นเมื่อตรวจสอบว่าใช้ตัวควบคุมแบบใหนอยู่ พบว่าเป็นแบบ CC (Custom Controller) แต่ปุ่ม toggle บน Freeboard ในรูปที่ 1 แสดง PID ซึ่งไม่ตรงกับความเป็นจริง
ทดลองตั้งค่าใหม่โดยพิมพ์ใน serial monitor เช่น kp=6 หรือ adma=on ค่าในตัวควบคุมจะถูกเปลี่ยน แต่ Freeboard จะไม่มีทางทราบเลย

วิธีง่ายที่สุดในการทำให้ค่าตรงกันตอนเริ่มต้นคือ ใส่คำสั่งในช่อง ON CREATED ACTION เพื่อส่งค่าไปอัพเดทค่าในตัวควบคุม แต่ไม่แนะนำวิธีนี้ด้วยเหตุผล 2 ประการคือ
- เราจะแน่ใจได้อย่างไรว่าค่าใน Freeboard เหมาะสมกว่าค่าที่ใช้อยู่บนตัวควบคุมในขณะนั้น ซึ่งอาจจะถูกปรับแต่งละเอียดโดยวิศวกรที่หน้างานไว้แล้ว (ในงานควบคุมอุตสาหกรรมจริง การปรับพารามิเตอร์ตัวควบคุมจากระยะไกลเป็นวิธีที่ควรหลีกเลี่ยงเพราะอาจเกิดอันตราย นอกจากมีความจำเป็นหรือในสถานการณ์ฉุกเฉินเท่านั้น)
- วิธีนี้ไม่สามารถแก้ปัญหาหากมีการเปลี่ยนแปลงผ่านพอร์ตอนุกรมหลังจากนั้นอีก
การอัพเดทโดย publish ค่าอย่างต่อเนื่อง
เราจะเริ่มจากวิธีที่ง่ายที่สุดคือการ publish ค่าของสถานะและพารามิเตอร์ในฟังก์ชัน loop() เช่นเดียวกับการส่งค่าให้กับ gauges และ feed แต่จะตั้งชื่อ topics ให้ต่างกัน จากตัวอย่างเดิมได้ตั้งชื่อ topic สำหรับค่า r, y, u ที่แสดงบน gauge widgets ไว้คือ
#define RYUDATATOPIC "/ryu/" ALIAS // topic to publish; in this case, /ryu/{ALIAS}
เราจะเพิ่ม topic ใหม่โดยใช้ชื่อตัวย่อ CSP (Controller Status and Parameters)
#define CSPDATATOPIC "/csp/" ALIAS // Controller Status and Parameters /csp/{ALIAS}
ซึ่งตัว sliders และ toggle widgets จะ subscribe topic นี้เพื่อรับข้อมูลอัพเดท
ในขณะนี้เรามี widget สำหรับพารามิเตอร์และสถานะตัวควบคุมทั้งหมด 8 ตัว ประกอบด้วย sliders 6 ตัว (Kp, Ki, Kd, Kt, Wp, Wd) และ toggle 2 ตัว (Controller Select และ MA Filter) ในที่นี้จะเรียงลำดับตัวแปรที่เกี่ยวข้องดังนี้
controltype, adma, kp, ki, kd, kt, wp, wd
โดยส่งไปทั้งสตริงและให้ widget แต่ละตัวไปแยกข้อมูลเอาเอง ใช้วิธีเช่นเดียวกับการ publish ค่าของ r, y, u คือเพิ่มคำสั่งใน loop() เพื่อสร้างสตริงและส่งให้ microgear.publish()
String cspstring =(String)controltype+","+(String)adma+","+(String)kp+","
+(String)ki+","+(String)kd+","+(String)kt+","+(String)wp+","+(String)wd;
microgear.publish(CSPDATATOPIC, cspstring);
โดยตั้งค่าคาบเวลาในการ publish ให้เหมาะสม ในช่วงเริ่มต้นอาจจะให้พิมพ์ใน serial monitor ดูว่าค่าถูกต้องหรือไม่
Serial.print("Publishing /csp/ --> ");
Serial.println(cspstring);
ตัวอย่างโปรแกรมคือ esp32_publishparms.ino (รวมอยู่ใน zip file ด้านล่าง) คอมไพล์และอัพโหลดลงบนบอร์ด เปิด serial monitor ดูจะเห็นสตริงที่ถูก publish ตามคาบเวลาที่ตั้งไว้ ดังในรูปที่ 4

งานที่เหลือก็คือในส่วนของ Freeboard widgets ซึ่งจะต้องไปตั้งค่าในฟิลด์ AUTOUPDATED VALUE ของแต่ละตัวเพื่อดึงค่าจากสตริงที่ถูก publish จะขอกล่าวถึง slider widget ก่อนโดยยกตัวอย่างตัว Kp คลิกรูปประแจเพื่อตั้งค่า และพิมพ์คำสั่งดังนี้ลงในช่อง AUTOUPDATED VALUE
datasources["myIoFCboard2"]["/myIoFC/csp/myIoFCdevice"].split(",")[2]
ดังแสดงในรูปที่ 5 (สำหรับส่วนต้นๆ ของคำสั่งจะมีตัวเลือกขึ้นมาให้เมื่อคลิกที่ +DATASOURCE แต่ในส่วนท้ายคือ .split(“,”)[2] ต้องพิมพ์เอง

อธิบายคำสั่งนี้ได้คือ ในส่วนต้นจะเป็นการเลือก datasource และ topic ที่จะ subscribe ส่วนท้ายคือการแยกข้อมูลออกจากสตริงโดยตัวคั่นคือ "," และค่าของ kp อยู่อันดับที่ 3 ในสตริง (ตัวชี้ของคำสั่ง split จะเริ่มจาก 0 ดังนั้นค่าที่ 3 ในสตริงจะมีตัวชี้เท่ากับ 2)
สำหรับ sliders ตัวอื่นๆ ที่เหลือก็ตั้งค่าโดยใช้คำสั่งเดียวกันนี้ เพียงแต่เปลี่ยนตัวชี้ใน [ ] ท้ายคำสั่งให้ตรงกับตำแหน่งของข้อมูลที่ต้องการเท่านั้น ตัวอย่างเช่น slider สำหรับ Kt จะใส่ตัวชี้เป็น [5] เป็นต้น
ต่อมาสำหรับ toggle switches 2 ตัว จะต้องตั้งค่าใน AUTO UPDATED VALUE เช่นเดียวกันโดยคำสั่งที่คล้ายกัน แต่จะเพิ่มตรงส่วนท้ายอีกเล็กน้อย ตัวอย่างเช่นการตั้งค่าสำหรับ Controller Select จะใช้คำสั่งดังนี้
datasources["myIoFCboard2"]["/myIoFC/csp/myIoFCdevice"].split(",")[0]==1
ดังแสดงในรูปที่ 6 อธิบายคำสั่งคือ ตำแหน่งข้อมูลของชนิดตัวควบคุมจะอยู่อันดับแรกในสตริง (ตัวชี้เท่ากับศูนย์) แต่หลังจากดึงข้อมูลแล้วจะต้องเขียนตรรกะเพื่อบอกว่าให้ toggle เปลี่ยนสถานะเป็น ON เมื่อข้อมูลมีค่าเท่ากับ 1 และจะกลับเป็น OFF เมื่อข้อมูลมีค่า 0 ซึ่งสำหรับ Controller Select toggle นี้จะตั้งไว้ว่า ON คือการเลือกตัวควบคุมที่ออกแบบเฉพาะ (Custom) และ OFF คือเลือกตัวควบคุม PID

หมายเหตุ: ในการทดลองครั้งแรกผู้เขียนไม่ได้ใส่ == 1 ท้ายคำสั่ง ผลคือ toggle เปลี่ยนค่าเป็น ON (Custom) เพียงครั้งแรกและไม่สามารถเปลี่ยนกลับเป็น OFF หลังจากนั้น ไม่ว่าจะคลิกด้วยเม้าส์หรือเปลี่ยนค่าใน serial monitor ก็ตาม
อย่าลืมตั้งค่าใน toggle อีกตัวหนึ่งคือ MA Filter โดยใช้คำสั่งเดียวกันเพียงเปลี่ยนแค่ตัวชี้เป็น [1] เท่านั้น
เมื่อแก้ไข widgets ครบทั้งหมดแล้ว ท่านจะเห็นว่าค่าพารามิเตอร์และสถานะของตัวควบคุมใน Freeboard จะถูกปรับให้ตรงกับค่าจริง ดังในรูปที่ 7 ทดลองเปลี่ยนค่าใน serial monitor จะเห็นว่า Freeboard widget ถูกอัพเดต โดยอัตราการอัพเดตจะสัมพันธ์กับคาบเวลาที่เรา publish ในโปรแกรม

การควบคุมโดย Freeboard จะเป็นไปตามปกติ คือเมื่อคลิกเลื่อนตัว sliders ค่าพารามิเตอร์ในตัวควบคุมจะถูกเปลี่ยน ทดลองคลิกที่ toggle switches ถ้าสถานะไม่เปลี่ยน ตรวจสอบคำสั่งใน AUTO UPDATED VALUE ว่าลืมใส่ ==1 ต่อท้ายหรือไม่
การ publish เฉพาะเมื่อสถานะหรือพารามิเตอร์ถูกเปลี่ยน
วิธีการ publish ค่าอย่างต่อเนื่องแบบที่กล่าวมามีข้อเสียที่ชัดเจนคือ โดยปกติหลังจากได้ค่าที่เหมาะสมแล้วผู้ใช้งานจะไม่ได้ปรับค่าสถานะและพารามิเตอร์ตัวควบคุมบ่อยครั้ง หรืออาจจะไม่ได้เปลี่ยนอีกเลยก็ได้ ดังนั้นการ publish ค่าอย่างต่อเนื่องเป็นการเปลืองแบนด์วิดธ์โดยเปล่าประโยชน์ หรือถ้าหาก publish นานๆ ครั้งก็จะมีปัญหาต้องรอนานกว่าค่าจะเปลี่ยน ดังนั้นวิธีที่ดีกว่าคือ publish เฉพาะเมื่อมีการเปลี่ยนแปลงสถานะหรือพารามิเตอร์ตัวใดตัวหนึ่งเท่านั้น ถ้าไม่มีการเปลี่ยนแปลงก็ไม่ต้องส่งข้อมูลใด
การเขียนโค้ดสำหรับวิธีนี้จะสะดวกกว่าหากรวมไว้เป็นฟังก์ชัน ที่สามารถเรียกใช้ในส่วนอื่นของโปรแกรม ตัวอย่างเช่น
// publish all parameters to update freeboard widgets
// whenever a parameter is changed
void update_freeboard(void)
{
// format is controller, adma, kp , ki, kd, kt, wp, wd
String cspstring = (String)controltype+","+(String)adma+","
+(String)kp+","+(String)ki+","+(String)kd+","+(String)kt
+","+(String)wp+","+(String)wd;
Serial.print("Publishing /csp/ --> ");
Serial.println(cspstring);
microgear.publish(CSPDATATOPIC, cspstring);
}
จากนั้นก็พิจารณาส่วนของคำสั่งหรือฟังก์ชันตรงจุดที่มีการเปลี่ยนค่าพารามิเตอร์ สำหรับตัวควบคุม IoFC การเปลี่ยนค่าอัตราขยาย PID แต่ละตัวจะเริ่มที่ฟังก์ชันแปลคำสั่ง CmdInt() หลังจากนั้นจะต้องเรียกพังก์ชัน PID_update() เพื่อคำนวณสัมประสิทธิ์ตัวควบคุมใหม่เสมอ ดังนั้นจุดที่เหมาะสมที่สุดที่จะเรียกฟังก์ชัน update_freeboard() คือในฟังก์ชัน PID_update() นั่นเอง
ส่วนสำหรับการเลือกตัวควบคุม และการเลือกใช้ MA Filter จะอยู่ใน CmdInt() ดังนั้นจึงใส่ update_freeboard() ไว้หลังจากที่เปลี่ยนค่าตัวแปรแล้ว
ตัวอย่างโปรแกรมคือ ESP32_publishparmsfn.ino ทดลองรันโปรแกรมนี้เพื่อตรวจสอบการอัพเดทค่าในตัวควบคุมกับบน Freeboard เมื่อเปิด serial monitor มาจะไม่เห็นการ publish ใดๆ เพราะยังไม่มีการเปลี่ยนค่า
ทดลองพิมพ์คำสั่งเปลี่ยนค่าพารามิเตอร์และสถานะตัวควบคุมดังในรูปที่ 8 จะเห็นว่าสตริงจะถูก publish ทันทีหลังจากที่แต่ละค่าถูกเปลี่ยน

และเมื่อตรวจสอบค่าบน Freeboard widgets ในรูปที่ 9 จะเห็นค่าถูกเปลี่ยนไปเป็นค่าใหม่โดยทันที เวลาในการตอบสนองต่อการเปลี่ยนแปลงจะดีกว่าการส่งค่าแบบเป็นคาบเวลา และไม่เปลืองแบนด์วิดธ์ด้วย

ไฟล์ตัวอย่างในบทความนี้รวมอยู่ใน ESP32_csp.zip
อ่านบทความนี้แล้วยังไม่หนำใจ มาร่วม ฝึกอบรมกับเราใน Workshop ตัวควบคุมป้อนกลับบนอินเทอร์เน็ต ครั้งที่ 1 โดยจะแจก printout หนังสือ “ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266” ที่เพิ่มเติมเนื้อหาที่เพิ่งเขียนใหม่อย่างเช่นในบทความนี้ หรือการพัฒนาบน ESP32 เบื้องต้น สำหรับผู้เข้าร่วมอบรมเท่านั้นครับ พร้อมของแถมอื่นๆ อีก
No comments:
Post a Comment