đưa gần nhất về IPC beckhoff nhất có thể
Mình sẽ xem cấu trúc project trước để sửa đúng khối Data Block của Ladder.
Mình đã sửa khối Data block của Ladder để có thêm kiểu dữ liệu và mảng như TIA Portal, nhưng chưa biên dịch được. Môi trường của mình không có dotnet, nên bạn cần build thử trên máy bạn.
Cách dùng: giải nén DataBlock_Array_update.zip đè lên project (giữ nguyên đường dẫn thư mục), rồi build.
Kiểu dữ liệu mới
- Có thêm: Char, SInt, USInt, UInt, UDInt, Time, String (trước đó chỉ có Bool, Byte, Int, Word, DInt, DWord, Real, LReal).
- Start value nhập được
'A'cho Char,T#1s500mscho Time, và16#FFhoặc2#1010cho số nguyên. - Giá trị Time hiển thị dạng
T#1s500ms, Char hiển thị'A'. - String tối đa 254 ký tự. Hiện chỉ lưu, xem và sửa trong bảng DB; lệnh ladder chưa dùng được String vì chương trình ladder đang chỉ làm việc với số.
- LInt, ULInt, LWord (64-bit) chưa có, vì bộ nhớ ladder dùng số double.
Mảng
- Ở ô Data type bạn gõ thẳng
Array[0..100] of Int, hoặc chọn mẫu gợi ý. Mảng tự bung thành các dòngtên[0],tên[1]... - Dòng mảng có nút ▸/▾ để thu hoặc bung. Mỗi lần hiện 100 phần tử, có nút “Hiện thêm”, tối đa 10 000 phần tử mỗi mảng.
- Start value ở dòng mảng áp cho mọi phần tử; mỗi dòng phần tử có thể đặt Start riêng. Nút “Giá trị hiện tại → Start” lưu riêng từng phần tử khác 0.
- Retain áp dụng cho cả mảng; Monitor sửa được từng phần tử.
- Dùng trong ladder: kéo phần tử từ danh sách tag bên phải (dòng mảng bấm để bung, gõ từ khoá thì liệt kê các phần tử khớp). Hoặc gõ tay
db_start.speed_35_rated[5]. - Đổi tên DB hoặc tên mảng thì mọi toán hạng
tên[i]đổi theo.
Giới hạn: chỉ số mảng phải là số cố định, chưa hỗ trợ chỉ số động kiểu arr[Var_1]. Chỉ số ngoài miền lo..hi thì toán hạng báo đỏ.
File trong zip
LadderDb.csvàComponents/LadderDialog.razorlà phần sửa chính.wwwroot/app.cssthêm kiểu hiển thị cho dòng mảng.LadderDriver.cschỉ đổi một chữ:TryTimethànhinternal.HUONG_DAN_DATA_BLOCK.mdcập nhật hướng dẫn.
Nếu build báo lỗi, bạn gửi dòng lỗi mình sửa tiếp. Chỗ dễ lỗi nhất là cú pháp Razor trong DbEditor và DbMonCell.
Mình chỉ đọc kỹ phần Data block, vòng quét và vài hàm đọc/ghi toán hạng, chưa xem hết bộ lệnh. Các góp ý dưới đây dựa trên phần đã đọc, ảnh chụp giao diện và kinh nghiệm chung về PLC/IPC. Bạn nên đối chiếu lại với bộ lệnh thực tế của bạn.
Lưu ý trước: chương trình chạy trên Windows/.NET, không phải hệ điều hành thời gian thực. Nó phù hợp cho logic giám sát, điều khiển mức SCADA và chạy thử. Với an toàn máy hoặc điều khiển cần thời gian đáp ứng cố định thì vẫn nên để PLC thật lo.
1. Độ tin cậy khi chạy (nên làm trước)
- Chu kỳ quét ổn định: trên giao diện thấy “Scan 11 ms (max 5308)”, tức có lần quét kẹt hơn 5 giây. PLC thật có cyclic OB với chu kỳ cố định và watchdog (quét quá lâu thì báo lỗi, dừng hoặc chạy khối xử lý lỗi). Nên có cấu hình chu kỳ, cảnh báo khi vượt ngưỡng, và ghi log nguyên nhân.
- Ảnh quá trình (process image): PLC thật đọc toàn bộ input ở đầu chu kỳ và ghi output ở cuối. Code hiện tại đọc tag trực tiếp và gom ghi theo từng network. Hai network cùng đọc một input có thể thấy giá trị khác nhau trong một chu kỳ nếu tag đổi giữa chừng. Chụp một ảnh tag ở đầu chu kỳ sẽ làm logic xác định hơn.
- Khối khởi động và khối lỗi: thiếu OB kiểu startup (chạy một lần khi RUN), khối xử lý mất kết nối tag/PLC, và khối xử lý lỗi lệnh. Hiện lỗi chỉ báo “Tag chưa có giá trị”.
- Sửa ladder khi đang RUN có hiệu lực ngay: tiện nhưng rủi ro. Nên có bước Compile (kiểm tra lỗi, danh sách lỗi) rồi Download/Apply, kèm cảnh báo hoặc quyền riêng cho thao tác sửa online.
- Retain: giá trị Retain đang lưu mỗi 2 giây, nên mất điện đột ngột có thể mất tối đa 2 giây dữ liệu. Với biến quan trọng (đếm sản lượng, năng lượng) nên ghi ngay khi đổi hoặc theo ngưỡng. Việc ghi file nguyên tử (atomic write) đang làm đúng.
2. Công cụ lập trình (khác biệt lớn nhất so với phần mềm chuyên nghiệp)
- Bảng Watch và bảng Force riêng: hiện có Modify trên từng toán hạng. TIA có Watch table (theo dõi nhiều biến, lưu lại) và Force table (có biểu tượng cảnh báo đang force và nút bỏ force toàn bộ).
- Cross-reference và tìm/thay tên: xem một biến được dùng ở network nào, để biết có thể xóa hoặc đổi tên an toàn không. Hàm
RenameTagđã có sẵn nên làm tiếp rất thuận. - Danh sách lỗi khi Compile: toán hạng thiếu, sai kiểu, cuộn dây ghi trùng một tag ở nhiều nơi (lỗi hay gặp), nhảy nhãn không tồn tại.
- Kiểm tra kiểu khi gán: MOVE từ Real sang Int, hoặc ghi giá trị vượt miền, nên cảnh báo thay vì ép lặng lẽ.
- Gỡ lỗi: chạy từng chu kỳ (step), điểm dừng, giá trị tại thời điểm xảy ra sự kiện. Trace oscilloscope cho vài biến cũng rất hữu ích.
- Tài liệu: tiêu đề và chú thích cho từng network, in/xuất PDF chương trình, so sánh hai phiên bản (diff), lịch sử thay đổi.
- Quyền và nhật ký: ai sửa chương trình, khi nào, sửa gì. Hệ thống SCADA đã có sẵn nền tảng người dùng nên phần này nên dùng chung.
3. Bộ lệnh và dữ liệu (so với IEC 61131-3 và TIA)
- Kiểm tra bộ lệnh có đủ: TON/TOF/TP/TONR, CTU/CTD/CTUD, so sánh, toán học, chuyển đổi kiểu (CONVERT), dịch/xoay bit, SEL/MUX/LIMIT, SCALE/NORM, PID. Từ ảnh mình thấy có bit logic, SR/RS, trigger, nhóm Basic instructions. Phần còn lại bạn nên đối chiếu.
- Mảng: hiện chỉ số cố định. Nâng cấp quan trọng nhất là chỉ số động
arr[Var_1], vì đó là lý do chính để dùng mảng (vòng lặp, bộ đệm, bảng tra). Mình chưa làm vì phải sửa cách driver đọc/ghi toán hạng. - UDT/Struct: nhóm biến thành kiểu có cấu trúc (ví dụ
Motorgồm Run, Fault, Speed) rồi tạo nhiều bản. Với SCADA nhiều thiết bị cùng loại thì rất tiết kiệm công. - Truy cập bit của Word/DWord (kiểu
Var.%X3), và kiểu 64-bit (LInt, ULInt, LWord) nếu cần. - DB trong SCL và String trong lệnh: hiện DB chưa dùng được trong network SCL (đã ghi trong hướng dẫn). Nên làm sớm vì người dùng SCL sẽ chạm vào ngay.
- Xuất DB ra tag cho SCADA/alarm: hiện phải MOVE sang tag InternalMemory. Cho phép đánh dấu biến DB là “hiển thị trên SCADA” sẽ gọn hơn.
4. Hiệu năng (liên quan trực tiếp phần mình vừa sửa)
Mỗi chu kỳ DbSync dựng lại bảng biến. Mình đã cache các phần tử mảng, nhưng với mảng lớn (gần 10 000 phần tử) vẫn nên đồng bộ theo thay đổi thay vì dựng lại mỗi chu kỳ. Việc này cũng có thể góp phần vào những lần quét kẹt như trên.
Thứ tự mình đề xuất: (1) chu kỳ quét ổn định và ảnh quá trình, (2) Compile và danh sách lỗi, (3) Watch/Force table và cross-reference, (4) chỉ số động của mảng và DB trong SCL, (5) UDT.
Bạn dự định dùng Ladder này để điều khiển thật (thay PLC) hay chủ yếu cho logic giám sát và chạy thử? Câu trả lời sẽ quyết định nên đầu tư vào độ ổn định hay vào tiện ích lập trình trước.Với logic giám sát thì hướng này hợp lý, vì giám sát không cần thời gian thực cứng. TwinCAT của Beckhoff dùng nhân thời gian thực riêng chạy cạnh Windows, và đó là phần khó nhất để bắt chước. Vì vậy mình đề xuất bám theo cách tổ chức và trải nghiệm lập trình của TwinCAT trước, còn thời gian thực cứng để sau.
Điểm mạnh TwinCAT mà Ladder của bạn nên học theo
- Ngôn ngữ chính là ST (Structured Text), Ladder chỉ là phụ. Người dùng Beckhoff phần lớn viết ST. Bạn đã có SCL, nên đầu tư cho nó là đúng hướng. Việc cần làm trước nhất là cho SCL dùng được biến DB, mảng và String, vì hiện chưa dùng được.
- UDT/Struct, Enum và Function Block có biến riêng (instance). Đây là cốt lõi của lập trình theo thiết bị. Ví dụ có kiểu
Motorgồm Run, Fault, Speed, rồi tạoMotor1..Motor50. Bạn đã có FB trong Widget lib, nên mở rộng sang Struct và Enum là bước tự nhiên. Kết hợp với mảng vừa làm,Array[1..50] of Motorlà thứ làm SCADA nhiều thiết bị nhẹ đi rất nhiều. - Task có chu kỳ riêng và độ ưu tiên. Beckhoff gán chương trình vào task (ví dụ 10 ms, 100 ms, 1 s). Với giám sát, bạn nên cho mỗi khối OB chọn chu kỳ của nó. Việc nặng như tính toán năng lượng thì chạy 1 s, còn logic liên động chạy 100 ms. Cách này cũng giải quyết luôn vấn đề quét bị kẹt mình nhắc ở trên.
- Thư viện dùng lại được. Library Manager của TwinCAT cho đóng gói FB và kiểu dữ liệu để dùng ở dự án khác. Phần Widget lib của bạn là nền tốt để phát triển thành thư viện có phiên bản.
- Persistent data tách riêng. Beckhoff có vùng dữ liệu bền vững được quản lý riêng. Cơ chế Retain của bạn đã tương tự, chỉ cần ghi tức thời cho biến quan trọng.
- Tách runtime khỏi giao diện. Trong TwinCAT, runtime chạy độc lập, giao diện chỉ kết nối vào qua ADS. Với bạn, ladder nên chạy trong service nền (bạn đã có
CHAY_NEN_SERVICE.md), còn trình soạn chỉ là client. Nếu trình duyệt đóng mà logic vẫn chạy ổn định thì mới đúng tinh thần IPC.
Lộ trình mình đề xuất, theo thứ tự
| Giai đoạn | Việc làm | Lý do |
|---|---|---|
| 1 | Chỉ số mảng động; DB, mảng và String dùng được trong SCL | Mở khóa viết logic dùng vòng lặp |
| 2 | Struct/UDT và Enum | Nền tảng cho thiết bị nhiều bản sao |
| 3 | Chu kỳ riêng cho từng khối, cảnh báo quét quá hạn | Ổn định, có số liệu để tin |
| 4 | Compile, danh sách lỗi, cross-reference, Watch/Force table | Trải nghiệm kỹ sư chuyên nghiệp |
| 5 | Thư viện FB có phiên bản; OOP nhẹ (method trong FB) | Tái sử dụng quy mô lớn |
| 6 | Gỡ lỗi: breakpoint, step, trace | Tìm lỗi nhanh |
Điều nên nói thẳng với người dùng của bạn: chương trình chạy trên Windows nên không đảm bảo chu kỳ ổn định ở mức mili giây như TwinCAT. Hãy định vị là “điều khiển giám sát và tối ưu mức SCADA”, không quảng cáo thay thế điều khiển an toàn hay điều khiển động học. Làm vậy tránh rủi ro pháp lý và kỳ vọng sai.
Nếu bạn muốn bắt đầu giai đoạn 1, mình đề xuất làm chỉ số mảng động trước, vì mình vừa làm xong phần mảng nên nền đã sẵn. Việc này cần sửa cách driver đọc và ghi toán hạng, và chỗ khó là bảo đảm chỉ số ngoài miền không làm sập vòng quét. Bạn có muốn mình làm tiếp phần đó không?Mình bắt đầu từ vòng quét hiện tại trong LadderDriver.cs để xem chu kỳ được tạo và đo thế nào, rồi mới sửa.
Mình đã sửa vòng quét Ladder theo hướng task của Beckhoff, nhưng chưa biên dịch và chưa chạy thử vì môi trường của mình không có dotnet. Bạn build và thử trên máy bạn, rồi gửi mình dòng lỗi nếu có.
Nguyên nhân scan max 5308 ms: lệnh ghi tag xuống PLC (eng.Write) chạy đồng bộ ngay trong vòng quét. PLC chậm hoặc mất kết nối thì cả vòng quét đứng chờ mạng. Đây là suy luận từ code, chưa đo trên hệ thống thật.
Đã sửa (file LadderRt.cs mới và LadderDriver.cs):
- Chu kỳ cố định: lịch quét theo mốc tuyệt đối trên đồng hồ đơn điệu. Trước đây chu kỳ thật bằng thời gian quét cộng ScanMs nên bị trôi.
- Bám mốc chính xác: ngủ thô rồi spin khoảng 2 ms cuối, bật timer Windows 1 ms (
timeBeginPeriod), luồng quét ưu tiên AboveNormal. Nếu một vòng quá hạn thì vòng sau chạy lại sau 1 ms, không bù dồn. - Tách I/O khỏi vòng quét: vòng quét chỉ xếp hàng lệnh ghi, một luồng I/O riêng ghi xuống PLC.
- Thứ tự ghi được giữ, mỗi tag chỉ giữ giá trị mới nhất.
- Ghi lỗi thì thử lại sau 2 giây.
- Các network phía sau vẫn đọc đúng giá trị vừa ghi trong lúc chờ.
- Đo đạc: thời gian quét (vừa rồi, trung bình, nhỏ nhất, lớn nhất), chu kỳ thực, jitter, số lần quá hạn, hàng đợi ghi, số lần ghi lỗi. Thanh trạng thái hiện các số này, chữ đỏ khi có quá hạn hoặc treo, click để xóa thống kê.
- Watchdog: báo “QUÉT TREO” nếu một vòng chạy quá max(1 giây, 10 lần chu kỳ).
- Tag cho SCADA và alarm: thêm các địa chỉ
SCAN_AVG,SCAN_MAX,PERIOD,JITTER,OVERRUN,WDOG,IOQ,IOFAIL,RESET_STATS. - Khác: ScanMs cho phép 5–1000 ms (trước 10–1000). Mọi network trong một vòng dùng chung một mốc giờ. Lỗi ngoại lệ trong vòng quét giờ được ghi lại thay vì bỏ qua.
Hành vi thay đổi bạn cần biết: lệnh ghi tag ngoài giờ có độ trễ vài ms, và bộ đệm outShadow bù cho các network đọc ngay sau đó. Nếu có mạch tự giữ dùng tag ngoài, nên thử kỹ phần này trước.
Cách kiểm tra:
- RUN rồi xem jitter lúc rảnh, nên dưới khoảng 10% chu kỳ.
- Rút mạng tới một PLC mà ladder đang ghi vào. Scan max không được tăng vọt nữa;
IOFAILtăng vàIOQgiữ nhỏ.
Chưa làm và phải nói thẳng:
- Windows/.NET không phải hệ điều hành thời gian thực. Jitter vài ms là bình thường và thỉnh thoảng có gai do GC hoặc tranh CPU. Vì vậy mình chỉ dám nói “đạt yêu cầu” cho giám sát và điều khiển mức SCADA, chưa phải mức cứng như TwinCAT. Chạy bằng Windows Service, tắt chế độ ngủ của máy.
- Timer, PID và năng lượng vẫn dựa vào giờ đồng hồ hệ thống. Đổi giờ PC đột ngột (NTP bước lớn, chuyển giờ mùa hè) có thể làm lệch một vòng.
- Vòng quét vẫn khóa
lock(prog)khi chạy network, nên thao tác giao diện giữ khóa lâu có thể làm trễ. Khi sửa chương trình đang RUN, bạn theo dõi jitter để biết.
Zip này gộp cả phần Data block và mảng làm lúc trước. File HUONG_DAN_CHU_KY_QUET.md giải thích từng thay đổi và gợi ý ngưỡng alarm: WDOG bằng 1, OVERRUN tăng, IOQ lớn hơn 50, jitter lớn hơn 30% chu kỳ.
Files are in Ladder_DataBlock_ScanCycle_update.zip.

