我使用msterSCADA4D,我创建了一个屏幕,该怎么往屏幕里添加饼状图,并与每扇绑定标签并实现动...

Créé le : 9 avril 2026

Répondu en utilisant GPT-5.4 Thinking par Chat01

Question

我使用msterSCADA4D,我创建了一个屏幕,该怎么往屏幕里添加饼状图,并与每扇绑定标签并实现动态显示?

Réflexion

undefined

Réflexion

Thought for 9s

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 27s

Réflexion

Thought for 33s

Réflexion

Thought for 37s

Réflexion

Thought for 43s

Réflexion

Thought for 59s

Réflexion

Thought for 1m 5s

Réflexion

Thought for 1m 14s

Réflexion

Thought for 2m 24s

Réponse

如果你说的是 MasterSCADA 4D,最稳妥的做法是:** 用 SVG 画饼图,再用 XML 把每个扇区和文字暴露成可绑定参数,最后把这些参数和标签连起来**。官方在线帮助明确支持把外部 SVG+XML 导入到窗口里,并把 SVG 的属性、文字内容等做成可动态绑定的参数。窗口本身是在“图形界面/窗口”里创建的,创建后会自动打开图形编辑器。(support.mps-soft.ru)

你可以按这个顺序做:

  1. 先准备标签
    比如你有 4 个扇区,就准备 4 个数值标签:Tag_ATag_BTag_CTag_D。如果还要显示百分比/名称,再准备对应文本或中间变量。MasterSCADA 4D 支持在图形客户端层做这类逻辑和辅助脚本,因此“先算比例,再喂给画面”这条路是可行的。(support.mps-soft.ru)

  2. 用 SVG 画一个饼图底图
    建议在 Figma / Inkscape / Illustrator 里画。官方要求 SVG 用外部编辑器制作;所有元素放在根组 g 下,根组要有 id="root";每个需要动态改动的元素都要有有意义的唯一 id。所以你的饼图最好这样命名:
    slice_1slice_2slice_3slice_4,文字则用 label_1label_2…… 这样导入时更稳定。(support.mps-soft.ru)

  3. 给 SVG 写同名 XML 描述文件
    官方要求 XML 文件和 SVG 同名、同目录。XML 的作用就是告诉 MasterSCADA:哪个 SVG 元素可以被外部控制、控制的是哪个属性、类型是什么。官方给出的结构是 <SvgDef><ParameterDefs><ParameterDef ... /></ParameterDefs></SvgDef>,其中:

  • ItemId 对应 SVG 元素 id
  • Path 对应要改的属性,比如 fillwidthclass,如果改文字内容就写 content
  • ParamType="attribute" 表示改元素属性,ParamType="style" 表示改样式
  • Type 常见有 STRINGHMI.SolidColorType。(support.mps-soft.ru)

可以先从这个 XML 模板起步:

xml
<?xml version="1.0"?> <SvgDef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ParameterDefs> <!-- 扇区1 --> <ParameterDef DisplayName="扇区1颜色" ParamType="attribute" ItemId="slice_1" Path="fill" Type="HMI.SolidColorType" /> <ParameterDef DisplayName="扇区1文字" ParamType="attribute" ItemId="label_1" Path="content" Type="STRING" /> <!-- 扇区2 --> <ParameterDef DisplayName="扇区2颜色" ParamType="attribute" ItemId="slice_2" Path="fill" Type="HMI.SolidColorType" /> <ParameterDef DisplayName="扇区2文字" ParamType="attribute" ItemId="label_2" Path="content" Type="STRING" /> <!-- 如果你还想显隐 --> <ParameterDef DisplayName="扇区1透明度" ParamType="attribute" ItemId="slice_1" Path="opacity" Type="STRING" /> </ParameterDefs> </SvgDef>

上面这种“颜色 + 文字 + 透明度”的绑定方式,和官方文档描述的参数化机制是完全一致的。(support.mps-soft.ru)

  1. 把 SVG 导入你已经建好的窗口
    在库里新建窗口后,右键窗口执行 Import SVG。官方说明里写得很清楚:选择 SVG 后,如果同目录下有对应 XML,会一起导入;导入完成后,这些参数会出现在属性里,并且可以和项目参数建立连接。(support.mps-soft.ru)

  2. 把导入好的 SVG 放进你的屏幕,并绑定标签
    导入后,SVG 会变成一个可配置的图形元素。官方示例里是把滑块的“当前值”拖到 SVG 的属性上进行绑定;同理,你可以把项目里的标签值绑定到 扇区1颜色扇区1文字扇区1透明度 这些属性上。官方也说明,导入后的 SVG 属性可以“与项目参数关联,以便在运行时变化”。(support.mps-soft.ru)


你要的“每扇绑定标签并动态显示”,有两种做法

做法 A:固定扇区大小,只让颜色/文字/显隐动态

这是最简单、最稳的。
比如 4 个扇区先在 SVG 里画成固定 25% + 25% + 25% + 25%,运行时只改:

  • fill:颜色随标签变化
  • content:显示实时值或百分比
  • opacity:某扇区无数据时设为 0,有数据时设为 1

这个方案完全不需要你去动态改几何形状,落地最快。它完全符合官方的 SVG/XML 动态属性机制。(support.mps-soft.ru)

做法 B:扇区角度跟数值一起变化,做“真正的动态饼图”

这个方案也能做,但需要你先在程序里算出每个扇区的角度,再把结果映射到 SVG。官方文档明确支持通过 XML 去改 SVG 元素属性;因此,按这个机制推断,你可以把每个扇区的 path d 当成字符串属性去更新,或者像官方“圆形进度条”示例那样,去动态改 stroke-dashoffset 之类的属性。官方示例已经证明:SVG 属性和值可以动态绑定,并且必要时可通过“线性分段转换”把源值映射成图形值。这里把 d 作为可绑定属性是基于官方属性参数化机制的推断,不是我在文档里看到的现成饼图案例。(support.mps-soft.ru)

你可以在 ST/FBD 里先这样算:

pascal
Total := Tag_A + Tag_B + Tag_C + Tag_D; IF Total > 0 THEN P1 := Tag_A / Total * 360.0; P2 := Tag_B / Total * 360.0; P3 := Tag_C / Total * 360.0; P4 := Tag_D / Total * 360.0; ELSE P1 := 0; P2 := 0; P3 := 0; P4 := 0; END_IF;

然后再算累计角度:

pascal
A1_Start := 0.0; A1_End := P1; A2_Start := A1_End; A2_End := A2_Start + P2; A3_Start := A2_End; A3_End := A3_Start + P3; A4_Start := A3_End; A4_End := 360.0;

最后把每个扇区转成 SVG path 字符串,输出到中间变量,比如:

pascal
Slice1_Path := SectorPath(50.0, 50.0, 40.0, A1_Start, A1_End); Slice2_Path := SectorPath(50.0, 50.0, 40.0, A2_Start, A2_End); ... Label1_Text := CONCAT('A ', REAL_TO_STRING(Tag_A));

然后在 XML 里把 slice_1dlabel_1content 暴露出来绑定。这里 content 是官方明确支持的,d 属于按“属性可参数化”机制做的工程实现。(support.mps-soft.ru)


一个更实用的建议

如果你现在是第一次做,先别直接上“真动态饼图”。建议你先做这个版本:

  • 4 个固定扇区
  • 每个扇区绑定一个标签
  • 文字显示实时值/百分比
  • 颜色根据阈值变化
  • 需要隐藏时改 opacity

等这个版本跑通,再升级成动态角度版本。这样排错最少。官方示例里“圆形进度条 + 文本”也是先把 SVG 元素 id、属性、文字内容暴露出来,再做绑定和转换,思路和这里完全一致。(support.mps-soft.ru)

如果你愿意,我下一条可以直接给你一份 “4 扇区饼图的完整 SVG + XML 示例”,你复制到 MasterSCADA 4D 里就能开始绑标签。

Question

<svg width="500" height="400" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg">

<!-- 背景 --> <rect x="0" y="0" width="500" height="400" fill="#dcdcdc"/> <!-- 标题 -->

<text x="250" y="40" font-size="24" font-weight="bold" text-anchor="middle" fill="#333">
Сравнение годных и чёрных фишек
</text>

<!-- 饼图 --> <g transform="translate(180,220)">
text
<!-- 良品(动态) --> <path id="sliceGood" d="M 0,0 L 0,-150 A 150,150 0 1,1 -150,0 Z" fill="#6ec35a" stroke="white" stroke-width="2"/> <!-- 不良品(动态) --> <path id="sliceBad" d="M 0,0 L -150,0 A 150,150 0 0,1 0,-150 Z" fill="#e04b36" stroke="white" stroke-width="2"/>
</g> <!-- 图例 --> <g transform="translate(320, 60)">
text
<rect x="0" y="0" width="16" height="16" fill="#6ec35a" rx="2" /> <text x="24" y="12" font-size="16" fill="#333"> Годные </text> <rect x="0" y="30" width="16" height="16" fill="#e04b36" rx="2" /> <text x="24" y="42" font-size="16" fill="#333"> Чёрные </text>
</g> </svg> 这是我的svg代码,为我写出对应的xml,要符合要求,而且我需要扇区角度跟数值一起变化,做“真正的动态饼图”,变更其余步骤详细的一步步的说明以及我应该怎么做?

Réflexion

undefined

Réflexion

Thought for 9s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 33s

Réflexion

undefined

Réflexion

undefined

Réflexion

Crafting final version with SVG tips

I need to explain that using full circles and normal wedges requires a d command structure change that prevents smooth interpolation. W3C confirms smooth interpolation only happens with the same command structure, so I’ll mention this. Also, the d numbers must use a decimal dot, not a comma — another important W3C point.

For the SVG, I’ll suggest something like:

svg
<svg ...> <g id="root"> ... </g> </svg>

And I’ll optionally note adding IDs for dynamic legend text.

Thought for 4m 59s

Réponse

可以,这个能做成真正的动态饼图。关键点有 4 个:

  1. 你的 SVG 里要把所有元素包进一个根组 <g id="root">
  2. XML 里要把两个扇区的 <path>d 属性暴露出来,因为 MasterSCADA 4D 官方就支持把 pathd 作为可绑定参数。
  3. 角度不要在“连接转换器”里硬凑,最好在 ST 程序里先算出每个扇区的 d 字符串,再直接绑定到 SVG 属性。
  4. 如果还想动态改文字,就给 <text> 元素加 id,XML 里用 Path="content"。MasterSCADA 4D 官方文档就是这么做的。 (MPS Soft Support)

先说一个必须改的地方:你现在这份 SVG 没有根组 g id="root",而官方对可动态 SVG 的通用要求里明确写了,所有图元应放在根组里,根组要有 Id="root";同一控件里需要外部访问的元素也要有清晰的 id。(MPS Soft Support)


1)先把你的 SVG 改成这个版本

下面是尽量少改动、但已经符合导入要求的版本。
我只做了 3 件事:

  • 外面加了 <g id="root">
  • 给饼图组和图例组补了 id,后面排错更方便
  • 给图例文字补了 id,方便你以后做动态文字
svg
<svg width="500" height="400" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg"> <g id="root"> <!-- 背景 --> <rect id="bgRect" x="0" y="0" width="500" height="400" fill="#dcdcdc"/> <!-- 标题 --> <text id="titleText" x="250" y="40" font-size="24" font-weight="bold" text-anchor="middle" fill="#333"> Сравнение годных и чёрных фишек </text> <!-- 饼图 --> <g id="pieGroup" transform="translate(180,220)"> <!-- 良品(动态) --> <path id="sliceGood" d="M 0,0 L 0,-150 A 150,150 0 1,1 -150,0 Z" fill="#6ec35a" stroke="white" stroke-width="2"/> <!-- 不良品(动态) --> <path id="sliceBad" d="M 0,0 L -150,0 A 150,150 0 0,1 0,-150 Z" fill="#e04b36" stroke="white" stroke-width="2"/> </g> <!-- 图例 --> <g id="legendGroup" transform="translate(320, 60)"> <rect id="legendGoodColor" x="0" y="0" width="16" height="16" fill="#6ec35a" rx="2" /> <text id="legendGoodText" x="24" y="12" font-size="16" fill="#333"> Годные </text> <rect id="legendBadColor" x="0" y="30" width="16" height="16" fill="#e04b36" rx="2" /> <text id="legendBadText" x="24" y="42" font-size="16" fill="#333"> Чёрные </text> </g> </g> </svg>

2)这份 SVG 对应的 XML

把下面内容保存成和 SVG 同名的 XML 文件,并且和 SVG 放在同一文件夹
例如:

  • chips_pie.svg
  • chips_pie.xml

MasterSCADA 4D 官方要求 XML 与 SVG 同名、同目录;XML 根结构就是 <SvgDef><ParameterDefs>...</ParameterDefs></SvgDef>,每个参数用 ParameterDef 描述。(MPS Soft Support)

xml
<?xml version="1.0"?> <SvgDef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ParameterDefs> <!-- 两个扇区的几何形状:真正动态饼图的核心 --> <ParameterDef DisplayName="GoodPath" ParamType="attribute" ItemId="sliceGood" Path="d" Type="STRING" /> <ParameterDef DisplayName="BadPath" ParamType="attribute" ItemId="sliceBad" Path="d" Type="STRING" /> <!-- 两个扇区的颜色 --> <ParameterDef DisplayName="GoodFill" ParamType="attribute" ItemId="sliceGood" Path="fill" Type="HMI.SolidColorType" /> <ParameterDef DisplayName="BadFill" ParamType="attribute" ItemId="sliceBad" Path="fill" Type="HMI.SolidColorType" /> <!-- 可选:0 或 1,用来在 0% / 100% 时隐藏某个扇区 --> <ParameterDef DisplayName="GoodOpacity" ParamType="attribute" ItemId="sliceGood" Path="opacity" Type="STRING" /> <ParameterDef DisplayName="BadOpacity" ParamType="attribute" ItemId="sliceBad" Path="opacity" Type="STRING" /> <!-- 可选:如果你想让图例颜色也跟着变 --> <ParameterDef DisplayName="LegendGoodFill" ParamType="attribute" ItemId="legendGoodColor" Path="fill" Type="HMI.SolidColorType" /> <ParameterDef DisplayName="LegendBadFill" ParamType="attribute" ItemId="legendBadColor" Path="fill" Type="HMI.SolidColorType" /> <!-- 可选:如果你想让图例文字也动态 --> <ParameterDef DisplayName="LegendGoodContent" ParamType="attribute" ItemId="legendGoodText" Path="content" Type="STRING" /> <ParameterDef DisplayName="LegendBadContent" ParamType="attribute" ItemId="legendBadText" Path="content" Type="STRING" /> </ParameterDefs> </SvgDef>

这里最关键的就是:

  • ItemId="sliceGood" Path="d"
  • ItemId="sliceBad" Path="d"

因为官方示例已经明确给过:path 元素的 d 可以在导入时作为参数暴露出来;同样,content 是用来动态改 <text>...</text> 里面文本内容的特殊路径。(MPS Soft Support)


3)真正动态饼图的做法

你的图只有两扇,所以实现其实很直接:

  • 良品值:GoodValue
  • 不良值:BadValue
  • 总和:Total = GoodValue + BadValue
  • 良品角度:GoodDeg = 360 * GoodValue / Total
  • 不良角度:BadDeg = 360 - GoodDeg

然后把这两个角度换成 SVG 的 path d 字符串。

你当前饼图的圆心在 translate(180,220) 后的局部坐标 (0,0),半径是 150,起点是正上方 (0,-150)
所以两扇区的路径都可以按这个逻辑生成:

  • 良品扇区:从上方开始,顺时针走 GoodDeg
  • 不良扇区:从良品终点开始,顺时针回到上方

SVG 标准里,d 就是 path 的路径字符串;里面用 M / L / A / Z 这些命令描述几何。(W3C)


4)你在工程里应该建哪些标签

建议你建这些标签:

外部原始标签

  • GoodValue
  • BadValue

内部计算标签

  • GoodPath —— STRING
  • BadPath —— STRING
  • GoodOpacity —— STRING
  • BadOpacity —— STRING
  • GoodFill —— 颜色
  • BadFill —— 颜色
  • LegendGoodText —— STRING
  • LegendBadText —— STRING

MasterSCADA 4D 支持在对象、节点、通道、标签、窗口等元素上挂程序,并在图形客户端层做逻辑和辅助脚本,所以这种“先计算,再绑定到 SVG 属性”的方法是对路的。(MPS Soft Support)


5)核心计算逻辑

下面给你的是两扇区专用算法,比通用多扇区更简单。

数学部分

半径固定:

text
R = 150

良品扇区终点角度:

text
EndDeg = -90 + GoodDeg

终点坐标:

text
EndX = R * COS(EndDeg * PI / 180) EndY = R * SIN(EndDeg * PI / 180)

大弧标志:

text
LargeGood = 1, 当 GoodDeg > 180 LargeGood = 0, 当 GoodDeg <= 180 LargeBad = 1, 当 BadDeg > 180 LargeBad = 0, 当 BadDeg <= 180

路径字符串

良品扇区:

text
M 0,0 L 0,-150 A 150,150 0 LargeGood,1 EndX,EndY Z

不良扇区:

text
M 0,0 L EndX,EndY A 150,150 0 LargeBad,1 0,-150 Z

6)你可以直接照着写的 ST 逻辑

下面我写成接近可直接抄的 ST 伪代码
不同版本里字符串拼接、字符串替换函数名可能略有差别,所以你只需要把 CONCAT / REAL_TO_STRING / “逗号替换点号”的函数名按你工程里现成函数改一下就行。

主逻辑

pascal
(* 输入 *) (* GoodValue : REAL *) (* BadValue : REAL *) (* 输出 *) (* GoodPath : STRING *) (* BadPath : STRING *) (* GoodOpacity : STRING *) (* BadOpacity : STRING *) (* LegendGoodText: STRING *) (* LegendBadText : STRING *) VAR Total : REAL; GoodDeg : REAL; BadDeg : REAL; EndDeg : REAL; EndRad : REAL; EndX : REAL; EndY : REAL; LargeGood : STRING; LargeBad : STRING; END_VAR Total := GoodValue + BadValue; IF Total <= 0.0 THEN GoodPath := 'M 0,0 Z'; BadPath := 'M 0,0 Z'; GoodOpacity := '0'; BadOpacity := '0'; ELSE GoodDeg := 360.0 * GoodValue / Total; BadDeg := 360.0 - GoodDeg; LegendGoodText := CONCAT('Годные: ', REAL_TO_STRING(GoodValue)); LegendBadText := CONCAT('Чёрные: ', REAL_TO_STRING(BadValue)); (* 0% / 100% 特殊处理 *) IF GoodDeg <= 0.001 THEN GoodPath := 'M 0,0 Z'; BadPath := 'M 0,0 L 0,-150 A 150,150 0 1,1 0,150 A 150,150 0 1,1 0,-150 Z'; GoodOpacity := '0'; BadOpacity := '1'; ELSIF GoodDeg >= 359.999 THEN GoodPath := 'M 0,0 L 0,-150 A 150,150 0 1,1 0,150 A 150,150 0 1,1 0,-150 Z'; BadPath := 'M 0,0 Z'; GoodOpacity := '1'; BadOpacity := '0'; ELSE GoodOpacity := '1'; BadOpacity := '1'; EndDeg := -90.0 + GoodDeg; EndRad := EndDeg * 3.1415926 / 180.0; EndX := 150.0 * COS(EndRad); EndY := 150.0 * SIN(EndRad); IF GoodDeg > 180.0 THEN LargeGood := '1'; ELSE LargeGood := '0'; END_IF; IF BadDeg > 180.0 THEN LargeBad := '1'; ELSE LargeBad := '0'; END_IF; GoodPath := CONCAT( CONCAT( CONCAT( CONCAT( CONCAT( CONCAT( 'M 0,0 L 0,-150 A 150,150 0 ', LargeGood ), ',1 ' ), SvgNum(EndX) ), ',' ), SvgNum(EndY) ), ' Z' ); BadPath := CONCAT( CONCAT( CONCAT( CONCAT( CONCAT( CONCAT( CONCAT( 'M 0,0 L ', SvgNum(EndX) ), ',' ), SvgNum(EndY) ), ' A 150,150 0 ' ), LargeBad ), ',1 0,-150' ), ' Z' ); END_IF; END_IF;

数字转 SVG 字符串的辅助函数

SVG 的路径数字一定要用点号小数点,不能用区域设置里的逗号。W3C 的 SVG Paths 规范明确写了,路径数据里允许的 decimal point 是 .,并举例说明像 13,000.56 这样的写法是无效的。(W3C)

所以你还要做一个辅助函数,把 REAL_TO_STRING() 结果中的逗号换成点:

pascal
FUNCTION SvgNum : STRING VAR_INPUT Value : REAL; END_VAR VAR s : STRING; END_VAR s := REAL_TO_STRING(Value); (* 这里把逗号替换成点号。 具体替换函数名按你的版本来写。 *) (* 例如:s := ReplaceCommaToDot(s); *) SvgNum := s; END_FUNCTION

这里我故意没把“替换函数名”写死,因为不同版本、不同库里字符串替换函数名可能不一样;但逻辑就是这一句:, 换成 .


7)导入和绑定,按这个顺序做

第一步:保存文件

把改好的 SVG 和 XML 放在同一目录,同名。
例如:

  • chips_pie.svg
  • chips_pie.xml

官方导入说明就是这么要求的。(MPS Soft Support)

第二步:在库里新建一个窗口,并导入 SVG

库 / 窗口 里新建一个窗口,然后右键这个窗口,执行 “导入 SVG”。官方示例和导入文档都是这条路径。(MPS Soft Support)

第三步:确认属性已经出来

导入成功后,在属性面板里你应该能看到:

  • GoodPath
  • BadPath
  • GoodFill
  • BadFill
  • GoodOpacity
  • BadOpacity
  • 以及可选的图例文字/颜色属性

官方示例里,导入后会在属性面板里出现对应的 SVG 属性。(MPS Soft Support)

第四步:把这个 SVG 控件拖进你的屏幕

官方 Path 示例的做法也是:先做成一个 SVG 窗口,再把它拖到另一个窗口/画面里使用。(MPS Soft Support)

第五步:创建输入标签和计算标签

至少先建:

  • GoodValue
  • BadValue
  • GoodPath
  • BadPath

如果你要颜色和显隐,再建:

  • GoodFill
  • BadFill
  • GoodOpacity
  • BadOpacity

如果要动态图例,再建:

  • LegendGoodText
  • LegendBadText

第六步:给窗口或对象挂 ST 程序

MasterSCADA 4D 支持在窗口等图形层元素上挂 IEC 61131-3 程序。把上面的逻辑写进去,让它持续根据 GoodValue / BadValue 计算路径字符串。(MPS Soft Support)

第七步:把程序输出绑定到 SVG 属性

直接绑定:

  • GoodPath → SVG 的 GoodPath
  • BadPath → SVG 的 BadPath
  • GoodFill → SVG 的 GoodFill
  • BadFill → SVG 的 BadFill
  • GoodOpacity → SVG 的 GoodOpacity
  • BadOpacity → SVG 的 BadOpacity

如果你还做了图例文字:

  • LegendGoodTextLegendGoodContent
  • LegendBadTextLegendBadContent

这里我建议你直接绑定字符串结果,不要走“点式转换”去枚举角度,因为真实饼图是连续变化的,点式转换只适合有限离散状态。官方的 Path 示例里是把路径字符串作为目标值来驱动 d 的。(MPS Soft Support)

第八步:在线测试

先用一组你能手算的值做验证,比如:

  • GoodValue = 75
  • BadValue = 25

这时:

  • GoodDeg = 270
  • 良品终点坐标应是 (-150,0)

所以你会得到:

text
GoodPath = M 0,0 L 0,-150 A 150,150 0 1,1 -150,0 Z BadPath = M 0,0 L -150,0 A 150,150 0 0,1 0,-150 Z

这和你现在 SVG 里那组静态形状正好是一致的。
如果这一步对上了,说明你的公式、弧标志和顺时针方向都没错。


8)几个最容易踩的坑

坑 1:没加 g id="root"

这会让 SVG 不符合官方动态化要求。(MPS Soft Support)

坑 2:REAL_TO_STRING 输出逗号小数

如果字符串里出现 -106,07 这种形式,SVG 的 d 解析很容易出错;路径数字要用 .。(W3C)

坑 3:0% 和 100% 不能当普通扇区算

完整圆不能只靠一条普通 A 弧线从起点绕一圈回自己,所以我在上面的逻辑里给了“两个半圆弧拼成整圆”的特殊写法。

坑 4:想做“平滑补间动画”

W3C 对 d 的说明是:只有当两次路径字符串的命令结构完全一致时,才能平滑插值;如果命令结构不同,就会离散跳变。也就是说,普通扇区之间可以尝试做平滑,但从“空扇区/整圆”切到普通扇区时,很可能是跳变。(W3C)


9)你现在最省事的落地顺序

按这个顺序做,成功率最高:

  1. 先把 SVG 改成我上面那版。
  2. 用我给你的 XML 导入。
  3. 先只绑定 GoodPath / BadPath,别急着做文字。
  4. 先用固定测试值 75/25、50/50、0/100、100/0 四组验证。
  5. 验证几何正确后,再加 LegendGoodContent / LegendBadContent
  6. 最后再加颜色和透明度。

如果你愿意,我下一条可以直接继续给你一份 “可直接粘贴的完整 ST 程序版本”,我把字符串拼接也按更接近 MasterSCADA 风格给你展开。

Question

image.png
image.png

我导入后,这是属性,以及我创建了st,我应该在st上面写什么,将完整代码给我,并详细告知我绑定标签的步骤,以及各种细节

Réflexion

undefined

Réflexion

Thought for 13s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 21s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 26s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 37s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 2m 38s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 2m 43s

Réflexion

undefined

Réflexion

undefined

Réflexion

Clarifying STRING length and path handling

If your IEC version allows it, increase the STRING length for GoodPath and BadPath to at least 120 characters to avoid truncation. If length can't be modified, the default should still suffice. Also, remember to verify with compile and online tests. For path icons, direct path binding is used, bypassing the converter. For screen editing, select instances and open Properties for further binding checks.

Clarifying binding process and program task properties

To avoid confusion:

  • If the pie chart is a standalone window, bind directly on that window.
  • If it's part of a page, bind to the pie_chart instance on the page.

Additionally, for task properties in the ST program: execution should be set to the parent object task with the default periodic execution method. For simplicity, keep the default setting. Special cases may arise with SVG arc syntax in full circle paths.

Thought for 6m 38s

Réponse

你现在这一步已经对了:导入后能看到 GoodPath / BadPath,说明 XML 已经把两个 <path>d 属性成功暴露成可绑定参数了;MasterSCADA 4D 官方的 Path 示例也是通过给 <path>id,再把属性 d 作为 SVG 参数导入来做动态图形。你把 ST 程序建在对象下面也没问题,MasterSCADA 4D 支持在对象、窗口等层级添加 IEC 61131-3 程序。(MPS Soft Support)

先注意一条很关键的规则:需要外部绑定的量,不要只在 ST 代码里声明。官方说明里写了,程序里有“参数”组用于和外部元素建立连接,而只在 ST 文本里声明的变量不能建立连接。所以 GoodValue / BadValue / GoodPath / BadPath ... 这些要在程序的输入输出端子里建成“参数”;代码里的 TotalR / EndDeg / EndXi 之类才放在 VAR ... END_VAR 里当局部变量。(MPS Soft Support)


1)先在 ST 程序里建这些参数

ST_program_1 里,用左右两侧的输入/输出端子创建参数,不要只写在代码里。ST 编辑器本身就有输入/输出端子,程序参数会出现在程序的“参数”组里,方便外部绑定。(MPS Soft Support)

输入参数

  • GoodValue : DINT
  • BadValue : DINT

输出参数

  • GoodPath : STRING
  • BadPath : STRING
  • GoodOpacity : STRING
  • BadOpacity : STRING
  • LegendGoodContent : STRING
  • LegendBadContent : STRING

先别绑 GoodFill / BadFill / LegendGoodFill / LegendBadFill
第一轮先把“扇区角度动态变化”跑通,颜色先用 SVG 里原本的绿色和红色。


2)把这段代码完整贴进 ST

注意:只粘贴程序体,不要自己再写 PROGRAM ... END_PROGRAM。官方说明里说,ST 编辑器里写的是程序体,输入输出参数靠端子定义。(MPS Soft Support)

pascal
VAR GoodR : REAL; BadR : REAL; TotalR : REAL; GoodDeg : REAL; BadDeg : REAL; EndDeg : REAL; EndRad : REAL; EndXr : REAL; EndYr : REAL; EndXi : INT; EndYi : INT; GoodPct : INT; BadPct : INT; LargeGood : STRING; LargeBad : STRING; SX : STRING; SY : STRING; T1 : STRING; T2 : STRING; END_VAR (* 1. 输入值转 REAL,便于后续三角函数计算 *) GoodR := DINT_TO_REAL(GoodValue); BadR := DINT_TO_REAL(BadValue); TotalR := GoodR + BadR; (* 2. 无数据时隐藏整个饼图 *) IF TotalR <= 0.0 THEN GoodPath := 'M 0,0 Z'; BadPath := 'M 0,0 Z'; GoodOpacity := '0'; BadOpacity := '0'; LegendGoodContent := CONCAT('Годные: ', DINT_TO_STRING(GoodValue)); LegendBadContent := CONCAT('Чёрные: ', DINT_TO_STRING(BadValue)); ELSE (* 3. 计算角度 *) GoodDeg := GoodR * 360.0 / TotalR; IF GoodDeg < 0.0 THEN GoodDeg := 0.0; END_IF; IF GoodDeg > 360.0 THEN GoodDeg := 360.0; END_IF; BadDeg := 360.0 - GoodDeg; (* 4. 计算百分比文字 *) GoodPct := REAL_TO_INT(GoodR * 100.0 / TotalR); IF GoodPct < 0 THEN GoodPct := 0; END_IF; IF GoodPct > 100 THEN GoodPct := 100; END_IF; BadPct := 100 - GoodPct; T1 := CONCAT('Годные: ', DINT_TO_STRING(GoodValue)); T1 := CONCAT(T1, ' ('); T1 := CONCAT(T1, INT_TO_STRING(GoodPct)); T1 := CONCAT(T1, '%)'); LegendGoodContent := T1; T2 := CONCAT('Чёрные: ', DINT_TO_STRING(BadValue)); T2 := CONCAT(T2, ' ('); T2 := CONCAT(T2, INT_TO_STRING(BadPct)); T2 := CONCAT(T2, '%)'); LegendBadContent := T2; (* 5. 特殊情况:0% *) IF GoodDeg <= 0.001 THEN GoodPath := 'M 0,0 Z'; BadPath := 'M 0,0 L 0,-150 A 150,150 0 1,1 0,150 A 150,150 0 1,1 0,-150 Z'; GoodOpacity := '0'; BadOpacity := '1'; (* 6. 特殊情况:100% *) ELSIF GoodDeg >= 359.999 THEN GoodPath := 'M 0,0 L 0,-150 A 150,150 0 1,1 0,150 A 150,150 0 1,1 0,-150 Z'; BadPath := 'M 0,0 Z'; GoodOpacity := '1'; BadOpacity := '0'; (* 7. 正常情况:0% ~ 100% 之间 *) ELSE GoodOpacity := '1'; BadOpacity := '1'; (* 起点固定在圆顶点 (0,-150),终点按角度计算 *) EndDeg := -90.0 + GoodDeg; EndRad := EndDeg * 3.1415926 / 180.0; EndXr := 150.0 * COS(EndRad); EndYr := 150.0 * SIN(EndRad); (* 转整数,避免 SVG 路径里出现小数格式问题 *) EndXi := REAL_TO_INT(EndXr); EndYi := REAL_TO_INT(EndYr); SX := INT_TO_STRING(EndXi); SY := INT_TO_STRING(EndYi); (* 大弧标志 *) IF GoodDeg > 180.0 THEN LargeGood := '1'; ELSE LargeGood := '0'; END_IF; IF BadDeg > 180.0 THEN LargeBad := '1'; ELSE LargeBad := '0'; END_IF; (* 良品扇区路径 *) GoodPath := 'M 0,0 L 0,-150 A 150,150 0 '; GoodPath := CONCAT(GoodPath, LargeGood); GoodPath := CONCAT(GoodPath, ',1 '); GoodPath := CONCAT(GoodPath, SX); GoodPath := CONCAT(GoodPath, ','); GoodPath := CONCAT(GoodPath, SY); GoodPath := CONCAT(GoodPath, ' Z'); (* 不良品扇区路径 *) BadPath := 'M 0,0 L '; BadPath := CONCAT(BadPath, SX); BadPath := CONCAT(BadPath, ','); BadPath := CONCAT(BadPath, SY); BadPath := CONCAT(BadPath, ' A 150,150 0 '); BadPath := CONCAT(BadPath, LargeBad); BadPath := CONCAT(BadPath, ',1 0,-150 Z'); END_IF; END_IF;

这段代码的核心就是动态生成 SVG 的 d 字符串。W3C 对 SVG 路径弧线命令 A 的定义里说明了:large-arc-flag 决定走大弧还是小弧,sweep-flag=1 代表按正角方向扫过去;所以代码里 GoodDeg > 180 时把大弧标志设成 1。(W3C)


3)程序属性怎么设

你的 ST_program_1 在对象下,最省事的设置是:

  • 执行位置:父对象任务
  • 执行方式:周期性

官方文档里这两个就是程序“任务”类别里的关键属性;程序可以运行在父对象任务里,也可以跑在屏幕任务里,但你现在这个场景先用“父对象任务 + 周期性”最稳。官方也说明了,不同任务之间的参数连接是支持双向同步的。(MPS Soft Support)


4)绑定顺序:一定按这个方向绑

你现在的逻辑链应该是:

PLC/内部标签 -> ST程序输入 -> ST程序输出 -> pie_chart控件参数

不要反过来。

第一步:把真实标签绑到 ST 输入

假设你的真实标签叫:

  • Tag_Good
  • Tag_Bad

那么把:

  • Tag_Good 绑定到 ST_program_1.GoodValue
  • Tag_Bad 绑定到 ST_program_1.BadValue

这里用直接连接,不要加转换器。
因为程序自己已经负责算比例和生成路径字符串了。

第二步:把 ST 输出绑到 pie_chart 的 SVG 参数

再把:

  • ST_program_1.GoodPathpie_chart.GoodPath
  • ST_program_1.BadPathpie_chart.BadPath
  • ST_program_1.GoodOpacitypie_chart.GoodOpacity
  • ST_program_1.BadOpacitypie_chart.BadOpacity
  • ST_program_1.LegendGoodContentpie_chart.LegendGoodContent
  • ST_program_1.LegendBadContentpie_chart.LegendBadContent

这里也用直接连接,不要开“点式转换”。
官方 Path 示例里,d 参数本来就是给路径字符串用的;只是官方示例用下拉框 + 转换器去切换离散图标,而你这里已经在 ST 里直接算好了最终字符串,所以不需要再做一次转换。(MPS Soft Support)


5)你应该在哪个地方绑定

这里分两种情况:

情况 A:你把 pie_chart 直接当成一个独立窗口用

那就直接在这个窗口本体上绑。

情况 B:你把资源窗口 pie_chart 拖进了另一个画面 123

那就应该在 123 这个画面里,选中 pie_chart 实例 后再绑。
也就是说,绑的是实例参数,不是资源定义本身。

你截图里 Resources -> Windows -> pie_chart 说明它现在是一个资源窗口。真正运行时若它被拖进 123,建议在 123 里选中该实例后再做连接,这样最不容易搞混。


6)第一次调试时,只测 4 组值

先别一上来接 PLC。
先手工给输入值,测这 4 组:

  • GoodValue = 75, BadValue = 25
  • GoodValue = 50, BadValue = 50
  • GoodValue = 0, BadValue = 100
  • GoodValue = 100, BadValue = 0

其中第一组最关键。
75 / 25 时良品应占 270°,终点正好接近 (-150, 0),这时路径应接近你现在静态示例里的那组字符串。
如果这组对了,说明你的角度、终点坐标和弧方向都对了。弧线的四种组合以及 large-arc-flag / sweep-flag 的含义,W3C 路径规范里有明确定义。(W3C)


7)最容易出错的 6 个点

1. 把输入输出写在代码里,没在端子里建参数

这样外部没法绑。官方明确说,代码里声明的变量不能建立连接。(MPS Soft Support)

2. 给 GoodPath/BadPath 加了转换器

不要加。ST 已经输出最终 d 字符串了。

3. 绑定错层级

如果 pie_chart 是被拖进 123 的,就在 123 里选实例再绑。

4. 程序没运行

检查 ST_program_1 的任务设置是不是“周期性”。

5. 文字不变

这通常是 legendGoodText / legendBadTextid 或 XML 里的 Path="content" 不一致。XML 必须严格对应 SVG 里的元素 id 和属性。(MPS Soft Support)

6. 改了 SVG / XML 但界面还是旧的

官方导入说明里写了:如果 SVG 已经加过,再选对应 XML 可以更新描述。也就是说你改过 SVG 或 XML 后,通常要重新导入或更新 XML 描述。(MPS Soft Support)


8)建议你现在就这么做

先只接 6 个输出:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

先把饼图“转起来”。
等这个跑通了,再决定要不要第二步加:

  • 动态颜色
  • 中心总数文字
  • 扇区外引线
  • 3 扇区 / 4 扇区版本

你要的话,我下一条直接给你画一张 “从标签到 ST,再到 pie_chart 的绑定示意图”,按你的对象树名字一一标出来。

Question

image.png

我已将代码写入,可我又如何将标签与st定义的输入绑定,又如何将把 ST 输出绑到 pie_chart 的 SVG 参数,详细说明每个步骤

Réflexion

undefined

Réflexion

Thought for 9s

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 29s

Réflexion

Thought for 49s

Réflexion

Thought for 1m 48s

Réponse

从你这张图看,现在 ST 程序还没有真正创建输入/输出参数,因为右侧属性里只有 En0,没有 GoodValue / BadValue / GoodPath / BadPath ...。在 MasterSCADA 4D 里,只有建在程序“输入/输出端子(клеммник)”上的参数,才能方便地和外部标签/窗口属性建立连接;仅在 ST 文本里声明的变量,官方明确说明“不能为其设置连接”。ST 编辑器左侧是输入端子,右侧是输出端子;创建后的参数会出现在图例的“参数”页签和树里的对应分组中。(support.mps-soft.ru)

你现在要做的,不是先去绑 pie_chart,而是先把 ST_program_1 的端子建完整。另外,导入 SVG 后,XML 暴露出来的 GoodPath / BadPath / Legend... 这些就是 SVG 的可绑定参数,XML 的作用正是告诉 MasterSCADA 哪些 SVG 属性会受 SCADA 变量驱动;XML 还必须严格对应 SVG 元素的 id 和属性名。(support.mps-soft.ru)

一、先把 ST 程序做成“可绑定”的程序

第 1 步:展开 ST 两侧的端子栏

打开 ST_program_1 编辑器后,左边是输入端子,右边是输出端子。如果你现在没看到完整端子栏,点左右两边的小切换按钮,把端子栏展开。官方文档里写了,输入端子在编辑区左边,输出端子在右边。(support.mps-soft.ru)

第 2 步:创建两个输入参数

你需要在左侧输入端子创建这两个参数:

  • GoodValue,类型建议 DINT
  • BadValue,类型建议 DINT

创建方式有两种,推荐你用第 1 种:

方法 A,最推荐:直接从左侧树里把真实标签拖进 ST 输入端子

你左边树里已经有两个实际标签,名字看起来就是:

  • годные
  • Чёрные

你可以直接把这两个标签从树里拖到 ST_program_1左侧输入端子区。官方说明写得很明确:** 把项目参数拖到程序里(端子、树、程序区域)时,程序会自动添加同名参数并与其建立连接**。(support.mps-soft.ru)

拖进去后,很可能自动生成两个输入参数,名称会跟原标签名一致,比如:

  • годные
  • Чёрные

如果你想继续用代码里的 GoodValue / BadValue 这两个名字,那就把新生成的两个输入参数重命名成:

  • GoodValue
  • BadValue

ST 编辑器官方说明:如果你在端子里重命名参数,而旧名字已经出现在代码中,会弹窗询问是否同步替换代码里的名字。(support.mps-soft.ru)

方法 B:手工新建输入参数

如果你不想拖拽,也可以在输入端子里手工“添加参数”,然后命名为:

  • GoodValue : DINT
  • BadValue : DINT

再把左侧树中的 годные 绑到 GoodValueЧёрные 绑到 BadValue。程序参数本来就建议加在端子上,这是官方推荐的经典用法。(support.mps-soft.ru)

第 3 步:创建 6 个输出参数

右侧输出端子创建这些参数:

  • GoodPath : STRING
  • BadPath : STRING
  • GoodOpacity : STRING
  • BadOpacity : STRING
  • LegendGoodContent : STRING
  • LegendBadContent : STRING

建好以后,这些输出会出现在程序右侧端子、图例参数页签,以及树中的程序参数组里。(support.mps-soft.ru)

第 4 步:检查代码里的变量归属

你代码里这些应该继续留在 VAR ... END_VAR 里,作为局部变量:

  • GoodR
  • BadR
  • TotalR
  • GoodDeg
  • BadDeg
  • EndDeg
  • EndRad
  • EndXr
  • EndYr
  • EndXi
  • EndYi
  • GoodPct
  • BadPct
  • LargeGood
  • LargeBad
  • SX
  • SY
  • T1
  • T2

而下面这些不要写进 VAR,它们必须是端子参数:

  • GoodValue
  • BadValue
  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

因为官方明确说,ST 文本里声明的变量可以用,但不能设置连接。(support.mps-soft.ru)


二、把真实标签绑定到 ST 输入

这一步做完,数据流应当是:

годные / Чёрные -> ST_program_1 输入 -> ST 计算

方法 1:如果你刚才是“拖标签到输入端子”创建的

那这一步其实已经自动完成了。官方文档写明,把项目参数拖到程序端子里时,程序参数会被创建并与之建立连接。(support.mps-soft.ru)

你可以这样检查:

  1. 选中 ST_program_1
  2. 看左侧输入端子里是否已有两个输入
  3. 鼠标悬停在连接/参数上,看是否指向左边树里的真实标签
  4. 在运行时观察 GoodValueBadValue 是否随真实标签变化

方法 2:如果你是手工建的输入参数

那你要手工把树中的真实标签绑到它们:

  1. 打开左侧树,找到真实标签 годные
  2. 将它拖到 ST_program_1 左侧输入端子中的 GoodValue
  3. 再把 Чёрные 拖到 BadValue

如果你的小版本里不能直接拖到参数名上,通常也可以先选中 GoodValue 这个输入参数,再在属性/连接界面里指定来源变量。这里不同小版本的按钮名字可能略有不同,但本质就是建立“标签 → 程序输入参数”的关系。官方确认程序参数就是用来和项目树参数建立这类关系的。(support.mps-soft.ru)

绑定完成后你应当看到什么

完成后,ST_program_1 的属性面板里就不该只有 En0 了,而应该能看到你新增的输入/输出参数。创建在端子里的参数还会出现在图例的“参数”页签,以及树中的程序参数分组里。(support.mps-soft.ru)


三、把 ST 输出绑定到 pie_chart 的 SVG 参数

这一步做完,数据流应当是:

ST_program_1 输出 -> pie_chart 实例参数 -> SVG 的 d/content 属性

先分清“资源窗口”和“窗口实例”

你左边树里看到的 pie_chartResources > Windows 下,它是资源窗口。真正显示在画面上的,应该是你把它拖进 123 这个窗口后的实例
你要绑定的,优先应该是 123 画面里那个 pie_chart 实例 的参数,而不是只绑定资源定义本身。否则经常会出现“资源里改了,运行画面没反应”。这点不是官方一句话写死的规则,而是 HMI 资源/实例的常见实际用法;你现在这个结构下,按实例绑最稳。

第 1 步:打开画面 123

切到窗口 123,确认里面已经放了一个 pie_chart。如果没放,就把资源窗口 pie_chart 从资源树拖进 123。导入 SVG 的官方流程就是先在库里建窗口,再把 SVG 加进去作为窗口内容。(support.mps-soft.ru)

第 2 步:在 123 里选中 pie_chart 实例

选中以后,看右侧属性面板。
在它的 Parameters 分组里,你应该能看到这些 SVG 参数:

  • GoodPath
  • BadPath
  • GoodFill
  • BadFill
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

这些参数之所以会出现,是因为 XML 已经把它们定义成了可动态绑定的 SVG 属性。(support.mps-soft.ru)

第 3 步:把 ST 输出逐一拖到 pie_chart 对应属性

现在再打开 ST_program_1,从它的输出端子或者图例-参数页签里,把输出参数拖到 pie_chart 实例的对应属性行上。

一一对应绑定成这样:

  • ST_program_1.GoodPathpie_chart.GoodPath
  • ST_program_1.BadPathpie_chart.BadPath
  • ST_program_1.GoodOpacitypie_chart.GoodOpacity
  • ST_program_1.BadOpacitypie_chart.BadOpacity
  • ST_program_1.LegendGoodContentpie_chart.LegendGoodContent
  • ST_program_1.LegendBadContentpie_chart.LegendBadContent

如果你的小版本允许直接拖到属性值单元格,这样最快。
如果不能直接拖到属性格里,就选中对应属性后,用该属性的“绑定/连接”按钮去指定来源参数为 ST_program_1 的对应输出。这里具体按钮图标在不同小版本可能略有差别,但本质上是让 SVG 参数的值来源于 ST 输出参数。官方关于 SVG/XML 的说明就是:XML 定义哪些 SVG 属性能动态变化,以及哪些 SCADA 数据会驱动它们。(support.mps-soft.ru)

第 4 步:第一轮不要先绑颜色

你先只绑这 6 个:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

把“扇区几何”和“图例文字”跑通以后,再决定是否要让颜色也动态。这样排错最少。


四、你现在代码要不要改

要,改一处就行:确保代码里用到的输入/输出名字,和你端子里创建的参数名字完全一致

也就是说:

  • 如果你输入端子叫 GoodValue / BadValue,代码就保持不变。
  • 如果你拖进来后系统自动建成了俄文名,比如 годные / Чёрные,那你就要么把端子重命名成 GoodValue / BadValue,要么把代码中的 GoodValue / BadValue 改成俄文名。

官方说明里,端子改名时可以联动替换 ST 代码中的旧名字。(support.mps-soft.ru)


五、最推荐的实际操作顺序

你照这个顺序做,最不容易乱:

1

ST_program_1 左边输入端子创建:

  • GoodValue
  • BadValue

2

ST_program_1 右边输出端子创建:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

3

检查代码里没有把这些名字写进 VAR 局部变量区。

4

把左边树里的真实标签绑定到:

  • годныеGoodValue
  • ЧёрныеBadValue

5

打开 123 画面,选中里面的 pie_chart 实例。

6

ST_program_1 的 6 个输出参数绑定到 pie_chart 的 6 个同名 SVG 参数。

7

编译/检查程序。

8

在线测试 4 组值:

  • 75 / 25
  • 50 / 50
  • 0 / 100
  • 100 / 0

六、你现在大概率会遇到的 5 个问题

1)右侧还是只有 En0

说明你还没在端子里真正创建程序参数。只写代码不够。官方明确说,ST 文本中声明的变量不能设置连接。(support.mps-soft.ru)

2)编译提示 GoodValueGoodPath 未定义

说明这些名字还没有在输入/输出端子里建出来。

3)ST 数值在变,但 pie_chart 不动

通常是你绑到了资源窗口 pie_chart,而不是绑到 123 画面里的实例

4)图例文字不变

说明 LegendGoodContent / LegendBadContent 没有绑定到实例参数,或者 XML 里的 content 对应的 id 不一致。XML 必须严格对应 SVG 的结构和元素 id。(support.mps-soft.ru)

5)你改了 SVG/XML,但属性没刷新

官方说明:SVG 已经导入过后,再选对应 XML 可以更新描述。也就是说改完 XML 后,通常要重新导入或更新该 SVG 的 XML 描述。(support.mps-soft.ru)


七、最省事的一种做法

你其实可以直接这么做:

  1. годные 拖到 ST 左侧输入端子
  2. Чёрные 拖到 ST 左侧输入端子
  3. 重命名它们为 GoodValueBadValue
  4. 右侧手工建 6 个输出
  5. 123 中选中 pie_chart 实例
  6. 逐个拖 ST 输出到 SVG 对应参数

这样最快。

如果你愿意,我下一条直接按你这棵树的名字,给你画一份**“从左侧标签到 ST,再到 123 里的 pie_chart 实例”的文字接线图**,你可以对着一个个连。

Question

image.png

我的左侧没有输入,这是为什么,而且我的标签也无法拖入没有输入的地方,这该如何解决?

Réflexion

undefined

Réflexion

Thought for 9s

Réflexion

undefined

Réflexion

undefined

Réflexion

Clarifying left terminal and variable declaration settings

It seems like the left input terminal is hidden because it’s collapsed. Even though you can declare VAR_INPUT and VAR_OUTPUT in the code, these variables cannot be externally linked in the editor. For external drag-and-drop functionality, it's better to use terminal parameters. I’ll explain this step-by-step.

Expanding terminal and adding parameters

To expand the input terminal, click the small switch or arrow at the far left of the gray strip. After expanding, if the terminal is still empty, right-click inside the terminal to add parameters, or you can drag labels from the project tree into the editor or terminal. Alternatively, add input parameters directly by setting the Access to Input.

Thought for 46s

Réponse

你这个不是“不能有输入”,而是左侧输入端子被折叠/没建参数了。

从你截图看:

  • 右侧输出端子还在,所以能看到 EnO
  • 左侧是一整条灰色空栏,最左边中间还有一个白色小箭头
  • 这正符合 MasterSCADA 4D 里“输入端子被收起”的状态:官方说明里写了,输入端子在编辑区左边,它的显示/隐藏由左侧的小按钮控制;收起时只显示切换按钮,展开时才显示整个输入端子列表。(support.mps-soft.ru)

另外,官方也明确说了:只在 ST 文本里写声明的变量,不能设置外部连接;要做你这种“标签绑定到 ST,再绑定到 SVG”的结构,推荐用程序端子参数。把项目里的参数拖到程序的端子、树或程序区,系统会自动创建程序参数并建立连接。(support.mps-soft.ru)


先解决“左侧没有输入”

第 1 步:展开左侧输入端子

你现在 ST 编辑器最左边那条灰色栏,中间靠左有一个白色小箭头
点它一次,左侧输入端子就会展开。

这是官方定义的“输入端子可见性开关”:输入端子在左边,小按钮控制“只显示开关”还是“显示整个端子栏”。(support.mps-soft.ru)

第 2 步:如果点开后还是空白,不是故障,是因为还没建输入参数

输入端子只是个容器。
你没创建输入参数时,它展开后也会是空的。


最稳的做法:先建输入/输出参数,再绑定

你照这个顺序做。


A. 创建 ST 输入参数

方法 A1:直接拖真实标签进去,最省事

官方说明:把项目参数拖到程序里(端子、树、程序区)时,程序会自动新增同名参数并和它建立连接。(support.mps-soft.ru)

你这样做:

  1. 展开左侧输入端子
  2. 在左侧项目树里找到真实标签
    你截图里应该是:
    • годные
    • Чёрные
  3. 用鼠标把 годные 拖到 ST 左侧输入端子空白区
  4. 再把 Чёрные 拖进去

拖进去以后,程序会自动生成两个输入参数,并且已经连上原标签。官方就是这么定义的。(support.mps-soft.ru)

方法 A2:如果拖不进去,就拖到 ST 代码区

官方同样写了:项目参数拖到程序区也会创建程序参数并建立连接。(support.mps-soft.ru)

所以如果你对着端子不好放,可以直接把:

  • годные
  • Чёрные

拖到中间白色代码编辑区里。

拖完后,程序里也会新增参数。


B. 创建 ST 输出参数

输出参数不能从项目树直接拖出来,因为它们是程序算出来的。
所以你需要在右侧输出端子自己加。

你现在右边能看到 EnO,说明右侧端子是打开的。
你需要再新增这 6 个输出参数:

  • GoodPath : STRING
  • BadPath : STRING
  • GoodOpacity : STRING
  • BadOpacity : STRING
  • LegendGoodContent : STRING
  • LegendBadContent : STRING

怎么新增

不同小版本按钮样式可能不一样,但通常有这几种方式之一:

  1. 在右侧输出端子空白处 右键
  2. 添加参数 / Add parameter
  3. 参数类型设为 STRING
  4. 参数访问方式设为 Output

官方定义里,右侧端子就是“访问方式为 Output 的程序参数”。(support.mps-soft.ru)

如果右键菜单里没有“添加参数”,就去:

  • 程序树里的参数组
  • 或图例 Parameters
  • 或属性面板里新增程序参数

但新增时一定保证它们是 Output


C. 你代码里要不要改

要看你刚才拖进去后生成的输入参数名字是什么。

情况 1:你拖进去后参数名自动变成俄文

例如变成:

  • годные
  • Чёрные

那你有两个选择:

方案 1:把参数重命名成你代码里的名字

改成:

  • GoodValue
  • BadValue

官方说明:在端子里重命名参数时,如果旧名字已经在 ST 代码里出现,系统会提示是否同步替换代码中的名称。(support.mps-soft.ru)

这是最推荐的。

方案 2:不改参数名,改代码

把代码里的:

pascal
GoodR := DINT_TO_REAL(GoodValue); BadR := DINT_TO_REAL(BadValue);

改成:

pascal
GoodR := DINT_TO_REAL(годные); BadR := DINT_TO_REAL(Чёрные);

但这个不太推荐,因为后面维护不方便。


D. 把 ST 输出绑到 pie_chart 的 SVG 参数

这一步你要去 123 画面里选中 pie_chart 实例,不是只盯着资源树里的 pie_chart

第 1 步:切到窗口 123

点击上方 123 标签页。

第 2 步:选中画面里的 pie_chart

让右侧属性栏显示这个图元的属性。
这时你应该能看到:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

这些是 XML 暴露出来的 SVG 参数,本来就是给动态绑定用的。(support.mps-soft.ru)

第 3 步:逐个建立连接

ST_program_1 的输出参数,绑定到 pie_chart 的同名参数:

  • ST_program_1.GoodPathpie_chart.GoodPath
  • ST_program_1.BadPathpie_chart.BadPath
  • ST_program_1.GoodOpacitypie_chart.GoodOpacity
  • ST_program_1.BadOpacitypie_chart.BadOpacity
  • ST_program_1.LegendGoodContentpie_chart.LegendGoodContent
  • ST_program_1.LegendBadContentpie_chart.LegendBadContent

怎么绑

常见有两种方式:

方式 1:拖拽

ST_program_1 的输出端子,把参数拖到 pie_chart 属性值单元格上。

方式 2:属性里选来源

pie_chart 某个属性值格,再用“绑定/连接”按钮指定来源为 ST_program_1 的对应输出。


E. 你现在最应该先做的验证

先不要一次全做完。先按这个最小闭环测试:

先只做 2 个输入 + 2 个输出

先让它跑最核心的几何:

输入:

  • GoodValue
  • BadValue

输出:

  • GoodPath
  • BadPath

然后在 pie_chart 里只先绑:

  • GoodPath
  • BadPath

如果饼图角度已经会变化,再继续加:

  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

这样排错最容易。


F. 你现在大概率遇到的是这 3 种情况之一

1. 左端子只是折叠了

解决:点最左边小箭头展开。
官方明确说左侧按钮控制输入端子显示。(support.mps-soft.ru)

2. 左端子展开了,但里面空白

解决:你还没创建输入参数。
годныеЧёрные 拖进去即可。官方说明拖入程序会自动建参数并连上。(support.mps-soft.ru)

3. 你只在代码里写了变量名,但没建程序参数

解决:必须通过端子/程序参数创建可连接的输入输出。
官方明确写了,ST 文本里声明的变量不能设置连接。(support.mps-soft.ru)


你现在就照这个做

  1. 点左侧白色小箭头,展开输入端子
  2. годные 拖进去
  3. Чёрные 拖进去
  4. 把它们重命名成 GoodValueBadValue
  5. 在右侧输出端子新增
    GoodPath / BadPath / GoodOpacity / BadOpacity / LegendGoodContent / LegendBadContent
  6. 切到 123
  7. 选中 pie_chart
  8. 把 ST 输出逐个绑到 pie_chart 同名参数

把你点开左侧端子后的截图再发我一张,我可以直接按你当前界面告诉你“下一步点哪里”。

Question

我现在没有实际的plc设备,我也只是在object1上面自己创建的标签,我该怎么测试图形的正确与否?我希望标签能够随时间变化,图形也跟变化,我该怎么测试?

Réflexion

undefined

Réflexion

Thought for 10s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 21s

Réflexion

undefined

Réflexion

undefined

Réflexion

undefined

Réflexion

Thought for 1m 1s

Réflexion

undefined

Réflexion

undefined

Réflexion

Configuring value range and period calculation

The goal is to create a range for GoodValue between 5 and 95, which works well for the chart. I can use a sine function and the formula Phase := DWORD_TO_REAL(TIME_TO_DWORD(TIME())) * 0.000785398 to achieve a period of 8 seconds. I'll convert values for GoodValue and BadValue using REAL_TO_DINT, with rounding being acceptable unless truncation is preferred. Object tags can be used for output, with GoodValue and BadValue connected.

Setting up simulation with dynamic pie chart

For a dynamic pie chart with a constant total of 100, I’ll set up two integer tags, GoodTest and BadTest, in Object1. The simulation program can be written under ST_simulator. I’ll connect outputs to these tags and assign them as outputs correctly. Then, I’ll set a periodic execution within the parent object.

Thought for 2m 49s

Réponse

可以,不用 PLC 也能完整测试。最实用的办法是把 Object1 里你自己建的标签当成“模拟 PLC 标签”,再加一个 “信号发生器”ST 程序,让这两个标签随时间自动变化;你的饼图程序继续像读取真实设备标签一样去读它们。MasterSCADA 4D 里对象参数可以直接建在对象里,程序参数建议放在程序端子上,并且把项目参数拖进程序时会自动创建并建立连接;另外,ST 里自己 VAR 出来的变量不能直接和外部项目元素建立连接。(support.mps-soft.ru)

最稳的测试分两步:

第一步:先做“静态正确性测试”

先别急着做动画。
先验证几何对不对。

你可以临时用一个很简单的 ST 程序输出固定值:

pascal
GoodValue := 75; BadValue := 25;

这时饼图应该明显是 3/4 绿色,1/4 红色
然后再改成下面几组去看是否正确:

pascal
GoodValue := 50; BadValue := 50; GoodValue := 0; BadValue := 100; GoodValue := 100; BadValue := 0; GoodValue := 25; BadValue := 75;

如果这 4 组都对,你的 GoodPath / BadPath 算法基本就通了。


第二步:做“动态测试”

这里我建议你单独建一个程序,名字比如:

  • ST_simulator

放在 Object1 下面,专门负责给测试标签喂数据。
你的饼图程序继续放在 Object2 或现在的位置,不用改思路。

你需要的结构

Object1 里

建两个整数标签,直接用你现在已有的也行,比如:

  • годные
  • Чёрные

再建一个程序:

  • ST_simulator

Object2 里

保留你现在的饼图程序:

  • ST_program_1

它的输入仍然是:

  • GoodValue
  • BadValue

它的输出仍然是:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

一、动态测试最推荐的 ST 模拟代码

这个版本不依赖 PLC,也不依赖系统时钟函数,只依赖程序周期执行。
它利用 Phase 这个局部变量在每个周期累加,再用 SIN() 生成平滑变化。MasterSCADA 4D 的普通本地变量 Local 会在调用之间保留值,而 Temp 才会每次重新初始化;SIN 的输入是弧度。(support.mps-soft.ru)

1)给 ST_simulator 建两个输出参数

在程序右侧输出端子创建:

  • GoodValue : DINT
  • BadValue : DINT

然后把下面代码粘进去:

pascal
VAR Phase : REAL; GoodR : REAL; END_VAR (* 每个周期推进一点相位,数值越大变化越快 *) Phase := Phase + 0.08; IF Phase > 6.283185 THEN Phase := Phase - 6.283185; (* 2*pi *) END_IF; (* 生成 5~95 之间变化的良品数 *) GoodR := 50.0 + 45.0 * SIN(Phase); GoodValue := REAL_TO_DINT(GoodR); BadValue := 100 - GoodValue;

这里 REAL_TO_DINT 会做四舍五入式转换。(support.mps-soft.ru)

这个代码会得到什么效果

  • GoodValue 会在大约 5 到 95 之间来回变化
  • BadValue 会自动变成 100 - GoodValue
  • 总和一直是 100
  • 所以饼图会一直保持完整圆,只是绿色和红色面积不断变化

这对验证饼图最直观。


二、怎么把“模拟程序”接到你的自建标签

方案 A:让 ST_simulator 直接输出到 Object1 的两个标签

这是最像“PLC 采集值”的测试方式。

步骤 1

Object1 下确认你有两个标签:

  • годные
  • Чёрные

它们用整数标签就行。MasterSCADA 4D 标准标签里有整数、实数、逻辑等类型。(support.mps-soft.ru)

步骤 2

打开 ST_simulator

步骤 3

在右侧输出端子创建:

  • GoodValue
  • BadValue

步骤 4

把这两个输出分别和 Object1 里的标签建立连接:

  • ST_simulator.GoodValueObject1.годные
  • ST_simulator.BadValueObject1.Чёрные

如果你习惯拖拽,直接把对象参数拖进程序/端子可以自动建立程序参数和连接;官方推荐经典做法还是通过程序端子来做。(support.mps-soft.ru)

步骤 5

保持 ST_simulator 为周期执行。
你截图里 Execution method = Periodic 已经是对的,继续保持就行。


三、怎么让饼图读这两个测试标签

现在你的 ST_program_1 就相当于“图形计算程序”。
它不要直接接 PLC,而是接刚才那两个测试标签。

ST_program_1 的输入端

确保有两个输入参数:

  • GoodValue
  • BadValue

绑定方式

Object1 的两个标签绑到这里:

  • Object1.годныеST_program_1.GoodValue
  • Object1.ЧёрныеST_program_1.BadValue

这样数据链路就是:

ST_simulator -> Object1 标签 -> ST_program_1 -> pie_chart

这和以后换成 PLC 的时候几乎一样,只是把数据源从 PLC 改成了你自己的模拟程序。


四、怎么验证 pie_chart 是否在动

123 画面里选中 pie_chart 实例,确认这几个参数已经绑定到 ST_program_1 输出:

  • GoodPath
  • BadPath
  • GoodOpacity
  • BadOpacity
  • LegendGoodContent
  • LegendBadContent

然后运行项目,看 3 件事:

  1. 图例文字里的数值是否在变
  2. 绿色和红色扇区面积是否在变
  3. 绿色增大时红色是否同步减小

如果这三件事同时成立,你的整条链路就是通的。


五、最简单的“纯动态测试闭环”

如果你想先最小化排错,建议你这样连:

在 Object1

  • 标签:годные
  • 标签:Чёрные
  • 程序:ST_simulator

在 Object2

  • 程序:ST_program_1
  • 窗口实例:pie_chart

连接顺序

  1. ST_simulator.GoodValueObject1.годные
  2. ST_simulator.BadValueObject1.Чёрные
  3. Object1.годныеST_program_1.GoodValue
  4. Object1.ЧёрныеST_program_1.BadValue
  5. ST_program_1.GoodPathpie_chart.GoodPath
  6. ST_program_1.BadPathpie_chart.BadPath
  7. ST_program_1.GoodOpacitypie_chart.GoodOpacity
  8. ST_program_1.BadOpacitypie_chart.BadOpacity
  9. ST_program_1.LegendGoodContentpie_chart.LegendGoodContent
  10. ST_program_1.LegendBadContentpie_chart.LegendBadContent

六、如果你想先不用 Object1 标签,直接做“内部自测”

也可以更简单:

  • 暂时不要 ST_simulator
  • ST_program_1 里直接写死输入值做校验

例如临时改成:

pascal
GoodValue := 75; BadValue := 25;

或者做一个很简单的动态版本:

pascal
VAR Phase : REAL; GoodR : REAL; END_VAR Phase := Phase + 0.08; IF Phase > 6.283185 THEN Phase := Phase - 6.283185; END_IF; GoodR := 50.0 + 45.0 * SIN(Phase); GoodValue := REAL_TO_DINT(GoodR); BadValue := 100 - GoodValue;

但这只是“自测几何”。
真正贴近以后接 PLC 的方式,还是前面那个“Object1 测试标签 + ST_simulator”的方案。


七、你可以怎么判断图形“正确”

用下面这几个观察点最容易:

  • 50 / 50 时,图应该正好半圆对半
  • 75 / 25 时,绿色应该大约占 3/4
  • 95 / 5 时,绿色应该接近整圆,只剩一点红
  • 0 / 100 时,只剩红色整圆
  • 100 / 0 时,只剩绿色整圆

如果这些状态都对,说明:

  • 角度计算对了
  • 大弧标志对了
  • sweep-flag 方向对了
  • 0% 和 100% 特殊处理也对了

八、如果动画太快或太慢,改哪一行

改这一行:

pascal
Phase := Phase + 0.08;
  • 改成 0.02:更慢
  • 改成 0.15:更快
  • 改成 0.30:很快

九、如果你想做“阶梯变化”而不是平滑变化

不用 SIN,直接做加减计数也行。
比如每周期加 1,到 95 后再减回 5。这样更容易肉眼检查每一级变化。

pascal
VAR GoodValueInt : DINT; DirUp : BOOL := TRUE; END_VAR IF DirUp THEN GoodValueInt := GoodValueInt + 1; IF GoodValueInt >= 95 THEN GoodValueInt := 95; DirUp := FALSE; END_IF; ELSE GoodValueInt := GoodValueInt - 1; IF GoodValueInt <= 5 THEN GoodValueInt := 5; DirUp := TRUE; END_IF; END_IF; GoodValue := GoodValueInt; BadValue := 100 - GoodValue;

这个版本的优点是:
你可以很容易看出是不是每一步都正确。


你现在最值得做的是:先加一个 ST_simulator,把上面的动态代码跑起来。等你把连接做好后,把你的对象树和 ST_simulator 端子截图发我,我可以直接按你的界面把“哪一根连哪一根”给你标出来。

Partager cette Q&R