跳转到内容
新建笔记

电机Modbus接口:历史寄存器表与待确认契约

这是一份电机控制项目的历史接口草案。原笔记包含串口设置、四类数据表和操作流程,但未附固件、设备型号或抓包,不能据此认定当前设备已经实现这些地址。

下面完整保留原地址与字段,并将字序、命令触发和故障处理中的矛盾写明。实际交付接口前,应由固件与上位机共同确认版本、有效范围、数据类型和验收报文。

1. 通信设置与地址口径

跳转到“1. 通信设置与地址口径”
项目历史记录
模式Modbus RTU,从站地址1
外设USART2
串口115200 bit/s,8数据位、无校验、1停止位,即8N1
各数据空间预留范围0x0000~0x00FF
下表地址作为PDU中的零基地址解释;落地前与实际固件核对

串行规范常规字符格式为11位:8E1,或无校验时8N2。8N1是很多设备采用的配置变体,不能把这份项目记录写成标准唯一格式;通信双方及RTU计时必须匹配。软件配置为115200也不代表线路质量和收发方向时序已经验收。串行规范

四个数据空间地址相同并不冲突;通过功能码区分。预留范围不意味着256个地址全部实现,未定义地址应有明确异常行为。

读取0x03,写单字0x06,写多个字0x10(十进制16)。32位字段建议用一次0x10写两个字,固件验证完整值后一起提交;仅一次请求也不自动保证业务任务读取时的原子性。

地址字段历史布局与单位待确认事项
0000~0001目标转速0000低16位,0001高16位;RPM有符号性、方向、允许范围
0002~0003目标位置低字在前;度×100绝对/模圈位置、有符号性、越界策略
0004加速度系数1~100,默认3系数含义、实际物理量与生效时机
0005减速度系数1~100,默认10同上;是否允许运行时改变
0006~0007相对位置低字在前;度×100正负方向、单次最大位移

表内地址为十六进制。系数不能没有公式就换算为确定的加速度;低/高字布局来自原稿,不代表通用设备约定。

读取0x01,写单线圈0x05,写多个线圈0x0F(十进制15)。下面保留原稿语义,最后一列指出需要解决的冲突。

地址名称原稿值定义触发契约
0000启动伺服1启动,0无动作原稿称上升沿;须定义清零、重复1和确认方式
0001停止伺服1停止,0无动作原稿称边沿;须定义停止优先级与完成条件
0002“急停”软件命令1触发,0无动作仅保留原名称;不能替代独立安全急停回路
0003回原点1执行,0无动作原稿称边沿;须定义忙碌时重复请求
0004报警复位1复位,0无动作原稿称边沿;须定义不可复位故障的返回状态
0005连续运行1运行,0停止连续运行值定义是电平状态,与“边沿触发”标注矛盾
0006相对定位1执行,0无动作原稿称边沿;重复触发可能造成重复位移
0007标定开关1开始,0停止标定值定义是电平状态,与“边沿触发”标注矛盾
0008Modbus使能1使能,0禁用值定义是电平状态;禁用后恢复路径不清楚

一种待确认的修订方案是:连续运行、标定开关和通信使能按电平处理,其余使用带确认的一次性命令;或统一设计命令编号及结果寄存器。不能一边写“写0无动作”,一边要求写0停止,也不能把“重复写1是否重执行”留给两端各自猜测。

若采用边沿,应明确谁清零、何时允许下一命令;仅依靠主站快速写1再写0可能在轮询任务看到前已被覆盖。异常或丢失响应后也要考虑命令是否已经执行,不能无条件重发相对定位。

全部使用0x02读取。以下是原稿的9个状态位,名称本身不定义更新周期和有效性。

地址状态1 / 0
0000报警状态有报警 / 正常
0001零速状态零速 / 非零速运行状态
0002目标到达到达 / 未到达
0003伺服就绪就绪 / 未就绪
0004回原点完成完成 / 未完成
0005定位完成完成 / 未完成
0006Modbus通信正常正常 / 异常,具体含义未定义
0007标定完成完成 / 未完成
0008电机运行运行 / 停止

需要补充零速阈值/滞回、到位窗口,以及“完成位”是当前状态还是上一次命令的锁存结果。新命令开始时若未正确清理旧完成位,上位机可能把旧结果当成这次完成。

通信已经断开时无法靠再读取0006检测断线。主站应根据最后一次合法响应时间、连续超时和本地连接状态判断数据是否陈旧;设备端状态位只能作为联通时的辅助信息。

5. 输入寄存器:测量与诊断

跳转到“5. 输入寄存器:测量与诊断”

使用0x04读取。原稿共占用10个16位寄存器:

地址字段历史布局与单位
0000~0001当前转速低字在前,32位,RPM
0002~0003当前位置低字在前,32位,度×100
0004~0005当前槽数低字在前,32位;计数定义待确认
0006~0007滑动误差低字在前,32位;单位与符号待确认
0008报警代码16位;需配套码表
0009通信错误计数16位;计数类型、回绕/饱和及复位条件待确认

固件应先取一致快照,再把32位值拆为两个寄存器。上位机一次读取两个字,可以避免两次请求跨更新周期,但仍依赖固件快照契约,不能保证任务恰在拆字中途更新的值一致。

6. 明确字节序与32位字序

跳转到“6. 明确字节序与32位字序”

每个16位寄存器的两个线上字节按高字节在前发送;两个寄存器组成32位数时,哪一字先出现由设备接口定义。本项目原记录明确低16位在低地址,因此应称低字在前、字内高字节在前,不能笼统称“整个32位大端”。

值低地址寄存器高地址寄存器线上数据字节
1000 RPM:000003E803E8000003 E8 00 00
360.00度:36000=00008CA08CA000008C A0 00 00

下面验证这种约定的整数编码。signed=True是示例可选能力,不表示原固件已支持有符号位置;双方必须先确认。

import struct
def encode_integer32(value, *, signed=False):
if isinstance(value, bool) or not isinstance(value, int):
raise TypeError("value must be an integer")
low, high = (-(1 << 31), (1 << 31) - 1) if signed else (0, (1 << 32) - 1)
if not low <= value <= high:
raise ValueError("value is outside the selected 32-bit range")
bits = value & 0xFFFFFFFF
return struct.pack(">HH", bits & 0xFFFF, bits >> 16)
def decode_integer32(data, *, signed=False):
low_word, high_word = struct.unpack(">HH", data)
bits = (high_word << 16) | low_word
return bits - (1 << 32) if signed and bits & 0x80000000 else bits
if __name__ == "__main__":
assert encode_integer32(1000) == bytes.fromhex("03 E8 00 00")
assert encode_integer32(36000) == bytes.fromhex("8C A0 00 00")
assert decode_integer32(encode_integer32(-9000, signed=True), signed=True) == -9000
print(encode_integer32(1000).hex(" "))

这段代码不处理浮点IEEE 754格式,也不把角度单位自动转换为整数。度×100的量化、四舍五入规则、有效范围及溢出拒绝策略需要额外规定。

7. 把控制流程写成可验收的状态变化

跳转到“7. 把控制流程写成可验收的状态变化”

原基本流程为:写目标转速→写启动线圈→观察零速状态→写停止线圈。补齐后应先确认就绪/无报警,再一次写入完整目标并读回;提交启动后观察对应命令结果及实际转速,停止后确认速度确实回到定义的零速范围。寄存器回显仅说明协议层处理结果。

原相对定位流程为:写0006~0007相对位置→触发线圈0006→观察离散输入0005。需要避免旧完成位和重复触发,记录此次命令的开始、忙碌、完成或失败状态。

测试顺序保留为:只读通信与诊断→参数写入/读回→受控动作→持续状态监测。另加入非法地址、非法值、报文中断、超时、重复命令、断线恢复、上电默认值与32位边界。错误计数为零不是线路健康的充分证据。

通信禁用与软件停止应定义本地恢复/互锁机制。软件线圈“急停”无法代替具有独立失效处理的安全回路;是否允许故障后自动恢复运动必须由设备控制设计明确,不能由上位机重连行为隐式决定。

此表是可评审的历史契约,不是已实机验证的控制说明。配套:地址映射、主站事务。来源:通信参数原稿。