LUA MODBUS應用
用戶使用Modbus協議時,可以通過LUA交互實現復雜的邏輯,提供豐富的modbus接口函數,如下所示:
序號 |
描述/API |
功能碼 |
應用范圍 |
1 |
獲取變量值:get_variant(name) |
- |
Fx2n/Xgus/Modbus |
2 |
設置變量值:set_variant(name) |
- |
Fx2n/Xgus/Modbus |
3 |
讀線圈變量:mb_read_coil_01 (slave,addr,quantity) |
0x01 |
Modbus |
4 |
讀離散變量:mb_read_input_02(slave,addr,quantity) |
0x02 |
Modbus |
5 |
讀保存寄存器:mb_read_reg_03(slave,addr,quantity) |
0x03 |
Modbus |
6 |
讀輸入寄存器:mb_read_input_reg_04(slave,addr,quantity) |
0x04 |
Modbus |
7 |
寫單個線圈:mb_write_coil_05 (slave,addr,status) |
0x05 |
Modbus |
8 |
寫單個保存寄存器:mb_write_reg_06 (slave,addr,reg) |
0x06 |
Modbus |
9 |
寫多個線圈:mb_write_coil_15 (slave,addr,quantity,coils) |
0x0F |
Modbus |
10 |
寫多個保存寄存器:mb_write_reg_16 (slave,addr,regs) |
0x10 |
Modbus |
更多組態配置Modbus、變量的創建請參考Modbus教程,本章節不在闡述。本章節屏幕作為modbus 主站,創建線圈、離散輸入、保存寄存器、輸入寄存器各2個變量,具體屬性可查看工程源文件,如下所示:
本章節主要描述以下內容:
1. 變量名讀寫值
2. 線圈讀寫
3. 讀離散變量
4. 保存寄存器讀寫
5. 讀輸入寄存器
適用范圍:M系列、W系列、X系列、F系列(固件版本 >= V4.2.401.0) 例程下載鏈接:《LUA-ModbusAPI應用》(http://www.bdklxf.com/uploads/file/20210628/Modbus%20-%20LuaAPI.zip 復制鏈接打開下載)
get_variant(name)/set_variant(name)函數適用于在【工具】→【協議與變量...】里面創建的變量,不局限與Modbus,同時適用于三菱Fx2n、Xgus等協議,用法一樣,參考本章節即可。
1. 函數說明
讀變量:get_variant(name)
- name:字符串,變量名,應用變量時候一定要和【工具】→【協議與變量...】里面創建的變量一 致
eg:local data = get_variant(“設置溫度”)
寫變量:set_variant(name,value)
- name:字符串,變量名,應用變量時候一定要和【工具】→【協議與變量...】里面創建的變量一 致
- value:數值
eg:set_variant(“設置溫度”,25)
2. 畫面配置
變量名讀寫是通過get_variant(name) /set_variant(name)函數來實現,畫面配置如下所示:
線圈的讀寫:
- 按鈕控件ID1:作為讀取“電源/開機”的觸發按鈕,并將值顯示在文本控件ID2中;
- 文本控件ID2:顯示get_variant(“電源/開機”)獲取后的值;
- 按鈕控件ID3:作為寫“電源/開機”的觸發按鈕,將獲取文本控件ID4的值在寫入;
- 文本控件ID4:鍵值輸入“電源/開機”的目標值。
保存寄存器的讀寫:
- 按鈕控件ID5:作為讀取“目標溫度”的觸發按鈕,并將值顯示在文本控件ID6中;
- 文本控件ID6:顯示get_variant(“設置溫度”)獲取后的值;
- 按鈕控件ID7:作為寫“設置溫度”的觸發按鈕,將獲取文本控件ID8的值在寫入;
- 文本控件ID8:鍵值輸入“設置溫度”的目標值。
3. LUA腳本
按鈕控件ID1按下時,將“電源/開機”顯示在文本控件ID1中,同理其他按鈕/文本對應控件聯動觸發、顯示,LUA腳本如下所示:
--用戶通過觸摸修改控件后,執行此回調函數。 --點擊按鈕控件,修改文本控件、修改滑動條都會觸發此事件。 function on_control_notify(screen,control,value) if screen == sc_variant then if control == 1 and value == 0 then local power = get_variant('電源/開機') set_value(sc_variant, 2, power) elseif control == 3 and value == 0 then local power = get_value(sc_variant, 4) set_variant('電源/開機', power) elseif control == 5 and value == 0 then local dstTempe = get_variant('設置溫度') set_value(sc_variant, 6, dstTempe) elseif control == 7 and value == 0 then local dstTempe = get_value(sc_variant, 8) set_variant('設置溫度', dstTempe) end ...... end end
4. 運行預覽
根據畫面配置和LUA腳本,運行結果如下所示
線圈的讀寫還可以通過mb函數來實現
1. 函數說明
讀取線圈:
mb_read_coil_01 (slave,addr,quantity)
- salve:從機站號
- addr:線圈起始地址
- quantity:讀取的個數
讀取成功:返回字節數組,8個線圈為一個字節;讀取失敗,返回nil
如:從0開始,讀取32個線圈,local coilsTb = mb_read_coil_01 (1, 0, 32)
假設讀取成功,返回的字節內容依次為 coilsTb[0]=0x12,coilsTb[1]=0x24,coilsTb[1]=0x0C,coilsTb[1]=0x08線圈和字節數組的每一位的對應關 系,如下所示:
寫單個線圈:mb_write_coil_05(slave,addr,state)
- salve:從機站號
- addr:線圈地址
- state:線圈狀態,0或1
寫成功,返回ture;寫失敗,返回false;
寫多個線圈:mb_write_coil_15 (slave,addr,quantity,coils)
- salve:從機站號
- addr:線圈地址
- quantity:讀取的個數
- coils:字節數組,設置的值,關系可參考上表
寫成功,返回ture;寫失敗,返回false;
2. 畫面配置
通過mb函數來實現,畫面配置如下所示
讀線圈:
- 按鈕控件ID1:作為讀取"線圈"的觸發按鈕,并將值顯示在文本控件ID2、ID4中
- 文本控件ID2:顯示mb_read_coil_01(, , , )獲取變量"電源"的值(coil1~coil16)
- 按鈕控件ID4:顯示mb_read_coil_01(, , , )獲取變量"模式"的值(coil17~coil32)
設置單個線圈"電源/開機":
- 按鈕控件ID5:設置線圈"電源/開機" = 1的觸發按鈕
設置多個線圈 "電源/開機"、"指示燈開關":
- 按鈕控件ID7:設置線圈"電源/開機" = 1、"指示燈開關" = 1的觸發按鈕
3. LUA腳本
按鈕控件ID1按下時,將?電源?、?模式?顯示在文本控件ID2、文本控件ID4中,同理其他按鈕/文本對應控 件聯動觸發、顯示,LUA腳本如下所示:
--設置位函數 --data:源數據 --bitmask:第幾位位置 --state:數值,0或1 function set_bits(data, bitmask, state) bitmask = (1 << bitmask) & 0xFF if state == 0 then data = data & (~bitmask) elseif state == 1 then data = data | bitmask end print(data) return data end --用戶通過觸摸修改控件后,執行此回調函數。 --點擊按鈕控件,修改文本控件、修改滑動條都會觸發此事件。 function on_control_notify(screen,control,value) ...... elseif screen == sc_coils then if control == 1 and value == 1 then local power, mode = 0, 0 --modbus coils: 請求從站號1,從地址0開始的32個線圈 local coilsTb = mb_read_coil_01(1, 0, 32) if coilsTb ~= nil then power = (coilsTb[1] << 8) | coilsTb[0] mode = (coilsTb[3] << 8) | coilsTb[2] print('power = '..power) print('mode = '..mode) set_text(sc_coils, 2, power) set_text(sc_coils, 4, mode) end elseif control == 5 then mb_write_coil_05(1, 0, value) elseif control == 7 and value == 0 then local power = 0 local mode = 0 --modbus read coils: 讀從站號1,從地址0開始的32個線圈 local coilsTb = mb_read_coil_01(1, 0, 32) if coilsTb ~= nil then coilsTb[0] = set_bits(coilsTb[0], 0, 1) --設置“開機-電源”= 1 coilsTb[2] = set_bits(coilsTb[2], 6, 1) --設置“狀態-打開指示燈” = 1 --modbus write coils: mb_write_coil_15 (1, 0, 32, coilsTb) end end ...... end end
4. 運行預覽
根據畫面配置和LUA腳本,運行結果如下所示:
1.函數說明
讀取離散輸入:mb_read_input_02(slave,addr,quantity)
- salve:從機站號
- addr:離散輸入寄存器的起始地址 quantity:讀取的個數
讀取成功:字節數組,8個離散輸入為一個字節;讀取失敗,返回nil
如:從0開始,讀取32個離散輸入,local discreteTb = mb_read_input_02 (1, 0, 32)
離散變量和字節數組的每一位的對應關系可參考線圈說明
2. 畫面配置
通過mb函數來實現【離散輸入】寄存器的讀取,畫面配置如下所示:
讀離散輸入寄存器:
- 按鈕控件ID1:作為讀取離散輸入寄存器“狀態”、“告警”的觸發按鈕,并將值顯示在文本控件ID2、ID4中
- 文本控件ID2:顯示mb_read_input_02(, , , )獲取變量“狀態”的值(discrete1~discrete16)
- 文本控件ID4:顯示mb_read_input_02(, , , )獲取變量"告警"的值(discrete17~discrete32)
3. LUA腳本
按鈕控件ID1按下時,將"狀態"、"告警"顯示在文本控件ID2、文本控件ID4中,LUA腳本如下所示:
--用戶通過觸摸修改控件后,執行此回調函數。 --點擊按鈕控件,修改文本控件、修改滑動條都會觸發此事件。 function on_control_notify(screen,control,value) ...... elseif screen == sc_discrete then if control == 1 and value == 1 then local status, alert = 0, 0 --modbus coils: 請求從站號1,從地址0開始的32個線圈 local discreteTb = mb_read_input_02(1, 0, 32) if discreteTb ~= nil then status = (discreteTb[1] << 8) | discreteTb[0] alert = (discreteTb[3] << 8) | discreteTb[2] print('status = '..status) print('alert = '..alert) set_text(sc_discrete, 2, status) set_text(sc_discrete, 4, alert) end end ...... end
4. 運行預覽
根據畫面配置和LUA腳本,運行結果如下所示:
1. 函數說明
讀取保持寄存器:mb_read_reg_03(slave,addr,quantity)
- salve:從機站號
- addr:保存寄存器的起始地址
- quantity:讀取的個數
讀取成功,返回字數組;讀取失敗,返回nil
寫單個保存寄存器:mb_write_reg_06 (slave,addr,reg)
- salve:從機站號
- addr:保存寄存器地址
- reg:寄存器值
寫成功,返回ture;寫失敗,返回false;
寫多個保存寄存器:mb_write_reg_16 (slave,addr,regs)
- salve:從機站號
- addr:寫的起始地址
- regs:數組,word字數組
寫成功,返回ture;寫失敗,返回false;
2. 畫面配置
通過mb函數來實現【保持寄存器】的讀寫,畫面配置如下所示:
讀保存寄存器:
- 按鈕控件ID1:作為讀取“設置溫度”、“設置濕度”的觸發按鈕,并將值顯示在文本控件ID2、ID4中
- 文本控件ID2:顯示mb_read_reg_03(,,,)獲取變量“設置溫度”的值
- 文本控件ID4:顯示mb_read_reg_03(,,,)獲取變量“設置濕度”的值
設置單個保存寄存器 “設置溫度”:
- 按鈕控件ID5:設置保存寄存器“設置溫度” = 25 的觸發按鈕
設置多個線圈 “設置溫度”、“設置濕度”:
- 按鈕控件ID7:設置保存寄存器“設置溫度” = 28、“設置濕度” = 60 的觸發按鈕
3. LUA腳本
按鈕控件ID1按下時,將“設置溫度”、“設置濕度”顯示在文本控件ID2、文本控件ID4中,同理其他按鈕/文本對應控件聯動觸發、顯示,LUA腳本如下所示:
--用戶通過觸摸修改控件后,執行此回調函數。 --點擊按鈕控件,修改文本控件、修改滑動條都會觸發此事件。 function on_control_notify(screen,control,value) ...... elseif screen == sc_holding then if control == 1 and value == 1 then local holdTb = mb_read_reg_03(1, 0, 2) if holdTb ~= nil then set_text(sc_holding, 2, holdTb[0]) set_text(sc_holding, 4, holdTb[1]) end elseif control == 5 and value == 0 then mb_write_reg_06(1, 0, 25) elseif control == 7 and value == 0 then local holdTb = {} holdTb[0] = 28 holdTb[1] = 60 mb_write_reg_16(1, 0, holdTb) end ...... end end
4. 運行效果
根據畫面配置和LUA腳本,運行結果如下所示
1. 函數說明
讀輸入寄存器:mb_read_input_reg_04(slave,addr,quantity)
- salve:從機站號
- addr:輸入寄存器的起始地址
- quantity:讀取的個數
讀取成功,返回字數組;讀取失敗,返回nil
2. 畫面配置
通過mb函數來實現【輸入寄存器】的讀取,畫面配置如下所示:
讀輸入寄存器:
- 按鈕控件ID1:作為讀取輸入寄存器“回風變量”、“回風濕度”的觸發按鈕,并將值顯示在文本控件ID2、ID4中
- 文本控件ID2:顯示mb_read_input_reg_04(,,,)獲取變量“回風溫度”的值
- 文本控件ID4:顯示mb_read_input_reg_04(,,,)獲取變量“回風濕度”的值
3. LUA腳本
按鈕控件ID1按下時,將“回風溫度”、“回風濕度”顯示在文本控件ID2、文本控件ID4中,LUA腳本如下所示:
--用戶通過觸摸修改控件后,執行此回調函數。 --點擊按鈕控件,修改文本控件、修改滑動條都會觸發此事件。 function on_control_notify(screen,control,value) ...... elseif screen == sc_input then if control == 1 and value == 1 then local inputTb = mb_read_input_reg_04(1, 0, 2) if inputTb ~= nil then set_text(sc_input, 2, inputTb[0]) set_text(sc_input, 4, inputTb[1]) end end ...... end
4. 運行預覽
根據畫面配置和LUA腳本,運行結果如下所示