Hôm nay chúng ta sẽ sử dụng thư viện TF6420 để kết nối với hệ quản trị cơ sở dữ liệu PostgreSQL, đồng thời cập nhật và truy xuất dữ liệu database bằng API do TwinCAT cung cấp
Bắt đầu thôi nào!
Thanks
Thanks Mr Quang dai for the translation.he is a professional factory automation engineer in Vietnam .And here is his LinkedIn profile:
https://www.linkedin.com/in/quang-%C4%91%E1%BA%A1i-990165224/
Liên kết tham khảo
Khối chức năng
Trong phần này, mình sẽ giới thiệu về các khối chức năng được sử dụng trong bài viết. Lần này, chúng ta sẽ sử dụng lệnh “UPDATE” và “SELECT” trong PostgreSQL DB, vì vậy chúng ta sẽ tạo một chương trình theo cấu trúc trong khung màu đỏ.
- Đối với các lệnh không lấy dữ liệu từ SQL DB Server, chẳng hạn như UPDATE,
- Dùng FB_SQLDatabase.Connect() để kết nối với Database
- Dùng FB_SQLDatabase.CreateCmd() khởi tạo khối chức năng FB_SQLCommand
- Dùng FB_SQLCommand.Execute() để gửi lệnh SQL
- Dùng FB_SQLDatabase.Disconnected() để ngắt kết nối tới SQL DB
- Đối với các lệnh lấy dữ liệu từ SQL DB Server, chẳng hạn như SELECT,
- Dùng FB_SQLDatabase.Connect() để kết nối với Database
- Dùng FB_SQLDatabase.CreateCmd() khởi tạo khối chức năng FB_SQLCommand
- Dùng FB_SQLCommand.ExecuteDataReturn() để gửi lệnh SQL
- Dùng FB_SQL_Result.Read() để đọc dữ liệu từ SQLDB
- Dùng FB_SQL_Result.Release() để xóa dữ liệu khỏi bộ đệm
- Dùng FB_SQLDatabase.Disconnected() để ngắt kết nối tới SQL DB
FB_SQLDatabaseEvt
Khối chức năng này được sử dụng để quản lý kết nối tới SQL Server.
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
sNetID | T_AmsNetID | Địa chỉ AMS net ID của thiết bị |
tTimeout | TIME | Đặt thời gian chạy tối đa của hàm đến khi bị hủy bỏ |
VAR_OUTPUT (Khai báo đầu ra)
Tên biến | Kiểu dữ liệu | Mô tả |
bBusy | BOOL | 1=Khối chức năng đang được thực hiện |
bError | BOOL | 1=Khối chức năng đã xảy ra lỗi |
ipTcResult | Tc3_EventLogger.I_TcMessage | Trạng thái hoạt động của Khối chức năng được trả về giao diện tin nhắn TC3 EventLogger |
Phương thức:Connect
Kết nối tới cơ sở dữ liệu.
METHOD Connect : BOOL VAR_INPUT hDBID: UDINT := 1; END_VAR |
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
hDBID | UDINT | Đặt ID của cơ sở dữ liệu được sử dụng |
RetureValue
Tên biến | Kiểu dữ liệu | Mô tả |
Connect | BOOL | True=Phương thức đã thực hiện xong (Khi có lỗi thì vẫn trả về giá trị True) |
Phương thức: CreateCmd
Phương thức này được sử dụng để khởi tạo FB_SQLCommand
Theo tài liệu thì việc khởi tạo khối chức năng FB_SQLCommand có thể được hoàn thành trong cùng 1 chu kỳ quét, nhưng để tránh lỗi bạn nên theo dõi xung cạnh lên và xuống của Busy
VAR_INPUT pSQLCommand: POINTER TO FB_SQLCommandEvt; END_VAR |
VAR_INPUTS (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
pSQLCommand | POINTER TO FB_SQLCommand | Lấy một phiên bản mới từ khối chức năng FB_SQLCommandEvt đã được khởi tạo |
ReturnValue
Tên biến | Kiểu dữ liệu | Mô tả |
CreateCmd | BOOL | True=Phương thức đã thực hiện xong (Khi có lỗi thì vẫn trả về giá trị True) |
FB_SQLCommandEvt
Khối chức năng để thực thi lệnh SQL. Để sử dụng được, nó cần được khởi tạo bởi khối chức năng FB_SQLDatabaseEvt.
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
sNetID | T_AmsNetID | Địa chỉ AMS net ID của thiết bị |
tTimeout | TIME | Đặt thời gian chạy tối đa của hàm đến khi bị hủy bỏ |
VAR_OUTPUT (Khai báo đầu ra)
Tên biến | Kiểu dữ liệu | Mô tả |
bBusy | BOOL | 1=Khối chức năng đang được thực hiện |
bError | BOOL | 1=Khối chức năng đã xảy ra lỗi |
ipTcResult | Tc3_EventLogger.I_TcMessage | Trạng thái hoạt động của Khối chức năng được trả về giao diện tin nhắn TC3 EventLogger |
Phương thức: Execute
Gửi lệnh SQL tới thông qua kết nối với cơ sở dữ liệu đã được mở bởi khối chức năng FB_SQLDatabase.
METHOD Execute : BOOL VAR_INPUT pSQLCmd: POINTER TO BYTE; cbSQLCmd: UDINT; END_VAR |
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
pSQLCmd | POINTER TO BYTE | Con trỏ đến bộ nhớ biến chuỗi của lệnh SQL cần thực thi (bạn có thể sử dụng hàm ADR) |
cbSQLCmd | UDINT | Độ dài của lệnh SQL (bạn có thể sử dụng hàm SIZEOF) |
ReturnValue
Tên biến | Kiểu dữ liệu | Mô tả |
Execute | POINTER TO BYTE | Giá trị trả về cho biết trạng thái thực thi của phương thức |
Phương thức: ExecuteDataReturn
Gửi lệnh SQL tới thông qua kết nối với cơ sở dữ liệu đã được mở bởi khối chức năng FB_SQLDatabase. Phiên bản của khối chức năng FB_SQLResult được chuyển đổi để đọc các giá trị trả về.
METHOD ExecuteDataReturn : BOOL VAR_INPUT pSQLCmd: POINTER TO BYTE; cbSQLCmd: UDINT; pSQLDBResult: POINTER TO FB_SQLResult; END_VAR |
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
pSQLCmd | POINTER TO BYTE | Con trỏ đến bộ nhớ biến chuỗi của lệnh SQL cần thực thi (bạn có thể sử dụng hàm ADR) |
cbSQLCmd | UDINT | Độ dài của lệnh SQL (bạn có thể sử dụng hàm SIZEOF) |
pSQLDBResult | POINTER TO FB_SQLResult | Giá trị trả về 1 phiên bản của FB_SQLResult |
ReturnValue (Giá trị trả về)
Tên biến | Kiểu dữ liệu | Mô tả |
ExecuteDataReturn | POINTER TO BYTE | Giá trị trả về cho biết trạng thái thực thi của phương thức |
FB_SQLResultEvt
Khối chức năng này dùng để đọc các giá trị được ghi trong bộ nhớ đệm.
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
sNetID | T_AmsNetID | Địa chỉ AMS net ID của thiết bị |
tTimeout | TIME | Đặt thời gian chạy tối đa của hàm đến khi bị hủy bỏ |
VAR_OUTPUT (Khai báo đầu ra)
Tên biến | Kiểu dữ liệu | Mô tả |
bBusy | BOOL | 1=Khối chức năng đang được thực hiện |
bError | BOOL | 1=Khối chức năng đã xảy ra lỗi |
ipTcResult | Tc3_EventLogger.I_TcMessage | Trạng thái hoạt động của Khối chức năng được trả về giao diện tin nhắn TC3 EventLogger |
Phương thức: Read
Phương thức này đọc một số lượng bản ghi được chỉ định trong bộ nhớ đệm của máy chủ cơ sở dữ liệu TwinCAT
VAR_INPUT (Khai báo đầu vào)
Tên biến | Kiểu dữ liệu | Mô tả |
nStartIndex | UDINT | Đặt giá trị index của bản ghi cần đọc |
nRecordCount | UDINT | Đặt số lượng bản ghi cần đọc |
pData | POINTER TO BYTE | Con trỏ đến bộ nhớ của mảng giá trị để lưu lại bản ghi đọc được(có thể dùng hàm ADR) |
cbData | UDINT | Đặt kích thước của mảng giá trị theo byte (có thể dùng hàm SIZE OF) |
bWithVerifying | BOOL | True=dữ liệu trả về đã được so sánh với mảng pData và được điều chỉnh |
bDataRelease | BOOL | Giải phóng bộ nhớ đệm |
ReturnValue (Giá trị trả về)
Tên biến | Kiểu dữ liệu | Mô tả |
Read | BOOL | True=Phương thức đã được thực thi (Khi có lỗi thì vẫn trả về giá trị True) |
Các bước thực hiện
PostgreSQL Server sẽ được cài trên Raspberry Pi4 và IPC Beckhoff C6920 sẽ truy cập vào database thông qua TF6420.
Cấu hình
Cấu hình máy chủ dữ liệu TF6420.
Thêm chương trình TwinCAT Database Server mới
Trên giao diện TwinCAT IDE hoặc Visual Studio, nhấn chuột phải>Add>New Project.
Chọn vào Empty TwinCAT Database Server Project và nhấn Next.
Đặt tên cho TwinCAT Database Server Project và nhấn Create.
TcDbServer đã được tạo.
Thêm server PostgreSQL Database
Nhấn chuột phải vào TcDbServer>Add New Database.
DB đã được tạo
DBID=1, ID này là tham số rất quan trọng khi sử dụng API của PLC
Database Type
Chọn kiểu database từ danh sách thả xuống
Trong trường hợp này, PostgreSQL sẽ được sử dụng
Hoàn thành!
Host
Host là địa chỉ IP của thiết bị mà được cài đặt PostgreSQL
Ở đây là 192.168.5.144.
Database
Database nên để giống với tên của DB trong PostgreSQL.
Bạn có thể kiểm tra bằng VSCODE’s PostgreSQL Plugin, tôi sẽ dùng db xa5.
Xong!
Port
Cổng giao tiếp mặc định của PostgreSQL là 5432.
Authentication
Bước tiếp theo là cài phương thức bảo mật; Mặc định là None.
Chọn Username/Password từ danh sách Authentication.
Khi bạn chọn Username/Password, mục Username and Password sẽ hiện ra
Nhập thông tin đăng nhập của bạn.
Connecton String
The Connection String displays the connection path according to the parameters you have just set.
Kiểm tra kết nối
Nhấn vào nút CHECK để kiểm tra kết nối giữa TwinCAT và Database.
Kích hoạt License..
Nếu bạn thấy lỗi 0x724, hãy kích hoạt giấy phép cho TF6420.
SYSTEM>License.
Tích chọn vào ô TF6420.
Chọn vào 7 Days Trial License để kích hoạt giấy phép dùng thử trong 7 ngày.
Nhập các kí tự theo mã.
Xong!
Nhấn vào Activate Configuration để đổ chương trình
Nhấn OK để tiếp tục
Chuyển sang Runmode OK
Kết Quả
Nhấn CHECK để thử lại. Lần này thì thông báo Configuration check succeded hiện ra. Như vậy là đã kết nối thành công!
Activate Configuration
Kích hoạt cấu hình của TwinCAT Database Server.
DB>Right click>Activate Configuration.
Thêm chương trình PLC
Tiếp theo, để thêm chương trình plc, nhấn chuột phải vào PLC>right click>Add New Item.
Chọn Standard PLC Project>Add.
Thêm thư viện
Để thêm thư viện database TF6420 vào chương trình, nhấp chuột phải vào References>Right click>Add library.
Thêm Tc3_Database.
Hoàn thành!
Lập trình
Bước tiếp theo là viết chương trình.
DUT_SQL
Tạo kiểu Struct giống với các tag của bảng được tạo trong cơ sở dữ liệu XA5
TYPE DUT_SQL : STRUCT tagname:STRING(255); tagvalue:STRING(255); END_STRUCT END_TYPE |
Ngoài ra còn có các chuỗi tagname và tagvalue trong VSCode’s PostgreSQL Plug-in.
Làm cách nào để biết được kích thước?
Bạn có thể kiểm tra kích thước biến của mỗi hàng bằng lệnh sau
SELECT tagvalue ,char_length(tagvalue) FROM tags; |
Như vậy, số byte sẽ tỉ lệ thuận với số kí tự, chẳng hạn như 505=3.
FC_SQL_UpdateCommands
Khối chức năng này tự động thực thi lệnh SQL Update.
FUNCTION FC_SQL_UpdateCommands : STRING(255) VAR_INPUT iValue:INT; iTag:STRING; END_VAR VAR END_VAR FC_SQL_UpdateCommands:=’UPDATE tags SET tagvalue = ‘; FC_SQL_UpdateCommands:=CONCAT(STR1:=FC_SQL_UpdateCommands,STR2:=INT_TO_STRING(iValue)); FC_SQL_UpdateCommands:=CONCAT(STR1:=FC_SQL_UpdateCommands,STR2:=’ ‘); FC_SQL_UpdateCommands:=CONCAT(STR1:=FC_SQL_UpdateCommands,STR2:=’WHERE tagname = ‘); FC_SQL_UpdateCommands:=CONCAT(STR1:=FC_SQL_UpdateCommands,STR2:=iTag); |
MAIN
Đây là trình tự điều khiển hiện tại.
- Step0=Khởi tạo tham số
- Step10=kết nối tới PostgreSQL DB
- Step20=Khởi tạo FB_SQLCommandEvt.
- Step30-45=Gửi lệnh Update tới PostgreSQL DB
- Step50=Gửi lệnh Select tới PostgreSQL
- Step60=Chuyển đổi dữ liệu truy xuất được bằng lệnh Select vào biến PLC
- Step70=Đợi 1 giây và quay lại step20
PROGRAM MAIN VAR FB_SQLDatabaseEvt:FB_SQLDatabaseEvt(sNetID := ”, tTimeout := T#5S); FB_SQLCommandEvt:FB_SQLCommandEvt(sNetID := ”, tTimeout := T#5S); FB_SQLResultEvt :FB_SQLResultEvt(sNetID := ”, tTimeout := T#5S); tags:ARRAY[0..99]OF DUT_SQL; iStep:INT; SQL_Commands:ARRAY[1..4]OF STRING(255); iCounter:INT:=0; i:INT; isubstep:INT; iErrorCounet :INT; sSelectDataCommand :STRING(255); TON_Process :TON; END_VAR CASE iStep OF 0: TON_Process(IN:=FALSE); iCounter:=1; iStep:=10; 10: FB_SQLDatabaseEvt.Connect( hDBID:=1 ); IF FB_SQLDatabaseEvt.bError THEN iErrorCounet:=iErrorCounet+1; iStep:=9991; END_IF IF FB_SQLDatabaseEvt.bConnected THEN iStep:=20; END_IF 20: FB_SQLDatabaseEvt.CreateCmd( pSQLCommand:=ADR(FB_SQLCommandEvt) ); IF FB_SQLDatabaseEvt.bError THEN iErrorCounet:=iErrorCounet+1; iStep:=9992; END_IF TON_Process(IN:=NOT FB_SQLDatabaseEvt.bBusy AND NOT FB_SQLDatabaseEvt.bError); IF TON_Process.Q THEN TON_Process(IN:=FALSE); iStep:=30; iCounter:=iCounter+1; IF iCounter>100 THEN iCounter:=1; END_IF END_IF 30: SQL_Commands[1]:=FC_SQL_UpdateCommands(iCounter,’$’Application/GVL_FactoryIO/qCounter1$’;’); SQL_Commands[2]:=FC_SQL_UpdateCommands(iCounter*10+1,’$’Application/GVL_FactoryIO/qCounter2$’;’); SQL_Commands[3]:=FC_SQL_UpdateCommands(iCounter*10+2,’$’Application/GVL_FactoryIO/qCounter3$’;’); SQL_Commands[4]:=FC_SQL_UpdateCommands(iCounter*10+3,’$’Application/GVL_FactoryIO/iFactoryIORunning$’;’); iStep:=40; isubstep:=0; i:=1; 40: IF FB_SQLCommandEvt.Execute(pSQLCmd:=ADR(SQL_Commands[i]),cbSQLCmd:=SIZEOF(SQL_Commands[i])) THEN IF FB_SQLCommandEvt.bError THEN iErrorCounet:=iErrorCounet+1; iStep:=9994; END_IF END_IF; IF FB_SQLCommandEvt.bBusy THEN isubstep:=1; END_IF IF NOT FB_SQLCommandEvt.bBusy AND isubstep=1 THEN iStep:=45; isubstep:=0; END_IF 45: i:=i+1; IF i >= 5 THEN iStep:=50; isubstep:=0; ELSE iStep:=40; END_IF 50: sSelectDataCommand:=’SELECT * FROM “tags” LIMIT 1000;’; IF FB_SQLCommandEvt.ExecuteDataReturn(pSQLCmd:=ADR(sSelectDataCommand),cbSQLCmd:=SIZEOF(sSelectDataCommand),pSQLDBResult:=ADR(FB_SQLResultEvt)) THEN IF FB_SQLCommandEvt.bError THEN iErrorCounet:=iErrorCounet+1; END_IF IF FB_SQLResultEvt.nDataCount >0 AND NOT FB_SQLCommandEvt.bBusy THEN iStep:=60; END_IF END_IF 60: IF FB_SQLResultEvt.Read( nStartIndex:=0 ,nRecordCount:=4 ,pData:=ADR(tags) ,cbData:=SIZEOF(tags) ,bWithVerifying:=TRUE ,bDataRelease:=TRUE ) THEN IF FB_SQLResultEvt.bError THEN iErrorCounet:=iErrorCounet+1; iStep:=9995; END_IF IF FB_SQLResultEvt.nDataCount=0 THEN iStep:=70; END_IF; END_IF; 70: TON_Process(IN:=TRUE,PT:=T#1S); IF TON_Process.Q THEN TON_Process(IN:=FALSE); iStep:=20; END_IF END_CASE |
Kết quả
Hoàn thành! Chúng ta đã có thể truy xuất dữ liệu mới nhất từ PostgreSQL DB và ghi nó vào biến plc.
Lấy dữ liệu mới nhất từ VSCODE’s PostgreSQL Plug-in.
SELECT * FROM “tags” LIMIT 1000; |
Xong! Bạn cũng đã nhận được dữ liệu cập nhật từ TwinCAT
Tải xuống
Bạn có thể tải chương trình mẫu trong bài viết theo liên kết dưới đây
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCATestWithSQL.tnzip