wincc怎么做设定曲线?
如果应用到程序升温的场合(金属热处理、玻璃窑炉的烘炉升温、聚合反应等)。SP曲线是随时间变化,可以比较SSP和SP曲线,判断目前处于什么阶段?升温速率是多少?本段升温大约多少时间结束?(升温曲线是由多段升温直线组成),可以提前对工艺设备、操作人员等作出合理安排。SSP是Schedule Set Point的缩写,主要功能是输出值是随着时间的推移而变化。可以通过输入端子(x1,x2,x3...x1,代表时间)和输入端子(y1,y2,y3...y10,输出值)来描述功能块的输出值与时间的关系。 今天把相关文档汇总整理一下,修改了一些错字,并将WinCC的UserArchive和Step7的SSP功能块连接起来,在Windows XP SP3 (English)+Step7 V5.4 SP5+WinCC V7.0 SP1平台下测试通过。
. 在Step7中
在Step7中建立一个SSP功能块,其定义如下:
1.1. 功能块的输入:
1.1.1. PV信号,就是我们需要控制的参数,Real。
1.1.2. x1,x2,x3...x10输入信号,代表时间间隔的参数,real。
1.1.3. y1,y2,y3...y10输入信号,代表输出值的参数,real。
由(x1,y1),(x2,y2)......(x10,y10)共计10点,组成折线表。
1.1.4. Start输入信号,控制SSP运行的信号,off:停止,on:运行。bool。
1.2. 功能块的输出信号
1.2.1. SSP输出,当Start=off时,SSP=PV。当Start=on时,SSP以当前的PV为初始值,由(x(n),y(n))和(x(n+1),y(n+1))组成的直线来决定SSP的值。real。
1.2.2. ElapseTime,代表SSP运行的时间,real。
1.3. 主要功能说明
1.3.1. Start=off,SSP=PV,ElapseTime=0。
1.3.2. Start从off→on的正跳变时,功能块要根据此时的PV值(计作y0),反向计算出对应的X值(计作xo)。主要是考虑无扰动切换。
1.3.3. Start=on,从x0开始,计算x值,并通过直线方程得到SSP值。
1.3.4. Start=on,ElapseTime=ElapseTime+OB35的时间。
2. 在WinCC中
2.1. 在WinCC中建立一个User Archive(名称为yhg),并建立X、Y两个字段(Field)。
2.2. 在TagLogging中,为Step7中的SSP功能块的输出SSP信号(也可以选择实际需要控制的参数作为归档信号)和ElapseTime信号建立归档记录。
2.3. 在图形中建立一个UserArchive 控件,在控件组态中指定UserArchive名称为yhg。
2.4. 在图形中建立一个FunctionTrend控件,在控件组态中建立2个变量:UserArchiveSSP和SSP。
a) UserArchiveSSP的数据源选择UserArchive/yhg,其X轴选择UserArchive中的yhg文件的x字段,Y轴选择UserArchive中的yhg的y字段。
b) SSP的数据源选择ArchiveTags,其X轴选择TagLogging中的ElapseTime,Y轴选择TagLogging中的SSP。
2.5. 在图形中增加一个按钮对象,名称为“Download to PLC”,并在鼠标事件中定义如下s cript:
#include "apdefap.h"
void OnLButtonUp(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)
{
#include "apdefap.h"
void UAReadFromArchive();
UAHCONNECT hConnect;
UAHARCHIVE hArchive;
LONG lField = 1;
LONG NumberOfFields;
int ID;
int FieldIndex;
int plCount;
float x_Axis[15];
float y_Axis[15];
float pfValue;
//******* Connect to Componente User Archive **********************
if(uaConnect(&hConnect)==FALSE)
{
printf("uaConnect error: %d\r\n",uaGetLastError());
return;
}
if(hConnect==NULL)
{
printf("Handle UAHCONNECT equals NULL\r\n");
return;
}
//******* Connect to Archive via Name ******************************
if(uaQueryArchiveByName(hConnect,"yhg",&hArchive)==FALSE)
{
printf("uaQueryArchive Error: %d\r\n",uaGetLastError());
uaDisconnect(hConnect);
return;
}
//********* Sort on the ID ******************************************
uaArchiveSetSort( hArchive, "ID" );
//******* Opens Archivs ********************************************
if(uaArchiveOpen(hArchive)==FALSE)
{
printf("uaArchive Open Error\r\n",uaGetLastError());
uaReleaseArchive(hArchive);
uaDisconnect(hConnect);
return;
}
//******* Get Number of *********************************************
NumberOfFields = uaArchiveGetFields( hArchive );
printf( "Number of Fields = %u\n", NumberOfFields );
//*******************************************************************
UAArchiveGetCount(hArchive,&plCount);
printf( "Number of data records: %d\r\n" , plCount);
uaArchiveMoveFirst(hArchive); //Return-Type: BOOL
for (FieldIndex = 1; FieldIndex < NumberOfFields; FieldIndex++)
{
uaArchiveMoveFirst(hArchive); //Return-Type: BOOL
for (ID=1; ID <= plCount; ID++)
{
if (uaArchiveGetFieldValueFloat(hArchive,lField,&pfValue)) //Return-Type: BOOL
{
if (lField==1)
{
x_Axis[ID] = pfValue;
printf( " x Value: %f\r\n" , x_Axis[ID]);
}
else
{
y_Axis[ID] = pfValue;
printf( " y Value: %f\r\n" , y_Axis[ID]);
}
uaArchiveMoveNext(hArchive); //Return-Type: BOOL
}
else
{
printf("Error:%d\n", uaGetLastError() );
break;
}
printf( " ID: %d\r\n" , ID);
}
lField++;
}
//******* Close Archive ********************************************
if(uaArchiveClose(hArchive)==FALSE)
{
printf("error on closing archive\r\n",uaGetLastError());
}
if(uaReleaseArchive(hArchive)==FALSE)
{
printf("error release archive\r\n",uaGetLastError());
}
//******* Disconnect Component User Archive ************************
if(uaDisconnect(hConnect)==FALSE)
{
printf("error on disconnection\n",uaGetLastError());
}
//******* Write to PLC **************************************
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.x1",x_Axis[1]); //Return-Type: BOOL
//......
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.x10",x_Axis[10]); //Return-Type: BOOL
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.y1",y_Axis[1]); //Return-Type: BOOL
//......
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.y10",y_Axis[10]); //Return-Type: BOOL
}
2.6. 在图形中增加一个按钮对象,名称为“Start”,并在鼠标事件中定义如下s cript:
#include "apdefap.h"
void OnLButtonDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)
{
if (GetTagBit("S7$Program(1)/CFC(1)/SSP.Start")) //Return-Type: BOOL
(SetTagBitWait("S7$Program(1)/CFC(1)/SSP.Start",FALSE)); //Return-Type: BOOL
else
(SetTagBitWait("S7$Program(1)/CFC(1)/SSP.Start",TRUE)); //Return-Type: BOOL
}
2.7. 测试
2.7.1. 在PLC或PLCSIM中运行Step7程序。
2.7.2. 运行WinCC,在UserArchive 控件输入相应的X、Y值,检查无误后,按“Download to PLC”按钮,将输入的X、Y值下载到PLC的SSP功能块的相应输入端子。
2.7.3. 在WinCC中按“Start”按钮,启动Step7中的SSP功能块。
2.7.4. 可以看到在WinCC中的FunctionTrend有2条曲线:
a) 一条是UserArchive的曲线,这是我们希望得到的曲线,该曲线不随时间变化
b) 另一条是实际的曲线,该曲线是随时间变化的。
其他的功能可以根据需要增加。
附效果图:
. 在Step7中
在Step7中建立一个SSP功能块,其定义如下:
1.1. 功能块的输入:
1.1.1. PV信号,就是我们需要控制的参数,Real。
1.1.2. x1,x2,x3...x10输入信号,代表时间间隔的参数,real。
1.1.3. y1,y2,y3...y10输入信号,代表输出值的参数,real。
由(x1,y1),(x2,y2)......(x10,y10)共计10点,组成折线表。
1.1.4. Start输入信号,控制SSP运行的信号,off:停止,on:运行。bool。
1.2. 功能块的输出信号
1.2.1. SSP输出,当Start=off时,SSP=PV。当Start=on时,SSP以当前的PV为初始值,由(x(n),y(n))和(x(n+1),y(n+1))组成的直线来决定SSP的值。real。
1.2.2. ElapseTime,代表SSP运行的时间,real。
1.3. 主要功能说明
1.3.1. Start=off,SSP=PV,ElapseTime=0。
1.3.2. Start从off→on的正跳变时,功能块要根据此时的PV值(计作y0),反向计算出对应的X值(计作xo)。主要是考虑无扰动切换。
1.3.3. Start=on,从x0开始,计算x值,并通过直线方程得到SSP值。
1.3.4. Start=on,ElapseTime=ElapseTime+OB35的时间。
2. 在WinCC中
2.1. 在WinCC中建立一个User Archive(名称为yhg),并建立X、Y两个字段(Field)。
2.2. 在TagLogging中,为Step7中的SSP功能块的输出SSP信号(也可以选择实际需要控制的参数作为归档信号)和ElapseTime信号建立归档记录。
2.3. 在图形中建立一个UserArchive 控件,在控件组态中指定UserArchive名称为yhg。
2.4. 在图形中建立一个FunctionTrend控件,在控件组态中建立2个变量:UserArchiveSSP和SSP。
a) UserArchiveSSP的数据源选择UserArchive/yhg,其X轴选择UserArchive中的yhg文件的x字段,Y轴选择UserArchive中的yhg的y字段。
b) SSP的数据源选择ArchiveTags,其X轴选择TagLogging中的ElapseTime,Y轴选择TagLogging中的SSP。
2.5. 在图形中增加一个按钮对象,名称为“Download to PLC”,并在鼠标事件中定义如下s cript:
#include "apdefap.h"
void OnLButtonUp(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)
{
#include "apdefap.h"
void UAReadFromArchive();
UAHCONNECT hConnect;
UAHARCHIVE hArchive;
LONG lField = 1;
LONG NumberOfFields;
int ID;
int FieldIndex;
int plCount;
float x_Axis[15];
float y_Axis[15];
float pfValue;
//******* Connect to Componente User Archive **********************
if(uaConnect(&hConnect)==FALSE)
{
printf("uaConnect error: %d\r\n",uaGetLastError());
return;
}
if(hConnect==NULL)
{
printf("Handle UAHCONNECT equals NULL\r\n");
return;
}
//******* Connect to Archive via Name ******************************
if(uaQueryArchiveByName(hConnect,"yhg",&hArchive)==FALSE)
{
printf("uaQueryArchive Error: %d\r\n",uaGetLastError());
uaDisconnect(hConnect);
return;
}
//********* Sort on the ID ******************************************
uaArchiveSetSort( hArchive, "ID" );
//******* Opens Archivs ********************************************
if(uaArchiveOpen(hArchive)==FALSE)
{
printf("uaArchive Open Error\r\n",uaGetLastError());
uaReleaseArchive(hArchive);
uaDisconnect(hConnect);
return;
}
//******* Get Number of *********************************************
NumberOfFields = uaArchiveGetFields( hArchive );
printf( "Number of Fields = %u\n", NumberOfFields );
//*******************************************************************
UAArchiveGetCount(hArchive,&plCount);
printf( "Number of data records: %d\r\n" , plCount);
uaArchiveMoveFirst(hArchive); //Return-Type: BOOL
for (FieldIndex = 1; FieldIndex < NumberOfFields; FieldIndex++)
{
uaArchiveMoveFirst(hArchive); //Return-Type: BOOL
for (ID=1; ID <= plCount; ID++)
{
if (uaArchiveGetFieldValueFloat(hArchive,lField,&pfValue)) //Return-Type: BOOL
{
if (lField==1)
{
x_Axis[ID] = pfValue;
printf( " x Value: %f\r\n" , x_Axis[ID]);
}
else
{
y_Axis[ID] = pfValue;
printf( " y Value: %f\r\n" , y_Axis[ID]);
}
uaArchiveMoveNext(hArchive); //Return-Type: BOOL
}
else
{
printf("Error:%d\n", uaGetLastError() );
break;
}
printf( " ID: %d\r\n" , ID);
}
lField++;
}
//******* Close Archive ********************************************
if(uaArchiveClose(hArchive)==FALSE)
{
printf("error on closing archive\r\n",uaGetLastError());
}
if(uaReleaseArchive(hArchive)==FALSE)
{
printf("error release archive\r\n",uaGetLastError());
}
//******* Disconnect Component User Archive ************************
if(uaDisconnect(hConnect)==FALSE)
{
printf("error on disconnection\n",uaGetLastError());
}
//******* Write to PLC **************************************
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.x1",x_Axis[1]); //Return-Type: BOOL
//......
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.x10",x_Axis[10]); //Return-Type: BOOL
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.y1",y_Axis[1]); //Return-Type: BOOL
//......
SetTagFloatWait("S7$Program(1)/CFC(1)/SSP.y10",y_Axis[10]); //Return-Type: BOOL
}
2.6. 在图形中增加一个按钮对象,名称为“Start”,并在鼠标事件中定义如下s cript:
#include "apdefap.h"
void OnLButtonDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)
{
if (GetTagBit("S7$Program(1)/CFC(1)/SSP.Start")) //Return-Type: BOOL
(SetTagBitWait("S7$Program(1)/CFC(1)/SSP.Start",FALSE)); //Return-Type: BOOL
else
(SetTagBitWait("S7$Program(1)/CFC(1)/SSP.Start",TRUE)); //Return-Type: BOOL
}
2.7. 测试
2.7.1. 在PLC或PLCSIM中运行Step7程序。
2.7.2. 运行WinCC,在UserArchive 控件输入相应的X、Y值,检查无误后,按“Download to PLC”按钮,将输入的X、Y值下载到PLC的SSP功能块的相应输入端子。
2.7.3. 在WinCC中按“Start”按钮,启动Step7中的SSP功能块。
2.7.4. 可以看到在WinCC中的FunctionTrend有2条曲线:
a) 一条是UserArchive的曲线,这是我们希望得到的曲线,该曲线不随时间变化
b) 另一条是实际的曲线,该曲线是随时间变化的。
其他的功能可以根据需要增加。
附效果图:
新闻详情