Skip to content

1. 简介

施耐德电气 EasyLogic DM2500 系列是一款高精度三相多功能电力仪表,覆盖 DM2510(3CT 三互感器接线)和 DM2511(4CT 四互感器接线)两款型号。仪表通过 RS-485 接口输出 Modbus RTU 协议数据,可采集三相电压、三相电流、功率因数、正向有功电能、电流/电压不平衡度、频率等 13 个核心电力参数。

本方案以 Schneider EasyLogic DM2500 系列 为接入对象,通过 KC11 LoRaWAN 采集设备 连接仪表的 RS-485 接口,并利用 KC11 内置的 EdgeBus 脚本完成 Modbus RTU 协议采集、数据封装与 LoRaWAN 上报,实现将配电柜电力数据无线接入 ThinkLink 平台。


2. 产品特点

  • 支持 Schneider EasyLogic DM2500 系列(DM2510 / DM2511)数据采集
  • 支持 RS-485 / Modbus RTU 接口接入
  • 通过 KC11 实现电力仪表数据 LoRaWAN 无线化接入
  • 支持 13 个电力参数 统一采集:电压、电流、电能、功率因数、频率、不平衡度
  • 支持配置 Modbus 从站地址,适合多表总线接入
  • 支持 采集/上传周期 统一配置(upPeriodIndex = periodIndex = app_70)
  • 支持 Class 0.5S 精度 电能计量(符合 IEC 62053-22)
  • 支持 ThinkLink 物模型解析与 RPC 下发配置参数
  • DM2510 与 DM2511 共用同一套 EB 代码和物模型

3. 适用范围

本方案适用于需要将 DM2500 系列电力仪表接入 ThinkLink / LoRaWAN 系统的场景,例如:

  • 工业厂房配电柜用电监测与分区域能耗统计
  • 商业楼宇配电房远程集中抄表,替代人工巡检
  • 企业能耗管理与电能质量分析(不平衡度、功率因数监测)
  • 租赁场景多用户独立计量与用电费用分摊
  • 含分布式光伏的双向用电场景(4 象限电能计量)
  • 存量电力仪表无线化改造
  • PLC / SCADA / 能源管理系统 MQTT 数据对接

4. 采集器信息

4.1 硬件信息

项目内容
采集设备型号KC11
通信接口RS-485
供电方式AC 85–270V 市电供电(导轨安装)
通信方式LoRaWAN Class C(常在线)
EdgeBus 支持支持
适配协议Modbus RTU
业务代码23102
模板名称DM2500

4.2 接线信息

电源与通讯接口

接口说明
电源输入KC11 采用 AC 85–270V 市电供电,与 DM2500 辅助电源可共同引自配电柜 220V
RS-485 A接入 DM2500 仪表背面 RS+ 端子
RS-485 B接入 DM2500 仪表背面 RS- 端子
485C/GND可选接公共参考地(DM2500 背面 C 端子)
LoRaWANKC11 通过 LoRaWAN 将采集数据上报至网关 / ThinkLink

传感器接口

DM2500 通过 RS-485 总线接入 KC11。背面端子说明:

端子信号接线
RS+RS-485 数据 +KC11 的 485A
RS-RS-485 数据 -KC11 的 485B
C公共参考地KC11 485C/GND(可选接地)
L+/N/-辅助电源接配电柜 AC 220V

接线注意事项:

  • RS-485 总线末端需接 120Ω 终端匹配电阻(KC11 提供 120Ω 短接端子至 485A)
  • 建议使用屏蔽双绞线,屏蔽层单端接地
  • 单总线最多可连接 32 台 DM2500 仪表,通过 Modbus 从站地址区分

5. 数据采集

本方案中,通过 Modbus RTU 协议(FC03 读保持寄存器) 读取以下数据项:

序号数据项英文字段单位寄存器(1-based)
1正向有功电能energy_importkWh2700–2701
2A 相电流current_aA3000–3001
3B 相电流current_bA3002–3003
4C 相电流current_cA3004–3005
5三相平均电流current_avgA3010–3011
6电流不平衡度current_unbalance%3012–3013
7A 相电压(L-N)voltage_anV3028–3029
8B 相电压(L-N)voltage_bnV3030–3031
9C 相电压(L-N)voltage_cnV3032–3033
10三相平均相电压voltage_ln_avgV3036–3037
11电压不平衡度voltage_unbalance%3038–3039
12总功率因数power_factor_total3084–3085
13频率frequencyHz3110–3111

5.1 寄存器定义

DM2500 采用 1-based 寄存器编号(与 Schneider 手册一致)。Modbus 实际 PDU 地址 = 寄存器号 − 1。

所有数据字段均为 FLOAT32 Big-Endian(高字在前,4 字节,IEEE 754)

数据项寄存器(1-based)PDU 地址数据类型采集组
正向有功电能2700–27010x0A8BFLOAT32 BE组 1(独立查询)
A 相电流3000–30010x0BB7FLOAT32 BE组 2(与 B/C 相同组)
B 相电流3002–30030x0BB9FLOAT32 BE组 2
C 相电流3004–30050x0BBBFLOAT32 BE组 2
三相平均电流3010–30110x0BC1FLOAT32 BE组 3(与电流不平衡同组)
电流不平衡度3012–30130x0BC3FLOAT32 BE组 3
A 相电压(L-N)3028–30290x0BD3FLOAT32 BE组 4(与 B/C 相同组)
B 相电压(L-N)3030–30310x0BD5FLOAT32 BE组 4
C 相电压(L-N)3032–30330x0BD7FLOAT32 BE组 4
三相平均相电压3036–30370x0BDBFLOAT32 BE组 5(与电压不平衡同组)
电压不平衡度3038–30390x0BDDFLOAT32 BE组 5
总功率因数3084–30850x0C0BFLOAT32 BE组 6(独立查询)
频率3110–31110x0C25FLOAT32 BE组 7(独立查询)

5.2 状态位定义

物模型解析逻辑中包含超时状态判断:

javascript
if ((tdata?.status & 0x02) === 0x02) {
    // time out, just update the status.
}
状态位含义
status & 0x02采集超时

当出现采集超时时,物模型脚本会保留设备上一帧遥测数据,仅更新 status 字段,避免因单次采集失败导致业务数据被异常清空。


6. EdgeBus 模型

本设备通过 RS-485 / Modbus RTU 连接,需要 KC11 + EdgeBus 完成协议采集并通过 LoRaWAN 上报到 ThinkLink。


6.1 EB 配置参数

串口与业务参数:

参数说明
BaudRate9600RS-485 波特率(出厂默认)
StopBits1停止位
DataBits8数据位
CheckbitNONE无校验(N81)
Batteryfalse市电供电,非电池
Class 模式Class C市电供电,适合 Class C 常在线
ConfirmDuty60确认周期配置
BzType23102业务代码
BzVersion13业务版本

周期与参数地址:

参数APP 地址说明
period_up70采集/上传周期(同一参数控制,默认 60 s)
addr_modbus150Modbus 从站地址(默认 1)

注意:本方案 upPeriodIndex = periodIndex = 70,即采集周期与上传周期使用同一 app 参数,不支持分开配置。


6.2 EB 代码

typescript
import { Buffer } from "buffer";
import { buildOtaFile } from "@EBSDK/run";
import {
  ActionAfertExpr, CalcData,
  CrcMode,
  CvtRule,
  EBBuffer,
  EBModel,
  ExprCondition,
  LoraUpEvent,
  QueryEvent, SetUpCovDataType,
  UserConfUPItem, EventInfoItem
} from "@EBSDK/EBCompiler/all_variable";
import { CheckbitEnum, getOtaConfig, HwTypeEnum, UpgrdTypeEnum } from "@EBSDK/otaConfig";
const eventInfo:UserConfUPItem[]=[
  {
    name:"dm251x_hk_power",port:22,version:"0x87",dataType:"0x02",upPeriodIndex:70,
    quInfo:[
      {   protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"2700", end:"2701"}
        ]
      },
      {   protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3000", end:"3001"},
          { start:"3002", end:"3003"},
          { start:"3004", end:"3005"}
        ]
      },
      { protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3010", end:"3011"},
          { start:"3012", end:"3013"}
        ]
      },
      { protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3028", end:"3029"},
          { start:"3030", end:"3031"},
          { start:"3032", end:"3033"}
        ]
      },
      { protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3036", end:"3037"},
          { start:"3038", end:"3039"}
        ]
      },
      { protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3084", end:"3085"}
        ]
      },
      { protocol:"modbus",addr:"0x01",code:"0x03",periodIndex:70,
        indexAPP:150,indexCMD:0,copySize:1,
        listVal:[
          { start:"3110", end:"3111"}
        ]
      }
    ]
  }
]
let otaConfig = getOtaConfig({
  BaudRate: 9600,
  StopBits: 1,
  DataBits: 8,
  Checkbit: CheckbitEnum.NONE,
  Battery: false,
  ConfirmDuty: 60,
  BzType: 23102,
  BzVersion: 13
})
const MODBUS_TT = (ebModel: EBModel) => {
  for (let i=0; i<eventInfo.length; i++){
    let event=new EventInfoItem(eventInfo[i]);
    event.upEventSetup()
    event.eventInstall()
  }
  return JSON.stringify(ebModel, null, 2)
}
buildOtaFile(__filename, otaConfig, MODBUS_TT)

6.3 说明

当前 EB 逻辑说明:

  1. KC11 通过 RS-485 接口连接 DM2500 仪表,采用 Modbus RTU FC03 读保持寄存器。

  2. EB 脚本包含 7 条 Modbus 查询事件,所有事件均使用同一 periodIndex:70,即采集与上传共用同一个周期参数。

  3. Modbus 从站地址存放在 APP 参数地址 150copySize:1,即 1 字节,范围 1–247),EB 在每次查询时从该地址读取实际从站地址并写入请求帧。

  4. 7 条查询的寄存器分组如下:

    查询组寄存器范围采集内容
    组 12700–2701正向有功电能(1 个 FLOAT32)
    组 23000–3005A/B/C 三相电流(3 个 FLOAT32)
    组 33010–3013三相平均电流 + 电流不平衡度(2 个 FLOAT32)
    组 43028–3033A/B/C 三相相电压 L-N(3 个 FLOAT32)
    组 53036–3039三相平均相电压 + 电压不平衡度(2 个 FLOAT32)
    组 63084–3085总功率因数(1 个 FLOAT32,4Q_FP_PF 编码)
    组 73110–3111频率(1 个 FLOAT32)
  5. 所有寄存器均为 FLOAT32 Big-Endian(高字在前),EB 按 listVal 指定的寄存器范围提取数据并顺序拼接到上行帧。

  6. EB 上行帧格式(port 22,总长 58 字节):

    字节范围内容
    0tag 0x87(业务版本标识)
    1tag 0x02(数据类型标识)
    2–5RSSI + 供电状态(KC11 市电模式,4 字节)
    6–9energy_import(FLOAT32 BE)
    10–13current_a
    14–17current_b
    18–21current_c
    22–25current_avg
    26–29current_unbalance
    30–33voltage_an
    34–37voltage_bn
    38–41voltage_cn
    42–45voltage_ln_avg
    46–49voltage_unbalance
    50–53power_factor_total
    54–57frequency
  7. COV(变化上传)未启用,所有数据按固定周期定时上报。

  8. KC11 为市电供电,Battery: false,适合 Class C 模式(网络侧随时可下发 RPC)。


7. 物模型

7.1 物模型基本信息

数据物模型

项目内容
名称[DM2500]
id Namedm2500_23102
LoRaWAN Port22
数据长度58 字节
是否包含 RSSI
Tag 1index: 0,tag: 0x87
Tag 2index: 1,tag: 0x02

参数物模型

项目内容
名称[DM2500-PARA]
id Namedm2500_para_23102
参数上报 Port214
参数内容采集/上传周期(period_up)、Modbus 地址(addr_modbus)

7.2 上行帧结构

字段位置 / 类型说明
port22数据上行端口
dataLen58帧总长度(字节)
rssitrue包含 RSSI 信号强度
battery4 字节KC11 市电供电状态(4 字节)
tagList[0]index: 0,tag: 0x87业务版本标识
tagList[1]index: 1,tag: 0x02数据类型标识(Modbus 采集)
appDataindex 6–5713 个 FLOAT32 BE 数据字段,顺序依次为电能、电流、电压、功率因数、频率

7.3 物模型脚本

数据物模型脚本

javascript
import {PayloadParser} from '#tklHelper'

function payload_parser({device, msg, thingModelId, noticeAttrs}) {
    let port=msg?.userdata?.port || null;
    let frameInfo = {
        port:22,
        dataLen:58,
        rssi:true,
        battery:4,
        tagList:[
            { index:0, tag:0x87 },
            { index:1, tag:0x02 }
        ]
    }
    let appInfo = [
        { name:"正向有功电能", field_name:"energy_import", unit:"kWh", index:6, type:"floatbe", decimal:2 },
        { name:"A相电流", field_name:"current_a", unit:"A", index:10, type:"floatbe", decimal:2 },
        { name:"B相电流", field_name:"current_b", unit:"A", index:14, type:"floatbe", decimal:2 },
        { name:"C相电流", field_name:"current_c", unit:"A", index:18, type:"floatbe", decimal:2 },
        { name:"三相平均电流", field_name:"current_avg", unit:"A", index:22, type:"floatbe", decimal:2 },
        { name:"电流不平衡度", field_name:"current_unbalance", unit:"%", index:26, type:"floatbe", decimal:2 },
        { name:"A相电压", field_name:"voltage_an", unit:"V", index:30, type:"floatbe", decimal:2 },
        { name:"B相电压", field_name:"voltage_bn", unit:"V", index:34, type:"floatbe", decimal:2 },
        { name:"C相电压", field_name:"voltage_cn", unit:"V", index:38, type:"floatbe", decimal:2 },
        { name:"三相平均相电压", field_name:"voltage_ln_avg", unit:"V", index:42, type:"floatbe", decimal:2 },
        { name:"电压不平衡度", field_name:"voltage_unbalance", unit:"%", index:46, type:"floatbe", decimal:2 },
        { name:"总功率因数", field_name:"power_factor_total", unit:"", index:50, type:"floatbe", decimal:3 },
        { name:"频率", field_name:"frequency", unit:"Hz", index:54, type:"floatbe", decimal:1 }
    ]
    let tdata={}
    let payParser=new PayloadParser({
        device:device,
        msg:msg,
        frameInfo:frameInfo,
        appInfo:appInfo,
    })
    tdata= payParser.telemetry()
    if((tdata?.status&0x02)===0x02) { // time out , just update the status.
        const status=tdata.status
        tdata={ ...(device.telemetry_data?.[thingModelId] ?? {})}
        tdata.status=status
    }
    tdata._modelName="dm2500_23102"
    return {
        telemetry_data: tdata,
        server_attrs: null,
        shared_attrs: null
    }
}

参数物模型脚本

javascript
import {PayloadParser, Utils} from '#tklHelper'

function payload_parser({device, msg, thingModelId, noticeAttrs}) {
    let port=msg?.userdata?.port || null;
    const rpcName="dm2500_set_23102"
    let paraDef= {
        app_20:  { name:"TimeOffset",  field_name:"TimeOffset",  unit:"",   index:20, type:"uint32le" },
        app_38:  { name:"pwron_delay", field_name:"pwron_delay", unit:"ms", index:38, type:"uint16le" },
        app_70:  { name:"period_up",   field_name:"period_up",   unit:"s",  type:"uint32LE" },
        app_150: { name:"addr_modbus", field_name:"addr_modbus", unit:"",   type:"uint8" }
    }
    if (port!==214) {
        let checkData=Utils.paraCheck(rpcName,device.server_attrs,device.shared_attrs)
        return {
            server_attrs: checkData.sdata,
            actions: checkData.actions,
        }
    }
    let pdata=(new PayloadParser({
        device:device,
        msg:msg,
        paraInfo:paraDef,
    })).paras()
    let checkData=Utils.paraCheck(rpcName,device.server_attrs,pdata)
    return {
        telemetry_data: pdata,
        server_attrs: checkData.sdata,
        shared_attrs: pdata,
        actions: checkData.actions,
    }
}

8. 第三方平台数据订阅

8.1 MQTT Topic

/v32/{Organization Account}/tkl/up/telemetry/{eui}

8.2 上报示例数据

json
{
    "eui": "6353012af10a9181",
    "active_time": "2026-05-24T08:30:00.000Z",
    "thingModelId": "111025554139803648",
    "thingModelIdName": "dm2500_23102",
    "telemetry_data": {
        "snr": 9.5,
        "rssi": -82,
        "status": 0,
        "energy_import": 12548.32,
        "current_a": 12.45,
        "current_b": 11.87,
        "current_c": 12.10,
        "current_avg": 12.14,
        "current_unbalance": 2.38,
        "voltage_an": 221.30,
        "voltage_bn": 220.85,
        "voltage_cn": 221.10,
        "voltage_ln_avg": 221.08,
        "voltage_unbalance": 0.21,
        "power_factor_total": 0.932,
        "frequency": 50.0
    }
}

说明:thingModelId 以平台实际生成值为准;thingModelIdName 对应数据物模型的 id_namepower_factor_total 使用 Schneider 4Q_FP_PF 编码(值域 ±0.0 ~ ±2.0),值 >1.0 或 <-1.0 表示超前(容性)负载,前端展示时需根据象限进行转换。


9. RPC

9.1 RPC 名称

配置参数(SET)

项目内容
名称[DM2500 SET] 23102
类型SET
id Namedm2500_set_23102

读取参数(GET)

项目内容
名称[DM2500 GET] 23102
类型GET
id Namedm2500_get_23102

9.2 参数定义

参数名字段名APP 地址类型单位默认值范围说明
采集/上传周期period_upapp_70uint32LEs601–3600DTU 轮询仪表并上报云端的间隔,采集与上传共用同一参数
Modbus 从站地址addr_modbusapp_150uint811–247DTU 查询的 Modbus 从站地址,多表组网时需与仪表设置一致

9.3 RPC 代码

配置参数 RPC(SET)

javascript
let classMode = (device?.shared_attrs?.class_mode) || "ClassC";
const rpcName = "dm2500_set_23102";
let paraDef = {
    app_20:  { name:"TimeOffset",  field_name:"TimeOffset",  unit:"",   index:20, type:"uint32le" },
    app_38:  { name:"pwron_delay", field_name:"pwron_delay", unit:"ms", index:38, type:"uint16le" },
    app_70:  { name:"period_up",   field_name:"period_up",   unit:"s",  type:"uint32LE" },
    app_150: { name:"addr_modbus", field_name:"addr_modbus", unit:"",   type:"uint8" }
}
let frames = RPCHelper.buildFrame({ paraDef, params });
let dnBuffer = Buffer.alloc(frames.writeBuffer.length + frames.readBuffer.length);
frames.writeBuffer.copy(dnBuffer, 0);
frames.readBuffer.copy(dnBuffer, frames.writeBuffer.length);
let msgQue = Utils.makeParaSetMSG({
    device, classMode, rpcName, params,
    paraDownBuffer: dnBuffer,
});
if (msgQue.length == 0) return null;
return msgQue;

读取参数 RPC(GET)

javascript
let classMode = (device?.shared_attrs?.class_mode) || "ClassC";
let sleepMs = classMode === "ClassA" ? 500 : 5000;
let paraDef = {
    app_20:  { name:"TimeOffset",  field_name:"TimeOffset",  unit:"",   index:20, type:"uint32le" },
    app_38:  { name:"pwron_delay", field_name:"pwron_delay", unit:"ms", index:38, type:"uint16le" },
    app_70:  { name:"period_up",   field_name:"period_up",   unit:"s",  type:"uint32LE" },
    app_150: { name:"addr_modbus", field_name:"addr_modbus", unit:"",   type:"uint8" }
}
let frames = RPCHelper.buildFrame({ paraDef, params });
let msg = RPCHelper.makeMSG({
    msgType: Utils.msgType.paras,
    device,
    dnBuffer: frames.readBuffer,
    sleepTime: sleepMs,
});
return [msg];

10. 模板选择

在 ThinkLink 平台中搜索模板:

DM2500

或按业务代码查找:

23102

推荐选择:

模板类型名称 / id Name
数据物模型[DM2500] / dm2500_23102
参数物模型[DM2500-PARA] / dm2500_para_23102
设置参数 RPC[DM2500 SET] 23102 / dm2500_set_23102
读取参数 RPC[DM2500 GET] 23102 / dm2500_get_23102

11. 补充说明

通信参数修改

DM2500 出厂默认 Modbus 地址为 1,波特率为 9600 bps(N81)。如需修改从站地址,可通过寄存器 6501 写入新地址(需要写权限),或通过 LCD 面板操作。

功率因数编码说明

DM2500 使用 Schneider 4Q_FP_PF 编码格式上报功率因数,值域为 ±0.0 ~ ±2.0:

  • 感性(Q1/Q4):PF = 寄存器原始值
  • 容性(Q2/Q3):PF = 寄存器值 ± 1

当前集成直接上报原始浮点值,前端或第三方系统接收到 power_factor_total 后,需根据象限进行解析转换。

电压字段有效性

voltage_anvoltage_bnvoltage_cn(L-N 相电压)在 3P4W 接线方式下有效。若现场为 3P3W 接线,这三个字段将返回无效值,建议使用线电压寄存器(3020–3021、3022–3023、3024–3025)代替(当前集成未采集,如需请联系集成方更新 EB 代码)。

DM2510 与 DM2511 共用说明

两款型号共用同一套 EB 代码和物模型。DM2511 专有的第四电流输入(I4,寄存器 3008–3009)当前未采集;如需采集请更新 EB 代码并增加 current_i4 字段。

通信报文示例

读取正向有功电能(Reg 2700,从站地址 1):
请求: 01 03 0A 8B 00 02 [CRC]
响应: 01 03 04 XX XX XX XX [CRC]  (4 字节 FLOAT32 BE = kWh 值)

读取 A/B/C 三相电流(Reg 3000–3005,从站地址 1):
请求: 01 03 0B B7 00 06 [CRC]
响应: 01 03 0C XX XX XX XX  XX XX XX XX  XX XX XX XX [CRC]

读取频率(Reg 3110):
请求: 01 03 0C 25 00 02 [CRC]
响应: 01 03 04 42 42 00 00 [CRC]  (示例:约 48.5 Hz)