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