品牌
其他厂商性质
所在地
GL485-4E3 3网口 4口485串口服务器
面议项目合作及代客研发服务
面议通过以太网为控制器扩展IO数量、扩展模拟量输出、扩展模拟量输入。
面议AiMaker600可编程控制器 采用嵌入式Lua语言 快速移植C\C#\VB\Delphi算法
面议GL-EXT600智能控制模块 集成8路DIO 8路模拟量采集 3路串口 2路以太网
面议GL-IO8以太网IO模块 2网口 8路开关量输入、8路继电器输出、1个232、1个485
面议AiGW600 6串口自学习式Modbus多主机网关 多主通讯无需手动配置Modbus参数
面议AiGW810 8串口自学习式Modbus多主机网关 多主通讯无需手动配置Modbus参数
面议AiGW800 8串口自学习式Modbus多主机网关 多主通讯无需手动配置Modbus参数
面议AiGW600G 6串口光纤Modbus多主机通讯网关
面议AiMaker900物联网可编程控制器
面议可由平台动态配置的Modbus转mqtt网关源码
面议1、概述
CDT协议通常用于电厂、电池系统直流屏数据监控,我公司的AiMaster、AiMaker系列可编程产品内置了CDT协议处理算法。通过Lua函数调用CDT协议库接口函数,这样可以根据不同的设备,设计出不同的协议转换产品。
CDT协议库当前可支持:A帧,B帧,C帧,D1帧,暂时不支持遥控命令。
在取得CDT数据后,就可以放入Modbus虚拟机的Modbus寄存器,提供给多个上位机同时读取。无需编写任何Modbus通讯代码。如果使用AiMaker600物联网PLC,还可以根据取得的数据做出控制动作。
AiMaster、AiMaker产品也对取得CDT数据,使用算法做进一步运算处理,也可以传输至云端,提供给APP读取。
2、以艾默生E10的CDT协议转Modbus为例子进行说明
注意!各个厂家的产品所支持的功能码都不相同,数据定义也不相同。
本CDT例程支持CDT协议所有功能码,但是直流屏通常仅支持有限的功能码数量,在使用前,请联系直流屏厂家获取所能支持的功能码信息,然后填入下列代码中。
本例子可以通过功能码,完整获取到CDT所有数据值,但是具体数据定义,请参考厂家说明书。
本例子的功能码定义如下:
A帧重要遥测帧定义
B帧次要遥测帧定义
C帧一般遥测帧定义
D1帧遥信帧定义
下面例子通过串口3读取CDT数据,并且转换数据至相应的Modbus寄存器。
转换的同时在2口原样输出CDT数据,所以3口可以连接现有的CDT监控设备,这样可以在不影响现有的CDT监控设备工作的同时,实现再转换出一路数据至Modbus。
print("CDT协议转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数据超时,默认为10秒,如果超过10秒未能收到CDT数据字节,
--则认为下位机通讯故障。
local frtreadtmo=2000
--CDT数据帧字符间隔,按照协议规定是4ms,此处设置为50ms,用于兼容慢速设备。
local sectmo=50
--通讯状态指示寄存器
local commstateaddr=1000
--modbus下位机地址码
local mbslaveid=1
local res=0
--cdt数组,用于存储原始CDT数据
local cdtdata={0}
--存储遥信数据
local cdtridata={0}
--待获取的遥信功能码列表,对于E10为0xF0,0xF1,0xF4,0xF7,0xF8
local cdtrifid={0xF0,0xF1,0xF4,0xF7,0xF8}
--存储遥测数据
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
--程序从数组个元素循环至第二个元素的值,循环读取一般遥测数据
--如果需要更多的C帧数据,例如转换12个电池组数据,改成cdtrmcntC={0x01,0x18}即可
local cdtrmcntC={0x0A,0x0B}
local cdtrmfid={}
--设置通讯状态为无通讯
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,1);
while(true) do
--readcdt函数等待接收CDT数据,如果收到数据,此函数将对CDT数据进行校验,
--如果校验成功,将输出完整的CDT数据帧。否则返回错误。
--参数1:串口号,为0起,0为个串口,以此类推。
--参数2:CDT输出数据
--参数3:接收个字节超时,如果达到此超时未能收到串口数据,此函数将返回错误。
--参数4:数据字节超时,收到个字节后,使用此超时接收剩余数据,在达到超时
--而未能收到数据时,此函数判定所有数据已经收齐,函数将返回收到的字节数据
--并输出完整CDT数据帧。
--返回:返回小于等0为错误。其他值为收到的字节数量
--清空缓存
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)
--接收到正确数据
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,0);
break;
else
--指示通讯错误
lib_vmb.setvaluefc1(commstateaddr,mbslaveid,1);
-- print(string.format("
接收错误:%d",res));
end
end
--判断是否为遥信数据
if (cdtdata[7]==0x71) and (cdtdata[8]==0xF4) then
--遥信数据的Modbus起始地址
ristaddr=cfgristaddr
print(string.format("
遥信数据Modbus地址:%d",ristaddr));
-的遥信数据
for i=1,table.getn(cdtrifid) do
--getrivalue函数,读取原始CDT数据中功能码的遥信数据
--参数1:遥信功能码
--参数2:经过检测过的CDT遥测数据
--参数3;是否校验数据块crc,0-校验,1不校验
--参数4;CDT数据块数量
--参数5:输出的遥信数据字节,固定为4个字节
--返回1:返回大于等于0为正常,小于0为错误。
res=lib_cdt.getrivalue(cdtrifid[i],cdtdata,1,cdtdata[9],cdtridata)
-- debug.printarray(cdtridata);
if (res>0) then
--设置进modbus虚拟机,此函数在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帧重要遥测数据
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帧次要遥测数据
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帧一般遥测状态
rmstaddr=cfgrmstaddrC
cdtrmfid=cdtrmcntC
print(string.format("
遥测C帧,Modbus寄存器地址:%d",rmstaddr));
setrmdatatomb_cnt(rmstaddr,mbslaveid,cdtdata,cdtdata[9],cdtrmfid)
end
--第二口为CDT原始数据输出口
lib_uart.uart_tx(1,cdtdata,0);
end
--将遥信数据设置进Modbus虚拟机
local function setridatatomb(ristaddr,mbslaveid,cdtridata,datacnt)
--设置所有数据进Modbus虚拟机
for i=1,datacnt do
--循环1至res,
for i2=1,8 do
--循环处理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
--将遥测数据设置进虚拟机
local function setrmdatatomb(rmstaddr,mbslaveid,cdtdata,datacnt,cdtrmfid)
local res,rmres1,rmres2,sdata1,sdata2
for i=1,table.getn(cdtrmfid) do
--遥测数据
--参数1:遥测功能码
--参数2:经过检测过的CDT遥测数据
--参数3;是否校验数据块crc,0-校验,1不校验
--参数4;CDT数据块数量
--返回1:遥测数据1状态,返回小于等于0的值为错误,其他值为正确
--返回2:遥测数据2状态,返回小于等于0的值为错误,其他值为正确
--返回3:遥测数据1
--返回4:遥测数据2
res,rmres1,rmres2,sdata1,sdata2=lib_cdt.getrmvalue(cdtrmfid[i],cdtdata,1,datacnt)
if (res>=0) then
--将遥测值设置进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
--将遥测数据设置进虚拟机
local function setrmdatatomb_cnt(rmstaddr,mbslaveid,cdtdata,datacnt,cdtrmfidcnt)
local res,rmres1,rmres2,sdata1,sdata2
--循环读取遥测数据功能码
for i=cdtrmfidcnt[1],cdtrmfidcnt[2] do
--遥测数据
--参数1:遥测功能码
--参数2:经过检测过的CDT遥测数据
--参数3;是否校验数据块crc,0-校验,1不校验
--参数4;CDT数据块数量
--返回1:遥测数据1状态,返回小于等于0的值为错误,其他值为正确
--返回2:遥测数据2状态,返回小于等于0的值为错误,其他值为正确
--返回3:遥测数据1
--返回4:遥测数据2
res,rmres1,rmres2,sdata1,sdata2=lib_cdt.getrmvalue(i,cdtdata,1,datacnt)
if (res>=0) then
--将遥测值设置进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