CDT規(guī)約轉(zhuǎn)Modbus協(xié)議
深圳市一天廣聯(lián)科技有限公司
參考價: | 面議 |
- 產(chǎn)品型號
- 品牌
- 其他 廠商性質(zhì)
- 所在地
訪問次數(shù):555更新時間:2021-07-27 15:30:18
1、概述
CDT協(xié)議通常用于電廠、電池系統(tǒng)直流屏數(shù)據(jù)監(jiān)控,我公司的AiMaster、AiMaker系列可編程產(chǎn)品內(nèi)置了CDT協(xié)議處理算法。通過Lua函數(shù)調(diào)用CDT協(xié)議庫接口函數(shù),這樣可以根據(jù)不同的設(shè)備,設(shè)計出不同的協(xié)議轉(zhuǎn)換產(chǎn)品。
CDT協(xié)議庫當(dāng)前可支持:A幀,B幀,C幀,D1幀,暫時不支持遙控命令。
在取得CDT數(shù)據(jù)后,就可以放入Modbus虛擬機的Modbus寄存器,提供給多個上位機同時讀取。無需編寫任何Modbus通訊代碼。如果使用AiMaker600物聯(lián)網(wǎng)PLC,還可以根據(jù)取得的數(shù)據(jù)做出控制動作。
AiMaster、AiMaker產(chǎn)品也對取得CDT數(shù)據(jù),使用算法做進一步運算處理,也可以傳輸至云端,提供給APP讀取。
2、以艾默生E10的CDT協(xié)議轉(zhuǎn)Modbus為例子進行說明
注意!各個廠家的產(chǎn)品所支持的功能碼都不相同,數(shù)據(jù)定義也不相同。
本CDT例程支持CDT協(xié)議所有功能碼,但是直流屏通常僅支持有限的功能碼數(shù)量,在使用前,請聯(lián)系直流屏廠家獲取所能支持的功能碼信息,然后填入下列代碼中。
本例子可以通過功能碼,完整獲取到CDT所有數(shù)據(jù)值,但是具體數(shù)據(jù)定義,請參考廠家說明書。
本例子的功能碼定義如下:
A幀重要遙測幀定義
B幀次要遙測幀定義
C幀一般遙測幀定義
D1幀遙信幀定義
下面例子通過串口3讀取CDT數(shù)據(jù),并且轉(zhuǎn)換數(shù)據(jù)至相應(yīng)的Modbus寄存器。
轉(zhuǎn)換的同時在2口原樣輸出CDT數(shù)據(jù),所以3口可以連接現(xiàn)有的CDT監(jiān)控設(shè)備,這樣可以在不影響現(xiàn)有的CDT監(jiān)控設(shè)備工作的同時,實現(xiàn)再轉(zhuǎn)換出一路數(shù)據(jù)至Modbus。
print("CDT協(xié)議轉(zhuǎn)Modbus")
--遙信Modbus寄存器起始地址,默認為0
local cfgristaddr=0
--A幀重要遙測Modbus寄存器起始地址,默認為0
local cfgrmstaddrA=0
--B幀次要遙測Modbus寄存器起始地址,默認為200
local cfgrmstaddrB=200
--C幀一般遙測Modbus寄存器起始地址,默認為400
local cfgrmstaddrC=400
--等待CDT數(shù)據(jù)超時,默認為10秒,如果超過10秒未能收到CDT數(shù)據(jù)字節(jié),
--則認為下位機通訊故障。
local frtreadtmo=2000
--CDT數(shù)據(jù)幀字符間隔,按照協(xié)議規(guī)定是4ms,此處設(shè)置為50ms,用于兼容慢速設(shè)備。
local sectmo=50
--通訊狀態(tài)指示寄存器
local commstateaddr=1000
--modbus下位機地址碼
local mbslaveid=1
local res=0
--cdt數(shù)組,用于存儲原始CDT數(shù)據(jù)
local cdtdata={0}
--存儲遙信數(shù)據(jù)
local cdtridata={0}
--待獲取的遙信功能碼列表,對于E10為0xF0,0xF1,0xF4,0xF7,0xF8
local cdtrifid={0xF0,0xF1,0xF4,0xF7,0xF8}
--存儲遙測數(shù)據(jù)
local cdtrmdata={0}
--待獲取的A幀,重要遙測功能碼列表,對于E10為0x06,0x07
local cdtrmfidA={0x06,0x07}
--待獲取的B幀,次要遙測功能碼列表,對于E10為0x01~0x04
local cdtrmfidB={0x01,0x02,0x03,0x04}
--存儲待獲取的C幀,一般遙測功能碼,對于E10為0x0A,0x0B
--程序從數(shù)組個元素循環(huán)至第二個元素的值,循環(huán)讀取一般遙測數(shù)據(jù)
--如果需要更多的C幀數(shù)據(jù),例如轉(zhuǎn)換12個電池組數(shù)據(jù),改成cdtrmcntC={0x01,0x18}即可
local cdtrmcntC={0x0A,0x0B}
local cdtrmfid={}
--設(shè)置通訊狀態(tài)為無通訊
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,1);
while(true) do
--readcdt函數(shù)等待接收CDT數(shù)據(jù),如果收到數(shù)據(jù),此函數(shù)將對CDT數(shù)據(jù)進行校驗,
--如果校驗成功,將輸出完整的CDT數(shù)據(jù)幀。否則返回錯誤。
--參數(shù)1:串口號,為0起,0為個串口,以此類推。
--參數(shù)2:CDT輸出數(shù)據(jù)
--參數(shù)3:接收個字節(jié)超時,如果達到此超時未能收到串口數(shù)據(jù),此函數(shù)將返回錯誤。
--參數(shù)4:數(shù)據(jù)字節(jié)超時,收到個字節(jié)后,使用此超時接收剩余數(shù)據(jù),在達到超時
--而未能收到數(shù)據(jù)時,此函數(shù)判定所有數(shù)據(jù)已經(jīng)收齊,函數(shù)將返回收到的字節(jié)數(shù)據(jù)
--并輸出完整CDT數(shù)據(jù)幀。
--返回:返回小于等0為錯誤。其他值為收到的字節(jié)數(shù)量
--清空緩存
cdtdata={0}
--清空緩存
cdtridata={0}
cdtrmdata={0}
while(true) do
res=lib_cdt.readcdt(2,cdtdata,frtreadtmo,sectmo)
if (res>0) then
--指示通訊正常
print(string.format("
接收正確:%d",res));
debug.printarray(cdtdata)
--接收到正確數(shù)據(jù)
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,0);
break;
else
--指示通訊錯誤
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,1);
-- print(string.format("
接收錯誤:%d",res));
end
end
--判斷是否為遙信數(shù)據(jù)
if (cdtdata[7]==0x71) and (cdtdata[8]==0xF4) then
--遙信數(shù)據(jù)的Modbus起始地址
ristaddr=cfgristaddr
print(string.format("
遙信數(shù)據(jù)Modbus地址:%d",ristaddr));
-的遙信數(shù)據(jù)
for i=1,table.getn(cdtrifid) do
--getrivalue函數(shù),讀取原始CDT數(shù)據(jù)中功能碼的遙信數(shù)據(jù)
--參數(shù)1:遙信功能碼
--參數(shù)2:經(jīng)過檢測過的CDT遙測數(shù)據(jù)
--參數(shù)3;是否校驗數(shù)據(jù)塊crc,0-校驗,1不校驗
--參數(shù)4;CDT數(shù)據(jù)塊數(shù)量
--參數(shù)5:輸出的遙信數(shù)據(jù)字節(jié),固定為4個字節(jié)
--返回1:返回大于等于0為正常,小于0為錯誤。
res=lib_cdt.getrivalue(cdtrifid[i],cdtdata,1,cdtdata[9],cdtridata)
-- debug.printarray(cdtridata);
if (res>0) then
--設(shè)置進modbus虛擬機,此函數(shù)在common lib頁中定義
setridatatomb(ristaddr,mbslaveid,cdtridata,res)
end
--遞增Modbus寄存器地址
ristaddr=ristaddr+32
end
end
rmstaddr=-1
if ((cdtdata[7]==0x71) and (cdtdata[8]==0x61)) then
--A幀重要遙測數(shù)據(jù)
rmstaddr=cfgrmstaddrA
cdtrmfid=cdtrmfidA
print(string.format("
遙測A幀,Modbus寄存器地址:%d",rmstaddr));
setrmdatatomb(rmstaddr,mbslaveid,cdtdata,cdtdata[9],cdtrmfid)
elseif ((cdtdata[7]==0x71) and (cdtdata[8]==0xC2)) then
--B幀次要遙測數(shù)據(jù)
rmstaddr=cfgrmstaddrB
cdtrmfid=cdtrmfidB
print(string.format("
遙測B幀,Modbus寄存器地址:%d",rmstaddr));
setrmdatatomb(rmstaddr,mbslaveid,cdtdata,cdtdata[9],cdtrmfid)
elseif ((cdtdata[7]==0x71) and (cdtdata[8]==0xB3)) then
--C幀一般遙測狀態(tài)
rmstaddr=cfgrmstaddrC
cdtrmfid=cdtrmcntC
print(string.format("
遙測C幀,Modbus寄存器地址:%d",rmstaddr));
setrmdatatomb_cnt(rmstaddr,mbslaveid,cdtdata,cdtdata[9],cdtrmfid)
end
--第二口為CDT原始數(shù)據(jù)輸出口
lib_uart.uart_tx(1,cdtdata,0);
end
--將遙信數(shù)據(jù)設(shè)置進Modbus虛擬機
local function setridatatomb(ristaddr,mbslaveid,cdtridata,datacnt)
--設(shè)置所有數(shù)據(jù)進Modbus虛擬機
for i=1,datacnt do
--循環(huán)1至res,
for i2=1,8 do
--循環(huán)處理8個bit,使用Modbus功能碼01,使用CDT上報的站號。
lib_vmb.setvaluefc1(ristaddr+((i2-1)+(i-1)*8),
mbslaveid,lib_bit.bit_is_set(cdtridata[i],i2-1));
end
end
end
--將遙測數(shù)據(jù)設(shè)置進虛擬機
local function setrmdatatomb(rmstaddr,mbslaveid,cdtdata,datacnt,cdtrmfid)
local res,rmres1,rmres2,sdata1,sdata2
for i=1,table.getn(cdtrmfid) do
--遙測數(shù)據(jù)
--參數(shù)1:遙測功能碼
--參數(shù)2:經(jīng)過檢測過的CDT遙測數(shù)據(jù)
--參數(shù)3;是否校驗數(shù)據(jù)塊crc,0-校驗,1不校驗
--參數(shù)4;CDT數(shù)據(jù)塊數(shù)量
--返回1:遙測數(shù)據(jù)1狀態(tài),返回小于等于0的值為錯誤,其他值為正確
--返回2:遙測數(shù)據(jù)2狀態(tài),返回小于等于0的值為錯誤,其他值為正確
--返回3:遙測數(shù)據(jù)1
--返回4:遙測數(shù)據(jù)2
res,rmres1,rmres2,sdata1,sdata2=lib_cdt.getrmvalue(cdtrmfid[i],cdtdata,1,datacnt)
if (res>=0) then
--將遙測值設(shè)置進Modbus虛擬機
if (rmres1<0) then
sdata1=0x8000
end
lib_vmb.setvaluefc3(rmstaddr,mbslaveid,6,sdata1)
if (rmres2<0) then
sdata2=0x8000
end
lib_vmb.setvaluefc3(rmstaddr+1,mbslaveid,6,sdata2)
end
rmstaddr=rmstaddr+2
end
end
--將遙測數(shù)據(jù)設(shè)置進虛擬機
local function setrmdatatomb_cnt(rmstaddr,mbslaveid,cdtdata,datacnt,cdtrmfidcnt)
local res,rmres1,rmres2,sdata1,sdata2
--循環(huán)讀取遙測數(shù)據(jù)功能碼
for i=cdtrmfidcnt[1],cdtrmfidcnt[2] do
--遙測數(shù)據(jù)
--參數(shù)1:遙測功能碼
--參數(shù)2:經(jīng)過檢測過的CDT遙測數(shù)據(jù)
--參數(shù)3;是否校驗數(shù)據(jù)塊crc,0-校驗,1不校驗
--參數(shù)4;CDT數(shù)據(jù)塊數(shù)量
--返回1:遙測數(shù)據(jù)1狀態(tài),返回小于等于0的值為錯誤,其他值為正確
--返回2:遙測數(shù)據(jù)2狀態(tài),返回小于等于0的值為錯誤,其他值為正確
--返回3:遙測數(shù)據(jù)1
--返回4:遙測數(shù)據(jù)2
res,rmres1,rmres2,sdata1,sdata2=lib_cdt.getrmvalue(i,cdtdata,1,datacnt)
if (res>=0) then
--將遙測值設(shè)置進Modbus虛擬機
if (rmres1<0) then
sdata1=0x8000
end
lib_vmb.setvaluefc3(rmstaddr,mbslaveid,6,sdata1)
if (rmres2<0) then
sdata2=0x8000
end
lib_vmb.setvaluefc3(rmstaddr+1,mbslaveid,6,sdata2)
end
rmstaddr=rmstaddr+2
end
end