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