施耐德 M340 M580 数据移动指令 EXTRACT
现状说明
施耐德自带的 MOVE 指令,只能适用于移动整体数据
若要移动单个数组中的部分数据、或移动到另一个数组的中间区域,则无法使用 MOVE 指令实现
需要使用EXTRACT
指令
EXTRACT 指令
EXTRACT
指令的特点
- 可指定复制源变量的起始位置、复制到目标变量的中间指定位置
- 源变量、目标变量可以是不同数据类型 (如 INT 与 DINT 数组)
只要目标变量中指定的区域足够容纳要复制的数据就能正常操作 - 具有 ERR 错误状态,可输出执行状态
- 类似 AB 中的
COP
指令、西门子中的PEAK_BLK
/POKE_BLK
指令
官方帮助
官方文档:
- 《EcoStruxure Control Expert - 标准 , 功能块库》
https://www.schneider-electric.cn/zh/download/document/33003679K01000/
调用功能块方法
调用路径:Libset/Base Lib/Arrays
,搜索名称为EXTRACT
的指令
参数介绍与简单示例
指令相关参数
简短的参数解析
参数 | 功能 |
---|---|
SRC | 源变量 从 SRC 这个变量复制数据 |
SRC_NELEM | 源变量的长度 下面的 CPY_NELEM 根据这个参数确定复制的每个元素的长度 |
SRC_POS | 在 SRC 中要复制的第一个元素的起始位置 按照 SRC_NELEM 中的数量确定单个元素长度、元素下标从 0 开始 |
DST_POS | 目标变量中存放复制数据的起始位置 按照 SRC_NELEM 中的数量确定单个元素长度、元素下标从 0 开始 |
CPY_NELEM | 要复制的元素数量 按照 SRC_NELEM 中的数量确定单个元素长度 |
DST | 目标变量 将数据复制到目标变量 DST 中 |
ERR | 状态字 0 / 非 0 = 指令运行正常 / 指令运行出错 |
参数设定
- 不论源变量在变量表中如何定义,在
EXTRACT
指令中,元素下标都是从 0 开始算起的
官方示例如下
- 设定的
SRC_NELEM
决定了单个元素的长度,源变量、目的变量中的统一换算为此元素的类型
- 不论原来定义的源变量、目标变量的类型如何,都按照
CPY_NELEM
规定的长度进行换算 - 根据换算后的数据类型,确定源变量中复制数据的起始地址、目的变量数据存放的起始地址
- 不论原来定义的源变量、目标变量的类型如何,都按照
不同参数设定的示例
- 示例1:常规用法 – 设置
SRC_NELEM
与定义的变量元素类型相同 - 示例2:非常规用法 – 设置
SRC_NELEM
长度 小于 定义的变量元素类型长度
参数值 | 含义 |
---|---|
SRC := TEST_EXT_SRC1 | 此变量定义的类型为 INT 型数组,元素数量 10,下标从 0 开始 |
SRC_NELEM := 20 | 设定源变量元素数量 = 20 相当于单个元素类型为 Byte(每个元素是 INT 长度的 1/2) |
SRC_POS := 2 DST_POS := 5 CPY_NELEM := 1 | 按照 Byte 类型长度 从源变量中第 2 个 byte (从 0 开始算) 复制 1 个 Byte 复制到目的变量中的第 5 个 Byte (从 0 开始算) |
DST => TEST_EXT_DST1 | 复制到 TEST_EXT_DST1 变量中 此变量原定义为 Byte 型数组,元素数量 20,下标从 0 开始 |
EXTRACT 指令整体执行逻辑 | 从 TEST_EXT_SRC1 中的 第 2 个 byte (从 0 开始算) 复制 1 个 Byte,复制到 TEST_EXT_DST1 元素的第 5 个 Byte (从 0 开始算) |
- 示例2:非常规用法 – 设置
SRC_NELEM
长度 小于 定义的变量元素类型长度
参数值 | 含义 |
---|---|
SRC := TEST_EXT_SRC1 | 此变量定义的类型为 INT 型数组,元素数量 10,下标从 0 开始 |
SRC_NELEM := 20 | 设定源变量元素数量 = 20 相当于单个元素类型为 Byte(每个元素是 INT 长度的 1/2) |
SRC_POS := 2 DST_POS := 5 CPY_NELEM := 1 | 按照 Byte 类型长度 从源变量中第 2 个 byte (从 0 开始算) 复制 1 个 Byte 复制到目的变量中的第 5 个 Byte (从 0 开始算) |
DST => TEST_EXT_DST2 | 复制到 TEST_EXT_DST2 变量中 此变量原定义为 DINT 型数组,元素数量 20,下标从 0 开始 |
EXTRACT 指令整体执行逻辑 | 从 TEST_EXT_SRC1 中的 第 2 个 byte (从 0 开始算) 复制 1 个 Byte,复制到 TEST_EXT_DST2 元素的第 5 个 Byte (从 0 开始算) |
- 示例3:非常规用法 – 设置
SRC_NELEM
长度 大于 定义的变量元素类型长度
参数值 | 含义 |
---|---|
SRC := TEST_EXT_SRC1 | 此变量定义的类型为 INT 型数组,元素数量 10,下标从 0 开始 |
SRC_NELEM := 20 | 设定源变量元素数量 = 20 相当于单个元素类型为 DINT(每个元素是 INT 长度的 2 倍) |
SRC_POS := 2 DST_POS := 5 CPY_NELEM := 1 | 按照 Byte 类型长度 从源变量中第 2 个 byte (从 0 开始算) 复制 1 个 Byte 复制到目的变量中的第 5 个 Byte (从 0 开始算) |
DST => TEST_EXT_DST3 | 复制到 TEST_EXT_DST3 变量中 此变量原定义为 DINT 型数组,元素数量 20,下标从 0 开始 |
EXTRACT 指令整体执行逻辑 | 从 TEST_EXT_SRC1 中的 第 2 个 DINT (从 0 开始算) 复制 1 个 Byte,复制到 TEST_EXT_DST2 元素的第 5 个 DINT (从 0 开始算) |
ERR
参数 – 错误状态字
ERR
参数输出指令执行的结果
- 0 = 执行成功无错误
- 非 0 = 执行出错,具体错误如下
使用示例:DTM 读写数据与变量表数据映射
在实际项目中,使用 NOC 网卡 + DTM 配置,读取从一个 Modbus TCP 网关的采集上来的连续的设备数据
将这些数据存放到 PLC 中划分好的不连续的地址中,示意如下
从 DTM 到 PLC 变量表,使用 EXTRACT 指令进行数据映射
使用【示例 1 - 常规用法】,从 NOC 网卡的 DTM 中抽取对应数据到 PLC =变量表中的特定位置
NOC 网卡对应的 DTM 变量:MB_GATEWAY1.Inputs.Free
,配置 NOC 网卡后自动生成,数据类型 INT 数组,长度 501 个寄存器
Modbus 网关及 NOC 网卡中的数据 <–> 各设备的地址区域对应关系如下
设备序号 | 在 Modbus 网关 / NOC DTM 变量中的数据数组的起始下标 | 每个设备数据占用的寄存器长度 (每个寄存器为标准 16 位 INT 型) | PLC 中每个设备预留的起始数据地址(定位地址,%MW区域) |
---|---|---|---|
1 | 0 | 7 | %MW500 |
2 | 7 | 7 | %MW900 |
3 | 14 | 1 | %MW1400 |
4 | 15 | 1 | %MW1800 |
5 | 16 | 1 | %MW2100 |
6 | 17 | 3 | %MW3100 |
7 | 20 | 3 | %MW3800 |
8 | 23 | 7 | %MW4600 |
9 | 30 | 55 | %MW5100 |
10 | 85 | 1 | %MW5400 |
11 | 86 | 7 | %MW5900 |
12 | 93 | 66 | %MW6700 |
13 | 159 | 48 | %MW6800 |
14 | 207 | 5 | %MW6900 |
15 | 212 | 14 | %MW7300 |
16 | 226 | 21 | %MW7400 |
17 | 247 | 80 | %MW8000 |
18 | 327 | 41 | %MW8300 |
19 | 368 | 73 | %MW9200 |
20 | 441 | 10 | %MW9600 |
21 | 451 | 23 | %MW10000 |
22 | 474 | 5 | %MW10800 |
23 | 479 | 1 | %MW12400 |
24 | 480 | 3 | %MW13300 |
25 | 483 | 5 | %MW14200 |
26 | 488 | 1 | %MW14700 |
27 | 489 | 12 | %MW14900 |
对应的 EXTRACT 赋值程序
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 0, 0, 7, %MW500:7, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 7, 0, 7, %MW900:7, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 14, 0, 1, %MW1400:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 15, 0, 1, %MW1800:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 16, 0, 1, %MW2100:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 17, 0, 3, %MW3100:3, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 20, 0, 3, %MW3800:3, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 23, 0, 7, %MW4600:7, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 30, 0, 55, %MW5100:55, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 85, 0, 1, %MW5400:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 86, 0, 7, %MW5900:7, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 93, 0, 66, %MW6700:66, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 159, 0, 48, %MW6800:48, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 207, 0, 5, %MW6900:5, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 212, 0, 14, %MW7300:14, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 226, 0, 21, %MW7400:21, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 247, 0, 80, %MW8000:80, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 327, 0, 41, %MW8300:41, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 368, 0, 73, %MW9200:73, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 441, 0, 10, %MW9600:10, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 451, 0, 23, %MW10000:23, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 474, 0, 5, %MW10800:5, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 479, 0, 1, %MW12400:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 480, 0, 3, %MW13300:3, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 483, 0, 5, %MW14200:5, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 488, 0, 1, %MW14700:1, Copy_Status);
EXTRACT(MB_GATEWAY1.Inputs.Free, 501, 489, 0, 12, %MW14900:12, Copy_Status);
自己编写的改良 COP 指令 (先挖坑后面补)
可见EXTRACT
指令比较繁琐,尤其是SRC_NELEM
需要注意配置
实际上更常见的情况通常是相同数据类型的两个数组变量间的数据传输(即上面的【常规】)
这种情况下可简化 SRC_NELEM
等参数的配置
以下是我自行编写的程序块