- Add CHINT DDSU666 profile (ddsu666.yaml): FC03 holding registers, voltage/ current/active power (kW)/reactive power (kvar)/PF/frequency, import+export active energy. Word/byte order left at big-endian as a documented best guess (manual has no float example) — to be confirmed on-device. - Add DDSU666-Modbus-Protocol.md reference extracted from the official manual, plus the source PDF (parity with the SDM120 reference). - Generalize driver.read_blocks to dispatch FC03 (holding) or FC04 (input) based on a function_code argument (default 4, SDM120 behaviour unchanged); the code is validated before any connection is attempted. - Wire profile.function_code through the CLI read command, the background poller, and the device /test endpoint — previously the profile field was declared but never honoured (read path was hardcoded to FC04). - Tests: default -> FC04, function_code=3 -> FC03 holding, invalid FC rejected before connecting.
14 KiB
DDSU666 Modbus 协议(从官方 PDF 提取)
来源:
docs/references/DDSU666 Single phase Smart Meter.pdf(CHINT / 正泰仪表 DDSU666 Single phase Smart Meter — Operation Manual,文档号ZTY0.464.1224,版本 V2,2020 年 8 月;厂商 Zhejiang Chint Instrument & Meter Co., Ltd.) 本文件是 PDF 的可读化提取,供本项目的 Modbus 采集驱动设计参考。以官方 PDF 为准,本文件如有出入以 PDF 为准。 同类文档见 SDM120 的SDM120-Modbus-Protocol.md;两表差异较大,见下方 §6「与 SDM120 的关键差异」。
设备速览(来自手册 Table 1 / Table 5)
| 项 | DDSU666(直接接入) | DDSU666-CT(经互感器) |
|---|---|---|
| 精度等级 | Active Class B | Active Class C |
| 参考电压 | 230 V | 230 V |
| 电流规格 | 0.25–5(80) A | 0.015–1.5(6) A |
| 表常数 | 800 imp/kWh | 6400 imp/kWh |
| 接入方式 | 直接接入 | 经电流互感器 |
- 单相电子式电能表,DIN35mm 导轨安装;测量电压、电流、有功/无功功率、频率、功率因数、正/反向有功电能。
- 电能测量范围
0~999999.99 kWh(LCD 只显示 6 位,自动移动小数点)。 - 通信:RS485,Modbus-RTU(也支持 DL/T 645-2007,可切换,见 §5
0005H ChangeProtocol)。 - 手册 Table 1 标注 Frequency Reference = 60Hz,但 LCD 示例又写
F=50.00Hz(手册自身不一致);实际频率以寄存器200EH读数为准,不要把 50/60 写死。
0. 本项目的接入方式(重要)
DDSU666 物理层是 Modbus RTU(RS-485 串口),半双工。和 SDM120 一样,本项目通过一个 Modbus-TCP 网关接入:
- 后端用 Modbus TCP(
IP:port)连到网关,网关在串口侧转成 RTU 与电表通信。 - TCP 帧用 MBAP header、无 CRC(CRC 由网关在 RTU 侧处理)。本文档里 RTU 帧的
CRC (Lo/Hi)字段在 TCP 模式下不需要我们关心。 - Slave Address / Unit ID = 电表的通信地址 Addr(范围 1–247;面板按键只能设 1–99;见 §5
0006H),在 TCP 请求里作为 unit id 传入。 - 若以后直连串口(RTU),才需要管波特率 / 数据格式 / CRC:默认串口格式是 8 数据位、无校验、2 停止位(8N2),与 SDM120 的 8N1 不同——直连时务必对齐。
- 电表必须处于 Modbus 协议模式(而非 DL/T 645)才能用本协议;可经面板长按切换,或写
0005H = 2(见 §5)。
1. 协议帧格式(Appendix A)
异步传输,按字节为单位。一帧 10 位字符 = 1 起始位(0) + 8 数据位(无校验) + 2 停止位(1)(其它格式可定制)。
信息帧结构(Table A.1)
| 字段 | 长度 | 说明 |
|---|---|---|
| Start(起始) | >3.5 字符静默 | 帧间至少 3.5 字符空闲时间作为分隔 |
| Address code(地址码) | 1 字节 | 目标从机地址 1–247;每个从机在总线上地址唯一 |
| Function code(功能码) | 1 字节 | 仅支持 03H / 10H(见 §2) |
| Data(数据域) | n 字节 | 随功能码不同而不同(起始地址、寄存器数、寄存器数据等) |
| CRC check code(CRC 校验) | 2 字节 | 16-bit CRC(低字节在前、高字节在后;多项式 A001) |
| End(结束) | >3.5 字符静默 | 帧间静默 |
TCP 网关模式下 Start/End 静默与 CRC 由网关处理,本项目不关心。
功能码 03H 示例(读寄存器,Table A.3/A.4)
读从机 01H、起始地址 0CH、2 个寄存器:
- 主机发送:
01 03 00 0C 00 02 04 08(最后04 08是 CRC,低字节04在前)。 - 从机返回(设
0CH/0DH内容为0000H、1388H):01 03 04 00 00 13 88 F7 6504= 字节数;00 00=0CH数据;13 88=0DH数据;F7 65= CRC(低字节F7在前)。
注意:单个 16-bit 寄存器内是「高字节在前、低字节在后」(Table A.4 里
0DH数据返回13 88=0x1388)。这一点对解码浮点的字节序很关键,见 §3。
功能码 10H 示例(写多个寄存器,Table A.5/A.6)
向从机 01H、起始地址 00H 连续写 3 个寄存器 0002H,1388H,000AH:
- 主机发送:
01 10 00 00 00 03 06 00 02 13 88 00 0A 9B E906= 写入字节数(3 寄存器 × 2 字节);随后是 3 个寄存器的数据;末尾9B E9CRC。
- 从机返回:
01 10 00 00 00 03 80 08(回显起始地址 + 寄存器数 + CRC80 08)。
异常响应(Table A.7/A.8)
- 异常时返回的 Function Code = 原功能码 + 128(即最高位置 1,
03H→83H、10H→90H)。 - 数据为单字节 Error Code:
| Error Code | 含义 | 说明 |
|---|---|---|
01H |
Illegal function code | 收到的功能码本表不支持 |
02H |
Illegal register address | 寄存器地址超出有效范围 |
03H |
Illegal data value | 数据值超出对应地址的取值范围 |
2. 功能码
DDSU666 只支持两个功能码(Table A.2):
| 功能码 | 作用 | 说明 |
|---|---|---|
| 03H | Read register(读寄存器) | 读一个或多个寄存器——测量值、电量、配置全部走它 |
| 10H | Write multiple registers(写多个寄存器) | 向 n 个连续寄存器写 n 个 16-bit 数据(改配置 / 清电量) |
⚠️ DDSU666 没有「输入寄存器 / FC04」概念——所有数据(包括电压电流功率)都用 FC 03H 读保持寄存器。这是它和 SDM120(测量值走 FC04)最大的踩坑差异,见 §6。
3. 数据编码
DDSU666 有两类数据:
- 配置 / 参数寄存器(§5,
0000H–0010H):每个 1 个寄存器、16-bit with symbols(16 位有符号整数)。 - 测量 / 电量寄存器(§4,
2000H+ /4000H+):每个参数 = 32-bit IEEE-754 单精度浮点(手册写 “single precision floating decimal”),占 2 个相邻寄存器(Length = 2 Word)。
浮点字节序 / 字序
- 字节序(byte order)= 大端:寄存器内高字节在前 —— 由 Table A.4 的
0x1388返回为13 88确认。 - 字序(word order,两个寄存器谁是高 16 位):手册没有给出浮点解码的实例,未明确标注。按标准 Modbus 浮点惯例应为大端字序(高寄存器在前,
ABCD),与本项目 SDM120 驱动一致(registers_to_float用>f,高寄存器在前)。 - ⚠️ 需上机实测确认:读
2000H(电压)应解出 ~230V 这样的合理值;若解出乱数,多半是字序相反,改成「低寄存器在前」再试。CHINT 同系列(DTSU/DDSU666)现场固件偶有字序差异,首次接入务必用一个已知量(电压)校验,不要凭手册想当然。
Python 解码(大端、高寄存器在前):
struct.unpack('>f', struct.pack('>HH', hi_reg, lo_reg))[0]。 pymodbus:BinaryPayloadDecoder.fromRegisters(regs, byteorder=Endian.BIG, wordorder=Endian.BIG)。
4. 测量 / 电量寄存器表(FC 03H 读)
全部为只读、Float(32-bit),每项占 2 个寄存器。地址为 Modbus 协议原始地址(即帧里的 Start Register Address Hi/Lo),手册用十六进制。
4.1 瞬时量(“Electric quantity of the secondary side”,2000H 段)
| 地址(hex) | 参数 | 代号 | 单位 | 备注 |
|---|---|---|---|---|
2000H |
电压 Voltage | U | V | |
2002H |
电流 Current | I | A | |
2004H |
有功功率 Active power | P | kW | 手册标注 “the unit is KW”——不是 W |
2006H |
无功功率 Reactive power | Q | kvar | |
2008H |
(保留 RESERVED) | — | — | 占 2 寄存器,跳过 |
200AH |
功率因数 Power factor | PF | — | 无量纲 |
200CH |
(保留 RESERVED) | — | — | 占 2 寄存器,跳过 |
200EH |
频率 Frequency | Freq | Hz |
4.2 电量(“Electrical data of the secondary side”,4000H 段)
| 地址(hex) | 参数 | 代号 | 单位 | 备注 |
|---|---|---|---|---|
4000H |
正向(导入)有功电能 Active in electricity | Ep | kWh | 正向 / forward active energy |
400AH |
反向(导出)有功电能 Reverse in electricity | -Ep | kWh | 反向 / reverse active energy |
手册里
4000H与400AH之间(4002H–4009H)未列出,视为保留/未文档化。
读取分块建议
- 瞬时量:
2000H–200FH共 16 个寄存器连续,一次块读即可覆盖 U…Freq(含两段 RESERVED,解码时跳过)。 - 电量:
4000H(2 寄存器)与400AH(2 寄存器)相距较远,分两小块读,或读4000H–400BH(12 寄存器)一次取出后挑用——以网关 / 电表是否允许跨保留地址块读为准,谨慎起见分开读更稳。
常用核心子集(日常监控够用)
电压 2000H、电流 2002H、有功功率 2004H(kW)、功率因数 200AH、频率 200EH、正向有功电能 4000H、反向有功电能 400AH。
5. 配置 / 参数寄存器表(FC 03H 读 / FC 10H 写)(Table 9)
每个 1 个寄存器、16-bit 有符号整数。R/W 列来自手册。
| 地址(hex) | 代号 | 含义 | R/W | 取值 / 说明 |
|---|---|---|---|---|
0000H |
UCode | 编程密码 Programming password code | R/W | 写配置前的密码字 |
0001H |
REV. | 保留;实际读出的是版本号 | R | |
0002H |
ClrE | 电能清零 CLr.E | R/W | 写 1 清除总电量(不可逆,慎用) |
0003H–0004H |
RESERVED | 保留 | — | |
0005H |
ChangeProtocol | 协议切换 | R/W | 2 = Modbus-RTU,1 = DL/T 645-2007 |
0006H |
Addr | 通信地址 | R/W | 1–247(面板按键仅 1–99) |
0007H–000AH |
RESERVED | 保留 | — | |
000BH |
Meter type | 表型 Meter type | R | 只读设备类型标识 |
000CH |
BAud | 通信波特率 | R/W | 1=2400bps,2=4800bps,3=9600bps(手册寄存器仅列这三档;通信章另提到也支持 1200bps) |
000DH–0010H |
RESERVED | 保留 | — |
⚠️ 写
0002H(清电量)、0006H(改地址)、000CH(改波特率)、0005H(切协议)都会改变电表状态或通信参数,配错可能清空累计电量或导致通信中断。本项目默认只读采集,不在自动化链路里写电表配置寄存器。 写配置通常需先经0000H UCode密码字校验;具体密码值手册正文未给出,需向厂商确认或经面板操作。
6. 与 SDM120 的关键差异(迁移 / 复用驱动时必看)
本项目已有 SDM120 profile(app/integrations/modbus/profiles/sdm120.yaml)。DDSU666 不能照搬,主要差异:
| 维度 | SDM120 (Eastron) | DDSU666 (CHINT) |
|---|---|---|
| 读测量值功能码 | FC 04(输入寄存器 3X) | FC 03(保持寄存器,无 FC04) |
| 测量值起始地址 | 0x0000 起(30001) |
瞬时量 0x2000 起;电量 0x4000/0x400A |
| 有功功率单位 | W(瓦) | kW(千瓦) —— 入库前注意换算 / 单位标注 |
| 无功功率单位 | VAr | kvar |
| 配置寄存器格式 | Float(FC03/16) | 16-bit 有符号整数(FC03/10) |
| 写功能码 | 16 / 0x10 | 10H(同 0x10) |
| 串口默认格式 | 8N1(1 停止位) | 8N2(2 停止位) |
| 多协议 | 仅 Modbus | Modbus 与 DL/T 645-2007 可切换(需确保在 Modbus 模式) |
| 浮点字序 | 大端、高寄存器在前(手册有实例佐证) | 字节序大端已确认;字序手册无实例,需上机实测 |
7. 给本项目采集驱动的要点小结
- 走 Modbus TCP 网关:
ModbusTcpClient(host, port),slave=<Addr>;电表须在 Modbus 协议模式。 - 所有读取(测量 + 电量 + 配置)都用 FC 03H——没有 FC04。
- 测量值在
0x2000段、电量在0x4000/0x400A,均为 float32;解码大端字节序,字序默认高寄存器在前但务必用电压实测校验。 - 有功功率单位是 kW、无功是 kvar——与 SDM120 的 W/VAr 不同,新建 profile / 入库映射时单位别抄错。
- 配置寄存器(
0x0000–0x0010)是 16-bit 有符号整数,不是 float。 - 默认只读;
0002H写 1 会清空累计电量、0006H/000CH/0005H会改通信参数,自动化链路里一律不写。 - 新建 profile 时这是
ddsu666这一个 register profile 的定义;建议function_code: 3、word_order: big(先按大端字序,接入后用电压读数验证)、瞬时量与电量分块读。
8. 实测记录(真机验证,2026-06-30)
首次接入一台 DDSU666 直接接入版(5(80)A) 实测,确认以下几点:
- 字序大端,确认无误:电压 / 电流 / 频率 / 电能用「大端、高寄存器在前」解码全部得到合理值(如 233.9 V / 0.055 A / 49.99 Hz),与 §3 的假设一致。
ddsu666.yaml的word_order: big/byte_order: big无需修改,§3 里「字序需上机实测」一项可视为已关闭。 - FC03 读通:所有量走 FC03,profile
ddsu666在采集链路(CLIread/ 设备/test/ 后台轮询)中工作正常。 - 低电流下「瞬时功率读 0、但电能照常累加」:测试负载仅为一台 PoE 交换机(≈230 V / 0.05 A,真实有功仅几瓦),远低于本表测量量程下限 Imin≈0.25 A。此工况下:
- 瞬时
active_power(0x2004)与power_factor(0x200A)寄存器返回全零(原始 hex0x0000 0x0000);电表 LCD 上功率在 03.3 W、PF 在 00.6 之间抖动。 - 抖动成因 = 低电流测量噪声 + 开关电源(SMPS,无 PFC)畸变电流(电流为电压峰值附近的窄脉冲、谐波重 → 畸变功率因数天然偏低)。不是「采样率与开关频率拍频」:计量芯片 SH79F7019 采样在 kHz 量级,远低于开关电源 50–200 kHz 的开关频率,两者不在一个频段。
- 但累计电能
import_energy(0x4000)正常累加(实测 0 → 0.01 kWh)——电表内部积分器在防潜动起始电流(0.004·Ib≈0.02 A)之上照常计量。 - 结论:低于量程下限时瞬时功率 / PF 不可信,但电能计量不丢;电流进入量程(正常负载)后瞬时量即稳定可信。这是 5(80)A 大量程表对极小负载的固有特性,非缺陷、非解码问题。
- 瞬时
- 排错提示:若日后看到 DDSU666「功率一直 0」,先确认负载电流是否在 Imin 以上——多半是负载太轻而非链路故障;可用
scripts/modbus_cli probe --fc 3 --address 0x2000 --count 16看0x2004/0x2005原始寄存器是否真为全零佐证。