简介:WHB-870系列微机装置103规约点表面向微机保护装置的调试、运维与二次开发人员,用于解决103规约接入时点号对照与信息点解析缺少权威参照的问题,适合电力系统自动化、变电站综自改造等场景下的技术人员使用。压缩包共1个pdf文件,约162KB,为V1.00版本点表文档。内容按保护动作故障信号、告警信号、状态信号三大类编排,逐条列出信息点名称、报文类型、INF点号与公共地址,并给出线路、充电、厂用变、电容器、电动机五类保护对象的FUN地址对应关系,如178、211、199、185、227;对过流Ⅰ至Ⅲ段、零序、负序、低零序、过热、重合闸及各类压板状态均有标注,带★者说明为选配项,需装置配置交流插件2时才有点号。凭借清晰的表格结构与可选配说明,读者可快速完成报文解析、点表建模与装置联调核对。该文档已有273人学习下载,适合用作规约配置与故障信号排查的案头参考。
1. 一次“装置灯亮了,主站没反应”背后的 103 规约点表
馈线过流Ⅱ段跳闸灯亮了,开关也确实分了,后台主站的告警窗却干干净净。二次回路查完,通信链路也通,最后问题落在 103 规约点表上:装置里这个点的 FUN 是 199(厂用变),主站数据库却按 178(线路)建的点,报文规规矩矩发上来了,主站找不到落点,直接当未知 INF 丢掉。WHB-870 系列把 WHB-871、WHB-872、WHB-876、WHB-877 四类装置的 103 规约点表合并成一份 V1.00 文档,按保护动作故障信号、告警信号、状态信号、控制、遥测、电度、总召唤、录波八块,逐点给出 INF、报文类型、FUN 和公共地址。这份表不是给运维翻着玩的,它是微机保护装置与变电站自动化主站之间唯一的地址契约,抄错一列,现场就得整站重新对点。
2. 拆解点表的四个寻址维度:FUN、INF、ASDU 与公共地址
一份 103 规约点表看起来是几十行表格,本质上是四个维度在做联合寻址:报文类型(ASDU)决定这条报文“长什么样、干什么用”,FUN 决定“是哪个保护对象”,INF 决定“是这个对象下的哪一条信息”,公共地址决定“是哪一台装置”。四个都对上,主站才能把一条上送报文准确落到某个具体测点上。少对任何一个,报文就变成一条无法解析的裸数据。
2.1 FUN 地址按保护对象分档,一张表定死
WHB-871 是典型的“一台装置顶多套保护”设计:同一套软硬件,通过配置成线路、充电、厂用变、电容器、电动机五种保护对象来适配不同间隔。区分手段就是 FUN,文档里单独给了一张对应关系表。
| 保护对象 | 线路 | 充电 | 厂用变 | 电容器 | 电动机 |
|---|---|---|---|---|---|
| FUN 地址 | 178 | 211 | 199 | 185 | 227 |
这张表是整个点表的地基。WHB-871 的后续章节里,很多行只在对应的保护对象列打勾,读的时候必须横向看到底哪些列有勾,再回头查 FUN 表。WHB-872(微机电动机保护测控装置)把 FUN 固定成 227,WHB-876(微机电压互感器监控装置)固定成 187,WHB-877(微机备用电源自投装置)固定成 248。也就是说,后三种装置的 FUN 是装置级常量,只有 WHB-871 需要按间隔对象做映射。
实际配置时我一般先把这张对照表做成一个字典落在脚本里,后面所有点都靠它换算,避免手抄。
# WHB-871 保护对象到 FUN 的映射,其它型号用固定值 FUN_TABLE = { "WHB-871": {"线路": 178, "充电": 211, "厂用变": 199, "电容器": 185, "电动机": 227}, "WHB-872": {"default": 227}, # 电动机保护测控,FUN 恒定 "WHB-876": {"default": 187}, # 电压互感器监控,FUN 恒定 "WHB-877": {"default": 248}, # 备自投,FUN 恒定 } def resolve_fun(device, obj_type=None): """按装置型号和保护对象解析 FUN,后三种装置忽略 obj_type""" table = FUN_TABLE[device] return table.get(obj_type, table.get("default"))resolve_fun的入参是装置型号加保护对象,返回该点应填的 FUN。对 WHB-872/876/877 传obj_type=None也能正确返回默认值,这样四种装置可以走同一套解析逻辑,不用在主流程里写分支。
2.2 (FUN, INF) 才是联合主键,单看 INF 必然撞车
新手最容易犯的错,是把 INF 当成全局唯一编号。WHB-871 的告警信号里,INF 221 同时对应“低零序过流告警”;状态信号里,INF 221 又对应“重合闸充电标志”。如果只拿 INF 建库,这两条直接主键冲突。正确做法是把(装置, 保护对象, 报文类型, FUN, INF)作为联合键。
# 检测同一 ASDU + FUN 下 INF 是否重复,重复即视为建模冲突 from collections import defaultdict import csv bucket = defaultdict(list) with open("whb870_points.csv", encoding="utf-8-sig") as f: for row in csv.DictReader(f): # row 需包含 device/obj/fun/asdu/inf/name 字段 key = (row["device"], row["obj"], row["asdu"], int(row["fun"]), int(row["inf"])) bucket[key].append(row["name"]) for key, names in bucket.items(): if len(names) > 1: print("冲突点:", key, "->", names)这段脚本遍历整理好的 CSV,按联合键归集点位名称。输出为空说明建模干净;如果有输出,先别急着删,通常有两种情况:一是同一物理量在不同 ASDU 下确实有两套 INF(下面 2.3 节讲),二是抄表时把列串了。区分办法就是看asdu字段是否相同,相同才算真冲突。
2.3 ASDU 决定语义,别拿遥信的 INF 去建遥控点
103 规约的报文类型号不是编号,是语法声明。WHB-870 点表里出现的几类各有分工:ASDU_1承载带时标的单点遥信,是告警、状态这类信号的主通道;ASDU_2承载带相对时间的单点事件,保护动作跳闸走这条;ASDU_70常与ASDU_2成对出现,同一动作既发事件也发遥信;ASDU_20是遥控命令,压板投退、信号复归、定值区切换都从这里下发;ASDU_41是双点开入,ASDU_50走遥测,ASDU_36走电度脉冲,ASDU_64用于断路器遥控输出。
对照 WHB-871 的控制表就会发现问题:状态信号里“低零反时限压板”是 INF 175,控制表里同一个压板却是 INF 65。这不是抄错,而是遥信区和遥控区各自维护了一套 INF 编号空间。建点时如果偷懒把遥信的 INF 直接复制到遥控点,装置收到命令后会解析成完全不相干的另一个对象,严重时误跳。
-- 主站侧点位表,ASDU 必须进主键,否则遥信/遥控会互相覆盖 CREATE TABLE whb870_point ( device VARCHAR(16) NOT NULL, -- 装置型号,如 WHB-871 obj_type VARCHAR(16) NOT NULL, -- 保护对象:线路/充电/厂用变/电容器/电动机 asdu VARCHAR(16) NOT NULL, -- 报文类型,如 ASDU_1 / ASDU_20 fun SMALLINT NOT NULL, -- 功能类型地址 inf SMALLINT NOT NULL, -- 信息序号 com_addr SMALLINT NOT NULL DEFAULT 1, -- 公共地址,文档注明统一为 1 point_name VARCHAR(64) NOT NULL, optional BOOLEAN NOT NULL DEFAULT FALSE, -- 星号标记的可选配项 PRIMARY KEY (device, obj_type, asdu, fun, inf) );asdu进主键是关键一步,它把遥信、遥控、遥测三类点彻底隔开。optional字段对应文档里带星号的条目,导入组态时可以先按optional = FALSE过滤,把必配点先跑通,再逐批放可选点,避免一次导几百个点连不上还查不出是谁的问题。
2.4 公共地址统一为 1,正文行尾的其它数字别乱搬
文档开头明确写了公共地址统一为 1,这是全表最省事的一条约定。但逐行读状态信号和控制两节会发现,有些行在末尾还跟着一个 0 或 2 的数字。这两个数字不是要你改公共地址,而是表内不同小节列序不统一造成的视觉错位——有的小节列序是“信息点名称 INF 报文类型 公共地址 FUN”,有的是“信息点名称 报文类型 INF FUN 公共地址”。抄表时把列序当成固定模板按位置截取,必然串列。
稳妥的处理方式是按小节分别声明列名再解析,而不是写死列号:
# 不同小节列序不同,按小节显式声明列名 SECTION_COLUMNS = { "1.1 保护动作故障信号": ["name", "asdu", "inf", "fun", "com_addr"], "1.3 状态信号": ["name", "inf", "asdu", "com_addr", "fun"], "1.4 控制": ["name", "inf", "asdu", "com_addr", "fun"], } # 统一落库时把 com_addr 强制归一到文档约定的 1 row["com_addr"] = 1这段代码解决两个问题:一是列序差异,二是把行内出现的杂散数字统一收敛到公共地址 1。收敛这步建议保留,即使某天文档真改了约定,改一行常量比改几百个点划算。
3. 把点表落成可维护的数据结构:从手工抄表到脚本生成
手工把上千个点敲进组态软件,出错概率几乎是一百。真实项目里我一般分三步走:先把点表摊平成标准 CSV,再用脚本体检,最后生成组态软件能直接吃的导入文件。三步之间靠固定字段名衔接,任何一步发现问题都能回退重跑。
3.1 把八个小节摊平成同一张宽表
八个小节的字段其实能归并到同一组列:装置型号、保护对象、报文类型、FUN、INF、点名称、是否可选配、所属小节。难点在于 WHB-871 的小节用打勾表示适用对象,一个点可能同时适用五个对象中的四个,这就要做“一拆多”。
OBJ_ORDER = ["线路", "充电", "厂用变", "电容器", "电动机"] def expand_871_section(section_rows, device="WHB-871"): """把带勾选列的小节展开成一行一个 (点, 对象) 的记录""" out = [] for row in section_rows: marks = row["marks"] # 形如 [True, False, True, True, True] for obj, marked in zip(OBJ_ORDER, marks): if not marked: continue out.append({ "device": device, "obj": obj, "asdu": row["asdu"], "fun": FUN_TABLE[device][obj], "inf": int(row["inf"]), "name": row["name"], "optional": row["optional"], }) return outmarks是按表头顺序排好的布尔列表,来自人工整理或 OCR 校正后的中间文件。zip把它们和保护对象对齐,只输出打了勾的组合。WHB-871 一行五点的情况很常见,展开后点数量会膨胀几倍,这是正常的——主站本来就是按“间隔 + 点”建点的。
3.2 用脚本做一次全表体检
摊平之后立刻体检,重点看三类问题:同一(device, obj, asdu, fun, inf)重复、INF 超出装置声明范围、可选配点是否在非选配配置里被启用。
# 体检结果落文本,方便和现场配置逐条比对 python check_points.py --input whb870_points.csv \ --out report.txt \ --strict-optional三个参数的作用:--input指定摊平后的 CSV;--out把冲突和越界行写进文本报告,不带这个参数只打屏,长表刷屏会漏看;--strict-optional打开后,凡optional = TRUE而装置实际未装交流插件 2 或信号插件 2 的点会全部列出来,交付前拿这份清单跟现场核对一次,能省掉大量返工。
体检报告里最常见的一类告警是“点号跳跃”。WHB-871 某保护对象的 INF 从 54 跳到 59、再跳到 60,中间空号不是漏抄,是给未选配功能预留的。这类空号不用补,但组态软件如果按连续地址段建点会直接报错。
3.3 生成组态可导入的 CSV 与点号对照表
体检通过后生成两份产物:一份给主站组态导入,一份给现场调试用的点号对照表。前者字段名严格按组态软件的模板,后者保留中文点名称和打勾信息,方便调试时肉眼找。
| 产物 | 用途 | 关键列 |
|---|---|---|
| 组态导入 CSV | 主站建点 | 点号、点名、ASDU、FUN、INF、公共地址、点类型 |
| 点号对照表 | 现场对点 | 保护对象、INF、中文点名、可选配标记 |
| 遥测偏移表 | 遥测/电度建点 | 起始 INF、对象数、每对象宽度 |
遥测和电度有个共同特点:它们不逐点列,只给一个起始 INF,后面按固定宽度往后排。WHB-871 的遥测从 INF 92 开始,WHB-872、WHB-876 同样从 92 开始;电度脉冲从 INF 6 起,正向有功、反向有功、正向无功、反向无功依次 6、7、8、9。建点时按这个起点加序号铺开,序号错一位,后面所有遥测全串。
4. 解析 WHB-870 点表时最容易踩的五个坑
点表本身不难,难在文档里藏着几条“读起来像废话、出问题时才知道要命”的规则。下面这几条是我在不同项目里反复遇到的,每一条都对应过实际故障。
4.1 ASDU_41 在总召唤时改成 ASDU_40 上送
点表在总召唤一节写得很直白:ASDU_41的 INF 在总召唤时改成对应的ASDU_40上送。意思是同一个双点开入(合位、跳位、手跳、弹簧未储能、隔离刀位置这些),平时主动上送走ASDU_41,主站发总召唤时走ASDU_40。
主站如果只按ASDU_41建了映射表,总召回来的ASDU_40报文会全部落到未定义区。排查时表现为:装置主动变位能收到,总召后画面却不刷新。解决办法是在主站的解析表里为同一个 INF 同时注册ASDU_40和ASDU_41两个入口,指向同一个点对象。
4.2 定值区变化在总召唤时不上送
同一条说明里还有半句:定值区变化在总召唤时不上送。ASDU_1的 INF 224(定值区变化)只在定值区真正切换时主动上送一次,总召响应里不会带它。这意味着主站重启后做一次总召,定值区号是拿不到的,必须额外读一次定值区当前值,或者等下一次定值区切换。
现场最常见的误判是“主站重启后定值区显示为 0,以为装置掉了定值”。实际定值一点没丢,只是这个点不走总召通道。组态时把它标记成“事件型”而非“状态型”,画面上就不会因为它为空报警。
4.3 星号可选配项与插件差异
带星号的点全部依赖硬件插件:带星号的保护多数要求装置选配交流插件 2,带星号的开关量要求选配信号插件 2。同一型号装置,装不装插件,点号集合完全不同。更麻烦的是录波通道数也跟着变。
处理办法是把optional和插件型号做成两个字段一起进库,导点前先确定现场实际插件配置。
-- 只导出当前插件配置下真正存在的点 SELECT point_name, asdu, fun, inf FROM whb870_point WHERE device = 'WHB-871' AND obj_type = '厂用变' AND (optional = 0 OR plugin_ac2 = 1); -- plugin_ac2 表示是否装交流插件 2这份查询在交付前跑一遍,能把“装置根本没这功能、主站却建了点”的僵尸点清掉。僵尸点常年不变位,最容易在事故分析时干扰判断。
4.4 多保护对象共用一台装置时的 FUN 错配
WHB-871 一台装置可配五种保护对象,FUN 各不相同。现场改扩建时经常出现“同一个间隔从线路改成充电”的情况,装置侧改了配置,主站侧 FUN 忘了改,于是所有报文都对不上。判断方法很直接:拿装置侧实际发出的 FUN 去比对主站建点用的 FUN,不一致就是错配。
提示 改扩建后不要只对单个跳闸点,把该 FUN 下的动作、告警、状态、控制四类点各抽一条做全链路验证,四类都通才算改完。
4.5 遥控 INF 与遥信 INF 是两套编号空间
这一条在 2.3 节提过,值得单独强调。压板类对象在状态信号和状态遥信里用一套 INF,在控制(遥控)里用另一套,两套编号互不相干。WHB-871 的“低零反时限压板”遥信是 175、遥控是 65,两者相差一百多,肉眼很难发现抄错。
建库时给 ASDU 加前缀做人工分组,比如把遥控点统一命名成YK_开头,导入前再做一次“同名不同号”的交叉比对,能在交付前拦掉大部分低级错误。
5. 录波通道地址编排与主站联调验证技巧
录波是这份点表里唯一按“通道序号”,而不是按 INF 组织的部分,也是最容易被忽略、出故障时又最需要它的部分。WHB-871、872、876 的录波通道规则并不完全一致,交付前值得单独核一遍。
5.1 模拟量从 1 起排,开关量接模拟量的尾巴
三份装置的模拟量通道都从 1 开始,依次加 1。开关量的起点则取决于模拟量占了多少个通道:WHB-872 模拟量 8 个通道(Ia1、Ic1、Ia2、Ic2、3I0、Ua、Ub、Uc),开关量从 9 开始;WHB-876 同样是 8 个模拟量(Ua1、Ub1、Uc1、Ul1、Ua2、Ub2、Uc2、Ul2),开关量也从 9 开始;WHB-871 的开关量起点不是一个固定数,而是“模拟量的最后一个加 1”,因为不同保护对象的模拟量数量本身不同。
以 WHB-871 选配交流插件 2 为例,线路、充电、电容器、电动机是 7 个模拟量通道,厂用变多出 U0、Ubp,共 9 个。对应的开关量起点就分别是 8 和 10,不存在统一的“从 9 开始”。工程师站配置录波通道时,必须按装置实际保护对象去推这个起点。
5.2 选配与未选配交流插件的两套开关量基准
WHB-871 的开关量录波表给了两套:选配交流插件 2 时,线路合位从通道 8 起;未选配交流插件 2 时,模拟量只剩 Ia、Ib、Ic 三个,合位从通道 5 起。同一份点表里两套序号并存,配置时一定要先确认插件状态,再选对应那一列。
| 装置 | 插件状态 | 模拟量通道 | 开关量起始通道 |
|---|---|---|---|
| WHB-871 | 选配交流插件 2 | 7 或 9 | 8 或 10(随对象) |
| WHB-871 | 未选配交流插件 2 | 3 | 5 |
| WHB-872 | — | 8 | 9 |
| WHB-876 | — | 8 | 9 |
通道序号错位不会导致通信中断,只会让录波波形张冠李戴:本该显示 A 相电流的通道里出现零序电压。事故分析时如果先入为主地相信通道标签,结论会完全跑偏。
5.3 用总召唤加定值区切换做一次闭环验证
点表交付前,我一般用三个动作做闭环:先发总召唤,验证所有ASDU_1和转换后的ASDU_40点位能正确刷新;再手动切一次定值区,验证 INF 224 主动上送且总召里不出现;最后投退一块压板,验证遥控 INF 下发的对象和遥信 INF 回读的对象是同一个。
# 用装置调试口抓一段报文,确认总召与定值区事件都在预期通道上 python i103_trace.py --port /dev/ttyUSB0 --baud 9600 \ --filter "ASDU_1,ASDU_40,ASDU_41" \ --save trace.log--filter只保留关心的报文类型,避免总召期间刷屏;--save把原始报文落盘,事后可以拿点位表逐条比对。三个动作跑完,点表里 90% 的坑都会在交付前暴露出来。剩下那 10%,多数藏在可选配点和录波通道序号的边界上,只能靠现场核对。
本文还有配套的精品资源,点击获取