พื้นฐานการเขียนโปรแกรม PLC ด้วยภาษา Structure Text
พื้นฐานการเขียนโปรแกรม PLC ด้วยภาษา Structure Text
ภาษา Structure Text หรือตัวย่อสั้นๆอาจจะเรียกว่า “ST” เป็นหนึ่งในภาษาที่อยู่ใน Standard IEC61131-3 ว่าด้วยเรื่องของมาตรฐานการเขียนโปรแกรมบน Programable Logic Controller (PLC) เป็นภาษาที่มีจุดเด่นในด้านความง่ายในการโปรแกรมที่มีการคำนวนที่ซับซ้อน มีการบวก ลบ คูณ หาร หรือการ mapping ข้อมูลจำนวนมาก ซึ่งถ้าใช้ Ladder Diagram อาจจะใช้จำนวนบล็อกที่มากกว่าในการทำงานอย่างเดียวกัน งานที่มีลักษณะการทำงานเป็นเงื่อนไข (IF ELSE) ก็สามารถจัดการได้ง่ายกว่า หรือแม้กระทั่งคำสั่งวนลูปต่างๆเพื่อนำไปใช้จัดการกับ Array ของข้อมูลจำนวนมาก ก็เหมาะอย่างยิ่งกับการเขียนด้วย Structure Text
ในบทความนี้ ผู้เขียนจะอ้างอิงโดยใช้ PLC ตระกูล Logix ของยี่ห้อ Allen-Bradley ซึ่งใน PLC แต่ละยี่ห้ออาจจะมีไวยากรณ์ที่ต่างกันบ้างเล็กน้อย แต่โดยรวมแล้วจะมีหลักการเขียนที่เหมือนกัน โดยผู้เขียนขอแบ่งหัวข้อออกเป็น 4 หัวข้อ ได้แก่
- Assignments การกำหนดค่าให้กับตัวแปร
- Expressions การคำนวนต่างๆ
- Instructions คำสั่งเฉพาะ
- Constructions การจัดการกับโปรแกรม
หัวข้อที่ 1 Assignments
เกี่ยวกับการกำหนดค่าให้ตัวแปรของเรา โดยจะใช้ไวยากรณ์ดังนี้
Tag := expression;
โดยที่
Tag คือ ตัวแปรที่สร้างไว้และกำลังจะรับค่าจากจาก expression
:= คือ เครื่องหมายสำหรับ assign ค่า
Expression คือ การคำนวนซึ่งได้มาซึ่งค่าๆหนึ่งซึ่งต้องการจะ assign ให้กับ Tag
; คือ เครื่องหมายจบ assignment
ตัวอย่าง
Tag1:=Tag2+Tag3; หมายถึง Tag1 จะมีค่าเท่ากับผลรวมของ Tag2 กับ Tag3
หัวข้อที่ 2 Expressions
คือ การคำนวนใดๆซึ่งได้ค่าผลลัพธ์ออกมา ไม่ว่าจะเป็นการกระทำการทางคณิตศาสตร์ การเปรียบเทียบค่า (Comparison) หรือคำนวนโดยใช้ฟังก์ชันต่างๆ
เครื่องหมายทางคณิตศาสตร์ที่ใช้ได้มีดังนี้
ฟังก์ชันที่ช่วยในการคำนวน
การเปรียบเทียบค่า (compare function) จะให้ผลลัพธ์เป็น BOOL คือมีค่าเป็น เท็จ (0) หรือจริง (1) เท่านั้น
การใช้ logical operator
ใช้เมื่อต้องการตรวจสอบเงื่อนไขที่มากกว่าหนึ่งเงื่อนไขว่าเป็นจริงหรือเท็จ โดยจะให้ผลลัพธ์เป็น BOOL คือมีค่าเป็น เท็จ (0) หรือจริง (1) เท่านั้น
**ใน PLC รุ่น CompactLogix และ ControlLogix สามารถใช้ Logical Operator กับ Tag ชนิด DINT ได้ โดยจะเป็นการเปรียบเทียบในระดับบิทแทน
การตีความผลลัพธ์ของ Expression จะทำจากซ้ายไปขวา โดยเรียงลำดับความสำคัญตามตารางดังนี้
ดังนั้น เพื่อให้เข้าใจง่ายและไม่มีความผิดพลาด แนะนำให้ใช้วงเล็บช่วยในการจัดกลุ่มเครื่องหมาย เมื่อมีการใช้หลายๆตัวแปรในการคำนวน expression
หัวข้อที่ 3 Instruction
Instruction คือ คำสั่งต่างๆที่ใช้ใน PLC จะมีคำสั่งอะไรบ้างนั้นขึ้นอยู่กับ PLC แต่ละรุ่นและยี่ห้อ เช่น คำสั่ง Motion, คำสั่งที่ใช้จัดการกับ ASCII และ STRING, Timer และ Counter และอื่นๆอีกมากมาย ซึ่งจะไม่ได้กล่าวถึงเนื้อหาในบทนี้
หัวข้อที่ 4 Construction
เป็นตัวควบคุมการ Execution ของโปรแกรม เนื่องจากถ้าไม่มีการควบคุม โปรแกรมจะ Execute จากบรรทัดบนสุดไปล่างสุด และวนกลับไปที่บรรทัดบนสุดและไปล่างสุดเสมอ ในบางครั้ง จำเป็นต้องมีการวางเงื่อนไขเพื่อให้การคำนวนเป็นไปตามต้องการ คำสั่งต่างๆที่เกี่ยวข้องได้แก่
1. IF…THEN
IF bool_expression THEN
<statement>;
END_IF;
ทำ <statement> เมื่อเงื่อนไข bool_expression เป็นจริง และข้ามในส่วนนี้ไปเลย ถ้า bool_expression เป็นเท็จเช่น
2. IF…THEN…ELSE
IF bool_expression THEN
<statement1>;
ELSE
<statement2>;
END_IF;
ทำ <statement1> เมื่อเงื่อนไข bool_expression เป็นจริง และทำ <statement2> เมื่อ bool_expression เป็นเท็จ เช่น
ใส่ [:=] เพื่อให้เคลียร์ค่า Tag นี้เป็น 0 เมื่อเริ่มรันโปรแกรม หรือปิดเปิดไฟใหม่
3. IF…THEN…ELSEIF
IF bool_expression1 THEN
<statement1>;
ELSEIF bool_expression2 THEN
<statement2>;
END_IF;
ทำ <statement1> เมื่อเงื่อนไข bool_expression1 เป็นจริง และทำ <statement2> เมื่อ bool_expression1 เป็นเท็จและ bool_expression2 เป็นจริง เช่น
4. CASE_OF
CASE numeric_expression OF
selector1: <statement>;
selectorN: <statement>;
ELSE
<statement>;
END_CASE;
ใช้ CASE เมื่อต้องการเขียนเงื่อนไขแบบตัวเลือกโดยใช้เงื่อนไขเดียวในการตรวจสอบ เช่น
5. FOR_DO
ใช้เพื่อวนลูปจนกว่า initial_value จะเกิน final_value ที่กำหนดโดนกำหนดให้เพิ่มค่าทีละ Increment_value โดยที่ ถ้าไม่ได้กำหนด increment_value จะทำการเพิ่มค่าทีละ 1
FOR count:=initial_value
TO final_value
BY increment_value (Optional)
DO
<statement>;
END_FOR;
การใช้งานคำสั่งวนลูปมักจะใช้ร่วมกับ Array เพื่อทำการคำนวนค่าในทุกๆช่องของ Array ได้อย่างรวดเร็ว เช่น
คำสั่งนี้เป็นการกำหนดให้ Array[0] – Array[31] มีค่าเป็น 0 ทั้งหมด
6. WHILE_DO
ให้วนลูปไปเรื่อยๆตราบที่ condition ที่ตรวจสอบยังเป็นจริงอยู่
WHILE bool_expression DO
<statement>;
END_WHILE;
ข้อควรระวังในการใช้ WHILE_DO คือ ถ้าเงื่อนไข bool_expression เป็นจริงตลอด โปรแกรมจะติดอยู่ใน loop และไม่ scan บรรทัดถัดไป จนทำให้ Controller Fault ได้ ดังนั้น จึงควรเขียนเงื่อนไขในการออกจาก Loop โดยใช้ IF_THEN ไว้ด้วย
ตัวอย่างการใช้ WHILE
ทำการค้นหา array ช่องแรกที่มีค่าเท่ากับ targetvalue โดยการตรวจสอบทีละช่องตั้งแต่ structarray[0] เมื่อเจอช่องที่มีค่าเท่ากับ targetvalue จะออกจาก Loop WHILE และได้ค่า Pos ของ array เพื่อใช้คำนวนอย่างอื่นต่อไป
7. REPEAT_UNTIL
ให้วนลูปไปเรื่อยๆจนกว่า เงื่อนไขจะเป็นจริง มีลักษณะคล้ายกับ While แต่ต่างกันตรงที่ While จะต้องมีเงื่อนไขเป็นจริงก่อนจึงจะเริ่มทำ statement แต่ REPEAT จะทำ statement ก่อนแล้วค่อยเช็คเงื่อนไข
REPEAT
<statement>;
UNTIL bool_expression
END_REPEAT;
ข้อควรระวังในการใช้ REPEAT_UNTIL คือ ถ้าเงื่อนไข bool_expression ไม่เป็นจริงเป็นเวลานาน โปรแกรมจะติดอยู่ใน loop และไม่ scan บรรทัดถัดไป จนทำให้ Controller Fault ได้ ดังนั้น จึงควรเขียนเงื่อนไขในการออกจาก Loop โดยใช้ IF_THEN ไว้ด้วย
ตัวอย่างการใช้งาน REPEAT
ทำการค้นหา array ช่องแรกที่มีค่าเท่ากับ targetvalue โดยการตรวจสอบทีละช่องตั้งแต่ structarray[0] เมื่อเจอช่องที่มีค่าเท่ากับ targetvalue จะออกจาก Loop REPEAT และได้ค่า Pos ของ array เพื่อใช้คำนวนอย่างอื่นต่อไป
เอกสารอ้างอิง
https://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm007_-en-p.pdf