ใช้ Barcode กำหนดสูตรการผลิต
เขียน Script ใน SKTool เก็บ Barcode ที่สแกนย้อนหลัง 10 ชุดด้วย Loop ซ้อน แสดงผลด้วย ASCII Display แก้ Bug ข้อมูลค้างใน Memory แล้วใช้ค่าที่สแกนเลือก Recipe ผ่าน RWI0 และ LB60100 เพื่อส่งค่าไปที่ PLC
เก็บ Barcode ย้อนหลัง 10 ชุดได้ด้วย Loop ซ้อนที่เลื่อนข้อมูลทีละ 50 Word (LW10000 → LW10050 → … → LW10500) แล้วเลือกสูตรการผลิตจากค่าที่สแกนด้วยการเขียน Recipe ID ลง RWIWord[0] และสั่ง LB60100 = 1 ให้ HMI ส่ง Recipe ไปที่ PLC
อัพเดทล่าสุด: 26 ตุลาคม 2569
ในตอนนี้ทำอะไร
ต่อจาก EP.14 ที่อ่านค่าจากเครื่องสแกน Barcode เข้า HMI ได้แล้ว ตอนนี้เพิ่มอีก 2 อย่าง
- เก็บ Barcode ที่สแกนย้อนหลัง 10 ชุดและแสดงบนหน้าจอ
- ใช้ค่าที่สแกนได้เลือกสูตรการผลิต (Recipe) แล้วส่งค่าของสูตรนั้นไปที่ PLC
แนวคิดการเก็บประวัติ Barcode
Barcode แต่ละชุดใช้พื้นที่ 50 Word ข้อมูลที่สแกนล่าสุดเก็บที่ LW10000 ทุกครั้งที่สแกนใหม่ให้เลื่อนข้อมูลลงไปทีละชุด
- LW10000 → LW10050
- LW10050 → LW10100
- LW10100 → LW10150
- … ไปเรื่อยๆ จนถึงชุดสุดท้ายที่ LW10500
รวมเป็นประวัติทั้งหมด 10 ชุด (LW10050 ถึง LW10500)
ค่าที่ประกาศไว้ใน Script (จาก EP.14)
| ชื่อ | ค่า | ความหมาย |
|---|---|---|
DownloadRecipeTriggerBit | 60100 | LB60100 สั่งเขียน Recipe ไปที่ PLC |
ScanFinishFlag | 60147 | LB บอกว่าสแกนเสร็จ |
ScanDataLength | 60999 | LW เก็บความยาวข้อมูลที่สแกน |
ScanDataStart | 61000 | LW เริ่มต้นของข้อมูลที่สแกน |
MaxDataLength | 50 | ความยาวสูงสุดต่อ 1 ชุด |
NumberOfBarcodes | 10 | จำนวนชุดที่เก็บย้อนหลัง |
SaveDataStart | 10000 | LW เริ่มต้นที่เก็บข้อมูล |
เขียน Loop ซ้อนเลื่อนข้อมูล
- เพิ่มตัวแปร
jในบรรทัดเดียวกับiภาษา C ประกาศหลายตัวแปรในบรรทัดเดียวได้โดยคั่นด้วยจุลภาค - Loop นอกให้
iเริ่มที่NumberOfBarcodes(10) เงื่อนไขi > 0และลดค่าทีละ 1 ด้วยi--— Loop นี้วนตามจำนวนชุดที่เก็บย้อนหลัง - Loop ในให้
jวิ่งจาก 0 ถึงMaxDataLength - 1(50 รอบ) เพื่อ Copy ข้อมูลทีละ Word
#include "MacroInit.h"
//#include "subFun1.c" //Example
void Macro_main(IN *p)
{
MarcoInit
int i, j;
for (i = NumberOfBarcodes; i > 0; i--)
{
for (j = 0; j < MaxDataLength; j++)
{
LocalWord[SaveDataStart + (MaxDataLength * i) + j] = LocalWord[SaveDataStart + (MaxDataLength * (i - 1)) + j];
}
}
}เช็ควงเล็บให้ดีว่าอะไรคำนวณก่อนหลัง วิธีเข้าใจ Loop นี้ที่ง่ายที่สุดคือลองแทนค่า
| i | j | บรรทัดนี้หมายถึง |
|---|---|---|
| 10 | 0 | LW10500 = LW10450 |
| 10 | 1 | LW10501 = LW10451 |
| 10 | 49 | LW10549 = LW10499 |
| 9 | 0 | LW10450 = LW10400 |
| 1 | 0 | LW10050 = LW10000 |
ที่ให้ i นับถอยหลังเพราะต้องย้ายชุดเก่าสุดก่อน ข้อมูลแต่ละชุดจะได้ไม่ถูกเขียนทับก่อนย้าย เขียนเสร็จกด Compile ให้ขึ้น Success ถ้าไม่ผ่านให้เช็คว่าเขียนตรงกับตัวอย่างหรือไม่
สร้าง ASCII Display แสดงประวัติ 10 ชุด
- Copy ASCII Display ตัวเดิมมา ปรับให้บางลง
- ตั้ง Monitor Address เป็น LW10050 และลดจำนวนตัวอักษรที่แสดง (Total) เหลือ 13 ตัว
- คลิกขวาที่ ASCII Display → Multiple Copies แล้วตั้งค่า
- Type: Interval
- Address setting: Increasing To Down, Increase value 50 (Address เพิ่มทีละ 50 ไล่ลงไปเรื่อยๆ)
- Numbers: X = 1, Y = 10
- Interval: X = 10, Y = 10 (ระยะห่างระหว่างแต่ละชุดที่ Copy)
- จะได้ ASCII Display 10 ตัว (LW10050, LW10100, … LW10500) จัดวางแล้ว Download ลงหน้าจอ ถอดสาย USB-C แล้วไปที่หน้า Barcode ลองสแกน ข้อมูลที่สแกนจะเลื่อนลงมาเรื่อยๆ
แก้ Bug ข้อมูลค้างใน Memory
ลองสแกน Barcode ที่ยาวไม่เท่ากัน เช่นสแกน CDEF (4 ตัวอักษร) แล้วสแกน AB (2 ตัวอักษร) หน้าจอจะแสดง ABEF ทั้งที่สแกน AB เพราะ EF จากครั้งก่อนยังค้างอยู่ใน Memory ของ Address ที่อ่านค่าสแกน
วิธีแก้คือ Clear Data ทุกครั้งหลังสแกน เปิด Script Editor ไปที่ Script ScanLogic แล้วเพิ่ม Loop ที่เขียนช่องว่าง (Space) ลงพื้นที่ข้อมูลสแกน 50 ตัว (LW61000 ถึง LW61049) ต่อจากจุดที่ Copy ข้อมูลไปเก็บแล้ว ข้อมูลไม่หายเพราะถูกเก็บไว้ที่ LW10000 แล้ว
#include "MacroInit.h"
//#include "subFun1.c" //Example
void Macro_main(IN *p)
{
MarcoInit
int i, j;
if (LocalBit[ScanFinishFlag] == 1)
{
for (i = 0; i < LocalWord[ScanDataLength]; i++)
{
LocalWord[SaveDataStart + i] = LocalWord[ScanDataStart + i];
}
LocalBit[ScanFinishFlag] = 0;
// Clear scan data area before the next scan
for (i = 0; i < MaxDataLength; i++)
{
LocalWord[ScanDataStart + i] = ' ';
}
for (i = NumberOfBarcodes; i > 0; i--)
{
for (j = 0; j < MaxDataLength; j++)
{
LocalWord[SaveDataStart + (MaxDataLength * i) + j] = LocalWord[SaveDataStart + (MaxDataLength * (i - 1)) + j];
}
}
}
}Compile และ Download อีกครั้ง แล้วลองสแกนตัวยาวสลับกับตัวสั้น ค่าที่แสดงจะถูกต้อง
ใช้ค่าที่สแกนเลือก Recipe
Reserved Register ที่ใช้มี 2 ตัว
- RWI0 — Recipe ID ปัจจุบันของหน้าจอ ใน Script เข้าถึงด้วย
RWIWord[0](Index ที่ 0) เขียนค่าลงไปเพื่อเปลี่ยน Recipe ปัจจุบัน - LB60100 — Trigger Bit ที่สั่งให้ HMI เขียน Recipe ไปที่ PLC (ใน Script ใช้ชื่อ
DownloadRecipeTriggerBit) ตั้งเป็น 1 แล้วระบบจะ Reset กลับเอง ไม่ต้องตั้งเป็น 0 ทีหลัง
Recipe ที่ทำไว้ใน EP.10 มี 3 สูตร คือ ID 0, 1, 2
เช็คค่า Barcode ด้วยเลขฐาน 16
ตัวอักษร ASCII A = 0x41 และ B = 0x42 แต่ละ Word เก็บได้ 2 ตัวอักษร โดยตัวอักษรตัวหลังอยู่ไบต์สูง ตอนเขียนเป็นเลขฐาน 16 จึงต้องเอาตัวหลังขึ้นก่อน — AB เขียนเป็น 0x4241, CD เป็น 0x4443 และ EF เป็น 0x4645
ต่อท้าย Script ScanLogic (ภายในบล็อก if (LocalBit[ScanFinishFlag] == 1))
#include "MacroInit.h"
//#include "subFun1.c" //Example
void Macro_main(IN *p)
{
MarcoInit
if (LocalWord[SaveDataStart] == 0x4241) // 41 => A, 42 => B
{
RWIWord[0] = 0;
LocalBit[DownloadRecipeTriggerBit] = 1;
}
else if (LocalWord[SaveDataStart] == 0x4443 && LocalWord[SaveDataStart + 1] == 0x4645) // CDEF
{
RWIWord[0] = 2;
LocalBit[DownloadRecipeTriggerBit] = 1;
}
else if (LocalWord[SaveDataStart] == 0x4443) // CD
{
RWIWord[0] = 1;
LocalBit[DownloadRecipeTriggerBit] = 1;
}
}- ใช้
else ifเพิ่มเงื่อนไขของ Barcode แต่ละค่า - Barcode ที่ยาวกว่า 2 ตัวอักษรต้องเช็คหลาย Word พร้อมกันด้วยตัวดำเนินการ
&&(AND) ซึ่งเป็นจริงเมื่อทั้งสองฝั่งเป็นจริง - เงื่อนไข CDEF ต้องอยู่ก่อน CD ถ้าเอา CD ไว้ก่อน สแกน CDEF ก็จะเข้าเงื่อนไข CD ก่อน และได้ Recipe ID 1 แทน 2
ทดสอบกับ PLC
ฝั่ง PLC Samkoon เขียนโปรแกรมทดสอบใน SamSoar2022 ให้หลอดไฟที่ Y0 แสดงผลต่างกันตามค่า D0 ที่ Recipe เขียนมา (Recipe สูตรที่ 1 ตั้ง D0 = 1, สูตรที่ 2 ตั้ง D0 = 4, สูตรที่ 3 ตั้ง D0 = 7)
| เงื่อนไข (ต่อขนานกันไปที่ Y0) | ผลที่ Y0 |
|---|---|
| D0 = K1 อนุกรม M8160 (สัญญาณคาบ 1 วินาที) | กะพริบทุก 1 วินาที |
| D0 = K4 อนุกรม M8159 (สัญญาณคาบ 100 ms) | กะพริบทุก 100 ms |
| D0 = K7 อนุกรม M8152 (เป็น 0 ขณะ PLC Run) | ไม่ติด |
Compile และ Download ทั้งสองฝั่ง แล้วทดสอบที่หน้า Barcode
- สแกน AB → Recipe ID 0 → D0 = 1 → ไฟกะพริบช้า
- สแกน CD → Recipe ID 1 → D0 = 4 → ไฟกะพริบเร็ว
- สแกน CDEF → Recipe ID 2 → D0 = 7 → ไฟไม่กะพริบ
พร้อมกันนั้นค่าที่สแกนจะถูกเก็บเป็นประวัติบนหน้าจอด้วย หลักการเดียวกันนี้นำไปใช้กับ Barcode หรือ Logic อื่นๆ ได้
ควรอ่านก่อน:
มีคำถาม? ติดต่อทีมงาน
