ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

变频器 Modbus RTU 寄存器地址与启停调速实战

变频器 Modbus RTU 寄存器地址与启停调速实战 简介这份资料面向工业自动化工程师、PLC与HMI编程人员及设备调试人员系统汇总了主流品牌变频器在Modbus RTU通信下的寄存器地址分配用于解决跨品牌设备集成时启停控制与频率读写地址查找繁琐、易出错的问题。包内仅1个docx文档约3.31MB按品牌与系列分层整理涵盖三菱、西门子、欧姆龙、松下、台达、信捷、永宏、产电、汇川、英威腾、施耐德、海为、和利时、台安、合信、罗克韦尔、富士、步科、安川及威纶通触摸屏等数十个系列涉及启动、停止、频率给定与读取、状态查询等常用功能。文档以速查表形式呈现条目清晰便于现场对照查阅和快速定位地址。目前已有5872人学习下载适合需要做远程控制、参数读取与故障诊断的工程人员作为选型与调试参考也可用于技术交底与项目归档。1. 变频器 Modbus RTU 寄存器地址为什么总是对不上现场最常见的场景PLC 按上一台设备的地址往 2001H 里写 5000期待 50.00Hz 输出电机一动不动换成另一台品牌的同功率机器同样的地址直接回异常码 0x02非法数据地址。问题不在协议本身——Modbus RTU 的帧格式几十年没变帧头、功能码、CRC 校验都是固定的问题在于寄存器地址是各家私有的约定。同一件事在不同品牌里可能叫 2000H、8192、48193 或者 40101启动位的定义、频率的缩放系数、可读可写的范围也都不一样。这里要做的是把启动、停止、频率读写这几个高频动作背后的地址分配规律讲清楚先是功能码与地址记法的换算再给出常见品牌的地址对照接着是用 Python 和 PLC 分别跑通一条完整的启停加调速链路最后落到多台设备轮询和排错。适合正在做 485 组网调试的自动化工程师、写上位机的开发以及第一次接手几十台变频器集中控制项目的人。2. Modbus RTU 报文结构与变频器寄存器地址的映射规则变频器的通信需求其实很窄窄到只需要三个功能码就能覆盖九成场景。把这三个功能码吃透再看任何品牌的地址表都不会慌因为剩下的差异只是表格里的数字不同而不是机制不同。2.1 变频器场景其实只用 03、06、10 三个功能码读状态和回读频率用 03读保持寄存器写单个控制字用 06写单个保持寄存器一次写控制字加频率给定用 10写多个保持寄存器。下面是写台达 VFD-M 的 2000H 为正转启动的完整帧从站地址 19600 8E1 下发送01 06 20 00 00 01 CRC_L CRC_H │ │ └──┬──┘ └──┬──┘ │ │ │ └── 写入值 0x0001b0 置 1 表示正转 │ │ └────────── 寄存器地址 0x2000高字节在前 │ └──────────────── 功能码 06写单个保持寄存器 └─────────────────── 从站地址 01响应帧是把请求原样回显八个字节主站只要比对一致就认为写成功。如果从站返回01 86 02 ...说明功能码最高位置 1 表示异常异常码 02 是非法数据地址意味着这个寄存器在这台机器上不存在或者不允许写。异常码 01 是非法功能码通常出现在把 06 发给了只支持 03 的设备上异常码 03 是非法数据值多半是写入值超出了参数允许范围。2.2 4xxxx 记法与协议地址的偏移陷阱同一个寄存器在手册、上位机、PLC 里可能有三套写法这是最容易出错的地方。规则只有一条协议层地址从 0 开始编号PLC 常用的 4xxxx 记法等于协议地址加 40001。设备/手册写法协议层地址十进制/十六进制PLC 4x 记法说明台达 2000H8192 / 0x20004819340001 8192台达 2001H频率给定8193 / 0x20014819440001 8193台达 2101H输出频率8449 / 0x21014845040001 8449西门子 V20 手册写 4010099 / 0x006340100手册已经是 4x 记法施耐德 ATV 手册写 85018501 / 0x21354850240001 8501写 Python 脚本时用的是协议层地址也就是 0x2000 或 8192在西门子 S7-200 SMART 的 MBUS_MSG 里填的 Addr 是 4x 记法台达那台要填 48193。搞混这一层最常见的表现就是读到一串 0 或者直接吃异常码 02而参数配置其实全对。2.3 缩放系数、字节序与串口格式的约定频率给定几乎不会用浮点都是用整数配一个缩放系数。台达和汇川大多是 0.01Hz/LSB50Hz 对应 5000施耐德 ATV 系列是 0.1Hz/LSB50Hz 对应 500西门子 V20 是百分比制0x4000 对应 100%按 P1082 最大频率折算。# 不同品牌的频率给定缩放统一用每 1Hz 对应的原始值表示 SCALE { siemens_v20: 16384 / 50.0, # 4000H100%假设 P1082 最大频率设为 50Hz delta_vfd: 100.0, # 0.01Hz/LSB50Hz - 5000 invt_md500: 100.0, # 0.01Hz/LSB schneider: 10.0, # 0.1Hz/LSB50Hz - 500 } def hz_to_raw(hz, brand): return int(round(hz * SCALE[brand])) # 必须取整寄存器只收 16 位整数 print(hz_to_raw(50, delta_vfd)) # 5000 print(hz_to_raw(50, siemens_v20)) # 16384单个 16 位寄存器在总线上永远高字节先发这一点不需要额外处理。真正需要注意的是 32 位数据比如累计运行时间、部分品牌的转矩或电能值它们占两个连续寄存器先发的是高字还是低字各家不同汇川的 PLC 组态里就专门有高低位转换的选项要勾。串口格式方面变频器出厂默认多为 9600、8 数据位、偶校验、1 停止位8E1偶校验在工业现场比无校验更抗干扰改波特率时记得主从两端同步改并且改完要重新上电或按手册保存参数。3. 主流品牌变频器启动、停止、频率读写寄存器地址汇总看地址表之前先建立通用三件套的概念任何一台变频器做远程控制都只需要找到三个东西——控制字启动、停止、复位、方向、频率给定、状态与频率回读。把这三点定位到具体寄存器通信就通了一大半。3.1 控制字的位定义是各品牌差异最大的地方台达 VFD-M 系列的 2000H 常见位定义是 b0 正转、b1 反转、b2 外部故障、b3 故障复位写 0x0001 正转、0x0002 反转、0x0000 停机自由停车需配合参数。西门子 V20 的 40100 走的是 PROFIdrive 风格的控制字b0 置 1 为 ON/OFF1 启动b7 置 1 为故障确认b11 置 1 为反向停止是 b0 清零。需要强调一点位定义会随固件版本和参数设置变化比如某些系列可以配置通信控制字 bit 含义改过参数后原来的值就未必生效了。因此下面的表只作为起点必须用 3.4 节的读操作在现场确认一遍再写程序。3.2 常见品牌的地址对照示例务必按手核实品牌/系列控制字启动/停止频率给定状态/频率回读关键参数设置西门子 SINAMICS V2040100协议地址 99401010x4000100%40110 状态字 / 40111 实际值P2010 波特率、P2011 从站地址、P2023 选 Modbus RTU、P07005、P10005、P0971 保存台达 VFD-M / VFD-EL2000Hb0 正转2001H0.01Hz2100H 状态 / 2101H 输出频率 0.01HzPr.09 通信地址、Pr.10 波特率、Pr.11 通信格式8E1 对应值汇川 MD500 / MD3802000H 通信控制字2001H0.01Hz3000H 状态 / 3001H 实际频率命令源与频率源切到通信常见 F0-02 / F0-03施耐德 ATV12 / ATV3128501 命令字85020.1Hz8602 状态字 / 8603 实际频率命令与频率通道设为 Modbus三菱 FR-D700 / E7004xxxx 区随系列不同4xxxx 区监视区先把 Pr.549 通信协议选为 Modbus RTU安川 V1000 / F70001H 运行指令0002H 频率指令0020H 起的监视区b1-01 频率指令来源设为通信同一品牌不同系列地址会变。台达从 VFD-M 换到 CP2000控制字仍然是 2000H但参数量程和部分监视寄存器就不同汇川 MD380 与 MD500 的读取区起点也不完全一致。所以这张表的价值不是让你直接抄进程序而是让你知道去哪一栏找、找出来的数大概长什么样。3.3 地址不固定的品牌怎么查三菱和 ABB 的两种思路三菱的变频器出厂默认跑的是自家变频器协议不是 Modbus。上 485 之前必须在参数里把通信协议切到 Modbus RTUD700 系列是 Pr.5490 为三菱协议1 为 Modbus RTU切完之后地址落在 4xxxx 区具体映射按手册的通信章节查不同系列的运行指令和频率给定寄存器号并不统一。ABB 走的是第三条路寄存器不是固定的而是在参数里做映射。ACS380、ACS580 这类机型需要先把 Modbus 通信使能再把控制字、给定值、状态字映射到 40101 往后的一段保持寄存器上映射关系由参数组决定。思路是先定义接口再写程序好处是同一套 PLC 程序能适配不同机型代价是每台设备的参数文档必须留档。3.4 用 03 功能码反查地址是否真的存在拿到一台没见过的机器不要先写先读。下面这段代码把候选地址挨个读一遍靠异常码和返回值就能判断地址是否存在from pymodbus.client import ModbusSerialClient client ModbusSerialClient(portCOM5, baudrate9600, bytesize8, parityE, stopbits1, timeout0.5) client.connect() for addr in (0x2000, 0x2001, 0x2100, 0x2101, 0x3000): rr client.read_holding_registers(addressaddr, count1, slave1) if rr.isError(): # 异常码 02非法数据地址地址不存在03非法数据值 print(hex(addr), 读取异常:, rr) else: print(hex(addr), -, rr.registers[0]) client.close()判断逻辑是返回具体数值说明地址存在且可读返回 0 说明地址存在但当前值为 0例如停机状态返回异常码 02 说明这个地址在这台设备上不被支持。注意 pymodbus 3.x 用slave指定从站号2.x 版本用的是unit报参数错误时先确认版本。另外读操作不要连续高频发每帧之间留 20ms 以上变频器 CPU 处理通信的优先级并不高。4. 用 Python 与 PLC 跑通变频器启停和频率读写知道地址之后把它变成能跑的代码只差三步打开串口、写控制字、写频率给定量。下面给一个完整可用的最小实现再对照西门子 PLC 侧的参数填法。4.1 Python 侧一条完整的启动到停机链路from pymodbus.client import ModbusSerialClient import time SLAVE, REG_CMD, REG_FREQ, REG_OUT 1, 0x2000, 0x2001, 0x2101 client ModbusSerialClient(portCOM5, baudrate9600, bytesize8, parityE, stopbits1, timeout1.0) if not client.connect(): raise SystemExit(串口打开失败检查端口号和驱动) def write(reg, value): rs client.write_register(addressreg, valuevalue, slaveSLAVE) if rs.isError(): raise RuntimeError(f写 {hex(reg)} 失败: {rs}) time.sleep(0.05) # 给变频器留出参数写入时间 def read(reg): rr client.read_holding_registers(addressreg, count1, slaveSLAVE) if rr.isError(): raise RuntimeError(f读 {hex(reg)} 失败: {rr}) return rr.registers[0] write(REG_FREQ, 3000) # 先给频率 30.00Hz再启动避免低频启动冲击 write(REG_CMD, 0x0001) # b0 置 1正转启动 time.sleep(3) print(输出频率:, read(REG_OUT) / 100.0, Hz) # 0.01Hz 缩放 write(REG_CMD, 0x0000) # 控制字清零停机 client.close()逻辑上有一个顺序问题值得注意先写频率再启动还是先启动再写频率不同品牌表现不同。台达这类控制字写入即生效的机型先给频率再启动更平稳有些机型要求先启动再给频率否则会被判为无效给定。参数方面timeout1.0是按变频器响应延迟给的现场总线较长时建议放大到 2 秒time.sleep(0.05)是帧间静默删掉它连续写会在部分机型上丢帧。4.2 S7-200 SMART 与 S7-1200 侧的地址怎么填S7-200 SMART 用 MBUS_MSG 做主站关键引脚是 Slave从站号、RW0 读 1 写、Addr4x 记法地址、Count寄存器个数、DataPtr本地数据区指针。控制台达那台Addr 填 48193Count 填 1RW 填 1DataPtr 指向存放 0x0001 的 VW 寄存器。S7-1200 用 MB_MASTER引脚名不同但含义一致MB_ADDR 是从站地址MODE 是功能码选择0 读、1 写DATA_ADDR 同样填 48193DATA_LEN 和 DATA_PTR 对应长度与本地地址。写多个寄存器时把 Count 改成 2本地数据区放两个连续字第一个是控制字、第二个是频率给定一条 10 功能码报文就能同时下发启动和频率。西门子 V20 的地址要按手册填 40100 和 40101如果 DATA_ADDR 填了 99多数固件会直接报地址错误。4.3 必调的通信参数对照参数常见取值说明从站地址1~247现场从 1 开始顺排方便算偏移波特率9600 / 1920032 台以上建议 19200数据格式8E1与变频器 Pr/参数里的通信格式一致响应超时300~1000ms总线越长给越大帧间延时≥20ms 或 3.5 字符时间高频轮询必加重试次数2~3 次超过 3 次说明是硬件问题5. 多台变频器轮询、高低位转换与排错单台通了不等于三十台能通规模上来之后限制因素从地址对不对变成时间够不够用。5.1 32 台变频器的轮询周期怎么算9600bps、8E1 下每个字节约 1.04ms。一次写控制字 读频率大概要走两条报文请求加响应约 25 字节折合 26ms再加上变频器内部 5~20ms 处理延迟和 3.5 字符静默单台刷新一轮大约 40ms。32 台串行轮询一遍就是 1.3 秒左右指望 100ms 刷新一轮在物理上做不到。常见做法是分层控制字按需下发不参与轮询频率回读按优先级分组关键设备 500ms 一轮辅助设备 2 秒一轮。把波特率提到 19200周期能砍掉近一半代价是对线缆和终端电阻的要求更高。5.2 汇川 PLC 的高低字节序转换32 位数据累计电量、运行时间占两个寄存器汇川 PLC 的 Modbus 指令里需要判断高低字顺序。若上位机按大端解析出 0x0000FFFF 这种明显异常值把两个字交换即可def join_u32(high, low, swapFalse): if swap: # 部分 PLC 侧把低字放在前一个寄存器 high, low low, high return (high 16) | low # 单寄存器内部仍是高字节在前 print(join_u32(0x0001, 0x86A0)) # 100000对应 100000 单位join_u32的swap开关就是给不同字节序留的出口调试时先读一个已知值比如额定频率对应的数值能对上就不用交换。5.3 通信故障按这个顺序排查现象大概率原因处理动作完全无响应A/B 接反、终端电阻缺失与另一台正常设备交换接线对比偶发超时帧间延时太短、总线过长加大间隔到 50ms、检查屏蔽层单端接地异常码 02地址不存在或写给了只读寄存器用 03 逐个读一遍确认地址数值相差 100 倍缩放系数用错核对是 0.01Hz 还是 0.1Hz频率对了电机不转命令源没切到通信通道检查 P0700 / F0-02 一类参数调试时把重试和日志打开记录失败地址和异常码比一句通信不稳定有用得多for slave in range(1, 33): try: write_to(slave, REG_FREQ, 5000) except RuntimeError as e: print(f站号 {slave} 失败: {e}) # 失败站号留在日志里直接对应物理位置排查顺序上先用一台设备把地址、缩放、位定义全部验证通过再把这个已验证的模板复制到其余 31 台只改从站号这样现场出问题时能立刻判断是新设备的问题还是总线的问题。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进