1 入门
本章节将带领大家安装部署LCC应用,并运行第一个应用。
1.1 产品介绍
事件驱动型低代码控制器(LCC in Action),以下简称低代码控制器(LCC),是一种基于事件驱动和AOE网络的通用型控制器。相比于同类产品,其具有强大的技术优势。
- 低代码:用户几乎不用编写代码,可以通过简单的excel编写(或流程图绘制,开发中),完成相关配置文件及控制器的部署。
- 通用硬件:低代码控制器支持Windows、Linux等多种操作系统,ARM、x86-64等多种指令集,以及intel、AMD以及国产芯片在内的多种芯片平台,支持硬件定制。主频1GHz之内的低配控制器硬件已可满足绝大多数简单控制场景,2GHz之内的高配控制器硬件可满足各类复杂控制场景。
- 适用广泛:该控制器提供了一种通用化的框架,支持各类控制场景,如:机械控制(如倒立摆控制)、温度控制(如房屋温度控制)、综合能源系统控制(如光伏最大功率点跟踪、储能辅助调频、储能削峰填谷)等。
- 此外,该控制器提供形象化的操作界面,控制过程形象、直观。提供稳定的运行机制,通过对系统错误实时诊断,保证其在工业控制场景中的高可靠性。
相关信息
- 个人版下载链接:EasyScript.exe
- 产品购买链接:极简2021的小店
- bilibili产品主页:极简物控
- 抖音官方账号:极简物控(67222285201)
- 微信公众号:极简物控
- QQ技术交流群:极简物控官方技术交流群(560683174)
产品定制请联系淘宝客服或QQ群管理员。
1.2 运行第一个控制应用
将您的控制器与监控设备置于同一局域网内。
在浏览器中输入控制器设备的IP地址,您会看到以下界面,请稍等片刻以供控制器加载相关服务。
输入用户名密码进入控制器概览界面。
单击“测点”,进入测点配置页面,单击上传文件,即可上传配置文件添加文件,PLCC允许用户上传多个配置文件。同理可上传通道及AOE配置文件。
上传示例'counter'中的POINTS,AOE文件,单击概览页面中的“重置”按键,即可运行counter程序。
1.3 监控你的控制器运行
单击量测进入量测页面,您可以进入测点数据实时量测页面。在这里可以在这里观测测点的数据变化情况。
点击报表和曲线按钮可在网页上方显示数据报表及走势图。
单击策略进入策略界面,您可以观测AOE的执行情况,开始与停止按键,可以控制AOE的开始与停止。
单击AOE结果进入AOE结果界面,您可以观测详细的AOE的执行情况。
2 设计一个AOE网络
本章介绍如何设计一个AOE网络,首先介绍事件驱动和AOE网络的概念,然后分别说明AOE基本语法、AOE网络触发类型、AOE事件类型和AOE动作类型,最后阐述AOE网络的设计流程。
2.1 事件驱动与AOE网络
什么是事件驱动
一个事件驱动流程,由事件(Events)和动作(Actions)按照一定的逻辑关系组合而成。
-
事件:事件是一种状态,这里用来描述被控对象。事件可以作为动作执行的条件,同时也可作为动作执行完成的标志。
-
动作:动作是一种行为,这里用来表述控制器执行的具体策略(指令),例如给变量赋值、执行优化计算等指令。
什么是AOE网络
AOE网络是一种由多个事件驱动流程(及一些附加参数)组成的加权有向无环图。图中,每个节点表示事件,每条边表示动作,边的方向表示节点所示事件之间的递进和迁移关系,这种关系由该条边所表示的动作决定。
当AOE网络中节点事件发生时,则会按照节点中定义的规则,执行对应的动作(边)。当动作执行完成后,则会进入到相应的节点,按照节点定义规则判断事件是否发生。下图是一个AOE网络的示意,其中包含6个节点和6条边:
2.2 AOE基本表达式
低代码控制器采用基于AOE事件驱动的控制方式,在利用AOE网络进行控制策略设计时,所涉及的基本语法介绍如下。
赋值
AOE可以直接将某一数值或表达式赋给某个变量。赋值号为冒号:
或等号=
,推荐使用冒号:
,赋值顺序为将赋值号右边的值赋给左边。
相关示例如下:
#示例1:直接将值1赋给变量State_POINT
State_POINT: 1;
#示例2:将由变量Cartset_POINT与Cart_POINT组成的表达式的值赋给变量ECar
Ecar: Cartset_POINT - Cart_POINT;
基本数值运算
AOE可完成的基本数值运算及涉及的运算符如下表所示。
名称 | 运算符 |
---|---|
四则运算 | + - * / |
关系运算 | < <= > >= == != |
逻辑运算 | && || |
取余运算 | % |
幂运算 | ^ |
位运算 | & | ^^ ~ << >> @ |
相关示例如下:
#示例3:简单四则运算
Iout: Iout + Igain * Ecarn1 * Ts;
#示例4:多种运算混合
Ilimout: (Iout <= Iuplim && Iout >= Idownlim) * Iout + (Iout > Iuplim) * Iuplim + (Iout < Idownlim) * Idownlim;
内置函数
AOE内置多种常用数学函数及实用时间获取函数,可通过向括号内传入参数进行直接调用,支持的函数及其具体功能如下表所示。
函数 | 功能 |
---|---|
abs() | 求绝对值 |
sqrt() | 求平方根 |
exp() | 求以e为底的指数 |
ln()、log10() | 求自然对数(以e为底)、求常用对数(以10为底) |
sin()、cos()、tan() | 正弦函数、余弦函数、正切函数,单位为弧度 |
asin()、acos()、atan() | 反正弦函数、反余弦函数、反正切函数 |
sinh()、cosh()、tanh() | 双曲正弦函数、双曲余弦函数、双曲正切函数 |
asinh()、acosh()、atanh() | 反双曲正弦函数、反双曲余弦函数、反双曲正切函数 |
floor() | 向下取整,即取不大于传入参数的最大整数 |
ceil() | 向上取整,即取不小于传入参数的最小整数 |
round() | 将传入参数进行四舍五入 |
signum() | 符号函数,指出参数正负号,若为正则返回1;零返回0;负返回-1 |
atan2() | 计算方位角,弧度表示 |
max()、min() | 求多个参数的最大值/最小值,参数用“,”分隔 |
rand() | 输出[0,1)之间的随机数 |
rand2(a,b) | 输出[a,b)之间的随机数 |
indexOfYear()、Year() | 返回日期的年 |
indexOfMonth()、Month() | 返回日期的月 |
indexOfWeekday()、Weekday() | 返回日期的星期几,星期一至星期日分别为1-7 |
indexOfDay()、Day() | 返回日期的日 |
indexOfHour()、Hour() | 返回时间的小时,从当天0点算起 |
indexOfMinute()、Minute() | 返回时间的分钟,从当天0点算起 |
indexOfSecond()、Second() | 返回时间的秒,从当天0点算起 |
now() | 返回当前13位时间戳 |
TotalMemory() | 返回总内存大小 |
UsedMemory() | 返回已使用内存大小 |
UsedMemorySelf() | 返回程序本身已使用内存大小 |
MemUsage() | 返回内存使用率 |
MemUsageSelf() | 返回程序本身内存使用率 |
TotalSwap() | 返回总Swap大小 |
UsedSwap() | 返回已使用Swap大小 |
CpuUsage() | 返回Cpu使用率 |
CpuUsageSelf() | 返回程序本身Cpu使用率 |
TotalSpace() | 返回总空间大小 |
UsedSpace() | 返回已使用空间大小 |
DiskUsage() | 返回已使用磁盘率 |
TotalReceived() | 返回总接收数据量 |
TotalTransmitted() | 返回总发送数据量 |
注:indexOfYear()等时间相关函数中,index不区分大小写。
数字表示约定
AOE支持的数学常数和数字表示约定如下表。
圆周率 | pi | |
自然常数 | e | |
科学计数法 | 1e-2 1E-3 |
测点值及采样时间相关表达式
注:以下以点号为1234,别名为POINT_EXAMPLE的测点为例。
若在前后几次采样中,测点值都相同,那么测点的变化可以指代两种情况,一种是指值的变化,只有值发生改变时,才认为测点发生了变化;另一种是无论值是否变化,只要进行一次采样,就认为测点发生了变化(更新)。这里对可能产生的歧义做一个说明。
- 一、默认情况下,按第二种方式判别测点的变化。
别名_t
表示最近一次的采样时间。别名_dt
是指最近一次采样和上一次采样的时间间隔,别名_err
是指这一次采样和上一次采样的测点值之差,别名_ddt
指测点值变化率。
在这几个值的计算中,都是将当前采样的时间和值与上一次采样得到的时间和值进行对比。举一个例子,假设通讯通道每隔 1s 获取一次数据,各个值列表如下:
本次采样时间 | 1ms | 2ms | 3ms | 4ms | 5ms | 6ms | 7ms | 8ms | 9ms |
---|---|---|---|---|---|---|---|---|---|
本次采样值 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 | 16 |
上次时间 | 0 | 1 | 2 | 3 | 4 | 4 | 4 | 4 | 8 |
上次值 | 0 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 |
t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
dt | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 | 1 |
err | 11 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
界面显示时间 | 1 | 2 | 3 | 4 | 4 | 4 | 4 | 8 | 9 |
界面显示的值 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 | 16 |
- 二、若希望测点值变化时,才认为是测点发生变化,则将测点变化条件设置为
测点_err!=0
。
别名_t
仍表示最近一次的采样时间。别名_dt
是指最近一次采样和上一次发生值变化的采样的时间间隔,别名_err
是指这一次采样和上一次发生值变化的采样的测点值之差,别名_ddt
指测点值变化率。仍然是上述例子,在这个设定下,各个值列表如下:
本次采样时间 | 1ms | 2ms | 3ms | 4ms | 5ms | 6ms | 7ms | 8ms | 9ms |
---|---|---|---|---|---|---|---|---|---|
本次采样值 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 | 16 |
上次时间 | 0 | 1 | 2 | 3 | 4 | 4 | 4 | 4 | 8 |
上次值 | 0 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 |
t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
dt | 1 | 1 | 1 | 1 | 1 | 2 | 3 | 4 | 1 |
err | 11 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
界面显示时间 | 1 | 2 | 3 | 4 | 4 | 4 | 4 | 8 | 9 |
界面显示的值 | 11 | 12 | 13 | 14 | 14 | 14 | 14 | 15 | 16 |
如果只关心测点值的改变和改变的时间间隔,则需要用上述第二种方案。
若需要分辨每次采样而不要求测点值一定发生改变,以通信成功获取测点值来作为触发aoe的条件,则需要通过别名_t
来辨别每次采样的时间,并用aoe中的变量记录上一次的采样时间,若别名_t
等于上一次采样的时间,则还没有获取新的通信数据,若别名_t
大于上一次采样的时间,则获成功取新的通信数据。
需要说明的是,上述测点是针对通信测点的采样进行阐述的,对于aoe的置点和计算点的计算也是同理的。
2.2.1 向量运算
AOE可完成向量运算,使用向量形式进行计算,可以使表达式更为简洁。
向量运算规则如下:
- 动作类型选择为“SET_POINTS2”或“SET_POINTS_WITH_CHECK2”,详细内容见AOE动作类型。
- 向量的组成元素可为常数或者变量。
- 向量赋值通过冒号
:
或等号=
实现(推荐使用冒号:
),赋值顺序为赋值号右边的向量按元素顺序赋值给左边向量对应元素,要求赋值号两边向量维数相同。 - 向量运算支持向量四则运算、幂运算等,向量元素运算支持前述表格中所有运算。
- 可在AOE策略文件配置的变量初始值中,事先定义变量来表示向量,后续运算可直接用变量替代向量。 如“var:[a1,a2];”,后续动作“var:[123,234];”表示a1赋值为123,a2赋值为234;“[a3,a4]:var;”表示a3:a1、a4:a2。
相关示例如下:
#示例1:简单四则运算
[a1,a2]:([1,2]+[15,10])*[10,10]+[1,2];
#示例2:多种运算混合
[a3,a4]:[1>0,1&0];
[a5,a6]:[a9^2,a10==2];
[a7,a8]:[t1,t2]*[10,10]*[10,10]+[1,1];
#示例3:幂运算
[a9,a10]:[a11,a12]^3;
2.3 AOE网络触发类型
AOE网络被激活并从起始节点开始运行整个网络的行为称为网络触发。
低代码控制器中的AOE网络触发类型默认为事件驱动方式,即起始节点所代表的事件满足其设定的触发条件时,起始节点被触发,继而触发后续边及节点;除此之外,根据实际场景的需要,AOE网络触发类型也可以设定为简单重复驱动或时间驱动,使低代码控制器更具灵活性和普适性。
具体的AOE网络触发类型及说明见下表。
2.4 AOE事件类型
AOE网络中的节点代表事件,节点与节点之间的边代表动作,详细定义可见事件驱动与AOE网络。节点的类型及其代表的事件说明如下表所示。
Condition 条件节点 |
Condition节点为事件触发型。 |
---|---|
若在设定的超时时间内节点的表达式为真,则节点事件被触发,该节点触发的所有动作(即所有该节点发出的支路)并行执行。 | |
Switch 分支节点 |
Switch节点为分支逻辑判断,该节点连接着两条支路,以节点的表达式作为逻辑判断。 |
触发后续动作的逻辑为:当表达式为真时,该节点序号为1的边进行动作;表达式为假时,序号为2的边进行动作(其中边的序号是按AOE配置文件中定义的顺序确定)。 | |
特别的,当Switch节点为AOE网入度为0的节点(首节点)时,Switch节点直接触发,若超时时间内表达式为真,则执行动作1,为假或者发生超时事件执行动作2。 | |
Switch2 分支节点2 |
Switch2节点为分支动作判断,该节点连接着两条支路,节点自身无表达式(即无需填写事件发生的条件),而是以指向此节点的动作的执行情况来作为逻辑判断。 |
触发后续动作的逻辑为:若指向此节点的动作都执行成功,该节点序号为1的边进行动作;否则序号为2的边进行动作。 |
2.5 AOE动作类型
动作指一个复杂的控制策略所细分出来的步骤,在AOE中表现为节点之间的有向边。当首节点所表示的事件被触发后,则按照节点事件中所定义的规则,对应的动作(边)将被执行。
按照不同的动作内容,AOE动作可分为以下几类。
动作类型 | 动作名称 | 含义 |
---|---|---|
None | 无动作 | 不进行任何动作 |
SET_POINTS | 置点 | 对测点和变量赋值 |
SET_POINTS_WITH_CHECK | 带检查的置点 | 对测点和变量赋值并等待测点值和置点命令一致 |
SET_POINTS2 | 支持向量计算的置点 | 对测点和变量赋值(支持向量计算) |
SET_POINTS_WITH_CHECK2 | 支持向量计算的带检查置点 | 对测点和变量赋值并等待测点值和置点命令一致(支持向量计算) |
Solve | 线性方程组求解 | 对线性方程组进行求解 |
NLSOLVE | 非线性方程组求解 | 对非线性方程组进行求解 |
MILP | 混合整数线性规划(稀疏) | 稀疏描述的混合整数线性规划问题求解 |
SimpleMILP | 混合整数线性规划(稠密) | 稠密描述的混合整数线性规划问题求解 |
NLP | 非线性规划 | 非线性规划问题求解 |
具体的配置格式详见AOE策略文件配置。
AOE各动作的具体含义和注意事项如下:
None(无动作)
无动作即控制器不执行任何动作,该节点事件被触发后,直接进入下一节点事件的等待触发状态。
SET_POINTS(置点)
置点动作可以进行测点的赋值,测点即指测点配置文件中用户已定义的对象;也可以进行变量的定义,此处的变量指本控制策略中涉及到的非测点对象,可用于定义控制过程中出现的数学计算式、声明物理意义的中间变量、为减少策略撰写工作量而对表达式整体标识一个别名等等。
置点动作可以直接赋值或赋予表达式,测点或已定义的变量可用于定义新变量。赋值对象的类型可以为数字量或者模拟量。
SET_POINTS_WITH_CHECK(带检查的置点)
主要置点功能与Set_Points一样,区别在于该动作指向的节点(事件)会等待测点值和置点命令一致(整型的指令一样,浮点数指令和测点值相差不超过1e-6)才算事件发生的条件之一,也就是说“指令生效 && 事件表达式结果 ”事件才算发生。
注意:SET_POINTS_WITH_CHECK动作指向的节点的超时时间要大于该测点采集时间,因为测点数据需下发后再采集才能进行“下发是否成功”的判断。
SET_POINTS2(支持向量计算的置点)
主要置点功能与Set_Points一样,区别在于该动作支持向量计算,向量计算格式要求如下:。
待赋值向量:向量计算表达式;
例:
[a1,a2]:([1,2]+[15,10])*10+[1,2]; %实现赋值a1=161,a2=122
注:
1.赋值号":"左右两侧向量维数需相同;
2.支持"+"、"-"、"*"混合运算,但目前不支持矩阵求逆等复杂计算;
3.该动作里向量元素可以为测点或变量,如“[a,b]:[1,2]”,这里a,b可以是测点或变量,如果a,b是变量,则它们的类型只能是浮点数,不能是张量;
4.该动作可以更新事先定义为向量类型的变量,比如定义变量c:[c1,c2,c3];d:[d1,d2,d3]。 则可通过该动作更新变量“c:[1,2,3];d:[3,3,4];”
5.可以定义变量 var=[a,b,c,d],其中a,b,c,d是测点或类型为浮点数的变量,然后在SET_POINTS2的动作里面可以使用“var:[1,3,4,5];”这种写法为a,b,c,d幅值。
SET_POINTS_WITH_CHECK2(支持向量计算的带检查置点)
主要置点功能与SET_POINTS_WITH_CHECK一样,区别在于该动作支持向量计算,该部分格式与SET_POINTS2相同。
Solve(线性方程组求解)
可求解线性方程组 Ax = b,其中 A 为系数矩阵,x 为未知数组成的向量,b 为常数项向量。
#1)方程组:#
<方程式1>;
<方程式2>;
...
#2)变量声明:#
<变量名1>,<变量名2>,...
NLSOLVE(非线性方程组求解)
可求解非线性方程组。
#1)方程组:#
<方程式1>;
<方程式2>;
...
#2)变量声明:#
<变量名1>,<变量名2>,...
注:为了使计算收敛,变量必要时需要赋初值,格式为<变量名:初值>;
MILP与SimpleMILP(混合整数线性规划)
此动作用于在给定可行域内,求解线性约束下线性目标函数的最优解及最优值。
MILP全称为Mixed-integer linear programming,即混合整数线性规划,指目标函数和约束条件均为线性,部分决策变量限制为整数的数学规划问题。具体来说,其约束条件支持等式约束及不等式约束;变量类型包括 0-1变量、整型变量、实数型变量。
在本控制器的动作设置中,MILP和SimpleMILP区别在于前者的约束为稀疏矩阵,即后者则为稠密矩阵。通常认为矩阵中非零元素的总数比上矩阵所有元素总数的值小于等于0.05时的矩阵为稀疏矩阵。
以混合整数线性规划(MILP)为例,其动作的设置参数包括:
#1)目标函数:#
min/max(<表达式>)
#2)约束条件:#
<bool表达式1>;
<bool表达式2>;
...
#3)变量声明:#
<变量名1>:<变量类型1>,
<变量名2>:<变量类型2>,
...
其中变量类型包括以下三类:
变量类型 | 含义 |
---|---|
1 | 0-1二进制变量 |
2 | 整型变量 |
3 | 实数型变量 |
实际列写时,按顺序写下目标函数、约束条件、变量声明的标准格式式子即可,上例中##
间的内容不必写入。具体例子详见微网储能削峰填谷——AOE边声明。
NLP(非线性规划)
此动作用于在给定可行域内,求解约束下目标函数的最优解及最优值,其中目标函数和约束条件至少有一个为非线性。
NLP全称为Nonlinear programming,即非线性规划,指目标函数和约束条件至少有一个为非线性的数学规划问题。具体来说,其约束条件支持等式约束及不等式约束;该动作变量类型为实数型变量。
#1)目标函数:#
<表达式>
#2)约束条件:#
<表达式1>:[表达式下限/表达式上限];
<表达式2>:[表达式下限/表达式上限];
...
#3)变量声明:#
<变量名1>:[变量下限/变量上限/初始值],
<变量名2>:[变量下限/变量上限/初始值],
...
注:
1.若无上下限对应位置不写,如x[/3]表示变量x≤3;
2.变量声明若无初始值要求,可简写为[变量下限/变量上限]。
2.6 AOE网络的设计流程
对于特定可控制对象和控制目标,AOE设计流程包含设计基于事件驱动的控制策略和构建AOE网络两步.
设计基于事件驱动的控制策略
-
单个动作进行计算时需要用到的中间量必须由测点获取、变量定义或者在前驱动作中通过置点确定。这里的前驱动作指事件发生前需要被执行的所有动作。
-
确定每个动作开始执行时需要满足的事件条件和前驱动作,构建控制策略的拓扑逻辑关系,其中开始执行时需要满足的事件条件指动作执行前需要满足的条件。
-
确定每个动作执行完成的事件条件、事件的超时时间,以及执行失败后需要采取的措施。其中:
执行完成的事件条件指动作执行后变量或测点需要满足的条件,根据控制策略具体情况确定需要满足的条件。
事件的超时时间指前驱动作执行后等待事件发生的最长时间。
执行失败后需要采取的措施指动作执行失败后可以选择的几种处理措施,包括:尝试重新执行失败的动作、忽略本次失败并不影响其它动作、停止受到影响的动作、停止本次控制策略的执行。
构建AOE网络
将策略分解为多个事件和由事件触发的动作之后,将这两类元素按照一定的执行逻辑组织起来形成AOE网络即可完成控制策略的设计。
-
动作和节点在计算中依赖的变量只能来自测点、变量定义或已经被执行过的动作中计算出的变量。
-
确定每个动作的顺序以及动作发生、需要满足的事件后,用节点表示事件,事件发生导致被执行的动作作为从这个节点出发的有向边,每条有向边指向的节点表示动作完成后需要判断是否发生的事件。
-
按照上述逻辑组织所有的节点和边,构成AOE网络拓扑。
3 通讯协议
LCC 控制器支持Modbus协议、DL /T 645协议、IEC 104协议、ETHERCAT协议(开发中),详细协议内容如下。若需了解如何在LCC中配置通信协议,请查看通道文件配置
3.1 Modbus通讯协议
Modbus是一种串行通讯协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本。
本控制器支持Modbus的Modbus-RTU、Modbus-TCP两种协议,并且支持控制器本机作为服务端、客户端两种模式。
Modbus协议规定由主站(客户端)发送指令包,并直至从站(服务端)回报为一次完整的通信过程。Modbus数据帧分为ASCII帧和RTU帧两种,ASCII帧数据帧格式如下
服务端ID | 功能码 | 数据内容 | LRC校验 |
---|---|---|---|
2 Bytes | 2 Bytes | n Bytes | 2 Bytes |
在RTU通信中Modbus客户端发送的两个指令包需要间隔至少3.5个字节时间。RTU帧数据帧格式如下
服务端ID | 功能码 | 数据内容 | CRC校验 |
---|---|---|---|
1 Bytes | 1 Bytes | n Bytes | 2 Bytes |
Modbus协议中,功能码如下
功能码 | 功能 | 作用 |
---|---|---|
0x01 | 读线圈寄存器 | 取得一组逻辑线圈的当前状态(ON/OFF) |
0x02 | 读离散输入寄存器 | 取得一组开关输入的当前状态(ON/OFF) |
0x03 | 读保持寄存器 | 在一个或多个保持寄存器中取得当前的二进制值 |
0x04 | 读输入寄存器 | 在一个或多个输入寄存器中取得当前的二进制值 |
0x05 | 写单个线圈寄存器 | 写入一个逻辑线圈寄存器 |
0x06 | 写单个保持寄存器 | 写入一个保持寄存器 |
0x0f | 写多个线圈寄存器 | 写入一组连续逻辑线圈寄存器 |
0x10 | 写多个保持寄存器 | 写入一组连续保持寄存器 |
详细Modbus协议规范请访问Modbus组织官网下载查看。
在LCC控制器中,Modbus配置的详细方法参见通道文件配置。
3.2 DL /T 645通讯协议
DL /T 645是多功能电能表与数据终端设备进行数据交换式的物理连接和协议的规范和标准,本设备依据协议采用中国电力企业联合会提出的DL /T 645-2007《多功能电能表》标准规约,实现设备与多功能电能表的信息通信。
详细协议可以参考《DL /T 645-2007 多功能电能表通信协议.pdf》。
在LCC控制器中,DL /T 645配置的详细方法参见通道文件配置。
3.3 IEC60870-5-104规约通讯协议
IEC60870-5-104规约,简称IEC104,IEC104规约由国际电工委员会制定。IEC104规约把IEC101的应用服务数据单元(ASDU)用网络规约TCP/IP进行传输的标准,该标准为远动信息的网络传输提供了通信规约依据。采用104规约组合101规约的ASDU的方式后,可很好的保证规约的标准化和通信的可靠性。
详细协议可以参考《IEC60870-5-104规约.pdf》。
在LCC控制器中,IEC104配置的详细方法参见通道文件配置。
3.4 MQTT通讯协议
MQTT协议是一种消息列队传输协议,采用订阅、发布机制,订阅者只接收自己已经订阅的数据,非订阅数据则不接收,既保证了必要的数据的交换,又避免了无效数据造成的储存与处理。因此在工业物联网中得到广泛的应用。MQTT协议采用ISO/IEC 20922标准
详细协议可以参考ISO/IEC 20922官方版及[《ISO/IEC 20922协议中文版》](./files/ISO-IEC 20922协议中文版.pdf)。
在LCC控制器中,MQTT配置的详细方法参见通道文件配置。
3.5 EtherCAT通讯协议
正在努力准备中...
3.6 协议转发
LCC 控制器不仅支持单种Modbus协议、DL/T 645协议、IEC 104协议、ETHERCAT协议的连接,还支持各类协议之间的转发,实现支持不同协议的设备间的通讯,极大方便用户对数据的处理。
若需了解如何在LCC中如何实现通信协议间转发,请查看下述内容:
3.6.1 Modbus-TCP转IEC 104协议
1、测试工具
该协议转发所需测试工具如下:
-
低代码控制器;
-
Vinci Software(支持协议IEC 60870-101/103/104和Modbus TCP/RTU/ASC,从模式和主模式测试);
-
Modbus Poll(Modbus客户端)和Modbus Slave(Modbus服务端)。
2、主要流程
Modbus部分:控制器作为Modbus客户端,Modbus Slave作为Modbus服务端,Modbus Slave主动上传采集的数据至控制器;
数据处理:将Modbus采集到数据转存与IEC 104协议对应测点之中。
IEC 104部分:控制器作为IEC 104服务端,Vinci作为IEC 104客户端,控制器主动上传数据至Vinci或Vinci发送总召命令读取控制器中所有数据。
3、控制器配置文件
3.1、测点配置文件
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | YX1 | TRUE | FALSE | 0 | 遥信1 |
2 | 100002 | 测点2 | YX2 | TRUE | FALSE | 0 | 遥信2 |
3 | 100003 | 测点3 | YX3 | TRUE | FALSE | 0 | 遥信3 |
4 | 100004 | 测点4 | YX4 | TRUE | FALSE | 0 | 遥信4 |
5 | 100005 | 测点5 | YX5 | TRUE | FALSE | 0 | 遥信5 |
6 | 100006 | 测点6 | YX6 | TRUE | FALSE | 0 | 遥信6 |
7 | 100007 | 测点7 | YX7 | TRUE | FALSE | 0 | 遥信7 |
8 | 100008 | 测点8 | YX8 | TRUE | FALSE | 0 | 遥信8 |
9 | 100009 | 测点9 | YX9 | TRUE | FALSE | 0 | 遥信9 |
10 | 100010 | 测点10 | YX10 | TRUE | FALSE | 0 | 遥信10 |
11 | 100011 | 测点11 | YC1 | FALSE | FALSE | 0 | 遥测1 |
12 | 100012 | 测点12 | YC2 | FALSE | FALSE | 0 | 遥测2 |
13 | 100013 | 测点13 | YC3 | FALSE | FALSE | 0 | 遥测3 |
14 | 100014 | 测点14 | YC4 | FALSE | FALSE | 0 | 遥测4 |
15 | 100015 | 测点15 | YC5 | FALSE | FALSE | 0 | 遥测5 |
16 | 100016 | 测点16 | YC6 | FALSE | FALSE | 0 | 遥测6 |
17 | 100017 | 测点17 | YC7 | FALSE | FALSE | 0 | 遥测7 |
18 | 100018 | 测点18 | YC8 | FALSE | FALSE | 0 | 遥测8 |
19 | 100019 | 测点19 | YC9 | FALSE | FALSE | 0 | 遥测9 |
20 | 100020 | 测点20 | YC10 | FALSE | FALSE | 0 | 遥测10 |
3.2、通信通道配置文件
Modbus通信通道配置文件
Modbus-TCP客户端的通信通道配置文件如下:
通道名称 | 测试通道1 | 序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|---|---|
测点个数 | 20 | 1 | COILS | 0 | Binary | FALSE | 5000 | 100001 |
服务端ip | 127.0.0.1 | 2 | COILS | 1 | Binary | FALSE | 5000 | 100002 |
服务端端口 | 5502 | 3 | COILS | 2 | Binary | FALSE | 5000 | 100003 |
slave id | 1 | 4 | COILS | 3 | Binary | FALSE | 5000 | 100004 |
通信协议 | XA | 5 | COILS | 4 | Binary | FALSE | 5000 | 100005 |
一次读寄存器数上限 | 125 | 6 | COILS | 5 | Binary | FALSE | 5000 | 100006 |
一次读开关数上限 | 2000 | 7 | COILS | 6 | Binary | FALSE | 5000 | 100007 |
一次写寄存器数上限 | 120 | 8 | COILS | 7 | Binary | FALSE | 5000 | 100008 |
一次写开关数上限 | 1968 | 9 | COILS | 8 | Binary | FALSE | 5000 | 100009 |
轮询周期(ms) | 5000 | 10 | COILS | 9 | Binary | FALSE | 5000 | 100010 |
超时(ms) | 1000 | 11 | HOLDING | 10 | TwoByteIntSigned | FALSE | 5000 | 100011 |
状态测点号 | 12 | HOLDING | 11 | TwoByteIntSigned | FALSE | 5000 | 100012 | |
13 | HOLDING | 12 | TwoByteIntSigned | FALSE | 5000 | 100013 | ||
14 | HOLDING | 13 | TwoByteIntSigned | FALSE | 5000 | 100014 | ||
15 | HOLDING | 14 | TwoByteIntSigned | FALSE | 5000 | 100015 | ||
16 | HOLDING | 15 | TwoByteIntSigned | FALSE | 5000 | 100016 | ||
17 | HOLDING | 16 | TwoByteIntSigned | FALSE | 5000 | 100017 | ||
18 | HOLDING | 17 | TwoByteIntSigned | FALSE | 5000 | 100018 | ||
19 | HOLDING | 18 | TwoByteIntSigned | FALSE | 5000 | 100019 | ||
20 | HOLDING | 19 | TwoByteIntSigned | FALSE | 5000 | 100020 |
IEC 104通信通道配置文件
IEC 104服务端的通信通道配置文件如下:
通道名称 | iec104服务通道1 | 连接名称 | 104连接1 | 序号 | 起始地址 | 点号 | 是否遥信 | 控制点地址 |
---|---|---|---|---|---|---|---|---|
连接个数 | 1 | 测点个数 | 20 | 1 | 1 | 100001 | TRUE | 6001 |
服务端端口 | 2404 | 客户端ip | 127.0.0.1 | 2 | 2 | 100002 | TRUE | 6002 |
遥信数据类型 | 1 | 客户端端口 | 9999 | 3 | 3 | 100003 | TRUE | 6003 |
遥测数据类型 | 13 | 通道状态点号 | 100020 | 4 | 4 | 100004 | TRUE | 6004 |
是否为客户端 | FALSE | 源发地址 | 0 | 5 | 5 | 100005 | TRUE | 6005 |
公共地址 | 1 | 6 | 6 | 100006 | TRUE | |||
公共地址字节数 | 2 | 7 | 7 | 100007 | TRUE | |||
传输原因字节数 | 2 | 8 | 8 | 100008 | TRUE | |||
信息体地址字节数 | 3 | 9 | 9 | 100009 | TRUE | |||
T1超时(ms) | 15000 | 10 | 10 | 100010 | TRUE | |||
T2超时(ms) | 10000 | 11 | 11 | 100011 | FALSE | 6011 | ||
T3超时(ms) | 20000 | 12 | 12 | 100012 | FALSE | 6012 | ||
最大发送报文参数 | 12 | 13 | 13 | 100013 | FALSE | 6013 | ||
最大接受报文参数 | 8 | 14 | 14 | 100014 | FALSE | 6014 | ||
控制方向是否带时标 | FALSE | 15 | 15 | 100015 | FALSE | 6015 | ||
总召时间间隔(ms) | 10000 | 16 | 16 | 100016 | FALSE | |||
是否为客户端 | FALSE | 17 | 17 | 100017 | FALSE | |||
点度量总召时间间隔(ms) | 10000 | 18 | 18 | 100018 | FALSE | |||
19 | 19 | 100019 | FALSE | |||||
20 | 20 | 100020 | FALSE |
4、测试过程
4.1Modbus Slave配置
如下图所示,配置Modbus服务端的IP地址及端口号(根据实际情况变动);并完成线圈及保存寄存器的地址+数据配置,完成后点击connection。
4.2低代码控制器配置
控制器作为Modbus客户端以及IEC 104服务端,上传第三节中的各配置文件,注意其中IP地址及端口号需根据实际情况变动。
4.3Vinci配置
如下图所示,配置IEC 104客户端的IP地址及端口号(根据实际情况变动),设置公共地址、源发地址与低代码控制器IEC 104通信通道配置文件一致,完成后点击Start,即可得到如图的数据。
由于控制器会主动上传数据至Vinci,所以能自动显示数据,同时Vinci可以发送总召命令读取控制器中公共地址相同的所有数据。
对比数据可知低代码控制器完成了Modbus-TCP至IEC 104协议转发任务。
3.6.2 IEC 104转Modbus-TCP协议
1、测试工具
该协议转发所需测试工具如下:
-
低代码控制器;
-
Vinci Software(支持协议IEC 60870-101/103/104和Modbus TCP/RTU/ASC,从模式和主模式测试);
-
Modbus Poll(Modbus客户端)和Modbus Slave(Modbus服务端)。
2、主要流程
IEC 104部分:控制器作为IEC 104客户端,Vinci作为IEC 104服务端,控制器读取Vinci上传的数据;
数据处理:将IEC 104采集到数据转存与Modbus协议对应测点之中。
Modbus部分:控制器作为Modbus服务端,Modbus Poll作为Modbus客户端,控制器将数据写入Modbus Poll中。
3、控制器配置文件
3.1、测点配置文件
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | YX1 | TRUE | FALSE | 0 | 遥信1 |
2 | 100002 | 测点2 | YX2 | TRUE | FALSE | 0 | 遥信2 |
3 | 100003 | 测点3 | YX3 | TRUE | FALSE | 0 | 遥信3 |
4 | 100004 | 测点4 | YX4 | TRUE | FALSE | 0 | 遥信4 |
5 | 100005 | 测点5 | YX5 | TRUE | FALSE | 0 | 遥信5 |
6 | 100006 | 测点6 | YX6 | TRUE | FALSE | 0 | 遥信6 |
7 | 100007 | 测点7 | YX7 | TRUE | FALSE | 0 | 遥信7 |
8 | 100008 | 测点8 | YX8 | TRUE | FALSE | 0 | 遥信8 |
9 | 100009 | 测点9 | YX9 | TRUE | FALSE | 0 | 遥信9 |
10 | 100010 | 测点10 | YX10 | TRUE | FALSE | 0 | 遥信10 |
11 | 100011 | 测点11 | YC1 | FALSE | FALSE | 0 | 遥测1 |
12 | 100012 | 测点12 | YC2 | FALSE | FALSE | 0 | 遥测2 |
13 | 100013 | 测点13 | YC3 | FALSE | FALSE | 0 | 遥测3 |
14 | 100014 | 测点14 | YC4 | FALSE | FALSE | 0 | 遥测4 |
15 | 100015 | 测点15 | YC5 | FALSE | FALSE | 0 | 遥测5 |
16 | 100016 | 测点16 | YC6 | FALSE | FALSE | 0 | 遥测6 |
17 | 100017 | 测点17 | YC7 | FALSE | FALSE | 0 | 遥测7 |
18 | 100018 | 测点18 | YC8 | FALSE | FALSE | 0 | 遥测8 |
19 | 100019 | 测点19 | YC9 | FALSE | FALSE | 0 | 遥测9 |
20 | 100020 | 测点20 | YC10 | FALSE | FALSE | 0 | 遥测10 |
3.2、通信通道配置文件
IEC 104通信通道配置文件
IEC 104客户端的通信通道配置文件如下:
通道名称 | iec104服务通道1 | 序号 | 起始地址 | 点号 | 是否遥信 | 控制点地址 |
---|---|---|---|---|---|---|
测点个数 | 20 | 1 | 1 | 100001 | TRUE | 6001 |
服务端ip | 127.0.0.1 | 2 | 2 | 100002 | TRUE | 6002 |
服务端端口 | 2404 | 3 | 3 | 100003 | TRUE | 6003 |
通道状态点号 | 4 | 4 | 100004 | TRUE | 6004 | |
源发地址 | 0 | 5 | 5 | 100005 | TRUE | 6005 |
公共地址 | 1 | 6 | 6 | 100006 | TRUE | |
公共地址字节数 | 2 | 7 | 7 | 100007 | TRUE | |
传输原因字节数 | 2 | 8 | 8 | 100008 | TRUE | |
信息体地址字节数 | 3 | 9 | 9 | 100009 | TRUE | |
T2超时(ms) | 15000 | 10 | 10 | 100010 | TRUE | |
T2超时(ms) | 10000 | 11 | 11 | 100011 | FALSE | 6011 |
T3超时(ms) | 20000 | 12 | 12 | 100012 | FALSE | 6012 |
最大发送报文参数 | 12 | 13 | 13 | 100013 | FALSE | 6013 |
最大接收报文参数 | 8 | 14 | 14 | 100014 | FALSE | 6014 |
控制方向是否带时标 | FALSE | 15 | 15 | 100015 | FALSE | 6015 |
总召时间间隔(ms) | 10000 | 16 | 16 | 100016 | FALSE | |
是否为客户端(必须是TRUE) | TRUE | 17 | 17 | 100017 | FALSE | |
点度量总召时间间隔(ms) | 10000 | 18 | 18 | 100018 | FALSE | |
19 | 19 | 100019 | FALSE | |||
20 | 20 | 100020 | FALSE |
Modbus通信通道配置文件
Modbus-TCP服务端的通信通道配置文件如下:
通道名称 | server测试通道 | 通道名称 | 测试通道1 | 序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 | |
---|---|---|---|---|---|---|---|---|---|---|---|
连接个数 | 1 | 测点个数 | 20 | 1 | COILS | 0 | Binary | FALSE | 5000 | 100001 | |
服务端口 | 502 | 服务端ip | 127.0.0.1 | 2 | COILS | 1 | Binary | FALSE | 5000 | 100002 | |
服务端端口 | 5502 | 3 | COILS | 2 | Binary | FALSE | 5000 | 100003 | |||
slave id | 1 | 4 | COILS | 3 | Binary | FALSE | 5000 | 100004 | |||
通信协议 | XA | 5 | COILS | 4 | Binary | FALSE | 5000 | 100005 | |||
一次读寄存器数上限 | 125 | 6 | COILS | 5 | Binary | FALSE | 5000 | 100006 | |||
一次读开关数上限 | 2000 | 7 | COILS | 6 | Binary | FALSE | 5000 | 100007 | |||
一次写寄存器数上限 | 120 | 8 | COILS | 7 | Binary | FALSE | 5000 | 100008 | |||
一次写开关数上限 | 1968 | 9 | COILS | 8 | Binary | FALSE | 5000 | 100009 | |||
轮询周期(ms) | 5000 | 10 | COILS | 9 | Binary | FALSE | 5000 | 100010 | |||
超时(ms) | 1000 | 11 | HOLDING | 10 | TwoByteIntSigned | FALSE | 5000 | 100011 | |||
状态测点号 | 12 | HOLDING | 11 | TwoByteIntSigned | FALSE | 5000 | 100012 | ||||
13 | HOLDING | 12 | TwoByteIntSigned | FALSE | 5000 | 100013 | |||||
14 | HOLDING | 13 | TwoByteIntSigned | FALSE | 5000 | 100014 | |||||
15 | HOLDING | 14 | TwoByteIntSigned | FALSE | 5000 | 100015 | |||||
16 | HOLDING | 15 | TwoByteIntSigned | FALSE | 5000 | 100016 | |||||
17 | HOLDING | 16 | TwoByteIntSigned | FALSE | 5000 | 100017 | |||||
18 | HOLDING | 17 | TwoByteIntSigned | FALSE | 5000 | 100018 | |||||
19 | HOLDING | 18 | TwoByteIntSigned | FALSE | 5000 | 100019 | |||||
20 | HOLDING | 19 | TwoByteIntSigned | FALSE | 5000 | 100020 |
4、测试过程
4.1Vinci配置
如下图所示,配置IEC 104服务端的IP地址及端口号(根据实际情况变动),设置公共地址、源发地址与低代码控制器IEC 104通信通道配置文件一致,并完成遥信、遥测的地址+数据配置以及控制点地址配置,完成后点击Start,即可得到如图的数据。
4.2低代码控制器配置
控制器作为IEC 104客户端以及Modbus服务端,上传第三节中的各配置文件,注意其中IP地址及端口号需根据实际情况变动。
4.3Modbus Poll配置
如下图所示,配置Modbus服务端的IP地址及端口号(根据实际情况变动),完成后点击connection。
由于控制器会主动上传数据至Modbus Poll,所以能自动显示数据。对比数据可知低代码控制器完成了IEC 104至Modbus-TCP协议转发任务。
4 配置文件编写
低代码控制器与被控对象进行通信,得到关于被控对象的测点信息,利用测点信息实现特定的控制策略,从而完成控制过程。控制策略由事件驱动的AOE网络实现,需要将控制策略转换为一个AOE网络。
与此对应的,低代码控制器文件配置分为三个部分:测点配置、通信通道配置和AOE配置。
测点配置用于描述测点所需要的属性。
通信通道配置用于描述控制器与被控对象的通信方式,并依据测点配置文件中的测点属性,给出保存测点值的寄存器信息和地址。
AOE配置是建立AOE网络模型来实现所需的控制策略。
三个配置文件可以用excel进行编辑,并在低代码控制器上传使用。低代码控制器支持后缀为.xls
、.xlsx
、.csv
的配置文件上传。
下面将分章节介绍三个配置文件。
配置文件模板请参见
注意:
- 低代码控制器支持后缀为
.xls
、.xlsx
、.csv
的配置文件上传,其中.csv
需保存为UTF-8或带BOM的UTF-8编码格式。 - 保存为
.csv
格式时,注意带有数字的单元格应显示完整数字(单元格格式可以转换为文本格式),勿出现科学计数法形式影响解析。 - 用Excel编辑操作时,删去多余的行最好直接删除整行,不要用“清除数据操作”。
4.1 测点(point)文件配置
如前所述,测点文件配置是对每一个测点的属性进行定义。
测点可以分为两类:采集点和计算点。
采集点是指通过通信(串口、以太网、wifi、蓝牙、CAN总线等方式)从设备采集上来的量测点。
计算点是配置了计算公式的测点,计算点公式里面一般包含其他采集点的别名或点号,或其他计算点的别名或点号。要注意的是,计算点之间不能存在循环依赖,例如计算点A公式里面包含了计算点B,计算点B的公式里面包含了计算点A,这是不合法的。
采集点的属性解释
按照配置文件excel中列的顺序排列,采集点的属性解释包括:
- 序号:u64类型,是测点配置表格里给各个测点的编号,只是配置表格中的一个标记,一般从1开始连续对测点进行编号,方便表格编写,不影响控制器程序功能。
- 点号:u64类型,是程序里给这个测点的编号id,可以自己定义,使用时,测点配置文件和通信配置文件中具有相同点号的测点一一对应,完成对接。注意:测点点号需从100001后开始编号。
- 名称:字符串类型,可包含中文,一般用
“测点+序号”
的格式来定义,注意不要出现回车符等特殊字符。 - 别名:字符串类型,由英文字母、数字与下划线组成,可以作为变量名用于计算点计算公式、AOE条件判断公式、变量定义公式和具体动作中。
- 是否离散:Bool类型,有TRUE和FALSE两个选项,用于表示测点是使用i64还是f64方法存储。一般开关量使用TRUE,表示测点是离散值,为整型数据;模拟量使用FALSE,表示测点是连续值,为浮点型数据。
- 是否是计算点:Bool类型,有TRUE和FALSE两个选项,用于表示测点是采集点还是计算点。该属性为TRUE代表该测点为计算点,FALSE代表该测点为采集点。
- 计算公式:采集点属性中,计算公式不起作用。
- 变换公式:对设备发来的数据进行函数变换后作为测点的值。该公式中的变量可能是该测点本身,也可以是简单的一个数字,后者将会和采集的数值相乘作为测量值。如果计算点配置了该测点作为变量,计算过程用的是变换后的值。
- 逆变换公式:与变换公式对应,用于在遥控遥调时,目标值经过变换再发给设备。例如:变换公式是10, 则逆变换公式为0.1; 变换公式为:测点别名^2, 则逆变换公式为:sqrt(测点别名)。
- 变化公式:该公式用于判断是否需要变化上传,如果计算结果>0则表示该次采集到的点需要上传。
- 判零公式:该公式用于判断测点是否为0,用于消除零飘现象的影响,该公式中的变量只能是该测点本身,例如:测点别名 < 0.01。
- 单位:字符串类型,表示测点的实际物理意义下的单位。
- 上限值:可以为空或一个数字,用于坏数据辨识,如果采集点的值大于该值则说明是坏数据,本次采集值会被抛弃。
- 下限值:可以为空或一个数字,用于坏数据辨识,如果采集点的值小于该值则说明是坏数据,本次采集值会被抛弃。
- 告警级别1判据:公式,用于判断是否需要告警,例如计算结果>0,将会产生告警信息。
- 告警级别2判据:公式,用于判断是否需要告警,例如计算结果>0,将会产生告警信息。
- 是否实时:Bool类型,有TRUE和FALSE两个选项。当属性是TRUE时,每次采集均会发布到云端,变化公式将不再起作用,常常用于测试,或某些比较重要的测点。当属性是FALSE时,不会实时上传。
- 是否SOE:Bool类型,有TRUE和FALSE两个选项。这里SOE表示事件顺序记录(Sequence Of Event),当属性是TRUE时,会将该测点状态发生的变化及其时间保存起来,后面查询时可按照时间顺序排列测点变化事件。
- 默认值:测点的初始值。
- 本地地址:u64类型,是本地程序里的地址。
- 备注:可以用来解释测点的具体作用。
计算点的属性解释
按照配置文件excel中列的顺序排列,采集点的属性解释包括:
- 序号、点号、名称:与采集点相同。
- 别名:字符串类型,由英文字母、数字与下划线组成,可以当做变量名用于其他计算点的计算公式、AOE条件判断公式、变量定义公式、设点动作中。
- 是否离散:与采集点相同。
- 是否是计算点:计算点该属性为TRUE。
- 计算公式:表示计算点的取值的计算公式,计算公式的写法。
- 变换公式、逆变换公式、判零公式:不起作用。
- 变化公式、单位、上限值、下限值、告警级别1判据、告警级别2判据、是否实时:与采集点相同
- 是否SOE:不起作用。
- 默认值:测点的初始值。
- 备注:可以用来解释测点的具体作用。
属性说明
告警:告警信息会发送、保存(如果isHisDb=true),当告警级别发生变化或复位(告警消失)均会发出消息,多次采集但告警级别不变,则只会发送最开始发生的告警。
测点(Point)文件相关规则与限制
单个文件大小不能超过设置,目前默认是不超过2M。
测点文件增加删除后需要reset才能生效。
测点文件配置的具体案例,可参考应用范例,配置模板请在配置文件模板中下载。
4.2 通道(transport)文件配置
通道文件配置可以分为通道参数配置和测点寄存器参数配置两个部分。
通道参数配置
目前通信协议支持Modbus RTU、Modbus TCP、IEC104、DL/T645和MQTT通信协议,后期会支持EtherCAT通讯协议。
若采用Modbus通讯协议,通道参数配置的内容包括客户端IP\服务端IP、客户端端口\服务端端口、slave id、通信协议等。通道参数配置可以根据不同协议类型参考如下说明。
- ModBus TCP服务端通道文件配置
- ModBus TCP客户端通道文件配置
- ModBus RTU服务端通道文件配置
- ModBus RTU客户端通道文件配置
- ModBus通道文件测点寄存器参数配置
- DL /T645 UART服务端通道文件配置
- DL /T645 TCP服务端通道文件配置
- DLT645通道文件测点寄存器参数配置
- IEC 104服务端通道文件配置
- IEC 104客户端通道文件配置
- IEC104通道文件测点寄存器参数配置
- MQTT通道文件配置
- MQTT通道文件测点寄存器参数配置
通信通道(transport)文件相关规则与限制
命名规则
通信通道(transport)文件命名要求以(tcp-mbc,rtu-mbc,tcp-mdb,rtu-mbd)开头,这些开头分别表示不同的协议,不得修改和删去。
文件名开头 | 协议 | 服务端/客户端 |
---|---|---|
tcp-mbd | Modbus TCP | 服务端 |
tcp-mbc | Modbus TCP | 客户端 |
rtu-mbd | Modbus RTU | 服务端 |
rtu-mbc | Modbus RTU | 客户端 |
dlt645 | DL /T 645 | 服务端 |
iec104d | DL /T 645 | 服务端 |
iec104c | DL /T 645 | 客户端 |
mqtt | MQTT | / |
文件命名示例:"tcp-mbd-transport-example.xlsx",表示Modbus TCP协议服务端。
文件大小
单个文件大小不能超过设置,目前默认是不超过2M大小。
文件上传
通道文件删除、更换或增加后需要reset才能生效,如果同名的通道文件更新不会增加新的文件,不需要reset通道也会自动生效。
通信协议配置的具体案例可见附件:配置文件模板,或参考应用范例。
4.2.1 ModBus TCP服务端通道文件配置
ModBus TCP服务端通道文件配置模板
用tcp-mbd
开头,表示该文件为Modbus TCP协议中的服务端配置文件。模板请在配置文件模板中下载。
通道参数配置
Modbus TCP服务端通道参数配置需要首先配置通道名称、连接个数和服务端口。
- 通道名称:字符串类型,可包含中文。
- 连接个数:u64类型,用正整数表示,指TCP服务端建立的通道数量。
- 服务端口:u64类型,用正整数表示,需设置为未占用端口。
TCP服务端可以建立多个通道,对于每个通道,需要配置如下信息:
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 客户端IP:字符串类型,格式为IPv4地址格式。
- 客户端端口:u64类型,用正整数表示。
- slave id:u64类型,用正整数表示。
- 通信协议:用XA、ENCAP中二者之一表示。ENCAP指Modbus RTU Over TCP/IP通信协议。XA指Modbus TCP/IP通信协议。
- 一次读寄存器数上限:u64类型,用正整数表示。
- 一次读开关数上限:u64类型,用正整数表示。
- 一次写寄存器上限:u64类型,用正整数表示。
- 一次写开关数上限:u64类型,用正整数表示。
- 轮询周期和超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
测点寄存器参数配置
测点寄存器参数配置,可以参见ModBus通道文件测点寄存器参数配置。
4.2.2 ModBus TCP客户端通道文件配置
ModBus TCP客户端通道文件配置模板
用tcp-mbc
开头,表示该文件为Modbus TCP协议中的客户端配置文件。模板请在配置文件模板中下载。
通道参数配置
Modbus TCP客户端通道参数配置与TCP服务端时的情况基本相同,只是不需要设置通道名称、连接个数和服务端口。另外,客户端IP和客户端端口改为服务端IP和服务端端口。TCP客户端配置中只有一个通道。
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 服务端IP:字符串类型,格式为IPv4地址格式。
- 服务端端口:u64类型,用正整数表示。
- slave id:u64类型,用正整数表示。
- 通信协议:用XA、ENCAP中二者之一表示。
- 一次读寄存器数上限:u64类型,用正整数表示。
- 一次读开关数上限:u64类型,用正整数表示。
- 一次写寄存器上限:u64类型,用正整数表示。
- 一次写开关数上限:u64类型,用正整数表示。
- 轮询周期和超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
- 写功能码:格式为
coil;holding
,例如5;16
表示该连接指定了coil的写功能码是05,holding的写功能码是16。同时,功能码可以只设置一个或不设置,例如;16
表示该连接指定了holding的写功能码是16。 如果一个通道有多个连接,没有设置写功能码的连接,其写功能码和之前连接的逻辑一致。
注意:1.多个连接通信协议可以设为XA和ENCAP,但是要保证所有连接是一样的。2. 每个连接的slave id必须不一样。
测点寄存器参数配置
测点寄存器参数配置,可以参见ModBus通道文件测点寄存器参数配置。
4.2.3 ModBus RTU服务端通道文件配置
ModBus RTU服务端通道文件配置模板
用rtu-mbd
开头,表示该文件为Modbus RTU协议中的服务端配置文件。模板请在配置文件模板中下载。
通道参数配置
Modbus RTU服务端通道参数配置如下信息。RTU服务端配置中只有一个通道。 不需要设置连接个数、描述和优先级。
- 通道名称:字符串类型,可包含中文。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 文件路径:字符串类型,表示串口地址信息,用
/
隔开。 - 波特率:u64类型,用正整数表示。
- slave id:u64类型,用正整数表示。
- 通信协议:RTU。
- 一次读寄存器数上限:u64类型,用正整数表示。
- 一次读开关数上限:u64类型,用正整数表示。
- 一次写寄存器上限:u64类型,用正整数表示。
- 一次写开关数上限:u64类型,用正整数表示。
- 轮询周期和超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
测点寄存器参数配置
测点寄存器参数配置,可以参见ModBus通道文件测点寄存器参数配置。
4.2.4 ModBus RTU客户端通道文件配置
ModBus RTU客户端通道文件配置模板
用rtu-mbc
开头,表示该文件为Modbus RTU协议中的客户端配置文件。模板请在配置文件模板中下载。
通道参数配置
Modbus RTU客户端通道参数配置需要首先配置通道名称、连接个数、波特率和文件地址。
- 通道名称:字符串类型,可包含中文。
- 连接个数:u64类型,用正整数表示,指RTU客户端建立的通道数量。
- 波特率:u64类型,用正整数表示。
- 文件地址:字符串类型,表示串口地址信息,用
/
隔开。
RTU客户端可以建立多个通道, 对于每个通道,需要配置如下信息:
- 连接名称:字符串类型,可包含中文。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 描述:字符串类型,可包含中文。
- 优先级:u64类型,用正整数表示。
- slave id:u64类型,用正整数表示。
- 通信协议:RTU。
- 一次读寄存器数上限:u64类型,用正整数表示。
- 一次读开关数上限:u64类型,用正整数表示。
- 一次写寄存器上限:u64类型,用正整数表示。
- 一次写开关数上限:u64类型,用正整数表示。
- 轮询周期和超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
- 写功能码:格式为
coil;holding
,例如5;16
表示该连接指定了coil的写功能码是05,holding的写功能码是16。同时,功能码可以只设置一个或不设置,例如;16
表示该连接指定了holding的写功能码是16。 如果一个通道有多个连接,没有设置写功能码的连接,其写功能码和之前连接的逻辑一致。
测点寄存器参数配置
测点寄存器参数配置,可以参见ModBus通道文件测点寄存器参数配置。
4.2.5 ModBus通道文件测点寄存器参数配置
测点寄存器配置用于给出存储测点数据的地址信息,包括序号、寄存器类型、起始地址、数据类型、新请求标志、轮询周期、点号。对于每个通道,都需要对具体测点的寄存器信息进行以下配置:
- 序号:u64类型,用正整数表示。序号是通道配置中给各个测点的编号,一般从1开始连续对测点进行编号。
- 寄存器类型:有COILS、DISCRETE、INPUT、HOLDING四种。其中COILS表示线圈寄存器,表示寄存器的单位是1位(bit)数据,类型为开关量,可进行读写;DISCRETE表示离散输入寄存器,只能读取开关量;HOLDING表示保持寄存器,该寄存器的单位是2个byte,可以存放具体的数据量,并且是可读写的,INPUT表示输入寄存器,只能读取保持寄存器数据。
- 起始地址:u64类型,用正整数表示,根据数据类型确定测点的地址偏移。
- 数据类型:用约定的类型声明表示,测点支持的数据类型如下表所示。不同的测点对应于不同的起始地址和数据长度所决定的一个数据,数据长度取决于测点的数据类型。
注:字节顺序(Modbus大小端)相关规则如下,当数据字节数大于等于2字节时,通过Swapped实现高低位的交换。
首先做如下标准声明:大端模式指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,其字节顺序用ABCD表示,其中A(B/C/D)表示一个字节; 小端模式指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,其字节顺序用DCBA表示。
具体对应关系如下表:
- 新请求标志:有TRUE和FALSE两个选项。
- 轮询周期:经过一个轮询周期,测点的值进行一次更新,单位为毫秒。
- 点号:正如在测点文件配置中所描述的那样,通信通道的点号与测点的点号一一对应完成对接。
4.2.6 DL /T 645 UART服务端通道文件配置
DL /T 645 UART服务端通道文件配置模板
用dlt645
开头,表示该文件为DL /T 645协议中的服务端配置文件。模板请在配置文件模板中下载。
通道参数配置
DL /T 645 UART服务端通道参数配置需要首先配置通道名称、连接个数和服务端口。
- 通道名称:字符串类型,可包含中文。
- 连接个数:u64类型,用正整数表示,指TCP服务端建立的通道数量。
- 服务端口:u64类型,用正整数表示,需设置为未占用端口。
- 文件地址:字符串类型,串口硬件地址
- 数据位:u64类型,数据位个数。
- 停止位:u64类型,停止位个数。
- 校验位:字符串类型,校验位校验方式。
DL /T 645 UART服务端可以建立多个通道,对于每个通道,需要配置如下信息:
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- slave id:字符串类型,客户端ID。即电表表号,不足12位将自动在前面补零。
- 客户端端口:u64类型,用正整数表示。
- 通道状态点号:u64类型,用正整数表示。
- 轮询周期:单位为毫秒,用正整数表示。
- 超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
测点寄存器参数配置
测点寄存器参数配置,可以参见DL /T 645通道文件测点寄存器参数配置。
4.2.7 DL /T 645 TCP服务端通道文件配置
DL /T 645 TCP服务端通道文件配置模板
用dlt645
开头,表示该文件为DL /T 645协议中的服务端配置文件。模板请在配置文件模板中下载。
通道参数配置
DL /T 645 TCP服务端通道参数配置需要首先配置通道名称、连接个数和服务端口。
- 通道名称:字符串类型,可包含中文。
- 连接个数:u64类型,用正整数表示,指TCP服务端建立的通道数量。
- 服务端口:u64类型,用正整数表示,需设置为未占用端口。
- 文件地址:字符串类型,IP:Port,IP地址格式为IPv4地址格式。
DL /T 645 TCP服务端可以建立多个通道,对于每个通道,需要配置如下信息:
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- slave id:字符串类型,客户端ID。即电表表号,不足12位将自动在前面补零。
- 客户端端口:u64类型,用正整数表示。
- 通道状态点号:u64类型,用正整数表示。
- 轮询周期:单位为毫秒,用正整数表示。
- 超时时间:单位为毫秒,用正整数表示。
- 通道状态测点号:u64类型,用正整数表示。
测点寄存器参数配置
测点寄存器参数配置,可以参见DL /T 645通道文件测点寄存器参数配置。
4.2.8 DL /T 645通道文件测点寄存器参数配置
测点寄存器配置用于给出存储测点数据的地址信息,包括序号、数据标识、轮询周期、点号。对于每个通道,都需要对具体测点的寄存器信息进行以下配置:
- 序号:u64类型,用正整数表示。序号是通道配置中给各个测点的编号,一般从1开始连续对测点进行编号。
- 数据标识:即请求的数据内容,如0x00010000表示正向有功总电能。具体请参照《DL /T 645-2007 多功能电能表通信协议.pdf》附录A.2-A.6。
- 轮询周期:经过一个轮询周期,测点的值进行一次更新,单位为毫秒。
- 点号:正如在测点文件配置中所描述的那样,通信通道的点号与测点的点号一一对应完成对接。
4.2.9 IEC104服务端通道文件配置
IEC104服务端通道文件配置模板
用iec104d
开头,表示该文件为IEC104协议中的服务端配置文件。模板请在配置文件模板中下载。
通道参数配置
IEC104服务端通道参数配置需要首先配置通道名称、连接个数和服务端口。
- 通道名称:字符串类型,可包含中文。
- 连接个数:u64类型,用正整数表示,指TCP服务端建立的通道数量。
- 服务端口:u64类型,用正整数表示,需设置为未占用端口。
- 遥信数据类型:u64类型,可取1、3、5、20、30、31、32。指本服务端的遥信类型标识的编号,它的数值与104规约的类型标识一一对应,具体对应关系见表1。
- 遥测数据类型:u64类型,可取7、9、11、13、15、21、33、34、35、36、37,指本服务端的遥信类型标识的编号,它的数值与104规约的类型标识一一对应,具体对应关系见表1。
- 是否为主站:布尔类型,TRUE或者FALSE。如果是标准104协议(服务端从站),这里需要配置为FALSE。对于反向非标准104协议(服务端主站),这里需要配置为TRUE,在此情况下,若配置了多个通道,则只取第一个通道。
IEC104服务端可以建立多个通道(标准104协议),对于每个通道,需要配置如下信息:
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 客户端IP:字符串类型,格式为IPv4地址格式。
- 客户端端口:u64类型,用正整数表示。
- 通道状态点号:u64类型,用正整数表示。
- 公共地址:u64类型,用正整数表示。
- 公共地址字节数:u64类型,用正整数表示。
- 传输原因字节数:u64类型,用正整数表示。
- 信息体地址字节数:u64类型,用正整数表示,
- T1超时(ms):u64类型,用正整数表示。默认值15000。
- T2超时(ms):u64类型,用正整数表示。默认值10000。
- T3超时(ms):u64类型,用正整数表示。
- k:u64类型,最大发送报文参数。
- w:u64类型,最大接收报文参数。
- 控制方向是否带时标:布尔类型,TRUE或者FALSE。
- 总召时间间隔(ms):u64类型,服务端不设置。
- 是否为主站:布尔类型,TRUE或者FALSE。如果是标准104协议(服务端从站),这里需要配置为FALSE。对于反向非标准104协议(服务端主站),这里需要配置为TRUE。
- 点度量总召时间间隔(ms):u64类型,服务端不设置。
测点寄存器参数配置
测点寄存器参数配置,可以参见IEC104通道文件测点寄存器参数配置。
4.2.10 IEC104服务端通道文件配置
IEC104服务端通道文件配置模板
用iec104c
开头,表示该文件为IEC104协议中的客户端配置文件。模板请在配置文件模板中下载。
通道参数配置
IEC104客户端通道参数配置与IEC104服务端时的情况基本相同,只是不需要设置通道名称、连接个数和服务端口。另外,客户端IP和客户端端口改为服务端IP和服务端端口。TCP客户端配置中只有一个通道。
- 连接名称:字符串类型。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 服务端IP:字符串类型,格式为IPv4地址格式。
- 服务端端口:u64类型,用正整数表示。
- 通道状态点号:u64类型,用正整数表示。
- 公共地址:u64类型,用正整数表示。
- 公共地址字节数:u64类型,用正整数表示。
- 传输原因字节数:u64类型,用正整数表示。
- 信息体地址字节数:u64类型,用正整数表示,
- T1超时(ms):u64类型,用正整数表示。默认值15000。
- T2超时(ms):u64类型,用正整数表示。默认值10000。
- T3超时(ms):u64类型,用正整数表示。
- k:u64类型,最大发送报文参数。
- w:u64类型,最大接收报文参数。
- 控制方向是否带时标:布尔类型,TRUE或者FALSE。
- 总召时间间隔(ms):u64类型,可空缺,空缺代表不需要定时总召。
- 是否为主站:布尔类型,只能写TRUE。104客户端暂时只支持主站,即标准104协议,故此处配置只能为TRUE。
- 点度量总召时间间隔(ms):u64类型,可空缺,空缺代表不需要定时总召。
测点寄存器参数配置
测点寄存器参数配置,可以参见IEC104通道文件测点寄存器参数配置。
4.2.11 IEC104通道文件测点寄存器参数配置
测点寄存器配置用于给出存储测点数据的地址信息,包括序号、起始地址、点号、是否遥信、控制点地址。对于每个通道,都需要对具体测点的寄存器信息进行以下配置:
- 序号:u64类型,用正整数表示。序号是通道配置中给各个测点的编号,一般从1开始连续对测点进行编号。
- 监视方向信息体地址:u64类型,用正整数表示,表示该测点在监视方向的信息体地址,用于遥测和遥信。
- 点号:正如在测点文件配置中所描述的那样,通信通道的点号与测点的点号一一对应完成对接。
- 是否遥信:布尔类型,TRUE或者FALSE。用于标识该测点属于遥测数据还是遥信数据。
- 控制方向信息体地址:u64类型,用正整数表示,表示该测点在控制方向的信息体地址,用于遥调和遥控。
4.2.12 MQTT通道文件配置
MQTT通道文件配置模板
用mqtt
开头,表示该文件为MQTT协议通道配置文件。模板请在配置文件模板中下载。
通道参数配置
MQTT通道参数配置如下信息。
- 通道名称:字符串类型,可包含中文。
- 服务端IP:字符串类型,格式为IPv4地址格式。
- 服务端端口:u64类型,用正整数表示。
- 测点个数:u64类型,用正整数表示这个通道中测点的个数。
- 通道状态测点号:u64类型,用正整数表示。
- 读主题:字符串类型,读主题地址。
- 写主题:字符串类型,写主题地址。
- 用户名:可选,mqtt协议用户名。
- 密码:可选,mqtt协议密码。
- JSON格式:布尔类型,TRUE则mqtt使用JSON格式报文,FALSE则mqtt使用protobuf格式报文。
- 转发:布尔类型,是否将测点信息自动转发。
测点寄存器参数配置
测点寄存器参数配置,可以参见MQTT通道文件测点寄存器参数配置。
4.2.13 MQTT通道文件测点寄存器参数配置
测点寄存器配置用于给出存储测点数据的地址信息,包括序号、点号、是否可写。对于每个通道,都需要对具体测点的寄存器信息进行以下配置:
- 序号:u64类型,用正整数表示。序号是通道配置中给各个测点的编号,一般从1开始连续对测点进行编号。
- 点号:正如在测点文件配置中所描述的那样,通信通道的点号与测点的点号一一对应完成对接。
- 是否可写:bool类型,使用FALSE/TRUE表示该测点是否可写。
4.3 AOE策略文件配置
AOE策略文件文件配置可以在excel中完成,AOE表格可以分为AOE网络定义、AOE变量定义、AOE事件定义、AOE动作定义四个部分。
AOE文件增加删除后需要reset才能生效。
测点文件配置的具体案例,可参考应用范例,配置文件模板请在配置文件模板中下载。
4.3.1 AOE网络定义
AOE网络定义部分,定义了表格之中的AOE网络个数和整体信息以及一些变量的初始值,其配置内容包括AOE ID、是否启用、名称、触发条件(及触发条件参数)、变量初始值。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
<u64> | <Bool> | <String> | Simple_Repeat Time_Drive Event_Drive | <u64> <String> < \ > | <String>:<Float> |
-
AOE ID:不同AOE网络的标识,用<u64>(64位无符号整数)表示。(注:AOE ID需从65536后开始编号)。
-
是否启用:决定该AOE网络是否启用,用<Bool>(布尔类型)表示。
-
名称:表达AOE网络的功能,便于理解,用<String>(表示字符串类型)表示。
-
触发条件分为三类,即SimpleRepeat(定时触发)、TimeDriven(时间驱动)、EventDriven(事件驱动)。
-
触发条件参数:参数配置格式如下表
触发条件 说明 Simple_Repeat 触发条件参数为重复驱动之间的时间间隔,用正整数<u64>表示,单位为ms Time_Drive 表示执行计划,写法参照cron表达式,在设置时间点触发 Event_Drive 为缺省值,无需设置 -
变量定义方式:<变量名1>:<表达式1>;<变量名2>:<表达式2>;…变量名为<String>,表达式为<Float>(32位浮点数)
注:时间驱动的写法式标准的cron表达式,可参考https://blog.csdn.net/sdujava2011/article/details/87343461。
4.3.2 AOE变量定义
变量的定义包含变量名称和变量的表达式,变量的表达式中可以使用测点值、变量和常数,若使用预先载入的测点表内的测点名,当测点名对应的测点数据在动作中被更新时,变量的信息也会被更新。
定义格式为:
AOE ID | 变量定义 |
---|---|
<u64> | <变量名1>:<表达式1> |
- 对于无需公式表达的变量定义,可以在AOE网络定义的“变量初始值”一栏中将名称和初始值定义好。
- 对于有公式表达的变量定义,公式可以包括测点相关的变量(与计算点类似),也可以包括第一类中的变量,和第二类中的变量,该类变量的初始值由对应测点和变量的初始值计算而来,无需设置。公式中的变量写法见本节末尾表格。
- 变量声明需要规定变量生效的AOE网络。多个AOE有同样的变量定义可以只定义一次,在“AOE ID”中用分号隔开多个AOE的ID即可,声明的方式为:<AOEID1>;<AOEID2>;…
&测点号 | ||
_测点号 | ||
测点别名 | ||
&测点号_err | ||
_ 测点号 _ err | ||
测点别名 _ err | ||
|
& 测点号 _ t | |
_ 测点号 _ t | ||
测点别名 _ t | ||
& 测点号 _ dt | 上一次发布到云端的采集时间之差。 |
|
_ 测点号 _ dt | ||
测点别名 _ dt | ||
& 测点号 _ ddt | ||
_ 测点号 _ ddt | ||
测点别名 _ ddt |
4.3.3 AOE事件定义
AOE事件定义(节点声明)配置内容:AOE ID、节点ID、名称、节点类型、超时时间、表达式。
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间 | 表达式 |
---|---|---|---|---|---|
<u64> | <u64> | <String> | Switch Condition | <u64> | <Expr> |
-
AOE ID:声明节点属于哪个AOE网络,用<u64>(64位无符号整数)表示。
-
节点ID:一个AOE网络下节点编号。
-
名称:便于理解事件内容,往往是对表达式的简要文字解释,用<String>(表示字符串类型)表示。
-
节点类型分为两类:Switch(分支节点)、Condition(条件节点)。具体含义及参数详见AOE事件类型。
-
超时时间:超时时间用正整数表示,含义是在超时时间内表达式成立才为真,若超出时间则判断为假;
当设置为0时,认为超时时间为无穷大;当aoe触发为事件触发,且判断条件中的变量在aoe中有置点时或aoe中有SET_POINTS_WITH_CHECK动作,aoe尾节点的超时时间不能设置为0,否则会多次触发aoe,出错;单位为ms,具体设置根据实际控制决定。 -
表达式:表达式格式详见AOE基本表达式。
4.3.4 AOE动作定义
AOE动作定义(边声明)配置内容:AOE ID、首尾节点、动作名称、失败模式、动作类型、动作参数。
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
<u64> | <u64>;<u64> | <String> | Default Ignore StopFailed StopAll | None Set_Points SET_POINTS_WITH_CHECK Set_Points2 SET_POINTS_WITH_CHECK2 Solve NLSOLVE MILP SimpleMilp NLP | < \ > <String>:<Expr>;… <Expr> <Expr> <Expr> <Expr> <Expr> <Expr> <Expr> |
-
AOE ID:声明动作属于哪个AOE网络,用<u64>(64位无符号整数)表示。
-
首尾节点:边需要声明首尾节点,用一对正整数表示,格式为:<尾节点ID>;<首节点ID>。边的方向为:尾节点→首节点。节点ID与AOE事件定义中相对应。
-
动作名称:便于理解动作内容,是对动作的简要文字解释,用<String>(表示字符串类型)表示。
-
失败模型:指动作执行失败后需要采取的措施。执行失败后可以选择以下几种处理措施:Default(尝试重新执行失败的动作)、Ignore(忽略本次失败并不影响其它动作)、StopFailed(停止受到影响的动作)、StopAll(停止本次控制策略的执行)。
-
动作类型:分为None(无动作)、SET_POINTS(置点)、SET_POINTS_WITH_CHECK(带检查的置点)、SET_POINTS2(支持向量计算的置点)、SET_POINTS_WITH_CHECK2(支持向量计算的带检查置点)、Solve(线性方程组求解)、NLSOLVE(非线性方程组求解)、MILP与SimpleMilp(混合整数线性规划)、NLP(非线性规划)。其中,SetPoints除了对测点设值之外,还可以进行变量定义和计算,动作参数分为数字量和模拟量。动作的含义及其参数详见 AOE动作类型。
-
动作参数:根据动作类型不同而表示不同的含义:
- 动作类型为无动作时,动作参数缺省;
- 动作类型为置点时,动作参数为字符串和表达式,并按照变量类型分为数字量和模拟量两部分,置点动作既可以进行变量的定义,也可以把数字量或者模拟量设置给测点,其中字符串表示变量或测点名称,表达式表示变量定义式或者测点被设置的值;
- 动作类型为线性方程组求解、稀疏混合整数线性规划问题求解、稠密描述的混合整数线性规划问题求解和非线性规划问题求解时,动作参数为描述对应的数学模型的字符串及相应参数。
失败模型说明
对节点i的事件是否会进行判断,取决于指向它的“动作“执行结果及失败模式,有以下几种情况:
- 动作1,2,3全部成功,将进入节点i事件判断;
- 动作1,2,3有失败的情况。这里假设动作1失败,又分为以下几种情况:
- 动作1失败模式是Ignore,会进入节点i事件判断;
- 动作1失败模式是Stop_Failed,不会进入节点i事件判断;
- 动作1失败模式是Stop_All,不会进入节点i事件判断,而且会退出整个AOE;
- 动作1失败模式是Default,会进入节点i事件判断。
综上,会进入节点i判断必须同时满足两个条件:
- 没有失败模式为StopAll或StopFailed的动作执行失败;
- 至少有一个执行成功或失败模式为Ignore的动作。
举例如下:
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70000 | 1;2 | 动作1 | Default | None | ||
70000 | 1;3 | 动作2 | Default | None | ||
70000 | 2;6 | 动作3 | Ignore | MILP | max(x1+x2); x1>=0; x1:2,x2:2 | |
70000 | 3;4 | 动作4 | Default | None | ||
70000 | 3;5 | 动作5 | Default | None | ||
70000 | 4;6 | 动作6 | Stop_Failed | MILP | max(x1+x2); x1>=0; x1:2,x2:2 | |
70000 | 5;6 | 动作7 | Stop_All | MILP | max(x1+x2); x1>=0; x1:2,x2:2 | |
70000 | 6;7 | 动作8 | Default | Set_Points | a4:a4+1; |
该例子中,由于MILP优化不收敛,动作将会失败,动作3、6、7都将失败,但只有经过失败模式为“Ignore”的动作3才会进入节点6,然后进行动作8的赋值。
附件:失败模式.rar
动作类型示例说明
None(无动作)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70001 | 1;2 | 事件不动作 | Default | None |
动作含义:ID为70001的AOE网络,节点1至节点2无动作。
SetPoints(置点)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70002 | 2;3 | 变量赋值 | Default | SetPoints | a:1; | b:1.0; |
动作含义:ID为70002的AOE网络,节点2至节点3进行赋值动作,离散型测点a(或变量)赋值为1,连续型测点b(或变量)赋值为1.0。
具体例子:房屋温度控制——AOE边声明。
SET_POINTS_WITH_CHECK(带检查的置点)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70002 | 2;3 | 赋值并检查 | Default | SET_POINTS_WITH_CHECK | a:1; | b:1.0; |
动作含义:ID为70002的AOE网络,节点2至节点3进行赋值并检查动作,离散型测点a(或变量)赋值为1,连续型测点b(或变量)赋值为1.0,并且等待测点a、b置点完成后,节点3事件才算发生。
Set_Points2(支持向量计算的置点)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70002 | 2;3 | 赋值并检查 | Default | Set_Points2 | [a1,a2]:([1,2]+[15,10])*[10,100]+[1,2]; | [b1,b2]:([1.0,2.5]+[15.0,10.0])*[10.0,100.0]+[1.0,2.0]; |
动作含义:ID为70002的AOE网络,节点2至节点3进行向量计算并赋值。等式右边向量计算结果为[161,1202],并赋值给向量[a1,a2],即a1=161,a2=1202, b1=161.0, b2=1252.0。
SET_POINTS_WITH_CHECK2(支持向量计算的带检查置点)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70002 | 2;3 | 赋值并检查 | Default | SET_POINTS_WITH_CHECK2 | [a1,a2]:[t1,t2]*[10,10]*[10,10]+[1,1]; | [b1,b2]:[t1,t2]*[10.0,10.0]*[10.0,10.0]+[1.5,1.5]; |
动作含义:ID为70002的AOE网络,节点2至节点3进行向量计算后赋值并检查动作。等式1右边向量计算结果为[100*t1+1,100*t2+1],等式2右边向量计算结果为[100.0*t1+1.5,100.0*t2+1.5]。测点b1赋值为100.0*t1+1.5,测点b2赋值为100.0*t2+1.5,并且等待向量[b1,b2]置点完成后,节点3事件才算发生。
Solve(线性方程组求解)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70003 | 2;3 | 方程组求解 | Default | Solve | x1+5/3*x2+min(2,5)*x3 = 1; 3*x2 = 4*3; 3*x2+sin(8-2)*x3 = 7; x1,x2,x3 |
动作含义:ID为70003的AOE网络,节点2至节点3进行非线性方程组求解动作。
具体例子:直流法潮流计算——AOE边声明。
NLSOLVE(非线性方程组求解)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70003 | 2;3 | 非线性方程组求解 | Default | NLSOLVE | x1^2-10*x1+x2^2+8; x1*x2^2+x1-10*x2+8; x1,x2 | max_iter:50; tol:1e-6 |
动作含义:ID为70003的AOE网络,节点2至节点3进行非线性方程组求解动作。动作参数2为可选求解参数,默认值为最大迭代次数max_iter=50,收敛精度tol=1e-6。
具体例子:交流法潮流计算——AOE边声明。
MILP与SimpleMilp(混合整数线性规划)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70004 | 2;3 | 混合整数线性规划 | Default | MILP | max((5*2)*x1+3*x2+2*x3+(10-3)*x4+4*x5); 2*x1+(2*4)*x2+4*x3+2*x4+max(1,5)*x5 <= 5*2; x1:1,x2:1,x3:1,x4:1,x5:1 | maxIt:500; primalT:1e-6 |
动作含义:ID为70004的AOE网络,节点2至节点3进行混合整数线性规划动作。动作参数2为可选求解参数,默认值为最大迭代次数maxIt=500,收敛精度primalT=1e-6等。
具体例子:储能辅助调频——AOE边声明。
NLP(非线性规划)
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数1 | 动作参数2 |
---|---|---|---|---|---|---|
70005 | 2;3 | 非线性规划 | Default | NLP | x1*x4*(x1+x2+x3)+x3; x1*x2*x3*x4:[25/2e19]; x1^2+x2^2+x3^2+x4^2:[40/40]; x1:[1/5],x2:[1/5],x3:[1/5],x4:[1/5] | max_iter:500; tol:1e-6 |
动作含义:ID为70005的AOE网络,节点2至节点3进行非线性规划动作。动作参数2为可选求解参数,默认值为最大迭代次数max_iter=50,收敛精度tol=1e-6等,详见Ipopt设置文档
具体例子:最优潮流计算——AOE边声明。
5 基本控制组态
实验目的
控制组态技术,指工程人员无需编写计算机程序,仅通过类似“搭积木”的简单方式即可配置所需的控制策略的技术。应用该项技术的组态软件,以其无需或仅需极少量编程的优势,解决了现场调试人员缺少编程基础与编程人员缺少现场经验的矛盾,极大提高了工业控制的效率。
基于AOE的控制组态技术,指采用AOE形式表达控制策略并设计控制组态的技术。采用AOE组态技术,相较于其他组态技术学习成本低、可读性高,能够更直观地表达复杂的控制策略,进一步降低了使用门槛。
基本控制组态:对于复杂系统,从结构上都可分解为若干个基本单元。因此,搭建和实现基本控制组态,是实现控制组态技术复杂控制的基础。本次实验中将实现如下六个基本控制环节,并对其AOE部署做出说明。
5.1 比例环节
比例环节又称为放大环节,其输出量成比例的复现输入信号的变化。其s域传递函数为Y(s)=K·X(s)
,差分方程为y(k)=K·x(k)
(K为比例系数)。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | input | FALSE | FALSE | 0 | 输入值 |
2 | 100002 | 测点2 | output | FALSE | FALSE | 0 | 输出值 |
3 | 100003 | 测点3 | p_coefficient | FALSE | FALSE | 2 | 比例系数 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为比例环节,触发条件设置为简单重复(Simple_Repeat),重复周期为20ms。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 比例环节 | Simple_Repeat | 20 |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10 | 1 |
70001 | 2 | 结束节点 | Condition | 10 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式设为1,表明始终满足条件触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70001 | 1;2 | 计算 | Default | Set_Points | output:p_coefficient*input; |
本案例中的边声明动作类型为为SetPoints,执行动作“输出值=比例系数*输入值”。 式中p_coefficient表示比例环节的系数;input表示当前时刻输出量的采样值;output表示当前时刻输入量的采样值。p_coefficient、input、output为设置的测点。
1.3、配置文件存储
在excel表格中编写完成之后,并供低代码控制器使用。
2、Simulink验证
为验证低代码控制器比例环节结果的正确性,本案例借助Simulink的比例环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 3 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为3,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
本实验中需要用3个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为2,分别为输入值与比例系数。输出个数为1,为计算后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1),'double');
write(m,'holdingregs',10,u(2),'double');
%pause(0.001);
sys = read(m,'holdingregs',6,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。当设置比例系数p_coefficient=2时,仿真结果如下图所示:
5.2 积分环节
积分环节在实际物理系统中都是在近似条件下实现。基于其s域传递函数Y(s)=X(s)/s
和差分方程y(k)=ΔT·x(k-1)+y(k-1)
(ΔT为采样周期),在采样周期足够小的时候,可以将曲线的积分近似为多个矩形面积的和。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | time | FALSE | FALSE | 0 | 时间 |
2 | 100002 | 测点2 | value | FALSE | FALSE | 0 | 输入值 |
3 | 100003 | 测点3 | out | FALSE | FALSE | 0 | 输出值 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为积分环节,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 积分环节 | Event_Drive | time_old:0; value_old:0; out_old:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10000 | time>time_old |
70001 | 2 | 结束节点 | Condition | 10000 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式为真时,动作触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 输出 | Default | Set_Points | out:out_old+value_old*(time-time_old); value_old:value; time_old:time; out_old:out_old+value_old*(time-time_old); |
本案例中的边声明动作类型为为SetPoints。 式中,out表示当前时刻输出量的采样值;time表示当前时刻;time_old表示上一时刻;value表示当前时刻输入量的采样值;value_old表示上一时刻输入量的采样值。out、value、time为设置的测点。
2、Simulink验证
为验证低代码控制器积分环节结果的正确性,本案例借助Simulink的积分环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 3 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为3,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
本实验中需要用3个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为2,分别为输入值与仿真时间。输出个数为1,为积分计算后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1)','double');
write(m,'holdingregs',6,u(2)','double');
%pause(0.01); % 等待10ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',10,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。对于函数f(t)=t,使用AOE组态技术配置的积分环节输出如下图所示:
5.3
微分环节
微分是对函数局部变化的一种线性描述,对于微分环节的实现,可以近似描述为后一时刻的函数值与前一时刻的函数值之差与时间间隔的商。其s域传递函数为Y(s)=s·X(s)
,差分方程为y(k)=(x(k)-x(k-1))/ΔT
(ΔT为采样周期)。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | value | FALSE | FALSE | 0 | 当前值 |
2 | 100002 | 测点2 | time | FALSE | FALSE | 0 | 当前时间 |
3 | 100003 | 测点3 | differential | FALSE | FALSE | 0 | 输出值 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为微分环节,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 微分环节 | Event_Drive | time_old:0; value_old:0; flag:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 30 | time>time_old |
70001 | 2 | 结束节点 | Condition | 10 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式为真时,动作触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70001 | 1;2 | 计算 | Default | Set_Points | differential:(flag==1)*(value-value_old)/(time-time_old); flag:1; time_old:time; value_old:value; |
本案例中的边声明动作类型为为SetPoints。 式中,out表示微分结果;time表示当前时刻;time_old表示上一时刻;value表示当前时刻函数值的采样值;value_old表示上一时刻函数值的采样值。out、value、time为设置的测点。
2、Simulink验证
为验证低代码控制器微分环节结果的正确性,本案例借助Simulink的微分环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 3 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为3,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
本实验中需要用3个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为2,分别为输入值与仿真时间。输出个数为1,为微分计算后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1:2)','double');
%pause(0.001); % 等待50ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',10,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。在满足判断标志位为1的条件时避免分母为0微分结果跳变的情况下,当间隔时间足够小时,使用AOE组态技术配置的微分环节输入与输出对比如下图所示:
5.4 惯性环节
惯性环节又称为非周期环节,是由一阶微分方程描述。其s域传递函数为Y(s)=K·X(s)/(T1·s+1)
,差分方程为y(k)=(T1-ΔT)/T1·y(k)+K·ΔT/T1·X(k-1)
(K为比例系数,ΔT为采样周期,T1为时间常数)。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | time | FALSE | FALSE | 0 | 时间值 |
2 | 100002 | 测点2 | T | FALSE | FALSE | 1 | 时间常数 |
3 | 100003 | 测点3 | value | FALSE | FALSE | 0 | 输入值 |
4 | 100004 | 测点4 | K | FALSE | FALSE | 1 | 比例系数 |
5 | 100005 | 测点5 | out | FALSE | FALSE | 0 | 输出值 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为惯性环节,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 惯性环节 | Event_Drive | time_old:0; value_old:0; out_old:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10000 | time>time_old |
70001 | 2 | 结束节点 | Condition | 10000 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式为真时,动作触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70001 | 1;2 | 计算 | Default | Set_Points | out:out_old*(T-(time-time_old))(1/T)+(1/T)(time-time_old)Kvalue_old; out_old:out_old*(T-(time-time_old))(1/T)+(1/T)(time-time_old)Kvalue_old; value_old:value; time_old:time; |
本案例中的边声明动作类型为为SetPoints。 式中,out表示当前时刻输出量的采样值;out_old表示上一时刻输出量的采样值;T表示时间常数;K表示比例系数;time表示当前时刻;time_old表示上一时刻;value表示当前时刻函数值的采样值;value_old表示上一时刻函数值的采样值。out、T、value、K、time为设置的测点。
2、Simulink验证
为验证低代码控制器惯性环节结果的正确性,本案例借助Simulink的惯性环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 5 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为5,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
4 | HOLDING | 13 | EightByteFloat | FALSE | 2000 | 100004 |
5 | HOLDING | 17 | EightByteFloat | FALSE | 2000 | 100005 |
本实验中需要用5个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 4;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为4,分别为T、value、K、time。输出个数为1,为惯性计算后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1)','double');
write(m,'holdingregs',6,u(2)','double');
write(m,'holdingregs',10,u(3)','double');
write(m,'holdingregs',14,u(4)','double');
pause(0.01); % 等待10ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',18,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。使用AOE组态技术配置的惯性环节在输入为单位阶跃响应时输出如下图所示,此时时间常数T=1,比例系数K=1:
5.5 延迟环节
延迟环节又称滞后环节,其特点是输出经过一段时间才可以复现输入信号。其s域传递函数为Y(s)=e-ts·X(s),差分方程为y(k)=x(k-1)。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | time | FALSE | FALSE | 0 | 时间值 |
2 | 100002 | 测点2 | T | FALSE | FALSE | 1 | 延迟时间 |
3 | 100003 | 测点3 | value | FALSE | FALSE | 0 | 输入值 |
4 | 100004 | 测点4 | value_old | FALSE | FALSE | 0 | 输出值 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为延迟环节,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 延迟环节 | Event_Drive | value:0; time_old:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10000 | time>time_old |
70001 | 2 | 结束节点 | Condition | 10000 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式为真时,动作触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70001 | 1;2 | 计算 | Default | Set_Points | value_old:value; value:value; time_old:time; |
本案例中的边声明动作类型为为SetPoints。 式中,time表示当前时刻;time_old表示上一时刻;T表示时间间隔;value表示当前时刻函数值的采样值;value_old为上一时刻函数值的采样值。time、value、T、value_old为设置的测点。
2、Simulink验证
为验证低代码控制器延迟环节结果的正确性,本案例借助Simulink的延迟环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 4 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为4,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
4 | HOLDING | 13 | EightByteFloat | FALSE | 2000 | 100004 |
本实验中需要用4个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 3;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为3,分别为输入值、仿真时间与延迟时间。输出个数为1,为延迟后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1)','double');
write(m,'holdingregs',6,u(2)','double');
write(m,'holdingregs',10,u(3)','double');
%disp(['address 2 = ' num2str(u(1:3)')]);
pause(0.01); % 等待10ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',14,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。当延迟时间为1s时,仿真结果如下图所示:
5.6 振荡环节
振荡环节的输出量和输入量的关系为二阶微分方程。其s域传递函数为Y(s)=X(s)/ (T12s2+2ξT1s+1),差分方程为**`y(k)=(2-2ξΔT/T1)·y(k-1)+(2ξΔT/T1-1-(ΔT/T1)2)·y(k-2)+(ΔT/T1)2·x(k-2)。
实验步骤
1、编写低代码控制器配置文件
实现本应用案例,低代码控制器需要完成两部分文件配置:测点配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | time | FALSE | FALSE | 0 | 时间值 |
2 | 100002 | 测点2 | T | FALSE | FALSE | 1 | 时间常数 |
3 | 100003 | 测点3 | value | FALSE | FALSE | 0 | 输入值 |
4 | 100004 | 测点4 | zeta | FALSE | FALSE | 1 | 阻尼比 |
5 | 100005 | 测点5 | out | FALSE | FALSE | 0 | 输出值 |
1.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为振荡环节,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 振荡环节 | Event_Drive | time_old:0; value_old1:0; value_old2:0; out_old1:0; out_old2:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10000 | time>time_old |
70001 | 2 | 结束节点 | Condition | 10000 | 1 |
本案例中共有2个节点,节点类型均为Condition,表达式为真时,动作触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70001 | 1;2 | 计算 | Default | Set_Points | out:(2-(1/T)2zeta*(time-time_old))out_old1+(2(1/T)zeta(time-time_old)-1-(1/T)(1/T)(time-time_old)(time-time_old))out_old2+(1/T)(1/T)value_old2(time-time_old)(time-time_old); out_old1:(2-(1/T)2zeta*(time-time_old))out_old1+(2(1/T)zeta(time-time_old)-1-(1/T)(1/T)(time-time_old)(time-time_old))out_old2+(1/T)(1/T)value_old2(time-time_old)(time-time_old); value_old1:value; value_old2:value_old1; out_old2:out_old1; time_old:time; |
本案例中的边声明动作类型为为SetPoints。 式中,out表示当前时刻输出量的采样值;out_old1表示上一时刻输出量的采样值;out_old2表示上两时刻输出量的采样值;T表示时间常数;zeta表示阻尼比;time表示当前时刻;time_old表示上一时刻;value表示当前时刻函数值的采样值;value_old1表示上一时刻函数值的采样值;value_old1表示上两时刻函数值的采样值;zeta表示阻尼比。out、time、T、value、zeta为设置的测点。
2、Simulink验证
为验证低代码控制器振荡环节结果的正确性,本案例借助Simulink的振荡环节运行结果来对照。为实现控制器与simulink仿真模型间通信,需要进行低代码控制器通道文件的配置以及Simulink的S函数程序编写,具体过程如下:
2.1、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 5 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
服务端口设定为502,测点个数为5,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
4 | HOLDING | 13 | EightByteFloat | FALSE | 2000 | 100004 |
5 | HOLDING | 17 | EightByteFloat | FALSE | 2000 | 100005 |
本实验中需要用5个寄存器存储数据,数据类型均为八位浮点数。
2.2、编写Simulink与控制器通信程序
modbusComproportion.m是本案例模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 4;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上述程序表示输入与输出个数的设置,本案例中的输入个数为4,分别为输入值、仿真时间、阻尼比与时间常数。输出个数为1,为计算后的输出值。
ts = [0.02,0];
上述程序表示模块的采样时间为0.02s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上述程序表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u(1)','double');
write(m,'holdingregs',6,u(2)','double');
write(m,'holdingregs',10,u(3)','double');
write(m,'holdingregs',14,u(4)','double');
%disp(['address 2 = ' num2str(u(1:3)')]);
pause(0.01); % 等待10ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',18,1,'double');
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。程序中的pause(0.001)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
2.3、低代码控制器配置与运行
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
3、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。当输入为单位阶跃信号,时间常数T=1,阻尼比ξ=0.5时,仿真结果如下图所示:
6 应用范例
此章节用来给出基于LCC的一些应用范例,以帮助用户尽快入门基于LCC控制器的开发工作。
持续更新中......
6.1 房屋温度控制
1、实验环境
该程序可在以下环境运行:
1.Matlab R2019a + Simulink v9.3及以上版本;
2.Matlab APP:Instrument Control Toolbox;
3.低代码控制器。
2、原始模型介绍
本实验原始模型来自于matlab R2021a中官方自带的simulink仿真案例中的 sldemo_househeat 模型。
可以通过在matlab命令行窗口中输入下面的命令打开此案例的模型:
openExample('simulink_general/sldemo_househeatExample');
该仿真案例包含模型初始化脚本sldemo_househeat_data.m文件,提供需要的房屋信息:
- 包括定义房屋几何信息(大小、窗户数量)
- 指定房屋材料的热属性
- 计算房屋的热阻
- 提供加热器特性(热空气温度、流速)
- 定义电力成本(0.09 美元/千瓦时)
- 指定初始室内温度 (20 ºC = 68 ºF)
房屋的热模型主要功能是模拟房屋内的加热和热损耗(House)来表现温度的变化,再由控制模块(Thermostat)控制温度在设定温度下内基本保持小范围的波动,并计算加热成本(cost)。
- 室温变化模型(House),是计算室温变化的子系统,会考虑来自加热器的热流和在环境中的热损失,室温变化模型方程为:
\[ \left(\frac{\text{d} Q}{\text{d} x}\right)_ {losses} = \frac{ T_{room} - T_{out} }{ R_{eq} } \]
\[ \frac{\text{d}T_{room}}{\text{d}t} = \frac{1}{M_{air}\cdot c}\left( \frac{\text{d}Q_{heater}}{\text{d}t}-\frac{\text{d}Q_{losses}}{\text{d}t} \right) \]
其中\(M_{air}\)表示屋内空气质量,\(R_{eq}\)表示房屋的等效热阻。
-
加热器模型(Heater),对恒定空气流速 Mdot 进行建模。
其值在sldemo_househeat_data.m 文件中指定。调温器信号用于打开或关闭加热器。当加热器打开时,它以恒定的 \(Mdot\) 流速(默认 1 千克/秒 = 3600 千克/小时)吹出温度 \( T_{heater} \)(默认为 50 ºC = 122 ºF)的热空气。
\[ \frac{\text{d}Q}{\text{d}t}=\left( T_{heater} - T_{room} \right)\cdot Mdot\cdot c \]
其中 \( \frac{\text{d}Q}{\text{d}t} \)表示从加热器流入房间的热流,\(c\)表示常压下的热容,\(Mdot\)表示空气流速,\( T_{heater} \) 和 \( T_{room} \)分别表示从加热器中输出的热空气温度和房间内空气的温度。
-
调温器(Thermostat),允许温度在理想室温上下 5 ºF 范围内波动。如果气温降到 65 ºF 以下,调温器会打开加热器。
-
环境建模模块,使用具有无限热容量和时变温度 Tout 的散热器。常量模块 Avg Outdoor Temp 指定室外平均气温。Daily Temp Variation Sine Wave 模块产生室外温度的日温波动。修改参数可以比较这些参数对于供暖成本的影响。
3、整体流程分析
模型主要检测内容是室内的温度,需要将室内温度与控制温度进行比较,将温度是否超出限定值范围的信息反馈给调温器。
调温器对加热器施加开启或者关闭的信号,若信号为开启信号,加热器启动,稳定输出固定流速的热空气,并对此动作产生的能量消耗进行价格的计算,在PlotResults中显示成本的曲线图,并将室外温度以及室内温度一起显示在结果之中,方便比较室内外温度变化对成本的影响。
此模型只用于计算供暖成本,如果室外温度高于室内温度,室内温度将超过所需的Set Point值。
如果需要计算制冷成本,可以修改此模型,使其包含空调(即修改加热器的参数指标)。
进行此修改,要在 sldemo_househeat_data.m 中添加如下参数:冷空气输出、空调气流的温度以及空调效率。由于需要同时控制空调和加热器,因此还需要修改调温器。
4、低代码控制器
本控制器是基于AOE引擎的低代码控制器。控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
5、matlab仿真测试
5.1、原始案例
使用原始代码进行仿真可以得到如下图所示仿真图像。
图中可以看出制热成本,室内外温度变化曲线。
5.2、低代码控制器替代原始调温器
图中的modbusCom1指代的是由控制器控制模拟得到的调温器。
5.3、文件配置
文件配置分为三个部分:测点配置、通信通道和AOE配置。
测点配置用于配置控制器输入和输出信号点的参数,本案例中需要的信号要是输入所需要的房间设定温度、测量温度和输出的加热器启停控制信号。
通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互。
而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
接下来分别介绍相关的三个方面的配置。
5.3.1、测点配置
测点配置表格的内容包含了测点的点号、名称(测点1/2/3)、别名、是否离散、是否是计算点以及默认值等。
点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。
别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,不用点号来表达,使得表达式的意思表达得更加清楚。
本例中的测点配置如下表所示:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | Tset_POINT | FALSE | FALSE | 20 | 设定温度值 |
2 | 100002 | 测点2 | T_POINT | FALSE | FALSE | 20 | 测量温度值 |
3 | 100003 | 测点3 | State_POINT | TRUE | FALSE | 0 | 控制器下发的遥控 |
本程序需要三个测点,分别问设定温度值、测量温度值以及控制器输出控制加热器启停。其中的别名对应的就是AOE文件之中设置节点事件的表达式的参量。表示在matlab的simulink模型中是如图所示的几个参数。
5.3.2、通信通道配置
表格中包含有通信通道的各种配置信息。
通道名称 | server测试通道 |
---|---|
连接个数 | 2 |
服务端口 | 502 |
服务端口可以自行设置。
建立通信时,modbus通信的时候两边有一个是主站,有一个是从站,主站可以轮询、发控制指令,从站响应主站。
客户端IP | 127.0.0.1 |
---|---|
客户端端口 | 9999 |
通道配置文件里的客户端就是指主站,主站在同一台机器就用本机地址127.0.0.1,客户端端口要设成9999。此文件之中,将控制器配置成从站,matlab配置成主站。
服务端IP | 127.0.0.1 |
---|---|
服务端端口 | 502 |
slave id | 1 |
通信协议 | XA |
当需要把控制器配置成主站时,将客户端ip改成服务端ip。
本案例中需要的通道配置如下:
通道名称 | server服务端 |
---|---|
连接个数 | 1 |
服务端口 | 502 |
连接个数设定为1,服务器端口自定义为502;
连接名称 | 测试通道1 |
---|---|
测点个数 | 3 |
客户端IP | 127.0.0.1 |
客户端端口 | 9999 |
客户端ip就是主站ip,端口需修改为9999,在实体控制器配置时需要改为与网络属性相关的ip,在网络属性中查询。
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | TwoByteIntUnsigned | FALSE | 2000 | 100003 |
利用3个测点设定的点号,将3个测点与寄存器的起始地址点号对应,两个温度值的数据类型为八位的浮点数,输出的数据类型规定为无符号整数。
其他参数本案例中不需要配置,在此不多赘述。
5.3.3、AOE配置
将AOE表格拆开之后可以分为四个部分。
- AOE网络声明
AOE网络声明部分,定义了表格之中的AOE网络个数和整体信息以及一些变量的初始值。
触发条件分为三类:SimpleRepeat(定时触发,需要自行设定定时时间)、TimeDriven(时间驱动)、EventDriven(事件驱动)。
变量的定义方式为:
<变量名1>:<表达式1>;<变量名2>:<表达式2>;…
本例中的AOE网络声明:
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 房屋温度控制 | Event_Drive | upDev:2.77778;downDev:2.77778 |
本程序的控制器的作用是实现房屋内温度的控制,所以名称定为房屋温度控制,触发条件是事件控制(即当温度超出阈值的事件发生时,控制器进行相应动作)。
变量upDev和downDev分别代表了向上和向下超出的设定温度的最大值(实测温度与设定温度最大差值的绝对值)为2.77778摄氏度(5华氏度)。
- 变量声明
变量声明需要规定变量生效的AOE网络,通过表达式定义,可以使用预先载入的测点表内的测点名,当测点名对应的测点数据在动作中被更新时,变量的信息也会被更新。
本案例中没有需要的变量声明,在此不多赘述。
- AOE节点声明
节点类型分为两类:Switch、Condition.
Switch节点为二分支逻辑判断,触发逻辑为:表达式为真时,该节点序号为1的边进行动作;表达式为假时,序号为2的边进行动作。当Switch节点为AOE网入度为0的节点(首节点)时,Switch节点直接触发,若超时时间内表达式为真,则执行动作1,为假或者发生超时事件执行动作2。
Condition节点的表达式为事件触发条件,超时时间内表达式为真,则节点事件发生,该节点出发的所有动作并行执行。
本例中的节点声明:
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 温度超出阈值事件 | Condition | 10 | Tset_Point-T_Point>downDev||T_POINT-Tset_POINT>upDev |
70001 | 2 | 温度超过下阈值事件 | Condition | 10 | Tset_Point-T_Point>downDev |
70001 | 3 | 温度超过上阈值事件 | Condition | 10 | T_Point-Tset_Point>upDev |
70001 | 4 | 结束节点 | Condition | 0 | 1 |
本案例中需要定义的节点有四个,都是事件触发条件,分别是温度超出阈值事件、温度超过下阈值事件、温度超过上阈值事件以及结束节点。
其中,前三个事件规定了超时时间,需要在超时时间内表达式为真才能触发,根据表达式进行运算和比较来控制是否触发事件,式子中用到的数据可以用测点配置里对应的别名来表示。
- AOE边声明
边需要声明首尾节点,格式为:
<尾节点ID>;<首节点ID>
边的方向为:尾节点→首节点。
边的动作类型有:None、SetPoints、Solve、MILP、SimpleMilp、NLP;
-
SetPoints除了对测点设值之外,还可以进行变量定义和计算,动作参数分为数字量和模拟量。
-
Solve求解方程\(Ax=b\)。
-
Milp为稀疏混合整数线性规划问题求解,
-
Nlp为非线性规划问题求解。
-
Milp的写法包括:
-
目标函数:min(<表达式>); 或者 max(<表达式>);
-
约束条件:<Bool表达式1>;<Bool表达式2>;…
-
变量声明:<变量名1>:<变量类型1>, <变量名2>:<变量类型2>,… (其中变量类型为:二进制(0/1)、整型和浮点数)
-
本案例中的AOE边声明如下图所示:
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 进入判断温度是否超过下阈值的节点 | Default | NONE | ||
70001 | 1;3 | 进入判断温度是否超过上阈值的节点 | Default | NONE | ||
70001 | 2;4 | 打开加热器 | Default | Set_Points | State_POINT:1; | |
70001 | 3;4 | 关闭加热器 | Default | Set_Points | State_POINT:0; |
本例一共用到了四条边声明,从节点1到节点2和节点3的两条边不需要判断,只需要执行进入下一个节点的动作,动作类型为None,不需要进行计算。
从节点2和节点3到节点4需要作出开加热器和关加热器的动作,动作类型为SetPoints,输出为1时,打开加热器,输出为0时,关闭加热器。
包含有节点以及边的流程如图所示:
5.4、建立控制器与matlab通讯以及仿真过程
- 连接低代码控制器
将matlab的路径切换到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器时,就是将所实现的功能通过实体的控制器实现,只需要将控制器与电脑接入同一局域网后后,修改主站和从站的ip地址,控制器(从站ip)可以从查找窗口获得。主站ip为本机ip地址,通过网络属性配置中可以查询。
- 配置低代码控制器的文件
打开一个浏览器,并输入控制器地址,然后输入账号和密码以进入控制器主界面。
进入主界面后,在左侧导航栏的设置项板块中分别点击测点
、通道
和AOE
按钮,进入相应界面后上传配置文件。
以测点配置文件上传为例,若界面已存在数据可以先清空数据,然后单击右上角的文件上传图标(具体见下图所示),选中需要上传的文件,确定即可完成上传。上传成功后界面将出现相应内容,可对其进行查看与编辑。
所有文件上传完成后,单击主页
或概览
返回概览界面,点击重置
按钮保存配置即可运行。操作界面如下图所示:
- matlab界面操作
配置完成后,进入matlab的界面。然后打开控制器的源文件modbusCom1.m文件,该文件是以S-Function模块模板为基础实现的利用Modbus通信协议与控制器进行通信的模块。
下面这个程序段是将控制信息的数据通过函数对控制器进行读写,S-Function模块中输出函数为mdlOutputs。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u','double'); % 将温度设定值和测量值写入控制器
pause(0.01); % 等待10ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',10,1,'uint16'); % 读取控制信号
同时需要设置输入和输出信号的个数,其中输入信号有两个(即设定温度和测量温度),输出信号有一个(控制器发出的指令信号)。
以下这个初始化程序段用于联系控制器与matlab,将modbusCom1中的建立modbus通信的代码中的,输入从站ip(“127.0.0.1”,当连接实体的控制器时,需要填写查找得到的控制器的ip地址)和端口(502,这个端口是由通信通道配置里选择的)。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
通过这个函数建立了simulink与控制器的通信,实现了仿真过程中和外界数据交互。
在matlab命令行窗口中输入以下命令可以测试modbus通信,判断通信是否成功连接。
m = modbus('tcpip', '127.0.0.1', 502);
- Simulink模型参数设置
mosbuscom1.m文件是s函数的源文件,放在.slx文件的目录下,应用到模型中的控制器中,替换控制算法部分,按如下图所示连接输入和输出端:
- 仿真结果
运行完成之后,得到完整的波形图如下图所示:
可以看出与原本程序自带的调温器所得的仿真结果是一样的。
5.5、总结
由仿真结果可以看出,低代码控制器的功能与原始的调温器的功能是一致的,但是低代码控制器并不需要繁复的程序代码的编写,根据需要编写相关的AOE配置、测点配置以及通信通道的配置就可以实现对应的功能,与目前常用的其他的控制方法相比,更方便于非编程技术背景人员对模型功能的设计和实现。
6.2 倒立摆控制
1、实验环境
该程序可在以下环境运行:
1.Matlab R2019a + Simulink v9.3及以上版本;
2.Matlab APP:Instrument Control Toolbox;
3.低代码控制器。
2、低代码控制器的功能实现目标
利用低代码控制器取代原本实验模型中包括前馈控制,PI反馈控制以及LQR控制算法在内的整个控制部分,并达到控制小车移动,摆杆不倒的控制目标。
3、仿真实验模型
3.1、实验模型图
- 原始模型图
倒立摆控制案例的原始模型来自于Matlab官方提供的Simulink例程中的Inverted Pendulum with Animation模型
可以在matlab命令行窗口中输入以下命令打开这一案例:
openExample('simulink_general/penddemoExample')
原始仿真模型如下图所示:
- 改造模型图
图中的modbusCom就是本实验模型中的控制器模块,实验模型中可以看出,控制器取代了包括PI反馈控制,前馈控制和LQR控制环节在内的所有控制环节,模型十分简洁。
3.2、实验模型中的通信文件
modbusCom.m是本实验模型控制器的源文件,建立与低代码控制器起通信的作用,仍然是以S-Function模板为基础编写的Modbus通信模块。
下面表示的是模块输入和输出值的个数,本实验中的输入有三个,包括设定小车的位置,测定小车的位置以及测定的摆杆与垂直方向的夹角。输出有一个,就是控制器的输出,控制的是输出在小车上的作用力。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 3;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
下面表示的是模块的采样时间为0.02s。
ts = [0.02,0];
下面的代码表示建立与控制器的通信。
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
如下面的代码所示,需要将输入写入控制器,再从控制器中读取控制信号。图中的pause(0.05)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u','double'); % 将小车位置设定值、小车位置测量值和倒立摆角度写入控制器
write(m,'holdingregs',18,1); % 将发起通信信号写入控制器
pause(0.05); % 等待50ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',14,1,'double'); % 读取控制信号
4、低代码控制器的文件配置
4.1、测点配置
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | Cartset_POINT | FALSE | FALSE | 0 | 设定的小车位置 |
2 | 100002 | 测点2 | Cart_POINT | FALSE | FALSE | 0 | 测量的小车位置 |
3 | 100003 | 测点3 | Pendulum_POINT | FALSE | FALSE | 0 | 测量的倒立摆与竖直方向夹角 |
4 | 100004 | 测点4 | U_POINT | FALSE | FALSE | 0 | 控制器下发的遥调->设定作用在小车上的力 |
5 | 100005 | 测点5 | DoCal_POINT | TRUE | FALSE | 0 | 根据测点状态判断控制器是否需要进行计算 |
本程序需要四个测点,分别为设定的小车位置、测量的小车位置以及控制器输出控制作用在小车上的作用力。其中的别名对应的就是AOE文件之中设置节点事件的表达式的参量。表示在matlab的simulink模型中是如图所示的几个参数。
第五个测点DoCal_POINT不是实际物理测点,并不是用于获取控制信号的,每通信一次,这个测点将被设成1让控制器进行计算,控制器开始执行AOE控制策略的时候这个测点会被置0。
4.2、通信通道配置
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 5 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 |
服务端口设定为502,测点个数为5,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
4 | HOLDING | 13 | EightByteFloat | FALSE | 2000 | 100004 |
5 | HOLDING | 17 | TwoByteIntUnsigned | FALSE | 2000 | 100005 |
本实验中需要用五个寄存器存储数据,前四个存储的是四个有测量数据的测点的监测结果,数据类型为八位浮点数,最后一个寄存器存储的是不进行监测的测点的值,这个测点只有0和1两个结果,所以数据类型设置为无符号整数。
4.3、AOE配置
本实验中的AOE网络图如下图所示:
- AOE网络声明
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 倒立摆控制 | Event_Drive | Ts:0.02; Ecar:0; Pgain:-9.4; Igain:0.06; Iuplim:5; Idownlim:-5; num1:7.12; num0:0; den1:1; den0:2; K1:0; K2:-18; K3:-166.5; K4:-15.2; uplim:10; downlim:-10; Pout:0; Iout:0; Ilimout:0; Feedforwardout:0; cartsetn1:0; cartn1:0; Pendulumn1:0; dcart:0; dPendulum:0; LQRout:0; ctrlout:0 |
将名称定为倒立摆控制,触发条件设置为事件触发(Event_Drive)。
本实验中需要定义的变量初始值比较多。
变量名 | 含义 |
---|---|
Ts | 指simulink仿真步长,设置为0.02s |
Ecar | 表示小车位置与设定位置的偏差,初始值为0 |
Pgain | 比例环节的增益系数,设定值为-9.4 |
Igain | 积分环节的增益系数,设定值为0.06 |
Iuplim & Idownlim | 积分环节的输出上限和下限,设定值为5和-5 |
num1 & num0 | 前馈环节传递函数分子(一次项和常数项)的系数,设定值为7.12和0 |
den1 & den0 | 前馈环节传递函数分母(一次项和常数项)的系数,设定值为1和2 |
K1 & K2 & K3 & K4 | LQR控制环节的最优反馈增益矩阵的元素,分别为0、-18、-166.5和-15.2 |
uplim & downlim | 作用在小车上的作用力的上下限,分别为10和-10 |
Pout & Iout | 比例和积分环节的输出,初始值都为0 |
Ecarn1 | 前一个仿真步长中小车位置与设定位置的偏差,初始值是0 |
Ilimout | 积分环节限幅之后的输出,初始值为0 |
Feedforwardout | 前馈环节的输出,初始值为0 |
cartsetn1 | 前一个仿真步长中,小车位置的设定值,初始值为0 |
cartn1 | 前一个仿真步长中小车的位置,初始值为0 |
Pendulumn1 | 前一个仿真步长中,摆杆与垂直方向的夹角,初始值为0 |
dcart | 小车的速度,初始值为0 |
dPendulum | 摆杆的角速度,初始值为0 |
LQRout | LQR环节的输出,初始值为0 |
ctrlout | PI反馈环节,前馈环节和LQR环节的总输出,初始值为0 |
- 变量声明
本实验中不需要此模块的填写,在此不多赘述。
- AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | simulink通信事件 | Condition | 10 | DoCal_POINT>0.5 |
70001 | 2 | 执行顺序计算中间节点1 | Condition | 10 | Tset_Point-T_Point>downDev |
70001 | 3 | 执行顺序计算中间节点2 | Condition | 10 | 1 |
70001 | 4 | 执行顺序计算中间节点3 | Condition | 10 | 1 |
70001 | 5 | 执行顺序计算中间节点4 | Condition | 10 | 1 |
70001 | 6 | 执行顺序计算中间节点5 | Condition | 10 | 1 |
70001 | 7 | 执行顺序计算中间节点6 | Condition | 10 | 1 |
70001 | 8 | 结束节点 | Condition | 10 | DoCal_POINT==0 |
本实验中一共有8个节点,第1个节点是simulink通信事件节点,为事件触发类型,当DoCal_POINT>0.5时,也就是测点5输出1,表示允许控制器计算时,该节点被触发,进入运算流程。
中间6个节点都是运算节点,也都是事件触发类型,当每个分步的计算步骤完成时,该节点被触发,并进入下一个计算步骤。
最后一个节点是结束节点,是事件触发类型,当所有的计算步骤都完成,信号传输后,进入结束节点,计算结束,并将DoCal_POINT的数值改为0,等待下一次通信之后,开始计算。超时时间定为100ms,因为需要DoCal_POINT置0再让AOE执行过程结束,防止AOE被反复触发。
- AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | aoe触发测点复位、计算小车位置偏差 | Default | Set_Points | DoCal_POINT:0 | Ecar: Cartset_POINT - Cart_POINT; |
70001 | 2;3 | 计算比例和积分环节输出 | Default | Set_Points | Pout: Pgain * Ecar; Iout: Iout + Igain * Ecarn1 * Ts; | |
70001 | 3;4 | 存储小车位置误差,计算积分环节限幅输出和前馈环节输出 | Default | Set_Points | Ecarn1: Ecar;Ilimout: (Iout <= Iuplim && Iout >= Idownlim) * Iout + (Iout > Iuplim) * Iuplim + (Iout < Idownlim) * Idownlim;Feedforwardout: (num1 * (Cartset_POINT - cartsetn1) + num0 * Ts * cartsetn1 + (den1 - den0 * Ts) * Feedforwardout) / den1; | |
70001 | 4;5 | 存储前馈环节输入值,计算小车速度、倒立摆角速度 | Default | Set_Points | cartsetn1: Cartset_POINT;dcart: (Cart_POINT - cartn1) / Ts;dPendulum: (Pendulum_POINT - Pendulumn1)/Ts; | |
70001 | 5;6 | 计算LQR控制输出值 | Default | Set_Points | LQRout: K1 * Cart_POINT + K2 * dcart + K3 * Pendulum_POINT + K4 * dPendulum; | |
70001 | 6;7 | 存储小车位置和倒立摆角度,计算比例环节、积分限幅环节、前馈控制环节、LQR控制总输出 | Default | Set_Points | cartn1: Cart_POINT;Pendulumn1: Pendulum_POINT;ctrlout: Pout + Ilimout + Feedforwardout - LQRout; | |
70001 | 7;8 | 作用在小车上的力限幅 | Default | Set_Points | U_POINT: (ctrlout <= uplim && ctrlout >= downlim) * ctrlout + (ctrlout > uplim) * uplim + (ctrlout < downlim) * downlim; |
本实验中的边声明全部都是SetPoints,连接节点的同时还需要进行动作。
接下来简单介绍一下每条边的动作:
-
连接第1和第2节点的边:动作名称:aoe触发测点复位,计算小车位置偏差,在这条边上首先需要将DoCal_POINT置0,防止置0之前,AOE的一次运行过程已经完成后,被再次触发。并通过Cartset_POINT - Cart_POINT的式子算出小车位置与设定位置的偏差值。
-
连接第2和第3节点的边:动作名称:计算比例和积分环节输出,通过Pgain * Ecar的式子算出比例环节的输出Pout,通过Iout + Igain * Ecarn1 * Ts算出积分环节的输出Iout。
-
连接第3和第4节点的边:动作名称:存储小车位置误差,计算积分环节限幅输出和前馈环节输出。
-
读取并存储小车位置误差Ecarn1: Ecar;
-
积分环节输出:Ilimout: (Iout <= Iuplim && Iout >= Idownlim) * Iout + (Iout > Iuplim) * Iuplim + (Iout < Idownlim) * Idownlim;当幅值小于幅值时,输出积分的值;当幅值超过幅值阈值时,会以阈值的数值输出。
-
前置环节输出:Feedforwardout: (num1 * (Cartset_POINT - cartsetn1) + num0 * Ts * cartsetn1 + (den1 - den0 * Ts) * Feedforwardout) / den1;
接下来简单介绍一下前置环节输出表达式的得出过程:
前置环节的输出计算公式可以表示为:
\[ y=\frac{num1*s+num0}{den1*s+den0}x \]
将分母乘出之后:
\[ num1*s*x+num0*x=den1*s*y+den0*y \]
利用反拉式变换可以得到:
\[ num1*\dot x+num0*x=den1*\dot y+den0*y \]
利用离散化计算可以得到:
\[ num1*\left(x_n-x_{n-1}\right)+num0*T_s*x_{n-1}=den1*\left( y_n-y_{n-1} \right)+den0*y_{n-1} \]
将输出表示出来可以得到:
\[ Y_n = \frac{num1*\left(x_n-x_{n-1}\right)+num0*T_s*x_{n-1}-den0*T_s*y_{n-1}+den1*y_{n-1}}{den1} \]
连接第4和第5节点的边:动作名称:存储前馈环节输入值,计算小车速度、倒立摆角速度,将前馈环节输入值写入cartsetn1: Cartset_POINT;将小车速度计算并写入dcart: (Cart_POINT - cartn1) / Ts;
将摆杆角速度计算并写入dPendulum: (Pendulum_POINT - Pendulumn1) / Ts;
连接第5和第6节点的边:动作名称:计算LQR控制输出值,利用LQR控制环节的最优反馈增益矩阵K计算得到LQRout: K1 * Cart_POINT + K2 * dcart + K3 * Pendulum_POINT + K4 * dPendulum;
连接第6和第7节点的边:动作名称:存储小车位置和倒立摆角度,计算比例环节、积分限幅环节、前馈控制环节、LQR控制总输出,输出小车位置cartn1: Cart_POINT;输出摆杆的角度Pendulumn1: Pendulum_POINT;包括各个环节之和的总输出ctrlout: Pout + Ilimout + Feedforwardout - LQRout;
连接第7和第8节点的边:动作名称:作用在小车上的力限幅,输出作用在小车上的作用力U_POINT: (ctrlout <= uplim && ctrlout >= downlim) * ctrlout + (ctrlout > uplim) * uplim + (ctrlout < downlim) * downlim,当作用力小于限制阈值时,输出计算得到的作用力,输出大于限制幅值时,输出值为阈值的限值。
5、低代码控制器
本控制器是基于AOE引擎的低代码控制器。控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
使用的时候,将电源线与电源相连,打开电源开关,再用网线将控制器与计算机连接,就可以使用。
6、MATLAB仿真过程
6.1、连接低代码控制器
将matlab的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时:就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。
当控制器启动并接入计算机,打开一个浏览器,并输入控制器地址可以得到如下界面。
主站ip为本机ip地址,通过网络属性配置中可以查询。
6.2、配置低代码控制器的文件
通过网页端上传的方法与案例1-房屋温度控制中介绍的步骤完全一致,此处不再赘述。
6.3、MATLAB界面操作
配置完成后,进入MATLAB的界面。然后打开控制器的源文件modbusCom.m文件。
m = modbus('tcpip', '127.0.0.1', 502);
以上这个程序段用于联系控制器与matlab,在建立modbus通信的代码中,输入从站ip(“127.0.0.1”,当连接实体的控制器时,需要填写查找得到的控制器的ip地址)和端口(502,这个端口是由通信通道配置里选择的)。
在命令行窗口中输入上述命令与控制器进行通信,判断是否成功连接。
6.4、simulink模型参数设置
运行过程中,需要将S-function name设成.m文件的文件名。
打开simulink里的configuration。
设置为定步长仿真(Fixed-step),仿真步长为0.02s,数值积分方法确定为一阶欧拉法,配置完成后保存配置。
完成后,点击运行,可以得到动画模型。了解动画的效果可以观看演示视频。
7、总结
本实验中,利用低代码控制器代替了原本实验模型中所有的控制部分,原本模型中的控制部分包括了三个方面,对于低代码控制器来说,几乎不需要进行代码的编写,就可以实现控制模型的功能,可以看出低代码控制器的优势在这个模型的仿真过程之中是十分显著的。
6.3 光伏最大功率点跟踪
1、实验环境
该程序可在以下环境运行:
1.Matlab R2019a + Simulink v9.3及以上版本;
2.Matlab APP:Instrument Control Toolbox;
3.低代码控制器。
2、低代码控制器的功能实现目标
利用低代码控制器实现本模型中的最大功率点跟踪(MPPT)技术,根据光伏电池的功率变化调整工作点的电压以获得最大功率。
3、仿真实验模型
3.1、实验模型图
图中的mpptCtrl就是本实验模型中的控制器模块,实验模型中可以看出,控制器的功能主要是控制PWM模块调整PWM的波形。
上图所示的部分是将光伏模型中产生的信号转化成电流。
上图所示部分是由控制器所控制的,需要根据光伏电压和电流的变化获得功率的变化,再根据功率的变化情况调整工作点的电压以获得理想条件下的最大功率。
上图所示的是实验中模拟的负载,负载两端工作电压的变化会对光伏信号产生影响从而影响光伏输出功率。
3.2、实验模型中的通信文件
MpptCtrl.m是本实验模型控制器的源文件,建立与低代码控制器起通信的作用。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
上面的初始化过程表示的是输入和输出值的个数的设置,本实验中的输入有两个,包括输入的电压值和电流值。输出有一个,就是控制器的输出,控制的是电压控制的设定值。
ts = [0.01,0];
上面表示的是模块的采样时间为0.01s。
global m;
m = modbus('tcpip', '127.0.0.1', 502); % 建立modbus通信
上面表示初始化过程中建立与控制器的通信。
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u','double'); % 将电流、电压测量值写入控制器
write(m,'holdingregs',14,1); % 将发起通信信号写入控制器
pause(0.02); % 等待20ms(实际时间),使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',10,1,'double'); % 读取控制信号
如上面的输出函数所示,需要将输入写入控制器,再从控制器中读取控制信号。图中的pause(0.02)用于设置等待时间,当控制器和计算机的性能较好时,可以适当修改这个参数,可以加快仿真通信的速度,使动画跟随的动作加快。
4、低代码控制器的文件配置
4.1、测点配置
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | I_POINT | FALSE | FALSE | 0 | 电流 |
2 | 100002 | 测点2 | U_POINT | FALSE | FALSE | 0 | 电压 |
3 | 100003 | 测点3 | Uset_POINT | FALSE | FALSE | 0 | 电压设定值 |
4 | 100004 | 测点4 | DoCal_POINT | TRUE | FALSE | 0 | 根据测点状态判断控制器是否需要进行计算 |
本程序需要三个测点,分别为输入电流值、输入电压值以及控制器输出给PWM的电压设定值。其中的别名对应的就是AOE文件之中设置节点事件的表达式的参量。表示在MATLAB的simulink模型中是如图所示的几个参数。
第四个测点DoCal_POINT不是实际物理测点,并不是用于获取控制信号的,每通信一次,这个测点将被设成1让控制器进行计算,控制器开始执行AOE控制策略的时候这个测点会被置0。
4.2、通信通道配置
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 4 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 |
服务端口设定为502,测点个数为4,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 9 | EightByteFloat | FALSE | 2000 | 100003 |
4 | HOLDING | 13 | TwoByteIntUnsigned | FALSE | 2000 | 100004 |
本实验中需要用四个寄存器存储数据,前三个存储的是三个有测量数据的测点的监测结果,数据类型为八位浮点数,最后一个寄存器存储的是不进行监测的测点的值,这个测点只有0和1两个结果,所以数据类型设置为无符号整数。
4.3、AOE配置
基本原理:
下图所示为光伏阵列的输出功率特性P-V曲线,由图可知当光伏阵列的工作电压小于最大功率点电压时,光伏阵列的输出功率随阵列端电压的上升而增加;当阵列的工作电压大于最大功率点电压时,阵列的输出功率随阵列端电压的上升而减小。
最大功率点跟踪(maximum power point tracking, MPPT)实质上是一个自寻优过程,即通过控制端电压,使光伏阵列能在各种不同的日照和温度环境下智能化地输出最大功率。
基本的最大功率点跟踪算法有恒定电压法、扰动观测法和增量电导法等,本次仿真模型的控制通过增量电导法来实现。
增量电导法的思路是通过调整工作点的电压,使它逐渐接近最大功率点的电压。光伏阵列的电压功率曲线是一个单峰的曲线,在输出功率最大点处,功率对电压的导数为零,要寻找最大功率点,仅需在功率对电压的导数大于零的部分增加电压,在功率对电压的导数小于零的部分减小电压,在导数等于零或很接近零时保持电压不变即可。
对功率表达式 ,等式两边对U求导:
\[ \frac{\text d P}{\text d U}=\frac{\text d \left(UI\right)}{\text d U}=I+U\frac{\text d I}{\text d U} \]
当dP/dU>0时,U小于最大功率点电压Um;当dP/dU<0时,U大于最大功率点电压Um;dP/dU=0时,U等于最大功率点电压Um。
根据基本原理,本实验中的AOE网络图如图所示:
- AOE网络声明
将名称定为光伏MPPT控制,触发条件设置为事件触发(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 光伏MPPT控制 | Event_Drive | dU:0; dI:0; In1:0; Un1:0; Uc:0.005; Uuplim:0.5; Udownlim:-0.5; dPdU:0; e:1e-10 |
上表可见本实验中需要定义的变量初始值,其具体含义为:
变量名称 | 含义 |
---|---|
dU | 表示电压的微分,初始值为0 |
dI | 表示电流的微分,初始值为0 |
In1 | 表示上一次网络运行时测得的电流值,初始值为0 |
Un1 | 表示上一次网络运行时测得的电压值,初始值为0 |
Uc | 控制量变化的步长,初始值为0.03 |
Ucb | 控制量变化的最大步长,设定值为0.03 |
Ucs | 控制量变化的最小步长,设定值为0.001 |
Uuplim | PWM波占空比控制量的最大值,设定值为0.5 |
Udownlim | PWM波占空比控制量的最小值,设定值为-0.5 |
dPdU | 计算所得的dP/dU,初始值为0 |
dPdUc | dP/dU的步长调整设定值,设定值为5 |
e | 无限趋近于0的常数,设定值为1e-10 |
- 变量声明
本实验中不需要此模块的填写,在此不多赘述。
- AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | simulink通信事件 | Condition | 10 | DoCal_POINT>0.5 |
70001 | 2 | 判断dU是否为0 | Switch | 10 | abs(dU)<e |
70001 | 3 | 判断dI是否为0 | Switch | 10 | abs(dI)<e |
70001 | 4 | 判断dI是否大于0 | Switch | 10 | dI>e |
70001 | 5 | 判断dP/dU是否为0 | Switch | 10 | abs(dPdU)<=e |
70001 | 6 | 判断dP/dU是否小于步长调整设定值 | Switch | 10 | abs(dPdU)<=dPdUc |
70001 | 7 | 判断dP/dU是否大于0 | Condition | 10 | dPdU>e |
70001 | 8 | 进入限幅操作中间节点1 | Condition | 10 | 1 |
70001 | 9 | 进入限幅操作中间节点2 | Condition | 10 | 1 |
70001 | 10 | 结束节点 | Condition | 100 | DoCal_POINT==0 |
本实验中一共有10个节点,第一个节点是simulink通信事件节点,为事件触发类型,当DoCal_POINT>0.5时,也就是测点4输出1,表示允许控制器计算时,该节点被触发,进入运算流程。
中间6个节点(第2—7个节点)都是逻辑判断节点,对于设定值进行大小比较,完成逻辑判断后根据结果进入两条不同动作的边:判断结果为真执行第1条边,否则执行第2条边,边的顺序是就是文件里面定义的顺序。
第8和9两个节点是事件触发类型,是中间节点,起连接的作用,节点被触发后,将通过下一条边进入结束节点。
最后一个节点是结束节点,是事件触发类型,当所有的计算步骤都完成,信号传输后,进入结束节点,计算结束,并将DoCal_POINT的数值改为0,等待下一次通信之后,开始计算。超时时间定为100ms,因为需要DoCal_POINT置0再让AOE执行过程结束,防止AOE被反复触发。
- AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | aoe触发测点复位,计算dU和dI | Default | Set_Points | DoCal_POINT: 0; | dU: U_POINT - Un1; dI: I_POINT - In1; |
70001 | 2;3 | 存储电压和电流值,进入判断dI是否为0的节点 | Default | Set_Points | Un1: U_POINT; In1: I_POINT; | |
70001 | 3;10 | 进入结束节点 | Default | NONE | ||
70001 | 3;4 | 进入判断dI是否大于0的节点 | Default | NONE | ||
70001 | 4;8 | 增大电压 | Default | Set_Points | Uset_POINT: Uset_POINT + Uc; | |
70001 | 8;10 | 电压限幅 | Default | Set_Points | Uset_POINT: (Uset_POINT <= Uuplim && Uset_POINT >= Udownlim) * Uset_POINT + (Uset_POINT > Uuplim) * Uuplim + (Uset_POINT < Udownlim) * Udownlim; | |
70001 | 4;9 | 减小电压 | Default | Set_Points | Uset_POINT: Uset_POINT - Uc; | |
70001 | 9;10 | 电压限幅 | Default | Set_Points | Uset_POINT: (Uset_POINT <= Uuplim && Uset_POINT >= Udownlim) * Uset_POINT + (Uset_POINT > Uuplim) * Uuplim + (Uset_POINT < Udownlim) * Udownlim; | |
70001 | 2;5 | 存储电压和电流值,计算dP/dU | Default | Set_Points | Un1:U_POINT; In1:I_POINT; dPdU:I_POINT+U_POINT*dI/dU; | |
70001 | 5;10 | 进入结束节点 | Default | NONE | ||
70001 | 5;6 | 进入判断dP/dU是否小于步长调整设定值的节点 | Default | NONE | ||
70001 | 6;7 | 减小电压增量 | Default | Set_Points | Uc:Ucs | |
70001 | 6;7 | 增大电压增量 | Default | Set_Points | Uc:Ucb | |
70001 | 7;8 | 增大电压 | Default | Set_Points | Uset_POINT:Uset_POINT+Uc | |
70001 | 7;9 | 减小电压 | Default | Set_Points | Uset_POINT:Uset_POINT-Uc |
本实验中的边声明包括了SetPoints和None两种动作类型,SetPoints连接节点的同时还需要进行动作,None只需要进行连接。
接下来简单介绍一下每条边的动作:
连接第1和第2节点的边:动作名称:AOE触发测点复位,计算dU和dI,动作类型为SetPoints,需要在这个边的动作上将DoCal_POINT置0,防止循环结束时还未置0导致网络再触发;
dU: U_POINT - Un1;计算电压的微分。
dI: I_POINT - In1;计算电流的微分。
1)连接第2和第3节点的边:动作名称:存储电压和电流值,进入判断dI是否为0的节点,动作类型为SetPoints,
Un1: U_POINT;存储电压值。
In1: I_POINT;存储电流值。
2)连接第3和第10节点的边:动作名称:进入结束节点,动作类型为None,没有动作参数只起连接作用。
3)连接第3和第4节点的边:动作名称:进入判断dI是否大于0的节点,动作类型为None,没有动作参数只起连接作用。
4)连接第4和第8节点的边:动作名称:增大电压,动作类型为SetPoints,Uset_POINT: Uset_POINT + Uc;在初始电压设定值的基础上增加一个步长。
5)连接第8和第10节点的边:动作名称:电压限幅,动作类型为SetPoints,Uset_POINT: (Uset_POINT <= Uuplim && Uset_POINT >= Udownlim) * Uset_POINT + (Uset_POINT > Uuplim) * Uuplim + (Uset_POINT < Udownlim) * Udownlim;判断电压是否超出限定值,未超出输出电压值,超出则输出电压设定值。
6)连接第4和第9节点的边:动作名称:减小电压,动作类型为SetPoints,Uset_POINT: Uset_POINT - Uc;在初始电压设定值的基础上减去一个步长。
7)连接第9和第10节点的边:动作名称:电压限幅,动作类型为SetPoints,Uset_POINT: (Uset_POINT <= Uuplim && Uset_POINT >= Udownlim) * Uset_POINT + (Uset_POINT > Uuplim) * Uuplim + (Uset_POINT < Udownlim) * Udownlim;判断电压是否超出限定值,未超出输出电压值,超出则输出电压设定值。
8)连接第2和第5节点的边:动作名称:存储电压和电流值,计算dP/dU,动作类型为SetPoints。
Un1: U_POINT;存储电压值。
In1: I_POINT;存储电流值。
dPdU: I_POINT + U_POINT * dI / dU;计算并存储dP/dU的值。
9)连接第5和第10节点的边:动作名称:进入结束节点,动作类型为None,没有动作参数只起连接作用。
10)连接第5和第6节点的边:动作名称:进入判断dP/dU是否小于步长调整设定值的节点,动作类型为None,没有动作参数只起连接作用。
11)连接第6和第7节点的边1:动作名称:减小电压增量,动作类型为SetPoints,Uc: Ucs;当dP/dU小于设定步长时,设定步长更改为最小步长。
12)连接第6和第7节点的边2:动作名称:增大电压增量,动作类型为SetPoints,Uc: Ucb;当dP/dU大于设定步长时,设定步长设定为最大步长。
13)连接第7和第8节点的边:动作名称:增大电压,动作类型为SetPoints,Uset_POINT: Uset_POINT + Uc;当dP/dU大于0,电压增大一个步长。
14)连接第7和第9节点的边:动作名称:减小电压,动作类型为SetPoints,Uset_POINT: Uset_POINT - Uc;当dP/dU小于0,电压减小一个步长。
5、低代码控制器
本控制器是基于AOE引擎的低代码控制器。控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
使用的时候,将电源线与电源相连,打开电源开关,再用网线将控制器与计算机连接,就可以使用。
6、MATLAB仿真过程
6.1、连接低代码控制器
这一步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
6.2、配置低代码控制器的文件
通过网页端上传的方法与案例1-房屋温度控制中介绍的步骤完全一致,此处不再赘述。
6.3、MATLAB界面操作
配置完成后,进入MATLAB的界面。然后打开控制器的源文件mpptCtrl.m文件。
打开mpptCtrl函数,修改相关参数。
以上这个程序段用于联系控制器与MATLAB,在建立modbus通信的代码中,输入从站ip(“127.0.0.1”,当连接实体的控制器时,需要填写查找得到的控制器的ip地址)和端口(502,这个端口是由通信通道配置里选择的)。
在命令行窗口中输入modbus通信,判断通信是否成功连接。
6.4、simulink模型参数设置
配置好所有文件,打开MATLAB配置好与控制器的通信后,打开simulink模型。
打开simulink里的configuration。
设置Configuration的相关参数如上图所示。
运行之后可以从光伏输出功率的变化窗口观察到功率的变化情况,可以发现最终功率已经保持在一个比较高的水平了。
7、总结
本实验中,利用低代码控制器实现了光伏模型中的最大功率点跟踪(MPPT)技术,模型中的AOE网络的建立十分的直观,可以通过这个网络直接观察到运行步骤的所有过程,模型的构建简洁明了,适合通过类比推导出各种不同功能的模型。
6.4 储能辅助调频
1、实验环境
该程序可在以下环境运行: 1.Matlab R2019a + Simulink v9.3及以上版本;
2.Matlab APP:Instrument Control Toolbox;
3.低代码控制器。
2、实验介绍
许多地区以火电机组做为主要调频资源,而储能的AGC调频效果远好于火电机组,引入相对少量的储能系统,将能够迅速并有效地解决区域电网调频资源不足的问题。
本案例中低代码控制器接收主控系统下发的调遥指令,根据八个调频储能的SOC、充放电总里程等条件,通过优化求解下发出力指令,控制八个储能的出力,从而达到储能辅助调频的目的。
3、实验模型
本实验模型需要自行搭建。根据储能电池模型,可搭建模型如下:
完成储能电池模型搭建后,对其进行封装,并引入S-函数,在S-函数中实现与低代码控制器通信功能,接收主控系统下发的调遥,完成储能功率分配并下发,如下图所示。
4、实验原理
本实验案例求解优化问题实现储能功率的分配。考虑到方差优化的复杂性,尽量避免将二次式作为优化目标,以SOC相对平均值的总偏差的绝对值和功率相对平均值的偏差绝对值作为目标函数:
\[ \min w_1\sum_{i=1}^8 |SOC_i-SOC_{mean}|\cdot|SOC_i^0-SOC_{mean}|+w_2\sum_{i=1}^8e^{-|SOC_i^0-SOC_{mean}|}|P_i-P_{mean}| \]
式中,\(w_1\)表示SOC均衡的影响权重,\(w_2\)表示功率变动带来的代价权重;\(SOC_{mean}\)为各SOC均值;\(SOC_i^0\)为当前电池的SOC值;\(P_i\)表示当前电池的功率值;\(P_{mean}\)表示当前电池功率的平均值;\(SOC_i\)表示在功率分发策略所计算出的功率工作下,下一时刻第i个电池的SOC值,具体计算式如下:
\[ SOC_i=SOC_i^0+\frac{x_i\Delta t}{E_{act,i}} \]
其中\(E_{act,i}\)表示电池i的实际容量。
5、实验步骤
低代码控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
5.1、编写低代码控制器配置文件
低代码控制器文件配置分为三个部分:测点配置、通信通道配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,本案例中需要的信号是八个储能的启停指令、充放电总里程、SOC、输出功率、工作状态、输出功率指令、额定里程、额定容量、最大充电功率、最大放电功率,以及系统收到的是否调频指令与调频功率指令。通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
5.1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。测点配置如下图所示:测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。测点配置如下图所示:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | EMS_MODE_AGC_POINT | TRUE | FALSE | 0 | 主控系统下发的遥控-->EMS模式 |
2 | 100002 | 测点2 | GEN_TOTAL_P_POINT | FALSE | FALSE | 0 | 主控系统下发的遥调->系统有功指令 |
3 | 100003 | 测点3 | PCS1_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
4 | 100004 | 测点4 | PCS2_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
5 | 100005 | 测点5 | PCS3_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
6 | 100006 | 测点6 | PCS4_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
7 | 100007 | 测点7 | PCS5_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
8 | 100008 | 测点8 | PCS6_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
9 | 100009 | 测点9 | PCS7_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
10 | 100010 | 测点10 | PCS8_CTRL_POINT | TRUE | FALSE | 0 | 下发给PMS的遥控 |
11 | 100011 | 测点11 | BAMS1_MILEAGE_TOTAL_POINT | FALSE | FALSE | 0 | 充放总里程 |
... |
(由于测点数量过多,具体测点文件在文末可下载)(由于测点数量过多,具体测点文件在文末可下载)
本程序共需要82个测点,具体包括八个储能的启停指令、充放电总里程、SOC、输出功率、工作状态、输出功率指令、额定里程、额定容量、最大充电功率、最大放电功率,以及系统收到的是否调频指令与调频功率指令。
5.1.2、通信通道配置
本案例中,控制器作为从站,具体的通道配置和寄存器配置如下:
通道名称 | server测试通道 | 连接名称 | 测试通道1 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 82 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 |
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | TwoByteIntUnsigned | FALSE | 2000 | 100001 |
2 | HOLDING | 2 | EightByteFloat | FALSE | 2000 | 100002 |
3 | HOLDING | 6 | TwoByteIntUnsigned | FALSE | 2000 | 100003 |
4 | HOLDING | 7 | TwoByteIntUnsigned | FALSE | 2000 | 100004 |
5 | HOLDING | 8 | TwoByteIntUnsigned | FALSE | 2000 | 100005 |
6 | HOLDING | 9 | TwoByteIntUnsigned | FALSE | 2000 | 100006 |
7 | HOLDING | 10 | TwoByteIntUnsigned | FALSE | 2000 | 100007 |
8 | HOLDING | 11 | TwoByteIntUnsigned | FALSE | 2000 | 100008 |
9 | HOLDING | 12 | TwoByteIntUnsigned | FALSE | 2000 | 100009 |
11 | HOLDING | 13 | TwoByteIntUnsigned | FALSE | 2000 | 100010 |
12 | HOLDING | 17 | EightByteFloat | FALSE | 2000 | 100011 |
... |
本案例中总共用到两种数据类型,TwoByteIntUnsigned对应开关量,占据一位寄存器;EightByteFloat对应连续或者离散的数据变量,占据4位寄存器。根据数据类型完成对起始地址的分配,即可完成通道文件的配置。
5.1.3、AOE配置
AOE网络声明
AOE网络声明部分,定义了表格之中的AOE网络个数和整体信息以及一些变量的初始值。其中触发条件分为三类:SimpleRepeat(定时触发,需要自行设定定时时间)、TimeDriven(时间驱动)、EventDriven(事件驱动);变量的定义方式为:<变量名1>:<初值1>;<变量名2>:<初值2>;…。
本案例中的AOE网络声明如下所示:
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | AGC辅助调频 | Event_Drive | deadband:100; SOCref:0.55; dt:0.25; last_cmd:100; w:0.0000005; max_power:1500 |
本实验中需要定义多个变量初始值。具体包括:deadband:SOC死区;SOCref:SOC参考值;dt:每步步长;w:系数w2;max_power:充放电功率上下限。
AOE节点声明
节点类型分为Switch和Condition两类,其中Switch节点为二分支逻辑判断,触发逻辑为:表达式为真时,该节点序号为1的边进行动作;表达式为假时,序号为2的边进行动作。当Switch节点为AOE网入度为0的节点(首节点)时,Switch节点直接触发,若超时时间内表达式为真,则执行动作1,为假或者发生超时事件执行动作2;Condition节点的表达式为事件触发条件,超时时间内表达式为真,则节点事件发生,该节点出发的所有动作并行执行。
本案例的节点声明如下:
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 1000 | EMS_MODE_AGC_POINT == 1 && GEN_TOTAL_P_POINT != last_cmd |
70001 | 2 | 中间量计算节点 | Condition | 15000 | 1 |
70001 | 3 | 优化求解结束 | Condition | 1000 | flag==1 |
70001 | 4 | 存在最优解 | Condition | 1000 | 1 |
70001 | 5 | 不存在最优解 | Condition | 1000 | 1 |
本案例中一共有5个节点,第1个节点是simulink通信事件节点,为事件触发类型,当EMS_MODE_AGC_POINT>0.5时,该节点被触发,进入运算流程。
第2个节点表示中间变量计算完成的事件,当考虑SOH因总充放电里程变化而减小时,计算并更新当前各储能的SOH以及储能运行寿命损耗导致的实际容量减少等,当计算动作完成后,节点2触发,开始进行优化计算。
第3个节点表示优化计算完成的事件,在控制器内置的优化求解方法里,当最优解不存在时所有优化变量的值均为0;而有最优解存在时,由于目标函数的设计,flag的值等于1,因此可以通过设置一位二进制变量flag来作为优化问题是否有解的判断条件。该节点类型位Switch,节点事件触发时,节点动作1被执行,否则发生超时之后,节点动作2被执行
第4 个节点表示优化问题已得到最优解的事件,该事件发生说明最优解被找到并下发,AOE策略结束。
第5个节点表示优化问题没有找到最优解,这种情况发生说明发生以下两种情况:1.EMS下发的AGC指令不合理;2.储能可调度容量太小。
AOE边声明
边需要声明首尾节点,格式为:<尾节点ID>;<首节点ID>。边的方向为:尾节点→首节点。边的动作类型有:None、SetPoints、Solve、MILP、SimpleMilp、NLP。其中,SetPoints除了对测点设值之外,还可以进行变量定义和计算,动作参数分为数字量和模拟量;Solve为求解方程Ax=b;Milp为混合整数线性规划问题求解;Nlp为非线性规划问题求解。
本案例中的AOE边声明如下图所示:本案例中的AOE边声明如下图所示:
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 计算中间量 | Default | Set_Points | QRate:10000 | |
70001 | 2;3 | 优化求解 | Default | MILP | <优化问题字符串> | |
70001 | 3;4 | 下发优化策略 | Default | Set_Points | BAMS1_CTRL_POINT:u1-v1; BAMS2_CTRL_POINT:u2-v2; BAMS3_CTRL_POINT:u3-v3; BAMS4_CTRL_POINT:u4-v4; BAMS5_CTRL_POINT:u5-v5; BAMS6_CTRL_POINT:u6-v6; BAMS7_CTRL_POINT:u7-v7; BAMS8_CTRL_POINT:u8-v8; PCS1_CTRL_POINT:y1; PCS2_CTRL_POINT:y2; PCS3_CTRL_POINT:y3; PCS4_CTRL_POINT:y4; PCS5_CTRL_POINT:y5; PCS6_CTRL_POINT:y6; PCS7_CTRL_POINT:y7; PCS8_CTRL_POINT:y8; last_cmd:GEN_TOTAL_P_POINT | |
70001 | 3;5 | 下发默认策略 | Default | Set_Points | BAMS1_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS2_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS3_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS4_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS5_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS6_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS7_CTRL_POINT:GEN_TOTAL_P_POINT/8; BAMS8_CTRL_POINT:GEN_TOTAL_P_POINT/8; PCS1_CTRL_POINT:1; PCS2_CTRL_POINT:1; PCS3_CTRL_POINT:1; PCS4_CTRL_POINT:1; PCS5_CTRL_POINT:1; PCS6_CTRL_POINT:1; PCS7_CTRL_POINT:1; PCS8_CTRL_POINT:1; last_cmd:GEN_TOTAL_P_POINT |
本实验中AOE主要进行的为优化求解功能。
表中*<优化问题字符串>*为描述实验原理一节中所建立优化问题的字符串:
min(flag+abs(BAMS1_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha1+w*exp(-abs(BAMS1_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta1+abs(BAMS2_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha2+w*exp(-abs(BAMS2_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta2+abs(BAMS3_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha3+w*exp(-abs(BAMS3_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta3+abs(BAMS4_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha4+w*exp(-abs(BAMS4_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta4+abs(BAMS5_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha5+w*exp(-abs(BAMS5_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta5+abs(BAMS6_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha6+w*exp(-abs(BAMS6_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta6+abs(BAMS7_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha7+w*exp(-abs(BAMS7_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta7+abs(BAMS8_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8)*alpha8+w*exp(-abs(BAMS8_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8))*beta8);
y1>=0;y1<=1;
y2>=0;y2<=1;
y3>=0;y3<=1;
y4>=0;y4<=1;
y5>=0;y5<=1;
y6>=0;y6<=1;
y7>=0;y7<=1;
y8>=0;y8<=1;
deadband*(GEN_TOTAL_P_POINT>=0)*y1-u1<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y1-u1>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y2-u2<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y2-u2>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y3-u3<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y3-u3>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y4-u4<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y4-u4>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y5-u5<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y5-u5>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y6-u6<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y6-u6>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y7-u7<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y7-u7>=0;
deadband*(GEN_TOTAL_P_POINT>=0)*y8-u8<=0;
max_power*(GEN_TOTAL_P_POINT>=0)*y8-u8>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y1-v1<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y1-v1>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y2-v2<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y2-v2>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y3-v3<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y3-v3>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y4-v4<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y4-v4>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y5-v5<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y5-v5>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y6-v6<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y6-v6>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y7-v7<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y7-v7>=0;
deadband*(GEN_TOTAL_P_POINT<0)*y8-v8<=0;
max_power*(GEN_TOTAL_P_POINT<0)*y8-v8>=0;
-dt/QRate*u1+dt/QRate*v1>=-BAMS1_SOC_POINT;
-dt/QRate*u1+dt/QRate*v1<=1-BAMS1_SOC_POINT;
-dt/QRate*u2+dt/QRate*v2>=-BAMS2_SOC_POINT;
-dt/QRate*u2+dt/QRate*v2<=1-BAMS2_SOC_POINT;
-dt/QRate*u3+dt/QRate*v3>=-BAMS3_SOC_POINT;
-dt/QRate*u3+dt/QRate*v3<=1-BAMS3_SOC_POINT;
-dt/QRate*u4+dt/QRate*v4>=-BAMS4_SOC_POINT;
-dt/QRate*u4+dt/QRate*v4<=1-BAMS4_SOC_POINT;
-dt/QRate*u5+dt/QRate*v5>=-BAMS5_SOC_POINT;
-dt/QRate*u5+dt/QRate*v5<=1-BAMS5_SOC_POINT;
-dt/QRate*u6+dt/QRate*v6>=-BAMS6_SOC_POINT;
-dt/QRate*u6+dt/QRate*v6<=1-BAMS6_SOC_POINT;
-dt/QRate*u7+dt/QRate*v7>=-BAMS7_SOC_POINT;
-dt/QRate*u7+dt/QRate*v7<=1-BAMS7_SOC_POINT;
-dt/QRate*u8+dt/QRate*v8>=-BAMS8_SOC_POINT;
-dt/QRate*u8+dt/QRate*v8<=1-BAMS8_SOC_POINT;
u1-v1+u2-v2+u3-v3+u4-v4+u5-v5+u6-v6+u7-v7+u8-v8>=GEN_TOTAL_P_POINT-0.1;
u1-v1+u2-v2+u3-v3+u4-v4+u5-v5+u6-v6+u7-v7+u8-v8<=GEN_TOTAL_P_POINT+0.1;
alpha1+dt/QRate*u1-dt/QRate*v1>= BAMS1_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha1-dt/QRate*u1+dt/QRate*v1>=-BAMS1_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha2+dt/QRate*u2-dt/QRate*v2>= BAMS2_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha2-dt/QRate*u2+dt/QRate*v2>=-BAMS2_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha3+dt/QRate*u3-dt/QRate*v3>= BAMS3_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha3-dt/QRate*u3+dt/QRate*v3>=-BAMS3_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha4+dt/QRate*u4-dt/QRate*v4>= BAMS4_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha4-dt/QRate*u4+dt/QRate*v4>=-BAMS4_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha5+dt/QRate*u5-dt/QRate*v5>= BAMS5_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha5-dt/QRate*u5+dt/QRate*v5>=-BAMS5_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha6+dt/QRate*u6-dt/QRate*v6>= BAMS6_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha6-dt/QRate*u6+dt/QRate*v6>=-BAMS6_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha7+dt/QRate*u7-dt/QRate*v7>= BAMS7_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha7-dt/QRate*u7+dt/QRate*v7>=-BAMS7_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha8+dt/QRate*u8-dt/QRate*v8>= BAMS8_SOC_POINT-(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
alpha8-dt/QRate*u8+dt/QRate*v8>=-BAMS8_SOC_POINT+(BAMS1_SOC_POINT+BAMS2_SOC_POINT+BAMS3_SOC_POINT+BAMS4_SOC_POINT+BAMS5_SOC_POINT+BAMS6_SOC_POINT+BAMS7_SOC_POINT+BAMS8_SOC_POINT)/8;
beta1-0.875*u1-0.875*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta2+0.125*u1+0.125*v1-0.875*u2-0.875*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta3+0.125*u1+0.125*v1+0.125*u2+0.125*v2-0.875*u3-0.875*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta4+0.125*u1+0.125*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3-0.875*u4-0.875*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta5+0.125*u1+0.125*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4-0.875*u5-0.875*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta6+0.125*u1+0.125*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5-0.875*u6-0.875*v6+0.125*u7+0.125*v7+0.125*u8+0.125*v8>=0;
beta7+0.125*u1+0.125*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6-0.875*u7-0.875*v7+0.125*u8+0.125*v8>=0;
beta8+0.125*u1+0.125*v1+0.125*u2+0.125*v2+0.125*u3+0.125*v3+0.125*u4+0.125*v4+0.125*u5+0.125*v5+0.125*u6+0.125*v6+0.125*u7+0.125*v7-0.875*u8-0.875*v8>=0;
beta1+0.875*u1+0.875*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta2-0.125*u1-0.125*v1+0.875*u2+0.875*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta3-0.125*u1-0.125*v1-0.125*u2-0.125*v2+0.875*u3+0.875*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta4-0.125*u1-0.125*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3+0.875*u4+0.875*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta5-0.125*u1-0.125*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4+0.875*u5+0.875*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta6-0.125*u1-0.125*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5+0.875*u6+0.875*v6-0.125*u7-0.125*v7-0.125*u8-0.125*v8>=0;
beta7-0.125*u1-0.125*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6+0.875*u7+0.875*v7-0.125*u8-0.125*v8>=0;
beta8-0.125*u1-0.125*v1-0.125*u2-0.125*v2-0.125*u3-0.125*v3-0.125*u4-0.125*v4-0.125*u5-0.125*v5-0.125*u6-0.125*v6-0.125*u7-0.125*v7+0.875*u8+0.875*v8>=0;
flag>=1;
u1:3,u2:3,u3:3,u4:3,u5:3,u6:3,u7:3,u8:3,
v1:3,v2:3,v3:3,v4:3,v5:3,v6:3,v7:3,v8:3,
y1:2,y2:2,y3:2,y4:2,y5:2,y6:2,y7:2,y8:2,
alpha1:3,alpha2:3,alpha3:3,alpha4:3,alpha5:3,alpha6:3,alpha7:3,alpha8:3,
beta1:3,beta2:3,beta3:3,beta4:3,beta5:3,beta6:3,beta7:3,beta8:3,flag:2
5.2、编写Simulink与控制器通信程序
modbusCom.m是本实验模型控制器的源文件,建立与低代码控制器通信的作用。
下面的代码表示的是输入和输出值的个数,本实验中的输入有66个,包括八个储能的充放电总里程、SOC、输出功率、工作状态、额定里程、额定容量、最大充电功率、最大放电功率,以及系统收到的是否调频指令与调频功率指令。输出有16个,为八个储能的启停指令与输出功率指令。
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 16;
sizes.NumInputs = 66;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
下图表示的是定步长仿真的仿真步长Modbus通信模块的在Simulink仿真模型中的采样时间为0.02s。下图表示的是定步长仿真的仿真步长Modbus通信模块的在Simulink仿真模型中的采样时间为0.02s。
ts = [0.02,0];
下图表示建立与控制器的通信。
m = modbus('tcpip', '192.168.137.170', 502);
6、低代码控制器配置与运行
该部分与温度控制案例相同。
7、仿真运行结果
先运行低代码控制器,再运行Simulink模型,进行仿真。利用低代码控制器进行优化求解,得到的控制结果如下所示:
8、总结
由该仿真实验可以看出,使用低代码控制器并不需要繁复的程序代码编写,只需要编写测点配置、通信通道配置和AOE配置文件就可以实现通信和控制功能,与目前常用的其他控制器相比,更方便于非编程技术背景人员的应用。
附件:储能辅助调频.rar
6.5 储能削峰填谷
1、实验目的
- 熟悉储能电池的数学模型和仿真实现方法;
- 了解储能削峰填谷控制原理;
- 基于低代码控制器实现储能削峰填谷;
- 实现Simulink模型与低代码控制器的硬件在环仿真。
2、实验模型
本实验的Simulink模型搭建如下图所示:
图中的modbusCom和pcsUpdate是S-函数模块,实现仿真模型与控制器的通信功能。
3、实验步骤
低代码控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
将控制器电源线与电源相连,打开电源开关,再用网线将控制器与计算机连接,然后打开一个浏览器,并输入控制器地址也可以得到如下界面。
输入账号和密码后,进入控制器住界面,选择并导入已编写好的测点、通道和AOE配置文件,具体操作同房屋温度控制,此处不再赘述。
(可点击附件下载配置文件和仿真模型,其中points-SH_sim.csv为测点配置文件,tcp-mbd-transport-SH_sim.csv为通道配置文件,aoe-pcsSH.csv为AOE配置文件,BESS_model.slx为仿真模型,modbusCom.m和pcsUpdate.m为S-函数源文件,其中语句m = modbus('tcpip', '192.168.137.170', 502);中的ip需要修改为控制器实际ip)。
4、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真,得到的储能削峰填谷仿真结果如下图所示。
由上图中储能功率和电价曲线可见,经过控制后,储能成功实现了削峰填谷,并且储能功率波动很小,SOC保持在给定范围内。
本实验利用低代码控制器实现了储能削峰填谷控制,其中AOE控制网络的建立十分直观,通过这个网络可以清晰展示控制过程的所有步骤,且控制功能实现无需复杂编程,适合非编程技术背景的人员学习使用。
附件:储能削峰填谷控制.zip
6.6 过零检测
1、实验目的
基于Simulink官方的过零检测仿真案例,采用低代码控制器代替其中的开关模块,选择输出信号,实现硬件在环仿真。
2、实验模型
本实验原始模型来自于Simulink官方的房屋温度控制模型,官网给出了该模型原理的详细介绍( https://ww2.mathworks.cn/help/simulink/slref/accurate-zero-crossing-detection.html ),在MATLAB命令行窗口中输入命令:openExample('simulink_general/sldemo_zeroxingExample')可打开该模型,如下图所示:
采用低代码控制器代替开关模块进行过零检测时,将开关模块替换为S-函数,在S-函数中实现与低代码控制器通信功能,修改后的模型如下图所示:
3、实验步骤
低代码控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
3.1、编写低代码控制器配置文件
低代码控制器文件配置分为三个部分:测点配置、通信通道配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,本案例中需要的信号是输入的正弦信号绝对值、按时间生成的过零信号,通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
3.1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下所示:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | Abs1_POINT | FALSE | FALSE | 0 | 正弦波绝对值信号1 |
2 | 100002 | 测点2 | Abs2_POINT | FALSE | FALSE | 1 | 正弦波绝对值信号2 |
3 | 100003 | 测点3 | Abs3_POINT | FALSE | FALSE | 1 | 正弦波绝对值信号3 |
4 | 100004 | 测点4 | Sat1_POINT | FALSE | FALSE | 1 | 正弦波限幅信号1 |
5 | 100005 | 测点5 | Sat2_POINT | FALSE | FALSE | 1 | 正弦波限幅信号2 |
6 | 100006 | 测点6 | Sat3_POINT | FALSE | FALSE | 1 | 正弦波限幅信号3 |
7 | 100007 | 测点7 | Switch_POINT | FALSE | FALSE | 0 | 开关控制信号 |
8 | 100008 | 测点8 | Out1_POINT | FALSE | FALSE | 0 | 输出信号1 |
9 | 100009 | 测点9 | Out2_POINT | FALSE | FALSE | 0 | 输出信号2 |
10 | 100010 | 测点10 | Out3_POINT | FALSE | FALSE | 0 | 输出信号3 |
11 | 100011 | 测点11 | DoCal_POINT | FALSE | FALSE | 0 | 策略控制信号 |
3.1.2、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下图所示,其中通道数量为1,服务端口需设置为未占用端口。
通道名称 | server测试通道 |
---|---|
连接个数 | 1 |
服务端口 | 502 |
然后对客户端信息和测点信息等进行配置,如下图所示:
连接名称 | 测试通道 | 序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|---|---|
测点个数 | 3 | 1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
客户端IP | 127.0.0.1 | 2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100002 |
客户端端口 | 9999 | 3 | HOLDING | 9 | TwoByteIntUnsigned | FALSE | 2000 | 100003 |
3.1.3、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
本案例中的AOE网络声明如下所示:
控制器的作用是实现过零检测,所以名称定为过零检测,触发条件设置为事件控制。变量初始值定义了过零比较值threshold为0.5。
AOE节点声明
本案例的控制逻辑可以用AOE网表示如下:
对应上图需要定义的节点有4个,节点声明如下所示:
第一个节点是simulink通信事件节点,为事件触发类型,当DoCal_POINT>0.5时,也就是测点11输出1,表示允许控制器计算时,该节点被触发,进入运算流程。
第2个节点是逻辑判断节点,对于设定值进行大小比较判断开关控制信号是否大于threshold,也就是测点7的值是否大于0,完成逻辑判断后根据结果进入两条不同动作的边:判断结果为真执行第1条边,否则执行第2条边,边的顺序是就是文件里面定义的顺序。
第3、4个节点是结束节点,是事件触发类型,当所有的计算步骤都完成,信号传输后,进入结束节点,计算结束,并将DoCal_POINT的数值改为0,等待下一次通信之后,开始计算。超时时间定为100ms,因为需要DoCal_POINT置0再让AOE执行过程结束,防止AOE被反复触发。
AOE边声明
本案例中的AOE边声明如下图所示:
本实验中的边声明的动作类型是SetPoints,SetPoints类型的动作边在连接节点的同时还需要进行动作。接下来简单介绍每条边的动作:
- 连接第1和第2节点的边:动作名称:aoe触发测点复位,需要在这个边的动作上将DoCal_POINT置0,防止循环结束时还未置0导致网络再触发。
- 连接第2和第3节点的边:动作名称:输出正弦波绝对值,动作类型为SetPoints,当第2个节点判断为真的时候,需要输出三组输出信号的绝对值,
- 连接第2和第4节点的边:动作名称:输出正弦波限幅值,动作类型为SetPoints,当第2个节点判断为假的时候,需要输出三组输出信号的限幅值。
3.2、编写Simulink与控制器通信程序
打开Simulink模型中S-函数的源文件,将S-函数的输入信号数量设置为2、输出信号数量设置为1,采样时间,采样时间设置为0.01(每仿真10ms与控制器通信一次)。添加建立Modbus通信的命令,其中需要服务端ip和端口参数:
添加温度设定值、温度测量值、读取控制指令程序:
3.3、低代码控制器配置与运行
该步骤具体操作同房屋温度控制,此处不再赘述。
3.4、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。得到的利用低代码控制器的输出信号与原模型十分接近。
由该仿真实验可以看出,使用低代码控制器并不需要繁复的程序代码编写,只需要编写测点配置、通信通道配置和AOE配置文件就可以实现通信和控制功能,与目前常用的其他控制器相比,更方便于非编程技术背景人员的应用。
附件:过零检测.rar
6.7 线损分析
1、实验目的
基于Simulink官方的配电网线损分析仿真案例,采用低代码控制器计算分路分段线损率,实现硬件在环仿真。
2、实验模型
分路分段线损分析是配电台区智能融合终端的重要分析业务功能之一,通过采集馈线侧与表箱侧的电能量数据、台区总电能量数据,通过汇总、对比,分级、分层进行线损分析和管理,便于查找线损点和窃电点。本实验以自主搭建台区配电线路模型为基础,用低代码控制器计算分路分段线损率,模型如下图所示:
3、实验步骤
低代码控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
3.1、编写低代码控制器配置文件
低代码控制器文件配置分为三个部分:测点配置、通信通道配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数,通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
3.1.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下图所示:
3.1.2、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下图所示,其中通道数量为1,服务端口需设置为未占用端口。
然后对客户端信息和测点信息等进行配置,如下图所示:
3.1.3、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
AOE网络声明部分,定义了表格之中的AOE网络个数和整体信息以及一些变量的初始值。本案例中的AOE网络声明如下所示:
aoe触发条件设置为事件驱动。
AOE节点声明
本案例的AOE节点声明如下所示:
第一个节点是simulink通信事件节点,为事件触发类型,当DoCal_POINT>0.5时,也就是测点11输出1,表示允许控制器计算时,该节点被触发,进入运算流程;第2个节点是计算中间节点;最后一个节点是结束节点,是事件触发类型,当所有的计算步骤都完成,信号传输后,进入结束节点,计算结束,并将DoCal_POINT的数值改为0,等待下一次通信之后,开始计算。超时时间定为100ms,因为需要DoCal_POINT置0再让AOE执行过程结束,防止AOE被反复触发。
AOE边声明
线损率的计算公式为:线损率=(台区总表日用电量-∑(户表日用电量))/台区总表日用电量。本案例中的AOE边声明如下图所示:
本实验中的边声明的动作类型是SetPoints,SetPoints类型的动作边在连接节点的同时还需要进行动作。
3.2、编写Simulink与控制器通信程序
打开Simulink模型中S-函数的源文件,将S-函数的输入信号数量设置为2、输出信号数量设置为1,采样时间,采样时间设置为0.1(每仿真0.1s与控制器通信一次)。添加建立Modbus通信的命令,其中需要服务端ip和端口参数:
添加数据采集、读取线损率计算结果指令程序:
3.3、低代码控制器配置与运行
该步骤具体操作同房屋温度控制,此处不再赘述。
3.4、运行仿真
先运行低代码控制器,再运行Simulink模型,进行仿真。通过验算易得低代码控制器能够正确分析分路分段线损。
由该仿真实验可以看出,使用低代码控制器并不需要繁复的程序代码编写,只需要编写测点配置、通信通道配置和AOE配置文件就可以实现通信和控制功能,与目前常用的其他控制器相比,更方便于非编程技术背景人员的应用。
附件:线损分析.rar
6.8 直流法潮流计算
1、实验目的
潮流计算是电力系统中非常重要的分析计算,指在给定电力系统网络拓扑、元件参数和发电、负荷参量条件下,计算有功功率、无功功率及电压在电力网中的分布。而直流法潮流计算是一种基于线性模型的简化潮流算法。
从数学上看,直流法潮流计算(DCPF)是求解一组由潮流方程描述的线性代数方程组。通过该应用案例,展示低代码控制器线性方程(Solve动作)求解功能。
2、实验原理
对于一个N节点电网,经过适当假设可得到直流法潮流方程(矩阵形式):P=Bθ。式中矩阵表示如下:
其中有功功率P、电纳矩阵B为已知量,待计算值为各节点电压相角。
3、实验步骤
本直流法潮流计算的对象选取为matpower中的case5标准算例。具体步骤如下
3.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | DoCal_POINT | TRUE | FALSE | 0 | 计算控制 |
2 | 100002 | 测点2 | theta1 | FALSE | FALSE | 0 | 节点1电压相角 |
3 | 100003 | 测点3 | theta2 | FALSE | FALSE | 0 | 节点2电压相角 |
4 | 100004 | 测点4 | theta3 | FALSE | FALSE | 0 | 节点3电压相角 |
5 | 100005 | 测点5 | theta4 | FALSE | FALSE | 0 | 节点4电压相角 |
6 | 100006 | 测点6 | theta5 | FALSE | FALSE | 0 | 节点5电压相角 |
3.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为直流法潮流计算,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 直流法潮流计算 | Event_Drive | x1:0;x2:0;x3:0;x4:0;x5:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10 | DoCal_POINT > 0.5 |
70001 | 2 | 计算节点 | Condition | 10 | 1 |
70001 | 3 | 幅值 | Condition | 10 | 1 |
70001 | 4 | 结束节点 | Condition | 10 | DoCal_POINT == 0 |
本案例中共有4个节点,节点类型均为Condition,表达式设为1,表明始终满足条件触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 进入直流潮流计算 | Default | Set_Points | DoCal_POINT:0; | |
70001 | 2;3 | 计算直流潮流 | Default | Solve | +224.7319x1-35.5872x2-32.8947x4-156.25x5=2.1; -35.5872x1+128.1798x2-92.5926x3=-3; -92.5926x2+126.2626x3-33.67x4=0.2349; x4=0; -156.25x1-33.67x4+189.92*x5=4.6651; x1,x2,x3,x4,x5 | |
70001 | 3;4 | 赋值 | Default | Set_Points | theta1:x1; theta2:x2; theta3:x3; theta4:0; theta5:x5; |
4、运行计算
将上述配置文件上传至低代码控制器中,运行即可得到计算结果,其运算结果如下所示。
matpower计算结果如下:
对比低代码控制器与matpower计算结果,可见低代码控制器对于直流法潮流能够精确计算。
附件:直流法潮流计算.rar
6.9 交流法潮流计算
1、实验目的
潮流计算是电力系统中非常重要的分析计算,指在给定电力系统网络拓扑、元件参数和发电、负荷参量条件下,计算有功功率、无功功率及电压在电力网中的分布。
从数学上看,交流法潮流计算(PF)是求解一组由潮流方程描述的非线性代数方程组。通过该应用案例,展示低代码控制器非线性方程(NLSOLVE动作)求解功能。
2、实验原理
对于一个N节点电网,其潮流方程(极坐标形式)如下所示:
对于PQ节点,已知量为节点负荷的有功与无功功率,未知量为节点电压幅值V、相角θ以及发电节点的无功输出Qg;对于PV节点,已知量为节点的有功功率和电压幅值V,因此加入约束条件Vi=已知幅值
;对于平衡节点已知电压幅值与相角,因此加入约束条件Vi=1,θ=0
。
3、实验步骤
本交流法潮流计算的对象选取为matpower中的case5标准算例。具体步骤如下
3.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | DoCal_POINT | TRUE | FALSE | 0 | 计算控制 |
2 | 100002 | 测点2 | v1 | FALSE | FALSE | 1 | 节点1电压幅值 |
3 | 100003 | 测点3 | v2 | FALSE | FALSE | 1 | 节点2电压幅值 |
4 | 100004 | 测点4 | v3 | FALSE | FALSE | 1 | 节点3电压幅值 |
5 | 100005 | 测点5 | v4 | FALSE | FALSE | 1 | 节点4电压幅值 |
6 | 100006 | 测点6 | v5 | FALSE | FALSE | 1 | 节点5电压幅值 |
7 | 100007 | 测点7 | theta1 | FALSE | FALSE | 0 | 节点1电压相角 |
8 | 100008 | 测点8 | theta2 | FALSE | FALSE | 0 | 节点2电压相角 |
9 | 100009 | 测点9 | theta3 | FALSE | FALSE | 0 | 节点3电压相角 |
10 | 100010 | 测点10 | theta4 | FALSE | FALSE | 0 | 节点4电压相角 |
11 | 100011 | 测点11 | theta5 | FALSE | FALSE | 0 | 节点5电压相角 |
12 | 100012 | 测点12 | qg1 | FALSE | FALSE | 0 | 发电机1无功输出 |
13 | 100013 | 测点13 | qg2 | FALSE | FALSE | 0 | 发电机2无功输出 |
14 | 100014 | 测点14 | qg3 | FALSE | FALSE | 0 | 发电机3无功输出 |
15 | 100015 | 测点15 | qg4 | FALSE | FALSE | 0 | 发电机4无功输出 |
16 | 100016 | 测点16 | qg5 | FALSE | FALSE | 0 | 发电机5无功输出 |
17 | 100017 | 测点17 | pg_balancenode | FALSE | FALSE | 0 | 平衡节点有功输出 |
3.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为交流法潮流计算,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 交流法潮流计算 | Event_Drive | V1:1;V2:1;V3:1;V4:1;V5:1; THETA1:0;THETA2:0;THETA3:0;THETA4:0;THETA5:0; QG1:0;QG2:0;QG3:0;QG4:0;QG5:0; PG_balancenode:0 |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10 | DoCal_POINT > 0.5 |
70001 | 2 | 计算节点 | Condition | 10 | 1 |
70001 | 3 | 幅值 | Condition | 10 | 1 |
70001 | 4 | 结束节点 | Condition | 10 | DoCal_POINT == 0 |
本案例中共有4个节点,节点类型均为Condition,表达式设为1,表明始终满足条件触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 进入交流潮流计算 | Default | Set_Points | DoCal_POINT:0; | |
70001 | 2;3 | 计算交流潮流 | Default | NLSOLVE | 2.10000000-0.00000000-V1*(V1*(22.25068569)+V2*(-3.52348402cos(THETA1-THETA2)+35.23484021sin(THETA1-THETA2))+V4*(-3.25690464cos(THETA1-THETA4)+32.56904638sin(THETA1-THETA4))+V5*(-15.47029703cos(THETA1-THETA5)+154.70297030sin(THETA1-THETA5))); 0.00000000-3.00000000-V2*(V1*(-3.52348402cos(THETA2-THETA1)+35.23484021sin(THETA2-THETA1))+V2*(12.69106745)+V3*(-9.16758343cos(THETA2-THETA3)+91.67583425sin(THETA2-THETA3))); 3.23490000-3.00000000-V3*(V2*(-9.16758343cos(THETA3-THETA2)+91.67583425sin(THETA3-THETA2))+V3*(12.50125013)+V4*(-3.33366670cos(THETA3-THETA4)+33.33666700sin(THETA3-THETA4))); PG_balancenode-4.00000000-V4*(V1*(-3.25690464cos(THETA4-THETA1)+32.56904638sin(THETA4-THETA1))+V3*(-3.33366670cos(THETA4-THETA3)+33.33666700sin(THETA4-THETA3))+V4*(9.92423804)+V5*(-3.33366670cos(THETA4-THETA5)+33.33666700sin(THETA4-THETA5))); 4.66510000-0.00000000-V5*(V1*(-15.47029703cos(THETA5-THETA1)+154.70297030sin(THETA5-THETA1))+V4*(-3.33366670cos(THETA5-THETA4)+33.33666700sin(THETA5-THETA4))+V5*(18.80396373)); QG1+QG2-0.00000000-V1*(V1*(--222.48437689)+V2*(-3.52348402sin(THETA1-THETA2)-35.23484021cos(THETA1-THETA2))+V4*(-3.25690464sin(THETA1-THETA4)-32.56904638cos(THETA1-THETA4))+V5*(-15.47029703sin(THETA1-THETA5)-154.70297030cos(THETA1-THETA5))); -0.98610000-V2*(V1*(-3.52348402sin(THETA2-THETA1)-35.23484021cos(THETA2-THETA1))+V2*(--126.89785446)+V3*(-9.16758343sin(THETA2-THETA3)-91.67583425cos(THETA2-THETA3))); QG3-0.98610000-V3*(V2*(-9.16758343sin(THETA3-THETA2)-91.67583425cos(THETA3-THETA2))+V3*(--124.99987125)+V4*(-3.33366670sin(THETA3-THETA4)-33.33666700cos(THETA3-THETA4))); QG4-1.31470000-V4*(V1*(-3.25690464sin(THETA4-THETA1)-32.56904638cos(THETA4-THETA1))+V3*(-3.33366670sin(THETA4-THETA3)-33.33666700cos(THETA4-THETA3))+V4*(--99.23235038)+V5*(-3.33366670sin(THETA4-THETA5)-33.33666700cos(THETA4-THETA5))); QG5-0.00000000-V5*(V1*(-15.47029703sin(THETA5-THETA1)-154.70297030cos(THETA5-THETA1))+V4*(-3.33366670sin(THETA5-THETA4)-33.33666700cos(THETA5-THETA4))+V5*(--188.02063730)); V1-1.00000000; V3-1.00000000; V4-1.00000000; V5-1.00000000; THETA4; QG1/0.40000000-QG2/1.70000000; V1:1,V2:1,V3:1,V4:1,V5:1,THETA1,THETA2,THETA3,THETA4,THETA5,QG1,QG2,QG3,QG4,QG5,PG_balancenode | |
70001 | 3;4 | 赋值 | Default | Set_Points | v1:V1; v2:V2; v3:V3; v4:V4; v5:V5; theta1:THETA1; theta2:THETA2; theta3:THETA3; theta4:THETA4; theta5:THETA5; qg1:QG1; qg2:QG2; qg3:QG3; qg4:QG4; qg5:QG5; pg_balancenode:PG_balancenode; |
4、运行计算
将上述配置文件上传至低代码控制器中,运行即可得到计算结果,其运算结果如下所示。
matpower计算结果如下:
对比低代码控制器与matpower计算结果,可见低代码控制器对于交流法潮流能够精确计算。
附件:交流法潮流计算.rar
6.10 最优潮流计算
1、实验目的
最优潮流(Optimal Power Flow,OPF)是指当系统的结构参数和负荷情况都已给定时,调节可利用的控制变量(如发电机输出功率、可调变压器抽头等)来找到能满足所有运行约束条件的,并使系统的某一性能指标(如发电成本或网络损耗)达到最优值下的潮流分布。
从数学上看,最优潮流计算是一个典型的非线性优化问题。通过该应用案例,展示低代码控制器非线性规划(NLP动作)求解功能。
2、实验原理
最优潮流的数学模型如下所示:
式中,F为目标函数;G为等式约束条件;H为不等式约束条件;x为状态变量,u为控制变量。
最优潮流的目标函数类型很多,常见为以下2种:
(1)系统运行成本最小,一般表示为火电机组燃料费用最小(不考虑启动、停机费用)。
(2)有功传输损耗最小,通常以有功传输最小为目标.
最优潮流考虑的系统约束条件有: (1)各节点有功功率和无功功率的平衡约束。 (2)各发电机有功出力上下界约束。 (3)各发电机、同步补偿机无功出力上下界约束。 (4)并联电抗器、电容器容量约束。 (5)移相器抽头位置约束。 (6)可调变压器抽头位置约束。 (7)各节点电压幅值上下界约束。 (8)各支路传输功率约束。
3、实验步骤
本最优潮流计算的对象选取为matpower中的case9标准算例,目标函数为系统运行成本最小(即发电机组有功出力最小)。具体步骤如下
3.1、测点配置
测点配置表格的内容包含了测点的点号、名称、别名、是否离散、是否是计算点以及默认值等。点号是程序里给这个测点的编号,可以自己定义,使用时,测点与通信通道的点号一一对应完成对接。别名是英文字母与下划线组合使用,可以当做变量名用于AOE表格里表达式的书写,使之可以不用点号来表达,使得表达式的意思表达得更加清楚。本案例测点配置如下:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | DoCal_POINT | TRUE | FALSE | 0 | 计算控制 |
2 | 100002 | 测点2 | V1 | FALSE | FALSE | 1 | 节点1电压幅值 |
3 | 100003 | 测点3 | V2 | FALSE | FALSE | 1 | 节点2电压幅值 |
4 | 100004 | 测点4 | V3 | FALSE | FALSE | 1 | 节点3电压幅值 |
5 | 100005 | 测点5 | V4 | FALSE | FALSE | 1 | 节点4电压幅值 |
6 | 100006 | 测点6 | V5 | FALSE | FALSE | 1 | 节点5电压幅值 |
7 | 100007 | 测点7 | V6 | FALSE | FALSE | 1 | 节点6电压幅值 |
8 | 100008 | 测点8 | V7 | FALSE | FALSE | 1 | 节点7电压幅值 |
9 | 100009 | 测点9 | V8 | FALSE | FALSE | 1 | 节点8电压幅值 |
10 | 100010 | 测点10 | V9 | FALSE | FALSE | 1 | 节点9电压幅值 |
11 | 100011 | 测点11 | THETA1 | FALSE | FALSE | 0 | 节点1电压相角 |
12 | 100012 | 测点12 | THETA2 | FALSE | FALSE | 0 | 节点2电压相角 |
13 | 100013 | 测点13 | THETA3 | FALSE | FALSE | 0 | 节点3电压相角 |
14 | 100014 | 测点14 | THETA4 | FALSE | FALSE | 0 | 节点4电压相角 |
15 | 100015 | 测点15 | THETA5 | FALSE | FALSE | 0 | 节点5电压相角 |
16 | 100016 | 测点16 | THETA6 | FALSE | FALSE | 0 | 节点6电压相角 |
17 | 100017 | 测点17 | THETA7 | FALSE | FALSE | 0 | 节点7电压相角 |
18 | 100018 | 测点18 | THETA8 | FALSE | FALSE | 0 | 节点8电压相角 |
19 | 100019 | 测点19 | THETA9 | FALSE | FALSE | 0 | 节点9电压相角 |
20 | 100020 | 测点20 | PG1 | FALSE | FALSE | 0 | 发电机1有功输出 |
21 | 100021 | 测点21 | PG2 | FALSE | FALSE | 0 | 发电机2有功输出 |
22 | 100022 | 测点22 | PG3 | FALSE | FALSE | 0 | 发电机3有功输出 |
23 | 100023 | 测点23 | QG1 | FALSE | FALSE | 0 | 发电机1无功输出 |
24 | 100024 | 测点24 | QG2 | FALSE | FALSE | 0 | 发电机2无功输出 |
25 | 100025 | 测点25 | QG3 | FALSE | FALSE | 0 | 发电机3无功输出 |
3.2、AOE配置
本案例中AOE文件配置内容分为三个部分。
AOE网络声明
名称为最优潮流计算,触发条件设置为事件驱动(Event_Drive)。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 最优潮流计算 | Event_Drive | V_1:1;V_2:1;V_3:1;V_4:1;V_5:1;V_6:1;V_7:1;V_8:1;V_9:1; THETA_1:0;THETA_2:0;THETA_3:0;THETA_4:0;THETA_5:0;THETA_6:0;THETA_7:0;THETA_8:0;THETA_9:0; PG_1:0;PG_2:0;PG_3:0; QG_1:0;QG_2:0;QG_3:0; |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10 | DoCal_POINT > 0.5 |
70001 | 2 | 计算节点 | Condition | 10 | 1 |
70001 | 3 | 幅值 | Condition | 10 | 1 |
70001 | 4 | 结束节点 | Condition | 10 | DoCal_POINT == 0 |
本案例中共有4个节点,节点类型均为Condition,表达式设为1,表明始终满足条件触发执行。
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 进入最优潮流计算 | Default | Set_Points | DoCal_POINT:0; | |
70001 | 2;3 | 最优潮流计算 | Default | NLP | 100.0PG_2(8.5PG_2 + 1.2) + 100.0PG_3*(12.25PG_3 + 1.0) + 100.0PG_1*(11.0PG_1 + 5.0) + 1085.0; 17.361111111111111111111111111111V_1V_4sin(THETA_1 -THETA_4) -PG_1:[0.00000000/0.00000000]; 16.0V_2V_8sin(THETA_2 -THETA_8) -PG_2:[0.00000000/0.00000000]; 17.064846416382252559726962457338V_3V_6sin(THETA_3 -THETA_6) -PG_3:[0.00000000/0.00000000]; 3.307378962025306456951057043625V_4^2 -V_4V_9*(1.365187713310580204778156996587cos(THETA_4 -THETA_9) - 11.60409556313993174061433447099sin(THETA_4 -THETA_9)) -V_4V_5(1.9421912487147263795270193076659cos(THETA_4 -THETA_5) - 10.510682051867930995087398606192sin(THETA_4 -THETA_5)) - 17.361111111111111111111111111111V_1V_4sin(THETA_1 -THETA_4):[0.00000000/0.00000000]; 3.2242003871388416058607617742382V_5^2 -V_4V_5(1.9421912487147263795270193076659cos(THETA_4 -THETA_5) + 10.510682051867930995087398606192sin(THETA_4 -THETA_5)) -V_5V_6(1.282009138424114920614049505276cos(THETA_5 -THETA_6) - 5.588244962361526013694401626708sin(THETA_5 -THETA_6)) + 0.9:[0.00000000/0.00000000]; 2.4370966193142118427772402355913V_6^2 - 17.064846416382252559726962457338V_3V_6sin(THETA_3 -THETA_6) -V_6V_7(1.1550874808900968235094275522337cos(THETA_6 -THETA_7) - 9.784270426363173093256327501274sin(THETA_6 -THETA_7)) -V_5V_6(1.282009138424114920614049505276cos(THETA_5 -THETA_6) + 5.588244962361526013694401626708sin(THETA_5 -THETA_6)):[0.00000000/0.00000000]; 2.772209954136232376422626125361V_7^2 -V_7V_8*(1.6171224732461355529131985731272cos(THETA_7 -THETA_8) - 13.697978596908442330558858501784sin(THETA_7 -THETA_8)) -V_6V_7(1.1550874808900968235094275522337cos(THETA_6 -THETA_7) + 9.784270426363173093256327501274sin(THETA_6 -THETA_7)) + 1.0:[0.00000000/0.00000000]; 2.8047268525372843761545027518878V_8^2 -V_7V_8*(1.6171224732461355529131985731272cos(THETA_7 -THETA_8) + 13.697978596908442330558858501784sin(THETA_7 -THETA_8)) - 16.0V_2V_8sin(THETA_2 -THETA_8) -V_8V_9*(1.1876043792911486361105956578215cos(THETA_8 -THETA_9) - 5.9751345333085915754314344034144sin(THETA_8 -THETA_9)):[0.00000000/0.00000000]; 2.5527920926017282354791859688703V_9^2 -V_4V_9*(1.365187713310580204778156996587cos(THETA_4 -THETA_9) + 11.60409556313993174061433447099sin(THETA_4 -THETA_9)) -V_8V_9(1.1876043792911486361105956578215cos(THETA_8 -THETA_9) + 5.9751345333085915754314344034144sin(THETA_8 -THETA_9)) + 1.25:[0.00000000/0.00000000]; 17.361111111111111111111111111111V_1^2 -QG_1 - 17.361111111111111111111111111111V_1V_4cos(THETA_1 -THETA_4):[0.00000000/0.00000000]; 16.0V_2^2 -QG_2 - 16.0V_2V_8cos(THETA_2 -THETA_8):[0.00000000/0.00000000]; 17.064846416382252559726962457338V_3^2 -QG_3 - 17.064846416382252559726962457338V_3V_6cos(THETA_3 -THETA_6):[0.00000000/0.00000000]; 39.308888726118972556378139415756V_4^2 -V_4V_9*(11.60409556313993174061433447099cos(THETA_4 -THETA_9) + 1.365187713310580204778156996587sin(THETA_4 -THETA_9)) - 17.361111111111111111111111111111V_1V_4cos(THETA_1 -THETA_4) -V_4V_5*(10.510682051867930995087398606192cos(THETA_4 -THETA_5) + 1.9421912487147263795270193076659sin(THETA_4 -THETA_5)):[0.00000000/0.00000000]; 15.840927014229457370220188749954V_5^2 -V_4V_5*(10.510682051867930995087398606192cos(THETA_4 -THETA_5) - 1.9421912487147263795270193076659sin(THETA_4 -THETA_5)) -V_5V_6(5.588244962361526013694401626708cos(THETA_5 -THETA_6) + 1.282009138424114920614049505276sin(THETA_5 -THETA_6)) + 0.3:[0.00000000/0.00000000]; 32.15386180510695623979700030759V_6^2 - 17.064846416382252559726962457338V_3V_6cos(THETA_3 -THETA_6) -V_6V_7(9.784270426363173093256327501274cos(THETA_6 -THETA_7) + 1.1550874808900968235094275522337sin(THETA_6 -THETA_7)) -V_5V_6(5.588244962361526013694401626708cos(THETA_5 -THETA_6) - 1.282009138424114920614049505276sin(THETA_5 -THETA_6)):[0.00000000/0.00000000]; 23.303249023271618511898850556463V_7^2 -V_7V_8*(13.697978596908442330558858501784cos(THETA_7 -THETA_8) + 1.6171224732461355529131985731272sin(THETA_7 -THETA_8)) -V_6V_7(9.784270426363173093256327501274cos(THETA_6 -THETA_7) - 1.1550874808900968235094275522337sin(THETA_6 -THETA_7)) + 0.35:[0.00000000/0.00000000]; 35.445613130217033415192418033257V_8^2 - 16.0V_2V_8cos(THETA_2 -THETA_8) -V_7V_8(13.697978596908442330558858501784cos(THETA_7 -THETA_8) - 1.6171224732461355529131985731272sin(THETA_7 -THETA_8)) -V_8V_9(5.9751345333085915754314344034144cos(THETA_8 -THETA_9) + 1.1876043792911486361105956578215sin(THETA_8 -THETA_9)):[0.00000000/0.00000000]; 17.33823009644852319866004108917V_9^2 -V_4V_9*(11.60409556313993174061433447099cos(THETA_4 -THETA_9) - 1.365187713310580204778156996587sin(THETA_4 -THETA_9)) -V_8V_9(5.9751345333085915754314344034144cos(THETA_8 -THETA_9) - 1.1876043792911486361105956578215sin(THETA_8 -THETA_9)) + 0.5:[0.00000000/0.00000000]; 17.361111111111111111111111111111V_1V_4sin(THETA_1 -THETA_4):[/2.50000000]; -17.361111111111111111111111111111V_1V_4sin(THETA_1 -THETA_4):[/2.50000000]; 1.9421912487147263795270193076659V_4^2 -V_4V_5*(1.9421912487147263795270193076659cos(THETA_4 -THETA_5) - 10.510682051867930995087398606192sin(THETA_4 -THETA_5)):[/2.50000000]; 1.9421912487147263795270193076659V_5^2 -V_4V_5*(1.9421912487147263795270193076659cos(THETA_4 -THETA_5) + 10.510682051867930995087398606192sin(THETA_4 -THETA_5)):[/2.50000000]; 1.282009138424114920614049505276V_5^2 -V_5V_6*(1.282009138424114920614049505276cos(THETA_5 -THETA_6) - 5.588244962361526013694401626708sin(THETA_5 -THETA_6)):[/1.50000000]; 1.282009138424114920614049505276V_6^2 -V_5V_6*(1.282009138424114920614049505276cos(THETA_5 -THETA_6) + 5.588244962361526013694401626708sin(THETA_5 -THETA_6)):[/1.50000000]; 17.064846416382252559726962457338V_3V_6sin(THETA_3 -THETA_6):[/3.00000000]; -17.064846416382252559726962457338V_3V_6sin(THETA_3 -THETA_6):[/3.00000000]; 1.1550874808900968235094275522337V_6^2 -V_6V_7*(1.1550874808900968235094275522337cos(THETA_6 -THETA_7) - 9.784270426363173093256327501274sin(THETA_6 -THETA_7)):[/1.50000000]; 1.1550874808900968235094275522337V_7^2 -V_6V_7*(1.1550874808900968235094275522337cos(THETA_6 -THETA_7) + 9.784270426363173093256327501274sin(THETA_6 -THETA_7)):[/1.50000000]; 1.6171224732461355529131985731272V_7^2 -V_7V_8*(1.6171224732461355529131985731272cos(THETA_7 -THETA_8) - 13.697978596908442330558858501784sin(THETA_7 -THETA_8)):[/2.50000000]; 1.6171224732461355529131985731272V_8^2 -V_7V_8*(1.6171224732461355529131985731272cos(THETA_7 -THETA_8) + 13.697978596908442330558858501784sin(THETA_7 -THETA_8)):[/2.50000000]; -16.0V_2V_8sin(THETA_2 -THETA_8):[/2.50000000]; 16.0V_2V_8sin(THETA_2 -THETA_8):[/2.50000000]; 1.1876043792911486361105956578215V_8^2 -V_8V_9*(1.1876043792911486361105956578215cos(THETA_8 -THETA_9) - 5.9751345333085915754314344034144sin(THETA_8 -THETA_9)):[/2.50000000]; 1.1876043792911486361105956578215V_9^2 -V_8V_9*(1.1876043792911486361105956578215cos(THETA_8 -THETA_9) + 5.9751345333085915754314344034144sin(THETA_8 -THETA_9)):[/2.50000000]; 1.365187713310580204778156996587V_9^2 -V_4V_9*(1.365187713310580204778156996587cos(THETA_4 -THETA_9) + 11.60409556313993174061433447099sin(THETA_4 -THETA_9)):[/2.50000000]; 1.365187713310580204778156996587V_4^2 -V_4V_9*(1.365187713310580204778156996587cos(THETA_4 -THETA_9) - 11.60409556313993174061433447099sin(THETA_4 -THETA_9)):[/2.50000000]; THETA_1:[0.00000000/0.00000000]; PG_1:[0.10000000/2.50000000/],PG_2:[0.10000000/3.00000000/],PG_3:[0.10000000/2.70000000/],QG_1:[-3.00000000/3.00000000/],QG_2:[-3.00000000/3.00000000/],QG_3:[-3.00000000/3.00000000/],V_1:[0.90000000/1.10000000/],V_2:[0.90000000/1.10000000/],V_3:[0.90000000/1.10000000/],V_4:[0.90000000/1.10000000/],V_5:[0.90000000/1.10000000/],V_6:[0.90000000/1.10000000/],V_7:[0.90000000/1.10000000/],V_8:[0.90000000/1.10000000/],V_9:[0.90000000/1.10000000/],THETA_1:[//],THETA_2:[//],THETA_3:[//],THETA_4:[//],THETA_5:[//],THETA_6:[//],THETA_7:[//],THETA_8:[//],THETA_9:[//] | |
70001 | 3;4 | 赋值 | Default | Set_Points | V1:V_1; V2:V_2; V3:V_3; V4:V_4; V5:V_5; V6:V_6; V7:V_7; V8:V_8; V9:V_9; THETA1:THETA_1; THETA2:THETA_2; THETA3:THETA_3; THETA4:THETA_4; THETA5:THETA_5; THETA6:THETA_6; THETA7:THETA_7; THETA8:THETA_8; THETA9:THETA_9; PG1:PG_1; PG2:PG_2; PG3:PG_3; QG1:QG_1; QG2:QG_2; QG3:QG_3; |
4、运行计算
将上述配置文件上传至低代码控制器中,运行即可得到计算结果,其运算结果如下所示。
matpower计算结果如下:
对比低代码控制器与matpower计算结果,可见低代码控制器对于交流法潮流能够精确计算(其中电压相角值的单位,低代码控制器为弧度,matpower为角度;低代码控制器的功率需乘以基准值100MW)。
附件:最优潮流计算.rar
6.11 低压继电保护控制
1、概述
随着电网结构日趋复杂,继电保护策略的要求逐渐提高,传统的微机继电保护设备面临着难以维护、扩建、代码容易过时等诸多问题,而低代码控制器是一种高效率、可靠性强、编程难度小的工业控制器,不仅能够实现各种复杂的控制场景,还提供了形象化的操作界面,能够观测控制效果的同时,还能快速维护和修改控制网络中的有关参数,非常适合于目前结构时常变化的新型低压电网保护体系的构建。
该案例利用simulink搭建起电力系统的仿真模型,并构造三段式电流保护控制的AOE网络图,在AOE网络图的基础下逐个完成配置文件的编写,利用S-Function模块建立起matlab与控制器的连接,最后在控制器网关监控界面与仿真示波器中观察控制器的实现效果。
2、 模型介绍
利用Matlab来搭建一个简单电力系统的Simulink仿真模型。对建立的模型进行保护定值的整定,得到相关整定值参数,通过整定值与模型的参数,来确定该电流保护三段各自的保护范围,并在对应的保护范围中设置相应的故障元件,用于在不同的范围内测试各段保护的动作情况。本设计中第三段过电流保护的验证通过加大负荷的功率来实现,建立如下图所示的电力系统simulink模型:
3、 文件配置
文件配置分为三个部分:测点配置、通信通道和AOE配置。
测点配置用于配置控制器输入和输出信号点的参数,本案例中需要的信号要是输入保护安装处的监测电流和输出的跳闸信号。
通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互。
而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
接下来分别介绍相关的三个方面的配置。
3.1、 测点配置
本例中的测点配置如下表所示:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | I_POINT | FALSE | FALSE | 1 | 电流值 |
2 | 100002 | 测点2 | Break_POINT | TRUE | FALSE | 1 | 开闸信号 |
3 | 100003 | 测点3 | Type | TRUE | FALSE | 0 | 保护类型 |
4 | 100004 | 测点4 | t2 | FALSE | FALSE | 0.5 | Ⅱ段延迟时间 |
5 | 100005 | 测点5 | t3 | FALSE | FALSE | 1 | Ⅲ段延迟时间 |
6 | 100006 | 测点6 | Iset1 | FALSE | FALSE | 150 | 速动整定电流 |
7 | 100007 | 测点7 | Iset2 | FALSE | FALSE | 100 | Ⅱ段整定电流 |
8 | 100008 | 测点8 | Iset3 | FALSE | FALSE | 55 | Ⅲ段整定电流 |
9 | 100009 | 测点9 | DoCal_POINT | TRUE | FALSE | 0 | 通讯控制 |
10 | 100010 | 测点10 | T | FALSE | FALSE | 0 | 仿真时间 |
其中测点1所对应的I_POINT为控制器的输入信号,即在MATLAB仿真模型中得到的保护安装处的监测电流的数值,测点2为控制器的输出信号,即满足跳闸条件后给出跳闸信号使得断路器动作。由于MATLAB仿真模型中的断路器在收到信号为“0”时跳闸,正常处于闭合时控制信号默认值应该为“1”,所以设定跳闸信号的默认值为“1”,只有当满足过流条件且跳闸动作执行后,跳闸信号Break_POINT才会置为“0”,此时断路器断路,完成跳闸动作。测点3为跳闸类型,用于在控制器监控网关界面实时观察跳闸类型。需要注意的是,本次设计中的I_POINT信号是已经经过MATLAB相关处理的电流信号,是三相电流取有效值后的最大值,实际上在真实的使用环境下,测点应该为该保护安装处的三相电流,每相电流对应一个测点,每个测点都对应一个相同的AOE网络来进行跳闸动作判断,因其操作流程具有可复制性,故不一一描述。
3.2、通信通道配置
低代码控制器通过Modbus协议与Simulink进行通信。由于Matlab仅有Modbus客户端功能,因此需要将低代码控制器配置为Modbus服务端,如下:
通道名称 | server测试通道 | 连接名称 | 测试通道 |
---|---|---|---|
连接个数 | 1 | 测点个数 | 4 |
服务端口 | 502 | 客户端IP | 127.0.0.1 |
客户端端口 | 9999 | ||
slave id | 1 | ||
通信协议 | XA | ||
一次读寄存器数上限 | 125 | ||
一次读开关数上限 | 2000 | ||
一次写寄存器数上限 | 120 | ||
一次写开关数上限 | 1968 | ||
轮询周期(ms) | 5000 | ||
超时(ms) | 1000 |
表格中包含有通信通道的各种配置信息。
服务端口设定为502,测点个数为4,客户端ip是本机的ip地址,可以在网络属性界面查询得到,客户端端口设置为9999.
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 1 | EightByteFloat | FALSE | 2000 | 100001 |
2 | HOLDING | 5 | EightByteFloat | FALSE | 2000 | 100010 |
3 | HOLDING | 9 | TwoByteIntUnsigned | FALSE | 2000 | 100009 |
4 | HOLDING | 10 | TwoByteIntUnsigned | FALSE | 2000 | 100002 |
本实验中需要用4个寄存器存储数据,其中电流值与仿真时间的数据类型均为八位浮点数,开闸信号与通信控制信号的数据类型均为二位无符号整型。
3.3、 AOE配置
AOE策略文件配置包括AOE网络定义、AOE变量定义、AOE节点定义、AOE动作定义四个部分。AOE策略文件配置是所有配置文件中最为关键的配置文件,它定义了AOE网络中的各个要素,是实现用户所需要实现的控制逻辑的关键文件。
AOE网络定义
在AOE网络定义中,定义出AOE网络个数和需要用到的一些变量的赋值,具体定义信息如下表所示:
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70001 | TRUE | 三段式电流保护 | Event_Drive | t:0; flag:1; |
本设计采用判断达到过流条件后启动AOE网络的模式,故选择事件控制(即Event_Drive)。
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 开始节点 | Condition | 10 | time>time_old |
70001 | 2 | 判断是否在一段范围 | Switch | 10 | I_POINT>Iset1 |
70001 | 3 | 结束节点1 | Condition | 10 | DoCal_POINT==0 |
70001 | 4 | 判断是否在二段范围 | Switch | 10 | I_POINT>Iset2 |
70001 | 5 | 二段延时判断 | Switch | 10 | (T-t)>t2 |
70001 | 6 | 结束节点2 | Condition | 10 | DoCal_POINT==0 |
70001 | 7 | 判断是否在三段范围 | Switch | 10 | I_POINT>Iset3 |
70001 | 8 | 三段延时判断 | Switch | 10 | (T-t)>t3 |
70001 | 9 | 结束节点3 | Condition | 10 | DoCal_POINT==0 |
70001 | 10 | 结束节点4 | Condition | 10 | DoCal_POINT==0 |
70001 | 11 | 结束节点5 | Condition | 10 | DoCal_POINT==0 |
70001 | 12 | 结束节点6 | Condition | 10 | DoCal_POINT==0 |
AOE动作定义
AOE动作定义又称AOE边定义,本项目中定义如下表:
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 进入保护判断 | Default | Set_Points | DoCal_POINT:0; | |
70001 | 2;3 | 一段跳闸 | Default | Set_Points | Break_POINT:0; Type:1; | |
70001 | 2;4 | 进入二段保护范围判断 | Default | NONE | ||
70001 | 4;5 | 进入二段保护延时判断 | Default | Set_Points | flag:0; t:T*flag+t*(flag==0); | |
70001 | 4;7 | 进入三段保护范围判断 | Default | NONE | ||
70001 | 5;6 | 二段跳闸 | Default | Set_Points | Break_POINT:0; Type:2;flag:1; | |
70001 | 5;11 | 二段不跳闸 | Default | NONE | ||
70001 | 7;8 | 进入三段保护延时判断 | Default | Set_Points | flag:0; t:T*flag+t*(flag==0); | |
70001 | 7;10 | 不动作 | Default | NONE | ||
70001 | 8;9 | 三段跳闸 | Default | Set_Points | Break_POINT:0; Type:3;flag:1; | |
70001 | 8;12 | 三段不跳闸 | Default | NONE |
不需要动作的边设置为NONE,最终判断结果为需要跳闸时,需要设置动作结果,发出跳闸信号(令Break_POINT等于0),并且反应动作的保护类型。时间记录位t用于记录进入某一次过流事件进入某段保护范围的初始时间,T为simulink的仿真时间。
4、 建立控制器与matlab通讯以及仿真过程
该步低代码控制器的连接和案例1中完全一致,将MATLAB的文件夹打开到低代码控制器替代后的simulink模型文件的文件夹。
当与实体的控制器连接时,就是将所实现的功能放入实体的控制器中,只需要将控制器与电脑通过网线连接后,修改主站和从站的ip地址。 控制器(从站ip)可以从发现工具获得。
主站ip为本机ip地址,通过网络属性配置中可以查询。
matlab界面操作
配置完成后,进入matlab的界面。然后打开控制器的源文件modbusCom1.m文件,该文件是以S-Function模块模板为基础实现的利用Modbus通信协议与控制器进行通信的模块。在输入输出量不同的控制模块下,必须先修改modbusCom1.m文件中的相关参数。
下面程序段用于修改输入输出量的个数:
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 1;
sizes.NumInputs = 2;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
当输入输出的个数发生改变时,要对应修改NumOutputs、NumInputs后对应的数字。
下面程序段用于建立simulink与控制器的通信:
global m;
m = modbus('tcpip', '127.0.0.1', 502);
输入的ip地址为从站ip,当从站ip不是本机即连接实体控制器时需要改为实体控制器的实际ip地址和端口,127.0.0.1和502为主从站为同一台机器下的配置。
下面程序段用于控制器的读写:
function sys=mdlOutputs(t,x,u)
global m;
write(m,'holdingregs',2,u','double');%写入电流值
write(m,'holdingregs',10,1);%通信标志位DoCal_POINT置1
%disp(['address 2 = ' num2str(u')]);
pause(0.02); % 等待20ms使得通过modbus通信之后读到最新控制值
sys = read(m,'holdingregs',11,1,'uint16');%读分闸信号
5、 仿真结果
(1)正常运行
仿真波形图:
测点监控图:
AOE节点监控图:
从仿真波形图可以观察到电流电压波形均正常,且跳闸信号始终保持为“1”,即断路器保持在不动作的状态。在控制器网关中打开AOE文件监控器和测点文件监控器可以观察各个节点的动作情况与测点电流的实时数值,以及跳闸类型、跳闸信号的数值变化。正常运行时AOE网络可靠不动作,无跳闸响应。
(2)过负荷运行
然后通过加大负荷功率来设置满足三段跳闸的过负荷电流。
仿真波形图:
AOE节点监控图:
测点监控图
可以从低代码控制器的网关监控界面和MATLAB的仿真波形中观察到定时限过电流保护正常启动,且满足延时跳闸的要求,跳闸后的电流可以忽略不计,且跳闸信号正确显示为“0”,跳闸类型正确显示为“3”。在AOE网络监控图中看到启动三段保护跳闸的节点顺序,且其余保护可靠闭锁,没有发生误动。在MATLAB仿真波形图中可以观测到延时跳闸的效果,由于过负荷电流是直接调大负荷的功率而产生的,所以过电流事件所对应的第一个节点在仿真开始那一刻就触发了AOE网络。可以看到在经过1s左右的仿真时间延时后,动作信号变为“0”使得断路器断闸。
(3)二段保护范围内短路故障
通过在二段保护范围内加入短路故障来仿真验证二段保护的动作情况。
仿真波形图:
AOE节点监控图:
测点监控图:
在仿真时长为0.5s左右时切除了故障,与AOE网络文件配置中二段保护延时时间和三段保护延时时间的设置完全吻合。和三段同理,在AOE网络节点监控界面以及测点文件监控界面,可以看到其余保护可靠闭锁,对应此故障点的二段保护正常动作,且保护类型显示正确。通过故障相电流波形以及跳闸信号图可以确定延时效果已经实现,二段保护效果正常实现。
(4)一段保护范围内短路故障
设置一段范围下的短路故障,得到以下结果。
仿真波形图:
AOE节点监控图:
测点监控图:
一段范围内的短路故障电流很大,设置的仿真时长与二段一致,也是0.1s,但可以看到保护在故障接入的0.04s后就已经启动切除了故障,故障电流持续0.04s,其余保护可靠不动作,一段保护虽然没有设置延时,应瞬时动作,但从仿真波形来看,有0.04s的动作延迟,故0.04s的仿真延时为控制器与matlab的通信时长和控制器的AOE网络判断实现的时长之和,通过多次实验的结果可知,一段动作的仿真延时在0.01-0.05s内波动,受到各种其他因素的影响,但总体上满足继电保护速动性的要求。
6、 总结
对于继电保护控制策略中最为基础的三段式电流保护,通过matlab建立仿真模型,并将配置文件上传至控制器中后,成功实现了三段式电流保护。对各段保护仿真实验结果进行分析,可见低代码控制器能够正确的实现低压继电保护策略中典型的三段式电流保护的控制功能,且满足继电保护选择性、可靠性、速动性的要求,能够应用于继电保护系统中,加速实现继电保护系统的保护、控制、测量、数据通信一体化。
附件:低压继电保护控制.rar
6.12 微网燃机平衡控制
1、实验环境
该程序可在以下环境运行:
-
TwinCAT 3;
-
Matlab/Simulink;
-
低代码控制器。
2、实验介绍
利用低代码控制器完成储能电站的黑启动、负荷(频率)平衡、顺序停机等功能。该储能电站是为钻井平台打造的小型微电网,其由8台330kW燃机、2台500kW储能电源和1台可变负荷组成。
3、实验模型
3.1、模型搭建
1)储能模型的搭建
储能电池的电路结构与控制结构如图所示,
储能电池承担着黑启动阶段建立系统所需频率和电压以及平抑负荷波动的责任,故对其采用 V-F 控制,锁相环通过获得网侧电压的相位,实现逆变器侧输出电流和网侧电压的同步;通过采样逆变器侧三相电压和电流经过 abc / dq 变换后输入电压环,得到电流控制器参考值 $i_{do}$ 和 $i_{qo}$ ,之后输入电流环经 dq / abc 变换后发出调制信号给调制模块,产生三相全桥逆变电路的驱动信号。
2)燃机模型的搭建
燃机的控制方式为给定功率指令使之输出满足负荷所需要的功率,本案例中燃机采用数值模型以进一步提高仿真速度,其建模以有功功率指令、功率因数、频率和系统电压未输入,依据的计算式为: $$ {Q_{ref}} = {P_{ref}} \cdot \tan (\theta ) $$
$$ {{i_{a_d}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {P_{ref}}}}{{3U}} \cdot sin\left( {wt} \right)}\ {{i_{b_d}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {P_{ref}}}}{{3U}} \cdot sin\left( {wt{\rm{ }} - {\rm{ }}\frac{{2\pi }}{3}} \right)}\ {{i_{c_d}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {P_{ref}}}}{{3U}} \cdot sin\left( {wt{\rm{ }} - {\rm{ }}\frac{{4\pi }}{3}} \right)} $$
$$ {{i_{a_q}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {Q_{ref}}}}{{3U}} \cdot sin\left( {wt{\rm{ }} - {\rm{ }}\frac{\pi }{2}} \right)}\ {{i_{b_q}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {Q_{ref}}}}{{3U}} \cdot sin\left( {wt{\rm{ }} - {\rm{ }}\frac{{2\pi }}{3}{\rm{ }} - {\rm{ }}\frac{\pi }{2}} \right)}\ {{i_{c_q}}{\rm{ }} = {\rm{ }}\frac{{\sqrt 2 {Q_{ref}}}}{{3U}} \cdot sin\left( {wt{\rm{ }} - {\rm{ }}\frac{{4\pi }}{3}{\rm{ }} - {\rm{ }}\frac{\pi }{2}} \right)} $$
$$ {{i_a} = {\rm{ }}{i_{a_d}}{\rm{ }} + {\rm{ }}{i_{a_q}}}\ {{i_b} = {\rm{ }}{i_{b_d}}{\rm{ }} + {\rm{ }}{i_{b_q}}}\ {{i_c} = {\rm{ }}{i_{c_d}}{\rm{ }} + {\rm{ }}{i_{c_q}}} $$
3)可变负荷的搭建
可变负荷被等效为反向电流源,给定有功负荷和无功负荷的值,采用与燃机相同的计算方法得到输出电流值,只是需要将电流反向。
3.2、从 MATLAB/Simulink 到 TwinCAT3
倍福公司开发出了TE1401和TE1400两款产品,在TwinCAT3中新增了Simulink Module的功能,允许用户事先在MATLAB中创建控制模型,包括控制代码和接口,然后将模块导入TwinCAT3实现直接的对硬件调试,其中TE1400,即Target for Simulink,可以将Simulink中搭建好的可视化控制模块通过Simulink Coder自动转换为C/C++代码,在转换为TwinCAT3可以识别的控制对象。如下图为使用TE1400将Simulink模型转换为TwinCAT3兼容的PLC项目时的配置界面。
4、实验原理
4.1、黑启动控制策略
本微网采用储能装置来辅助黑启动,其控制策略流程如下:
(1)系统自检查。为了避免微电网在黑启动初期储能电池容量不足、负载较大而出现故障停机等现象,需要对系统各设备进行检查。自检查包括电池剩余容量检查、切除全部负荷、燃气轮机合闸状况检查等。保证系统不出现储能功率不足等问题。
(2)启动储能装置。通过储能设备的VF控制建立微电网系统的电压和频率。要求储能装置的额定功率应能够满足微电网交流母线的空载损耗, 同时其输出能够承受系统中非黑启动电源在启动时产生的功率冲击。
(3)投入负荷。为了快速恢复重要负荷的供电, 在考虑储能装置额定容量的前提下投入部分重要负荷;在投入过程中, 应保证系统电压和频率在额定范围内波动, 以免造成整个系统发生失稳现象。
(4)接入燃气轮机等非黑启动源。此时微电网系统已经具有一定的容量,需在综合评估微电网系统中的容量匹配情况后逐步启动非黑启动源,以扩大系统的发电容量。
(5)增加负荷。随着各发电装置的接入, 系统供电容量增加, 此时可以根据负荷特性以及系统发电容量逐步增加负荷。
4.2、燃机启停判定策略
黑启动结束后,功率分配策略开始运行,当启动的燃机稳定输出分配的指令后,开始恢复系统其他负荷。逐渐投入负荷,判定是否需要启动/关闭燃机,具体的判定方法如下: $$ lack = \frac{{{P_{load}} - m{P_{m\max }} - {P_{es\max }}}}{{{P_{m\min }}}} $$ 式中, $P_{load}$ 为负荷功率; $m$ 为上一调度周期计算得到的需要开启燃机台数; $P_{es\max}$ 为当前储能最大出力; $P_{m\min}$ ,$P_{m\max}$ 分别为燃机的出力下限和上限。
需要说明的是, lack 值仅在大于0时有意义,即需要开启 lack 台燃机。
当燃机所分配的功率均不能达到 $P_{m\min}$ 时,则分闸一台燃机。
4.3、燃机功率分配策略
通过判断式判断现有合闸的燃机数,之后根据储能的 $SoC$ 计算应该分配给燃机的功率,平均分给所有合闸的燃机,如下所示,
N:((XA_EMStoRJ1_bPowerON!=0)&&(VT_RJ1_OPENCOMMAND==0))+((XA_EMStoRJ2_bPowerON!=0)&&(VT_RJ2_OPENCOMMAND==0))+((XA_EMStoRJ3_bPowerON!=0)&&(VT_RJ3_OPENCOMMAND==0))+((XA_EMStoRJ4_bPowerON!=0)&&(VT_RJ4_OPENCOMMAND==0))+((XA_EMStoRJ5_bPowerON!=0)&&(VT_RJ5_OPENCOMMAND==0))+((XA_EMStoRJ6_bPowerON!=0)&&(VT_RJ6_OPENCOMMAND==0))+((XA_EMStoRJ7_bPowerON!=0)&&(VT_RJ7_OPENCOMMAND==0))+((XA_EMStoRJ8_bPowerON!=0)&&(VT_RJ8_OPENCOMMAND==0));//判断现有合闸的燃机数
CN_middlepower:(((CN_MaxPowerProportioninLowerSOC+CN_MinPowerProportioninLowerSOC)/2)*CN_RatedPower)*(SOC<CN_LowSOCofExpect)+(((CN_MaxPowerProportioninMiddleSOC+CN_MinPowerProportioninMiddleSOC)/2)*CN_RatedPower)*((SOC>=CN_LowSOCofExpect)&&(SOC<CN_UpSOCofExpect))+(((CN_MaxPowerProportioninUpperSOC+CN_MinPowerProportioninUpperSOC)/2)*CN_RatedPower)*(SOC>=CN_UpSOCofExpect);//储能的期望出力
RJ_TotalPOWER:P600-CN_middlepower;//应该分配给燃机的功率
XA_EMStoRJ1_dActivePower:((XA_EMStoRJ1_bPowerON!=0)&&(VT_RJ1_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ2_dActivePower:((XA_EMStoRJ2_bPowerON!=0)&&(VT_RJ2_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ3_dActivePower:((XA_EMStoRJ3_bPowerON!=0)&&(VT_RJ3_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ4_dActivePower:((XA_EMStoRJ4_bPowerON!=0)&&(VT_RJ4_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ5_dActivePower:((XA_EMStoRJ5_bPowerON!=0)&&(VT_RJ5_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ6_dActivePower:((XA_EMStoRJ6_bPowerON!=0)&&(VT_RJ6_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ7_dActivePower:((XA_EMStoRJ7_bPowerON!=0)&&(VT_RJ7_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
XA_EMStoRJ8_dActivePower:((XA_EMStoRJ8_bPowerON!=0)&&(VT_RJ8_OPENCOMMAND==0))*min(RJ_TotalPOWER/N,RJ_maxpower_proportion*RJ_ratedpower);
//平均分给所有合闸的燃机
5、实验步骤
低代码控制器的特点在于不需要对控制器进行代码的编写,只要在excel文件之中进行测点配置、通信通道和AOE配置就可以实现相应的控制。
5.1、编写低代码控制器配置文件
低代码控制器文件配置分为三个部分:测点配置、通信通道配置和AOE配置。测点配置用于配置控制器输入和输出信号点的参数。通信通道的配置是为了将控制器与simulink仿真模型建立modbus通信,实现仿真模型与控制器的信息交互,而AOE配置是建立AOE模型网络来实现所需的控制逻辑和功能。
5.1.1、测点配置
本程序共需要293个测点,包括八台燃机的启停指令、分合闸指令、燃机缺额指令、功率值、功率指令,两台储能的功率值和功率指令,可变负荷的负荷值设置指令等。部分测点配置如下图所示,具体测点文件在文末可下载:
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
... | |||||||
76 | 103437 | 测点76 | XA_EMStoRJ1_bPowerON | FALSE | FALSE | 0 | 燃机1合闸完成信号 |
... | |||||||
84 | 103453 | 测点84 | XA_EMStoRJ1_bPowerOFF | FALSE | FALSE | 0 | 燃机1分闸完成信号 |
... | |||||||
100 | 103458 | 测点100 | XA_EMStoRJ1_dActivePower | FALSE | FALSE | 0 | 燃机1输出功率指令 |
... | |||||||
188 | 103661 | 测点188 | VT_RJ1_ERROR | TRUE | FALSE | 0 | 燃机1故障报错信号 |
... | |||||||
204 | 103693 | 测点204 | VT_RJ1_STARTCOMMAND | TRUE | FALSE | 0 | 燃机1开机信号 |
... | |||||||
223 | 103731 | 测点223 | VT_RJ1_CLOSECOMMAND | TRUE | FALSE | 0 | 燃机1合闸信号 |
... | |||||||
228 | 103731 | 测点223 | P1 | FALSE | FALSE | 0 | 燃机1输出功率值 |
... |
5.1.2、通信通道配置
本案例中,具体的通道配置和寄存器配置如下:
| 通道名称 | 测试通道1 | | :-- | :-- | | 测点个数 | 293 | | 服务端IP | 192.168.0.200 | | 服务端端口 | 502 | | slave id | 1 | | 通信协议 | XA | | 一次读寄存器数上限 | 125 | | 一次读开关数上限 | 2000 | | 一次写寄存器数上限 | 120 | | 一次写开关数上限 | 1968 | | 轮询周期(ms) | 2000 | |超时(ms)|1000|
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 13287 | FourByteIntSigned | FALSE | 2000 | 103287 |
2 | HOLDING | 13289 | FourByteIntSigned | FALSE | 2000 | 103289 |
3 | HOLDING | 13291 | FourByteIntSigned | FALSE | 2000 | 103291 |
4 | HOLDING | 13293 | FourByteIntSigned | FALSE | 2000 | 103293 |
5 | HOLDING | 13295 | FourByteIntSigned | FALSE | 2000 | 103295 |
6 | HOLDING | 13297 | FourByteIntSigned | FALSE | 2000 | 103297 |
7 | HOLDING | 13299 | FourByteIntSigned | FALSE | 2000 | 103299 |
8 | HOLDING | 13301 | FourByteIntSigned | FALSE | 2000 | 103301 |
9 | HOLDING | 13303 | FourByteIntSigned | FALSE | 2000 | 103303 |
10 | HOLDING | 13305 | FourByteIntSigned | FALSE | 2000 | 103305 |
11 | HOLDING | 13307 | FourByteIntSigned | FALSE | 2000 | 103307 |
12 | HOLDING | 13309 | FourByteIntSigned | FALSE | 2000 | 103309 |
... |
本案例中数据类型均为 FourByteIntSigned 。根据数据类型完成对起始地址的分配,即可完成通道文件的配置。
5.1.3、AOE 配置
AOE 网络声明
AOE网络声明部分,定义了表格之中的AOE网络个数和整体信息以及一些变量的初始值。其中触发条件分为三类:SimpleRepeat(定时触发,需要自行设定定时时间)、TimeDriven(时间驱动)、EventDriven(事件驱动);变量的定义方式为:<变量名1>:<初值1>;<变量名2>:<初值2>;…。
本案例中燃机启动及合闸部分的 AOE 网络声明如下所示
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70011 | TRUE | 燃机1启动 | SimpleRepeat | 5000 | VT_RJ1_start_times:0 |
70012 | TRUE | 燃机2启动 | SimpleRepeat | 5000 | VT_RJ2_start_times:0 |
70013 | TRUE | 燃机3启动 | SimpleRepeat | 5000 | VT_RJ3_start_times:0 |
70014 | TRUE | 燃机4启动 | SimpleRepeat | 5000 | VT_RJ4_start_times:0 |
70015 | TRUE | 燃机5启动 | SimpleRepeat | 5000 | VT_RJ5_start_times:0 |
70016 | TRUE | 燃机6启动 | SimpleRepeat | 5000 | VT_RJ6_start_times:0 |
70017 | TRUE | 燃机7启动 | SimpleRepeat | 5000 | VT_RJ7_start_times:0 |
70018 | TRUE | 燃机8启动 | SimpleRepeat | 5000 | VT_RJ8_start_times:0 |
70021 | TRUE | 燃机1合闸 | SimpleRepeat | 5000 | VT_RJ1_close_times:0 |
70022 | TRUE | 燃机2合闸 | SimpleRepeat | 5000 | VT_RJ2_close_times:0 |
70023 | TRUE | 燃机3合闸 | SimpleRepeat | 5000 | VT_RJ3_close_times:0 |
70024 | TRUE | 燃机4合闸 | SimpleRepeat | 5000 | VT_RJ4_close_times:0 |
70025 | TRUE | 燃机5合闸 | SimpleRepeat | 5000 | VT_RJ5_close_times:0 |
70026 | TRUE | 燃机6合闸 | SimpleRepeat | 5000 | VT_RJ6_close_times:0 |
70027 | TRUE | 燃机7合闸 | SimpleRepeat | 5000 | VT_RJ7_close_times:0 |
70028 | TRUE | 燃机8合闸 | SimpleRepeat | 5000 | VT_RJ8_close_times:0 |
AOE节点声明
节点类型分为Switch和Condition两类,其中Switch节点为二分支逻辑判断,当表达式为真时,该节点序号为1的边进行动作;表达式为假时,序号为2的边进行动作。当Switch节点为AOE网入度为0的节点(首节点)时,Switch节点直接触发,若超时时间内表达式为真,则执行动作1,为假或者发生超时事件执行动作2;Condition节点的表达式为事件触发条件,超时时间内表达式为真,则节点事件发生,该节点出发的所有动作并行执行。
本案例中燃机启动及合闸部分的部分节点声明如下:
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70011 | 1 | 虚拟首节点 | Condition | 5000 | VT_RJ1_STARTCOMMAND == 1 |
70011 | 2 | 燃机RJ1是否可用 | Switch | 0 | XA_RJ1OnlineState==1 && XA_RJ1toEMS_bPermissiRun!=0 && XA_INTERFACE_RJ1Select!=0 && VT_RJ1_ERROR == 0 |
70011 | 3 | 燃机RJ1启动完成 | Switch | 5000 | XA_RJ1toEMS_bIfOnline!=0 |
70011 | 4 | 结束节点 | Condition | 0 | VT_RJ1_STARTCOMMAND ==0 && XA_RJ1toEMS_bIfopen ==1 |
70011 | 5 | 结束节点 | Condition | 0 | 1 |
70011 | 6 | 结束节点 | Condition | 60000 | 0 |
70021 | 1 | 虚拟首节点 | Condition | 5000 | VT_RJ1_CLOSECOMMAND==1 && XA_RJ1toEMS_bSetRoll!=0 |
70021 | 2 | 燃机RJ1是否能合闸 | Switch | 2000 | XA_RJ1toEMS_bIfopen!=0 |
70021 | 3 | 结束节点 | Condition | 0 | 1 |
70021 | 4 | 结束节点 | Condition | 0 | 1 |
AOE边声明
边需要声明首尾节点,格式为:<尾节点ID>;<首节点ID>。本案例中主要使用None、SetPoints以及SETPOINTS_WITH_CHECK三类动作。
本案例中燃机启动及合闸部分的AOE边声明如下所示:
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 |
---|---|---|---|---|---|
70011 | 1;2 | 事件动作 | Default | NONE | |
70011 | 2;3 | 燃机RJ1启动 | Default | Set_Points | XA_PLCTORJ_START:XA_PLCTORJ_START|1; |
70011 | 2;5 | 连接失败 | Default | Set_Points | VT_RJ1_ERROR:1;VT_RJ1_STARTCOMMAND:0; |
70011 | 3;4 | 燃机RJ1启动成功 | Default | Set_Points | XA_RJ1toEMS_bIfopen:1;XA_PLCTORJ_START:XA_PLCTORJ_START&254;VT_RJ1_STARTCOMMAND:0;RJ_OPEN:RJ_OPEN+1; |
70011 | 3;6 | 燃机RJ1启动失败记录 | Default | Set_Points | VT_RJ1_start_times:VT_RJ1_start_times+1;VT_RJ1_ERROR:VT_RJ1_start_times>3;VT_RJ1_STARTCOMMAND:VT_RJ1_ERROR==0; |
70021 | 1;2 | 事件动作 | Default | NONE | |
70021 | 2;3 | 燃机RJ1合闸 | Default | Set_Points | XA_EMStoRJ1_bPowerON:255;XA_EMStoRJ1_bPowerOFF:0;VT_RJ1_CLOSECOMMAND:0;XA_RJ1toEMS_bPermissiStop:1;RJ_OPEN:RJ_OPEN-1; |
70021 | 2;4 | 燃机RJ1合闸失败 | Default | Set_Points | VT_RJ_LACK:VT_RJ_LACK+1;VT_RJ1_ERROR:1;VT_RJ1_STARTCOMMAND:0; |
70012 | 1;2 | 事件动作 | Default | NONE | |
70012 | 2;3 | 燃机RJ2启动 | Default | Set_Points | XA_PLCTORJ_START:XA_PLCTORJ_START|2; |
70012 | 2;5 | 连接失败 | Default | Set_Points | VT_RJ2_ERROR:1;VT_RJ2_STARTCOMMAND:0; |
70012 | 3;4 | 燃机RJ2启动成功 | Default | Set_Points | XA_RJ2toEMS_bIfopen:1;XA_PLCTORJ_START:XA_PLCTORJ_START&253;VT_RJ2_STARTCOMMAND:0;RJ_OPEN:RJ_OPEN+1; |
70012 | 3;6 | 燃机RJ2启动失败记录 | Default | Set_Points | VT_RJ2_start_times:VT_RJ2_start_times+1;VT_RJ2_ERROR:VT_RJ2_start_times>3;VT_RJ2_STARTCOMMAND:VT_RJ2_ERROR==0; |
6、低代码控制器配置与运行
- 进入控制器网页端
了解测点、信道和aoe文件的上传方法,以及上传配置文件后的解析方法。 打开一个浏览器,并输入控制器地址,然后输入账号和密码打开控制器。
以测点配置文件上传为例,单击图标,选中需要上传的文件,确定即可完成上传。上传成功后界面将出现相应内容,可对其进行查看与编辑。操作界面如图所示。
所有文件上传完成后,单击“主页”活“概览”返回概览界面,点击“重置”按钮保存配置即可运行。操作界面如下图所示:
运行后可以在查询项查看测点值和AOE运行情况等信息。
在量测界面还可以观测测点的曲线和报表(历史数据)。
7、仿真运行结果
编译TwinCAT文件,运行工控机,再运行低代码控制器进行仿真。利用低代码控制器对建立在工控机中的被控对象进行控制,得到的控制结果如下所示:
8、总结
由该仿真实验可以看出,使用低代码控制器并不需要繁复的程序代码编写,只需要编写测点配置、通信通道配置和AOE配置文件就可以实现通信和控制功能,与目前常用的其他控制器相比,更方便于非编程技术背景人员的应用。
附件:微电网控制.rar
7 典型问题解决方案
本章节用于给出一些常见典型问题解决方案。
持续更新中......
7.1 心跳包
为检测服务端与客户端之间通讯故障,可采用该心跳包方案来确认服务端和客户端通讯状态。
该心跳包定义一个变量HeartBeat,并以2*T为周期切换0/1,如果该变量没有按照2*T周期更新,则表示服务端与客户端之间出现了通讯故障。
该典型解决方案可按照一下方式配置:
通道文件配置
通道文件中,该心跳包测点通道可按如下配置。
测点文件配置
测点文件可按如下配置。
策略文件配置
策略文件可按如下配置。其中,策略执行周期,即T,可按照实际需要设为合适的值。
附件:心跳包AOE例程.rar
7.2 使用触摸板
使用触摸板请联系开发者团队获取更多技术支持!。
7.3 使用LabVIEW作为上位机
LabVIEW是一种程序开发环境,相较于C和BASIC开发环境,LabVIEW有着显著的区别:其他计算机语言都是采用基于文本的语言产生代码,而LabVIEW使用的是图形化编辑语言G编写程序,产生的程序是框图的形式。因此,LabVIEW非常适合应用于电气工程等领域的非专业计算机人员开发系统。
为了满足用户使用LabVIEW作为上位机的需求,低代码控制器提供了相应的解决方案。
使用LabVIEW作为上位机,需要实现实时数据和历史数据的交互。
实时数据交互
LabVIEW支持Modbus、TCP/IP等多种数据传输的通信协议,而低代码控制器也支持Modbus、MQTT等通信协议,因此可以用双方均满足的数据通信协议来实现实时数据交互。本节中以Modbus-TCP为例来实现实时数据交互。
首先LabVIEW需要安装Modbus组件,包含下图中所示的函数:
然后创建一个Modbus-TCP实例,如下图:
最后根据需求添加读取、写入线圈和寄存器的模块,完成连接后输入IP地址即端口号就可以进行数据通信。
历史数据交互
LabVIEW可以通过HTTP客户端软件包编程来访问服务器对外开放的Web API服务,而低代码控制器也提供自己的Web服务器,因此LabVIEW可以通过HTTP协议来远程访问低代码控制器的Web应用服务器以获取历史数据。
LabVIEW与低代码控制器间通过HTTP交互数据首先需要明确数据格式,一般会采用json格式。
然后LabVIEW侧建立相关访问程:LabVIEW有自带的HTTP协议函数(在数据通信--协议--http客户端,要实现post方法一般要用到打开句柄、POST、添加头、关闭句柄),在添加头函数的文件头处要留意头文件格式。相关程序可以参考下图:
最后双方统一URL,在POST函数中写入要上报的信息或文件到缓存区和获取返回消息的头部和体部了。此外,LabVIEW还有json格式的实现,可以直接使用字符串--平化还原字符串--平化至json,具体使用方法可以查看LabVIEW的帮助文档。
7.4 进行二次开发
二次开发请联系开发者团队获取更多技术支持!。
7.5 脚本生成控制策略
为解决测点多、控制策略简单重复、配置文件用户手动书写繁琐等问题,可采用脚本生成控制策略(包括测点文件、通信通道文件和AOE文件)。
控制策略的配置文件可写为CSV格式,即由字符串组成的文本文件,所以任何能语言、软件都能实现脚本生成控制策略。
本章节以python语言和Matlab脚本为例,介绍脚本生成控制策略的实现过程。
基于python实现脚本生成控制策略
python实现脚本生成控制策略,主要用到了open()
、write()
等函数,需要注意的是低代码控制器的控制策略配置文件为CSV格式时,需要设置编码为UTF-8
或UTF-8(BOM)
,因此open()
函数中加入参数encoding='utf-8-sig'
。
import math
ProcessNum = 1000;
PointNum = 5;
SET = 10;
TimeSet = 2000;
ModbusCycle = 2000;
ClientIP='192.168.1.130';
ServerIP='192.168.1.151';
# AOE配置文件脚本
f=open('aoe-py-'+str(ProcessNum)+'-'+str(PointNum)+'.csv','w',encoding='utf-8-sig');
f.write('AOE ID,是否启用,名称,触发条件,触发条件参数,变量初始值\n');
for k in range(1,ProcessNum+1):
f.write(str(70000+k)+',TRUE,压力测试'+str(k)+',Event_Drive,,SET='+str(SET)+';\n');
f.write(',,,,,\n');
f.write('AOE ID,变量定义,,,,\n');
f.write(',,,,,\n');
f.write(',,,,,\n');
f.write('AOE ID,节点ID,名称,节点类型,超时时间(ms),表达式\n');
for k in range(1,ProcessNum+1):
f.write(str(70000+k)+',1,超出阈值事件,Condition,10,D'+str((k-1)*PointNum+1)+' > SET || 0-D'+str((k-1)*PointNum+1)+' > SET\n');
f.write(str(70000+k)+',2,超过下阈值事件,Condition,10,0-D'+str((k-1)*PointNum+1)+' > SET\n');
f.write(str(70000+k)+',3,超过上阈值事件,Condition,10,D'+str((k-1)*PointNum+1)+' > SET\n');
f.write(str(70000+k)+',4,结束节点,Condition,0,1\n');
f.write(',,,,,\n');
f.write('AOE ID,首尾节点,动作名称,失败模式,动作类型,动作参数\n');
for k in range(1,ProcessNum+1):
f.write(str(70000+k)+',1;2,进入判断是否超过下阈值的节点,Default,NONE,\n');
f.write(str(70000+k)+',1;3,进入判断是否超过上阈值的节点,Default,NONE,\n');
f.write(str(70000+k)+',2;4,递增器,Default,Set_Points,I'+str(k)+': 1;\n');
f.write(str(70000+k)+',3;4,递减器,Default,Set_Points,I'+str(k)+': -1;\n');
f.close
f=open('aoe-2-py-'+str(ProcessNum)+'-'+str(PointNum)+'.csv','w',encoding='utf-8-sig');
f.write('AOE ID,是否启用,名称,触发条件,触发条件参数,变量初始值\n');
for k in range(1,ProcessNum+1):
f.write(str(80000+k)+',TRUE,压力测试slave'+str(k)+',Simple_Repeat,'+str(TimeSet)+',\n');
f.write(',,,,,\n');
f.write('AOE ID,变量定义,,,,\n');
f.write(',,,,,\n');
f.write(',,,,,\n');
f.write('AOE ID,节点ID,名称,节点类型,超时时间(ms),表达式\n');
for k in range(1,ProcessNum+1):
f.write(str(80000+k)+',1,方向判断,Switch,10,I'+str(k)+' == 1\n');
f.write(str(80000+k)+',2,结束节点,Condition,100,0\n');
f.write(str(80000+k)+',3,结束节点,Condition,100,0\n');
f.write(',,,,,\n');
f.write('AOE ID,首尾节点,动作名称,失败模式,动作类型,动作参数\n');
for k in range(1,ProcessNum+1):
f.write(str(80000+k)+',1;2,递增,Default,Set_Points,');
for kk in range(1,PointNum+1):
f.write('D'+str((k-1)*PointNum+kk)+':D'+str((k-1)*PointNum+kk)+'+1;');
f.write('\n');
f.write(str(80000+k)+',1;3,递减,Default,Set_Points,');
for kk in range(1,PointNum+1):
f.write('D'+str((k-1)*PointNum+kk)+':D'+str((k-1)*PointNum+kk)+'-1;');
f.write('\n');
f.close
# 测点配置文件脚本
f=open('points-py-'+str(ProcessNum)+'-'+str(PointNum)+'.csv','w',encoding='utf-8-sig');
f.write('序号,点号,名称,别名,是否离散,是否计算点,计算公式,变换公式,逆变换公式,变化公式,判零公式,单位,上限值,下限值,最大变化,最小变化,是否实时点,是否SOE,默认值,备注\n');
for k in range(1,ProcessNum*PointNum+1):
f.write(str(k)+','+str(100000+k)+',测点'+str(k)+',D'+str(k)+',TRUE,FALSE,,,,,,,9999,-9999,0,0,TRUE,FALSE,0,\n');
for k in range(1,ProcessNum+1):
f.write(str(k+ProcessNum*PointNum)+','+str(80000+k+ProcessNum*PointNum)+',测点'+str(k+ProcessNum*PointNum)+',I'+str(k)+',TRUE,FALSE,,,,,,,9999,-9999,0,0,FALSE,FALSE,0,\n');
f.close
# 通信通道配置文件脚本
if PointNum*ProcessNum < 12:
print('transport manu');
else:
AllNum = (PointNum+1)*ProcessNum;
f=open('tcp-mbd-transport-py-'+str(ProcessNum)+'-'+str(PointNum)+'.csv','w',encoding='utf-8-sig');
f.write('通道名称,server测试通道,,连接名称,测试通道1,序号,寄存器类型,起始地址,数据类型,新请求标志,轮询周期,点号\n');
f.write('连接个数,1,,测点个数,'+str(AllNum)+',1,HOLDING,1,EightByteFloat,FALSE,'+str(ModbusCycle)+',100001\n');
f.write('服务端口,502,,客户端IP,'+ClientIP+',2,HOLDING,5,EightByteFloat,FALSE,'+str(ModbusCycle)+',100002\n');
f.write(',,,客户端端口,9999,3,HOLDING,9,EightByteFloat,FALSE,'+str(ModbusCycle)+',100003\n');
f.write(',,,slave id,1,4,HOLDING,13,EightByteFloat,FALSE,'+str(ModbusCycle)+',100004\n');
f.write(',,,通信协议,XA,5,HOLDING,17,EightByteFloat,FALSE,'+str(ModbusCycle)+',100005\n');
f.write(',,,一次读寄存器数上限,250,6,HOLDING,21,EightByteFloat,FALSE,'+str(ModbusCycle)+',100006\n');
f.write(',,,一次读开关数上限,2000,7,HOLDING,25,EightByteFloat,FALSE,'+str(ModbusCycle)+',100007\n');
f.write(',,,一次写寄存器数上限,250,8,HOLDING,29,EightByteFloat,FALSE,'+str(ModbusCycle)+',100008\n');
f.write(',,,一次写开关数上限,1968,9,HOLDING,33,EightByteFloat,FALSE,'+str(ModbusCycle)+',100009\n');
f.write(',,,轮询周期(ms),5000,10,HOLDING,37,EightByteFloat,FALSE,'+str(ModbusCycle)+',100010\n');
f.write(',,,超时(ms),1000,11,HOLDING,41,EightByteFloat,FALSE,'+str(ModbusCycle)+',100011\n');
f.write(',,,通道状态测点号,,12,HOLDING,45,EightByteFloat,FALSE,'+str(ModbusCycle)+',100012\n');
for k in range(13,AllNum+1):
f.write(',,,,,'+str(k)+',HOLDING,'+str(4*k-3)+',EightByteFloat,FALSE,'+str(ModbusCycle)+','+str(100000+k)+'\n');
f.close;
f=open('xa-mbc-transport-py-'+str(ProcessNum)+'-'+str(PointNum)+'.csv','w',encoding='utf-8-sig');
f.write('通道名称,测试通道1,序号,寄存器类型,起始地址,数据类型,新请求标志,轮询周期,点号\n');
f.write('测点个数,'+str(AllNum)+',1,HOLDING,1,EightByteFloat,FALSE,'+str(ModbusCycle)+',100001\n');
f.write('服务端ip,'+ServerIP+',2,HOLDING,5,EightByteFloat,FALSE,'+str(ModbusCycle)+',100002\n');
f.write('服务端端口,502,3,HOLDING,9,EightByteFloat,FALSE,'+str(ModbusCycle)+',100003\n');
f.write('slave id,1,4,HOLDING,13,EightByteFloat,FALSE,'+str(ModbusCycle)+',100004\n');
f.write('通信协议,XA,5,HOLDING,17,EightByteFloat,FALSE,'+str(ModbusCycle)+',100005\n');
f.write('一次读寄存器数上限,250,6,HOLDING,21,EightByteFloat,FALSE,'+str(ModbusCycle)+',100006\n');
f.write('一次读开关数上限,2000,7,HOLDING,25,EightByteFloat,FALSE,'+str(ModbusCycle)+',100007\n');
f.write('一次写寄存器数上限,2500,8,HOLDING,29,EightByteFloat,FALSE,'+str(ModbusCycle)+',100008\n');
f.write('一次写开关数上限,1968,9,HOLDING,33,EightByteFloat,FALSE,'+str(ModbusCycle)+',100009\n');
f.write('轮询周期(ms),5000,10,HOLDING,37,EightByteFloat,FALSE,'+str(ModbusCycle)+',100010\n');
f.write('超时(ms),1000,11,HOLDING,41,EightByteFloat,FALSE,'+str(ModbusCycle)+',100011\n');
for k in range(12,AllNum+1):
f.write(',,'+str(k)+',HOLDING,'+str(4*k-3)+',EightByteFloat,FALSE,'+str(ModbusCycle)+','+str(100000+k)+'\n');
f.close;
基于Mablab实现脚本生成控制策略
Matlab实现脚本生成控制策略,主要用到了fopen()
、fprintf()
等函数,需要注意的是低代码控制器的控制策略配置文件为CSV格式时,需要设置编码为UTF-8
或UTF-8(BOM)
。
下面以交流潮流为例展示基于Mablab实现脚本生成控制策略,Matpower提供的潮流计算案例由于节点较多,手动配置会非常繁琐,因此需要脚本生成控制策略。
具体脚本如下所示:
%数据读入
[dfile,pathname]=uigetfile('*.m','Select Data File');
if pathname == 0
error(' you must select a valid data file')
else
data=loadcase(dfile);
end
%数据预处理
[baseMVA, bus, gen, branch] = deal(data.baseMVA, data.bus, data.gen, data.branch);
ref = find(bus(:, 2) == 3);%平衡节点序号
nb = size(bus, 1);
ng = size(gen, 1);
%matpower计算对比输出
result = runpf(data);
solution = [result.bus(:,8);result.bus(:,9)*pi/180;result.gen(:,3)/baseMVA;result.gen(find(result.gen(:,1)==ref,1),2)/baseMVA];
equation_filname= strcat(dfile(1:length(dfile)-2),'_pf_result','.txt');
testf1=fopen(equation_filname,'w+','n','UTF-8');
fprintf(testf1, '%.8f\n',solution);
%创建直流潮流计算方程文件
equation_filname= strcat(dfile(1:length(dfile)-2),'_pf_polar','.txt');
testf2=fopen(equation_filname,'w+','n','UTF-8');
PFequation(data,testf2);
%创建测点文件
point_filname= strcat('points-',dfile(1:length(dfile)-2),'-pf.csv');
testf3=fopen(point_filname,'w+','n','UTF-8');
fprintf(testf3, '序号,点号,名称,别名,是否离散,是否计算点,计算公式,变换公式,逆变换公式,变化公式,判零公式,单位,上限值,下限值,最大变化,最小变化,是否实时点,是否SOE,默认值,备注\n');
fprintf(testf3,'1,100001,测点1,DoCal_POINT,TRUE,FALSE,,,,,,,9999,-9999,0,0,FALSE,FALSE,0,\n');
for k=1:nb
fprintf(testf3,'%s,%s,测点%s,v%s,FALSE,FALSE,,,,,,,99999,-99999,0,0,FALSE,FALSE,1,\n',int2str(k+1),int2str(k+100001),int2str(k+1),int2str(k));
end
for k=1:nb
fprintf(testf3,'%s,%s,测点%s,theta%s,FALSE,FALSE,,,,,,,99999,-99999,0,0,FALSE,FALSE,0,\n',int2str(k+1+nb),int2str(k+100001+nb),int2str(k+1+nb),int2str(k));
end
for k=1:ng
fprintf(testf3,'%s,%s,测点%s,qg%s,FALSE,FALSE,,,,,,,99999,-99999,0,0,FALSE,FALSE,0,\n',int2str(k+1+2*nb),int2str(k+100001+2*nb),int2str(k+1+2*nb),int2str(k));
end
fprintf(testf3,'%s,%s,测点%s,pg_balancenode,FALSE,FALSE,,,,,,,99999,-99999,0,0,FALSE,FALSE,0,\n',int2str(2+2*nb+ng),int2str(100002+2*nb+ng),int2str(2+2*nb+ng));
%创建AOE文件
AOE_filname= strcat('aoe-matlab-',dfile(1:length(dfile)-2),'-pf.csv');
testf4=fopen(AOE_filname,'w+','n','UTF-8');
fprintf(testf4,'AOE ID,是否启用,名称,触发条件,触发条件参数,变量初始值,,\n');
BL='';%变量初始值
for k=1:nb
BL=strcat(BL,'V',int2str(k),':1;');
end
for k=1:nb
BL=strcat(BL,'THETA',int2str(k),':0;');
end
for k=1:ng
BL=strcat(BL,'QG',int2str(k),':0;');
end
BL=strcat(BL,'PG_balancenode:0');
fprintf(testf4,'70001,TRUE,交流潮流计算,Event_Drive,,%s,,\n',BL);
fprintf(testf4,',,,,,,,\n');
fprintf(testf4,'AOE ID,变量定义,,,,,,\n');
fprintf(testf4,',,,,,,,\n');
fprintf(testf4,',,,,,,,\n');
fprintf(testf4,'AOE ID,节点ID,名称,节点类型,超时时间(ms),表达式,,\n');
fprintf(testf4,'70001,1,首节点,Condition,10,DoCal_POINT > 0.5,,\n');
fprintf(testf4,'70001,2,计算节点,Condition,10,1,,\n');
fprintf(testf4,'70001,3,赋值,Condition,10,1,,\n');
fprintf(testf4,'70001,4,结束节点,Condition,1000,DoCal_POINT==0,,\n');
fprintf(testf4,',,,,,,,\n');
fprintf(testf4,'AOE ID,首尾节点,动作名称,失败模式,动作类型,动作参数,,\n');
fprintf(testf4,'70001,1;2,进入交流潮流计算,Default,Set_Points,DoCal_POINT:0;,,\n');
fprintf(testf4,'70001,2;3,计算交流潮流计算,Default,NLSOLVE,');
fprintf(testf4,'"');
PFequation(data,testf4);
fprintf(testf4,'",,\n');
fprintf(testf4,'70001,3;4,赋值,Default,Set_Points,,');
fprintf(testf4,'"');
for k=1:nb
fprintf(testf4,'v%s:V%s;\n',int2str(k),int2str(k));
end
for k=1:nb
fprintf(testf4,'theta%s:THETA%s;\n',int2str(k),int2str(k));
end
for k=1:ng
fprintf(testf4,'qg%s:QG%s;\n',int2str(k),int2str(k));
end
fprintf(testf4,'pg_balancenode:PG_balancenode",\n');
7.6 定期保存或上传
在实际应用中,为了保证数据的准确性和实时性,当数据距上次采集时间超过一定时长,需要进行再次采集(数据上传)。低代码控制器可采用测点文件配置中的变化公式配置,实现该定期保存或上传的功能,具体方案如下所示:
在测点文件配置的采集点配置中,存在变化公式配置项,该配置项用于判断是否需要变化上传,如果计算结果>0则表示该次采集到的点需要上传。
该方案中,变化公式配置为 "abs($点号_err) >= 10 || $点号_dt >= 5000"
,其含义为测点变化量超过10或者采样时间间隔大于5秒都会上报,具体配置文件如下:
测点文件配置
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 变化公式 | 默认值 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | a1 | FALSE | FALSE | abs($1001_err)>= 10||$1001_dt >= 5000 | 1 |
2 | 100002 | 测点2 | a2 | FALSE | FALSE | abs($1002_err)>= 10||$1002_dt >= 5000 | 2 |
3 | 100003 | 测点3 | a3 | FALSE | FALSE | abs($1003_err)>= 10||$1003_dt >= 5000 | 3 |
通道文件配置
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 0 | TwoByteIntSigned | FALSE | 300000 | 100001 |
2 | HOLDING | 1 | TwoByteIntSigned | FALSE | 300000 | 100002 |
3 | HOLDING | 2 | TwoByteIntSigned | FALSE | 300000 | 100003 |
附件:定期保存或上传.rar
7.7 如何配置只写不读的采集点
在实际应用中,采集点会存在配置为只写不读的需求,为实现该采集点配置,可采用如下方案。
采集点的读取与通道配置文件的轮询周期有关,当轮询周期配置很大时,例如设置为100年,即可实现只写不读的效果。
该典型解决方案可按照一下方式配置:
通道文件配置
通道文件中,该测点通道可按如下配置。
序号 | 寄存器类型 | 起始地址 | 数据类型 | 新请求标志 | 轮询周期 | 点号 |
---|---|---|---|---|---|---|
1 | HOLDING | 0 | TwoByteIntSigned | FALSE | 9999999999999 | 100001 |
2 | HOLDING | 1 | TwoByteIntSigned | FALSE | 9999999999999 | 100002 |
3 | HOLDING | 2 | TwoByteIntSigned | FALSE | 9999999999999 | 100003 |
测点文件配置
测点文件可按如下配置。
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|
1 | 100001 | 测点1 | a1 | FALSE | FALSE | 0 | 变量1 |
2 | 100002 | 测点2 | a2 | FALSE | FALSE | 0 | 变量2 |
3 | 100003 | 测点3 | a3 | FALSE | FALSE | 0 | 变量3 |
7.8 系统监控
对于系统的运行状态,如内存存储状态、CPU使用情况、磁盘使用空间等状态,可采用如下系统监控方案来进行监控。
该典型解决方案可按照一下方式配置:
测点文件配置
测点文件定义了系统各状态的变量,可按如下配置。
序号 | 点号 | 名称 | 别名 | 是否离散 | 是否计算点 | 单位 | 默认值 | 备注 |
---|---|---|---|---|---|---|---|---|
1 | 100001 | TotalMemory | TotalMemory | FALSE | FALSE | MB | -1 | 总内存大小 |
2 | 100002 | UsedMemory | UsedMemory | FALSE | FALSE | MB | -1 | 已使用内存大小 |
3 | 100003 | UsedMemorySelf | UsedMemorySelf | FALSE | FALSE | MB | -1 | 程序本身已使用内存大小 |
4 | 100004 | MemUsage | MemUsage | FALSE | FALSE | % | -1 | 内存使用率 |
5 | 100005 | MemUsageSelf | MemUsageSelf | FALSE | FALSE | % | -1 | 程序本身内存使用率 |
6 | 100006 | TotalSwap | TotalSwap | FALSE | FALSE | MB | -1 | 总Swap大小 |
7 | 100007 | UsedSwap | UsedSwap | FALSE | FALSE | MB | -1 | 已使用Swap大小 |
8 | 100008 | CpuUsage | CpuUsage | FALSE | FALSE | % | -1 | Cpu使用率 |
9 | 100009 | CpuUsageSelf | CpuUsageSelf | FALSE | FALSE | % | -1 | 程序本身Cpu使用率 |
10 | 100010 | TotalSpace | TotalSpace | FALSE | FALSE | MB | -1 | 总空间大小 |
11 | 100011 | UsedSpace | UsedSpace | FALSE | FALSE | MB | -1 | 已使用空间大小 |
12 | 100012 | DiskUsage | DiskUsage | FALSE | FALSE | % | -1 | 已使用磁盘率 |
13 | 100013 | TotalReceived | TotalReceived | FALSE | FALSE | Byte | -1 | 总接收数据量 |
14 | 100014 | TotalTransmitted | TotalTransmitted | FALSE | FALSE | Byte | -1 | 总发送数据量 |
策略文件配置
策略文件可按如下配置。各变量都有相应的函数进行数值的读取。
AOE网络声明
名称为设备监控,触发条件设置为简单重复循环(Simple_Repeat),循环周期为5s。
AOE ID | 是否启用 | 名称 | 触发条件 | 触发条件参数 | 变量初始值 |
---|---|---|---|---|---|
70007 | TRUE | 设备监控 | Simple_Repeat | 5000 |
AOE节点声明
AOE ID | 节点ID | 名称 | 节点类型 | 超时时间(ms) | 表达式 |
---|---|---|---|---|---|
70001 | 1 | 赋值 | Condition | 1000 | 1 |
70001 | 2 | 结束 | Condition | 1000 | 1 |
AOE边声明
AOE ID | 首尾节点 | 动作名称 | 失败模式 | 动作类型 | 动作参数 | |
---|---|---|---|---|---|---|
70001 | 1;2 | 赋值 | Default | Set_Points | TotalMemory:TotalMemory(); UsedMemory:UsedMemory(); UsedMemorySelf:UsedMemorySelf(); MemUsage:MemUsage(); MemUsageSelf:MemUsageSelf(); TotalSwap:TotalSwap(); UsedSwap:UsedSwap(); CpuUsage:CpuUsage(); CpuUsageSelf:CpuUsageSelf(); TotalSpace:TotalSpace(); UsedSpace:UsedSpace(); DiskUsage:DiskUsage(); TotalReceived:TotalReceived(); TotalTransmitted:TotalTransmitted(); |
8 配置文件模板
- AOE文件配置模板
- 测点文件配置模板
- ModBus TCP服务端通道文件配置模板
- ModBus TCP客户端通道文件配置模板
- ModBus RTU服务端通道文件配置模板
- ModBus RTU客户端通道文件配置模板
- DL /T 645 UART服务端通道文件配置模板
- DL /T 645 TCP服务端通道文件配置模板
- IEC104服务端通道文件配置模板
- MQTT通道文件配置模板
全部下载:配置文件模板