跳至主要內容

天力

chanchaw大约 7 分钟客户资料

概述

天力的能源系统使用 [TAS](串口通信 | 天尘的知识库open in new window) 设备单口或者多口交换机,TCP版本的流量计测试工具在阿里云盘:备份文件 > setup > dev > 流量计测试工具IP

智能硬件

2024年10月21日 要采集水表数据,同一个厂家有两个规格的水表使用的通讯协议不一样 DN80open in new windowDN150open in new window 后来又联系到厂家另外一个人给的是DN150通讯协议,在:阿里云盘 > 备份文件 > 客户资料 > 天力 > 智能硬件 > 水表 > DN150 > DN150通讯协议CH.docx

DN80

仪表参数设置的说明书在:阿里云盘> 备份文件 > 客户资料 > 天力 > 智能硬件 > 水表 > DN80 > 电磁流量计使用说明书v2.02021年9月24日.pdf 。仪表密码100000

采用标准的 modbus rtu 协议通讯,读取数据是功能码03,支持波特率 1200,2400,4800,9600,19200,串口参数为:1 位起始位 8 位数据位 1 位停止位 N 无校验。2024年12月12日 10:53:27 高松发来仪表密码:07206

采集数据发送的指令介绍

01 04 10 10 00 02 74CE
# 01 - 设备地址码
# 04 - 功能码,读取设备数据
# 10 - 读取寄存器的地址高位
# 10 - 读取寄存器的地址地位
# 00 - 读取寄存器长度的高位
# 02 - 读取寄存器长度的低位
# 74CE - CRC校验码

接受到的数据

01 04 04 C4 1C 60 00 2F72
# 01 - 设备地址
# 04 - 功能码,表示读取
# 04 - 数据长度,4个寄存器
# C41C6000 - 瞬时流量,4个字段浮点数
# 2F72 - CRC校验码

瞬时流量数据为 Float Inverse 格式,采用 IEEE754,32 位浮点数格式,计算 C41C6000 的结果是 -625.5。

下面介绍读取正向累计整数部分数据的方法

01 04 10 18 00 02 F50C
# 01 - 仪表地址码
# 04 - 读取数据
# 10 - 被读取的寄存器地址高位
# 18 - 被读取的寄存器地址低位
# 00 - 读取寄存器长度的高位
# 02 - 读取寄存器长度的低位
# F50C - CRC校验码

# 接受到的数据:
01 04 04 01 23 45 67 78C8
# 01 - 地址码
# 04 - 功能码,表示读取数据
# 04 - 数据长度,表示4个寄存器
# 01 23 45 67 - 读取到的数据
# 78C8 - CRC校验码

解析上面的数据 1234567 ,正向累积量整数部分数据为 Long Inverse 格式,所以最终计算的结果是 19088743。下面是 2024年10月21日 16:43:15 天力厂里解析数据的实例

发送指令: 010410180002F50C
接受数据: 010404 000044D8 C8DE
上面 000044D8 整型数据,Long Inverse 计算方式如下:
4*16^3+4*16^2+13*16+8 = 16384 + 1024 + 208 + 8 = 17624

DN150

系统设置

  1. 在主界面长按“确认键”会弹出密码验证,输入1000进入设置界面

  2. 进入系统设置

  3. 查看协议版本号 MAY-18 2023 = Li协议 JUN-28 2023 = Li协议 AUG-16 2023 = 兰申协议

兰申协议读取正向累积数值整数(下面指令与仪表厂家技术确认过,还没有实际测试)

01 04 10 18 00 02 F50C
# 01 - 仪表地址码
# 04 - 读取数据
# 10 - 被读取的寄存器地址高位
# 18 - 被读取的寄存器地址低位
# 00 - 读取寄存器长度的高位
# 02 - 读取寄存器长度的低位
# F50C - CRC校验码

后来联系仪表厂家后又拿到一个 DN150的通讯说明书,在阿里云盘:备份文件 > 客户资料 > 天力 > 水表 > DN150 > DN150通讯协议CH。根据该协议通讯方式如下

# 读取正向累计整数
01030008000245C9
# 得到的响应数据如下
010304 00D92338 332A
# 解析其中的数据同 DN80 的正向累计整数部分是 Long Interverse 的方式解析数据
00D92338 换算成十进制为 14230328 即正向累计整数部分
# vb6 中转换数据:00D92338 = CLng("&H" + "00D92338") = 14230328

源码

2024年10月24日 制作的DN80,DN150构建读取指令、解析累计数据的源码如下

' 新东方智能化天力水表,苏州百业兴阀门科技有限公司
' 规格型号:LD-DN80
' 数据采集解析工具

' 传入地址码(一般为01),返回读取“正向累计量整数”的指令
Public Function GetInstruction80(ByVal port As String) As String
    Dim ret As String
    ret = port + "0410180002"

    Dim crc As String
    crc = GetCRCString(ret)

    GetInstruction80 = ret + crc
End Function

Public Function GetInstruction(ByVal port As String) As String
    Dim ret As String
    ret = port + "0410180002"

    Dim crc As String
    crc = GetCRCString(ret)

    GetInstruction = ret + crc
End Function

Public Function GetInstruction150(ByVal port As String) As String
    Dim ret As String
    ret = port + "0300080002"

    Dim crc As String
    crc = GetCRCString(ret)

    GetInstruction150 = ret + crc
End Function

'传入响应的数据,返回“正向累计量整数”
Public Function GetData(ByVal res As String) As Long
    Dim data As String
    data = Mid(res, 7, 8)
    GetData = CLng("&H" + data)
End Function

'传入字符串
'返回CRC的校验码
'返回值是用字符串表示的16进制
Private Function GetCRCString(ByVal vData As String) As String
    Dim arrByteInstruction() As Byte
    arrByteInstruction = String2ByteArray(vData)

    Dim lCRC As Long
    lCRC = GetCRCLong(arrByteInstruction)

    Dim szCRC As String
    szCRC = Hex(lCRC)

    'CRC-16得到的校验码字符串长度应该是4
    '检测缺少几个字符就在前面补足几个0
    Dim diffLength As Integer
    diffLength = 4 - Len(szCRC)
    Dim i As Integer
    For i = 1 To diffLength
        szCRC = "0" & szCRC
    Next i

    GetCRCString = szCRC
End Function

'VB6实现CRC的工具类
'字节值表的方法

Private Function GetCRCHi(Ind As Long) As Byte
    GetCRCHi = Choose(Ind + 1, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, _
    &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, _
    &H41, &H0, &HC1, &H81, &H40)
End Function

Private Function GetCRCLo(Ind As Long) As Byte
    GetCRCLo = Choose(Ind + 1, &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, _
    &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, _
    &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1F, &HDD, _
    &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, _
    &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, _
    &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, &H3B, &HFB, &H39, _
    &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, _
    &HED, &HEC, &H2C, &HE4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, _
    &H21, &H20, &HE0, &HA0, &H60, &H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, _
    &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, _
    &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, _
    &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, _
    &H71, &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, _
    &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, _
    &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, _
    &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, _
    &H81, &H80, &H40)
End Function

'将使用字符串表示的数值转换为字节数组
Private Function String2ByteArray(ByVal vData As String) As Byte()
    Dim byteInstruction() As Byte
    Dim i As Long
    If Len(vData) Mod 2 = 0 And Len(vData) <> 0 Then '检验16进制字符串长
        ReDim byteInstruction(Len(vData) / 2 - 1)
        For i = 0 To Len(vData) - 1 Step 2
           byteInstruction(i / 2) = Val("&H" & Mid(vData, i + 1, 2))
        Next
    End If

    String2ByteArray = byteInstruction
End Function




'传入:字节数组
'返回:CRC校验码的整数类型
'将返回的整数类型通过Hex(整数类型校验码)转换为16进制的字符串
Private Function GetCRCLong(data() As Byte) As Long

    Dim CRC16Hi As Byte
    Dim CRC16Lo As Byte

    CRC16Hi = &HFF
    CRC16Lo = &HFF

    Dim i As Integer
    Dim iIndex As Long

    For i = 0 To UBound(data)

    iIndex = CRC16Hi Xor data(i)

    CRC16Hi = CRC16Lo Xor GetCRCHi(iIndex) '低位处理

    CRC16Lo = GetCRCLo(iIndex) '高位处理

    Next i

    Dim ReturnData(1) As Byte
    Dim test As Long

    ReturnData(0) = CRC16Hi 'CRC低位

    ReturnData(1) = CRC16Lo 'CRC高位

    test = Val(Str(ReturnData(0))) * 256 + Val(Str(ReturnData(1)))

    GetCRCLong = test

End Function