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 端子) |
| LoRaWAN | KC11 通过 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_import | kWh | 2700–2701 |
| 2 | A 相电流 | current_a | A | 3000–3001 |
| 3 | B 相电流 | current_b | A | 3002–3003 |
| 4 | C 相电流 | current_c | A | 3004–3005 |
| 5 | 三相平均电流 | current_avg | A | 3010–3011 |
| 6 | 电流不平衡度 | current_unbalance | % | 3012–3013 |
| 7 | A 相电压(L-N) | voltage_an | V | 3028–3029 |
| 8 | B 相电压(L-N) | voltage_bn | V | 3030–3031 |
| 9 | C 相电压(L-N) | voltage_cn | V | 3032–3033 |
| 10 | 三相平均相电压 | voltage_ln_avg | V | 3036–3037 |
| 11 | 电压不平衡度 | voltage_unbalance | % | 3038–3039 |
| 12 | 总功率因数 | power_factor_total | — | 3084–3085 |
| 13 | 频率 | frequency | Hz | 3110–3111 |
5.1 寄存器定义
DM2500 采用 1-based 寄存器编号(与 Schneider 手册一致)。Modbus 实际 PDU 地址 = 寄存器号 − 1。
所有数据字段均为 FLOAT32 Big-Endian(高字在前,4 字节,IEEE 754)。
| 数据项 | 寄存器(1-based) | PDU 地址 | 数据类型 | 采集组 |
|---|---|---|---|---|
| 正向有功电能 | 2700–2701 | 0x0A8B | FLOAT32 BE | 组 1(独立查询) |
| A 相电流 | 3000–3001 | 0x0BB7 | FLOAT32 BE | 组 2(与 B/C 相同组) |
| B 相电流 | 3002–3003 | 0x0BB9 | FLOAT32 BE | 组 2 |
| C 相电流 | 3004–3005 | 0x0BBB | FLOAT32 BE | 组 2 |
| 三相平均电流 | 3010–3011 | 0x0BC1 | FLOAT32 BE | 组 3(与电流不平衡同组) |
| 电流不平衡度 | 3012–3013 | 0x0BC3 | FLOAT32 BE | 组 3 |
| A 相电压(L-N) | 3028–3029 | 0x0BD3 | FLOAT32 BE | 组 4(与 B/C 相同组) |
| B 相电压(L-N) | 3030–3031 | 0x0BD5 | FLOAT32 BE | 组 4 |
| C 相电压(L-N) | 3032–3033 | 0x0BD7 | FLOAT32 BE | 组 4 |
| 三相平均相电压 | 3036–3037 | 0x0BDB | FLOAT32 BE | 组 5(与电压不平衡同组) |
| 电压不平衡度 | 3038–3039 | 0x0BDD | FLOAT32 BE | 组 5 |
| 总功率因数 | 3084–3085 | 0x0C0B | FLOAT32 BE | 组 6(独立查询) |
| 频率 | 3110–3111 | 0x0C25 | FLOAT32 BE | 组 7(独立查询) |
5.2 状态位定义
物模型解析逻辑中包含超时状态判断:
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 配置参数
串口与业务参数:
| 参数 | 值 | 说明 |
|---|---|---|
| BaudRate | 9600 | RS-485 波特率(出厂默认) |
| StopBits | 1 | 停止位 |
| DataBits | 8 | 数据位 |
| Checkbit | NONE | 无校验(N81) |
| Battery | false | 市电供电,非电池 |
| Class 模式 | Class C | 市电供电,适合 Class C 常在线 |
| ConfirmDuty | 60 | 确认周期配置 |
| BzType | 23102 | 业务代码 |
| BzVersion | 13 | 业务版本 |
周期与参数地址:
| 参数 | APP 地址 | 说明 |
|---|---|---|
| period_up | 70 | 采集/上传周期(同一参数控制,默认 60 s) |
| addr_modbus | 150 | Modbus 从站地址(默认 1) |
注意:本方案
upPeriodIndex = periodIndex = 70,即采集周期与上传周期使用同一 app 参数,不支持分开配置。
6.2 EB 代码
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 逻辑说明:
KC11 通过 RS-485 接口连接 DM2500 仪表,采用 Modbus RTU FC03 读保持寄存器。
EB 脚本包含 7 条 Modbus 查询事件,所有事件均使用同一
periodIndex:70,即采集与上传共用同一个周期参数。Modbus 从站地址存放在 APP 参数地址
150(copySize:1,即 1 字节,范围 1–247),EB 在每次查询时从该地址读取实际从站地址并写入请求帧。7 条查询的寄存器分组如下:
查询组 寄存器范围 采集内容 组 1 2700–2701 正向有功电能(1 个 FLOAT32) 组 2 3000–3005 A/B/C 三相电流(3 个 FLOAT32) 组 3 3010–3013 三相平均电流 + 电流不平衡度(2 个 FLOAT32) 组 4 3028–3033 A/B/C 三相相电压 L-N(3 个 FLOAT32) 组 5 3036–3039 三相平均相电压 + 电压不平衡度(2 个 FLOAT32) 组 6 3084–3085 总功率因数(1 个 FLOAT32,4Q_FP_PF 编码) 组 7 3110–3111 频率(1 个 FLOAT32) 所有寄存器均为 FLOAT32 Big-Endian(高字在前),EB 按
listVal指定的寄存器范围提取数据并顺序拼接到上行帧。EB 上行帧格式(port 22,总长 58 字节):
字节范围 内容 0 tag 0x87(业务版本标识) 1 tag 0x02(数据类型标识) 2–5 RSSI + 供电状态(KC11 市电模式,4 字节) 6–9 energy_import(FLOAT32 BE) 10–13 current_a 14–17 current_b 18–21 current_c 22–25 current_avg 26–29 current_unbalance 30–33 voltage_an 34–37 voltage_bn 38–41 voltage_cn 42–45 voltage_ln_avg 46–49 voltage_unbalance 50–53 power_factor_total 54–57 frequency COV(变化上传)未启用,所有数据按固定周期定时上报。
KC11 为市电供电,
Battery: false,适合 Class C 模式(网络侧随时可下发 RPC)。
7. 物模型
7.1 物模型基本信息
数据物模型
| 项目 | 内容 |
|---|---|
| 名称 | [DM2500] |
| id Name | dm2500_23102 |
| LoRaWAN Port | 22 |
| 数据长度 | 58 字节 |
| 是否包含 RSSI | 是 |
| Tag 1 | index: 0,tag: 0x87 |
| Tag 2 | index: 1,tag: 0x02 |
参数物模型
| 项目 | 内容 |
|---|---|
| 名称 | [DM2500-PARA] |
| id Name | dm2500_para_23102 |
| 参数上报 Port | 214 |
| 参数内容 | 采集/上传周期(period_up)、Modbus 地址(addr_modbus) |
7.2 上行帧结构
| 字段 | 位置 / 类型 | 说明 |
|---|---|---|
| port | 22 | 数据上行端口 |
| dataLen | 58 | 帧总长度(字节) |
| rssi | true | 包含 RSSI 信号强度 |
| battery | 4 字节 | KC11 市电供电状态(4 字节) |
| tagList[0] | index: 0,tag: 0x87 | 业务版本标识 |
| tagList[1] | index: 1,tag: 0x02 | 数据类型标识(Modbus 采集) |
| appData | index 6–57 | 13 个 FLOAT32 BE 数据字段,顺序依次为电能、电流、电压、功率因数、频率 |
7.3 物模型脚本
数据物模型脚本
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
}
}参数物模型脚本
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 上报示例数据
{
"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_name。power_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 Name | dm2500_set_23102 |
读取参数(GET)
| 项目 | 内容 |
|---|---|
| 名称 | [DM2500 GET] 23102 |
| 类型 | GET |
| id Name | dm2500_get_23102 |
9.2 参数定义
| 参数名 | 字段名 | APP 地址 | 类型 | 单位 | 默认值 | 范围 | 说明 |
|---|---|---|---|---|---|---|---|
| 采集/上传周期 | period_up | app_70 | uint32LE | s | 60 | 1–3600 | DTU 轮询仪表并上报云端的间隔,采集与上传共用同一参数 |
| Modbus 从站地址 | addr_modbus | app_150 | uint8 | — | 1 | 1–247 | DTU 查询的 Modbus 从站地址,多表组网时需与仪表设置一致 |
9.3 RPC 代码
配置参数 RPC(SET)
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)
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_an、voltage_bn、voltage_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)