联系我们

联系人:黄勇(先生)

联系手机:13701633515

固定电话:31660605

企业邮箱:77956468@qq.com

联系我时,请说是在地方电气网上看到的,谢谢!

今日最新资讯
热门资讯
地方电气网资讯
    西门子0.37千瓦变频器6SL32110KB137BA1
    发布者:黄工  发布时间:2016-04-10 14:23:24  访问次数:114

    西门子0.37千瓦变频器6SL32110KB137BA1,西门子0.37千瓦变频器6SL32110KB137BA1

                               {心中有空间,梦想就有可能}

                     {西门子与客户携手,让关键所在,逐一实现}

    联   系   人: 黄勇《黄工》   24小时联系手机:  13701633515
    直线销售 电 话: 021-31660605    在 线 商 务 QQ:  77956468 
    单位:台                                                                                  产品单价:电议

    供货数量:不限                                                                      最小定量:1

    包装说明:齐全                                                                      产品规格:全新原装

    西门子S7-200子程序,多次调用的“怪”现象

    在S7-200编程中,子程序想必大家都用过,使用子程序可以更好地组织程序结构,便于阅读和调试,也可以缩短程序代码。但是使用子程序也有一些需要注意的地方,除了子程序在同一周期内被多次调用时,不能使用上升沿、下降沿、定时器和计数器之外,还有子程序中局部变量的特点,在编程多次调用带参数子程序时要特别注意。下面就是前些天热线上遇到的一个Case,非常有代表性,在这里跟大家分享。
    E:您好,西门子技术支持。
    C:您好,我想问下,200子程序是不是多次调用时会不好使?
    E:不会啊,您是不是在子程序里使用了沿指令或者定时器?
    C:没有啊,我就编了一句很简单的开关程序,开关闭合,线圈导通,然后主程序里调用了两次这个子程序,结果第一个I点闭合了,两个Q点都导通了。
    E:(心里活动:看来是和子程序的局部变量有关了,估计客户程序逻辑有问题)那请您描述一下您的子程序吧,我帮您看看。
    于是客户描述了一下自己的程序,大致了解了之后告知客户我这边测试下,稍后回复。
    客户的程序是这样的:
    子程序:是个常见的自保持逻辑,接口参数如红框所示。

    图. 01
    主程序:调用了两次上面的子程序,实现I0.0和I0.1控制Q0.0的闭合和断开,I0.2和I0.3控制Q0.1的闭合和断开。

    图. 02
    那么在线测试下程序执行情况,发现果然如客户所描述的,I0.0为1后,Q0.0和Q0.1都为1了。见下图.03所示。而如果闭合I0.2,则Q0.0和Q0.1都断开。

    图. 03
    为什么会这样呢?首先我们先明确子程序局部变量的特点。局部变量的变量类型分为四种:IN,IN_OUT,OUT和TEMP,局部变量存储区是在子程序调用时开辟的,子程序调用完成,局部变量占用的存储空间释放。
    我们来分析下客户的子程序。
    在主程序第一次调用子程序时,如果I0.0为1,I0.1为0,它们将自身值分别传给输入局部变量#AA和#BB,子程序中程序逻辑执行如下图.04所示。此时局部变量#CC值为1,子程序完成,#CC将值传送到输出参数Q0.0上,使其置1。根据局部变量的特点,子程序第一次调用完成后,局部变量存储区释放。

    图.04

    那么当主程序第二次调用该子程序时,开辟临时存储空间,但是此时的存储空间与第一次调用时开辟的不一定一致。可是,也有可能由于程序简单,仍然使用第一次调用时占用的存储空间。如果这种情况发生了,那么第一次调用时已经将#CC的L0.2置了1,而此值依旧存在,那么第二次调用时虽然输入参数I0.2和I0.3为0 ,但是#CC(L0.2)为1,由于客户的子程序逻辑有自保持部分,所以最后L0.2的逻辑结果仍然是1。子程序完成后,#CC将值传送到输出参数Q0.1上,使其置1。所以就会出现客户反映的那种问题。
    那么该如何避免这种情况呢?
    大家是否还记得刚刚介绍局部变量参数类型时除了IN, OUT类型外,还有一种类型叫IN_OUT,这种类型的参数是先读入,然后再写出,这里我们就可以利用它的特点解决上面的问题。
    下面对子程序的参数进行修改,将原先的#CC变量类型改为IN_OUT。如下图所示:

    图.05
    主程序结构不变,如下所示,可以看到由于#CC的类型是IN-OUT,它在子程序块的接口位置也转到了左侧输入侧。

    图.06
    下面再次将I0.0置1,其他输入都为0,监控程序状态,如图.07所示,可以看到只有Q0.0为1,Q0.1状态为0。而如果将I0.1置1, Q0.0被复位,Q0.1还是0,这样就符合客户的控制要求了。

    图.07
    同样,如果只给I0.2置1,那么也只有Q0.1会亮,不会再影响Q0.0。
    了解了IN_OUT类型变量的特点,就不难分析以上的结果。因为每次调用子程序时,局部变量#CC都会先去读取输入参数Q0.0或Q0.1的状态,所以即使两次调用子程序时,#CC变量使用的同一区域,该区域的值也会在开始被Q点的状态所修改,就不存在两次调用相互影响的情况了。
    另外,如果在子程序一开始就添加一条指令,对局部变量#CC进行赋初值(如图.08),也可以避免临时变量区数值不定的问题,您可以尝试测试下。

    图.08
    所以,在编写200子程序时要特别注意局部变量的特点,一旦出现多次调用不正常的情况,就可以从局部变量的特点出发分析,看看是不是存在隐患。善加利用IN_OUT变量也许可以解决许多问题。

    运用VC#编程通过OPC方式实现PC机与西门子PLC通讯

    1、 配置OPC服务器
    对于服务器的配置与同步通讯的配置一样,这里不需再讲解,若有不清楚的,可以参阅之前发布的<运用VC#编程通过OPC方式实现PC机与西门子PLC通讯>
    2、 OPC编程
    变量组、项的命名规则与同步通讯的一样,这里不再描叙,下面主要就开发一个异步通讯类 AsynServer来讲解如何编程。
    <1>、引用
    在VC#开发环境中添加对OpcRcw.Da库以及OpcRcw.Comn库的引用,该库属于.NET库,不属于COM库,西门子虽然编写了类库,以提供对.NET平台的支持,但这些类库仍然难于编程,里面包含了大量的在托管和非托管区传输数据,因此我们需要在它的基础上再开发一个类库,以简化以后的编程,首先在类的开头使用命名空间:
    using OpcRcw.Comn;
    using OpcRcw.Da;
    using System.Runtime.InteropServices;
    using System.Collections;
    <2>、编程
    异步编程的原理就是在OPC服务器那边检测当前活动的变量组,一但检测到某一个变量,譬如变量Q0.0从1变成0,就会执行一个回调函数,以实现针对变量发生变化时需要实现的动作,在这里可以采用委托来实现该功能。
    1、 在命名空间的内部、类 AsynServer声明之前添加委托的申明:
    // 定义用于返回发生变化的项的值和其对应的客户句柄
    public delegate void DataChange(object[] values,int[] itemsID);
    2、 该类继承于西门子提供的库接口IOPCDataCallback
    public class AsynServer:IOPCDataCallback
    在类的开头部分声明变量:
    struct groupStru
    {
    public int groupID;
    public object groupObj;
    }
    internal const int LOCALE_ID = 0x407; //本地语言
    private Guid iidRequiredInterface;
    private string serverType="";
    private int hClientGroup = 0; //客户组号
    private int nSvrGroupID; // server group handle for the added group 
    private Hashtable hashGroup; //用于把组收集到一起
    private int hClientItem=0; //Item号
    3、编写构造函数,接收委托参数已确定当数据发生变化时需要执行的方法入口点:
    //创建服务器
    //svrType 服务器类型的枚举
    //dataChange 提供用于在数据发生变化时需要执行的函数入口
    public AsynServer(ServerType svrType,DataChange dataChange)
    {
    switch(svrType)
    {
    case ServerType.OPC_SimaticHMI_PTPR
    serverType="OPC.SimaticHMI.PTPro";break;
    case ServerType.OPC_SimaticNET:
    serverType="OPC.SimaticNET";break;
    case ServerType.OPC_SimaticNET_DP:
    serverType="OPC.SimaticNET.DP";break;
    case ServerType.OPC_SimaticNET_PD:
    serverType="OPC.SimaticNET.PD";break;
    case ServerType.OPCServer_WinCC:
    serverType="OPCServer.WinCC";break;
    }
    hashGroup=new Hashtable(11);
    dtChange=dataChange;
    }

    4、创建服务器
    // 创建一个OPC Server接口
    //error 返回错误信息
    //若为true,创建成功,否则创建失败
    public bool Open(out string error)
    {
    error="";bool success=true;
    Type svrComponenttyp ;
    //获取 OPC Server COM 接口
    iidRequiredInterface = typeof(IOPCItemMgt).GUID;
    svrComponenttyp = System.Type.GetTypeFromProgID(serverType);
    try
    {
    //创建接口
    pIOPCServer =(IOPCServer)System.Activator.CreateInstance(svrComponenttyp);
    error="";
    }
    catch (System.Exception err) //捕捉失败信息
    {
    error="错误信息:"+err.Message;success=false;
    }
    return success;
    }
    5、 编写添加Group的函数
    ///


    /// 添加组
    /// 
    /// 组名
    /// /创建时,组是否被激活
    /// //组的刷新频率,以ms为单位
    /// 返回错误信息
    /// 若为true,添加成功,否则添加失败
    public bool AddGroup(string groupName,int bActive,int updateRate,out string error)

    error="";bool success=true;
    int dwLCID = 0x407; //本地语言为英语 
    int pRevUpdateRate;
    float deadband = 0;
    // 处理非托管COM内存
    GCHandle hDeadband;
    IntPtr pTimeBias = IntPtr.Zero;
    hDeadband = GCHandle.Alloc(deadband,GCHandleType.Pinned);
    try
    {
    pIOPCServer.AddGroup(groupName, //组名
    bActive, //创建时,组是否被激活
    updateRate, //组的刷新频率,以ms为单位
    hClientGroup, //客户号
    pTimeBias, //这里不使用
    (IntPtr)hDeadband,
    dwLCID, //本地语言
    out nSvrGroupID, //移去组时,用到的组ID号
    out pRevUpdateRate, //返回组中的变量改变时的最短通知时间间隔
    ref iidRequiredInterface,
    out pobjGroup1); //指向要求的接口
    hClientGroup=hClientGroup+1; 
    groupStru grp=new groupStru();
    grp.groupID=nSvrGroupID;grp.groupObj=pobjGroup1;
    this.hashGroup.Add(groupName,grp);//储存组信息
    // 对异步操作设置回调,初始化接口
    pIConnectionPointContainer = (IConnectionPointContainer)pobjGroup1;
    Guid iid = typeof(IOPCDataCallback).GUID;
    pIConnectionPointContainer.FindConnectionPoint(ref iid,out pIConnectionPoint);
    pIConnectionPoint.Advise(this,out dwCookie);
    }
    catch (System.Exception err) //捕捉失败信息
    {
    error="错误信息:"+err.Message;success=false;
    }
    finally
    {
    if (hDeadband.IsAllocated) hDeadband.Free();
    }
    return success;
    }

    6、 编写激活、或者取消激活组的函数

    在同步编程中对于组的激活或者取消激活没有实质的意义,但在异步通讯编程中却异常重要,这是因为OPC服务器只对当前处于活动状态的组中的变量进行监控,同时这也是很有必要的,因为我们可以把不同界面中的变量编程不同的组,即同一界面中的变量规成一个组,而在某一时刻提供给用户的只有一个界面,让该界面中用到的组处于活动状态,这样执行委托调用时只会执行于该界面中有关的变量检测,而如果让所有的组处于活动状态,则当前没有显示给用户的界面用到的变量若发生变化也会触发对委托函数的调用,这根本是没有必要的,同时会大大降低程序的性能,请严格控制组的激活。
    ///
    /// 激活或者取消激活组
    /// 
    /// 指定组名
    /// true为激活,false为取消激活
    /// 若有错误,返回错误信息
    /// 若为true,添加成功,否则添加失败
    public bool AciveGroup(string groupName,bool toActive,out string error)
    {
    error="";bool success=true;
    //通过名称获取组
    object grp=((groupStru)hashGroup[groupName]).groupObj;
    IOPCGroupStateMgt groupStateMgt=(IOPCGroupStateMgt)grp;
    //初始化传递参数
    IntPtr pRequestedUpdateRate = IntPtr.Zero; //由客户指定的Item更新间隔时间
    int nRevUpdateRate = 0; //由服务器返回的能够更新的最短时间间隔
    IntPtr hClientGroup = IntPtr.Zero; //客户组
    IntPtr pTimeBias = IntPtr.Zero;
    IntPtr pDeadband = IntPtr.Zero;
    IntPtr pLCID = IntPtr.Zero; 

    // 激活或者取消激活组
    int nActive = 0; 
    GCHandle hActive = GCHandle.Alloc(nActive,GCHandleType.Pinned);
    if(toActive)
    hActive.Target = 1;
    else
    hActive.Target = 0;
    try 
    {
    groupStateMgt.SetState(pRequestedUpdateRate,out nRevUpdateRate,hActive.AddrOfPinnedObject(),pTimeBias,pDeadband,pLCID,hClientGroup); 
    }
    catch(System.Exception err)
    {
    error="错误信息:"+err.Message;success=false;
    }
    finally
    {
    hActive.Free(); 
    }
    return success;
    }

    7、 向指定的组中添加变量的函数
    ///
    /// 向指定的组添加一系列项
    /// 
    /// 指定组名
    /// 完整的item名数组
    /// 由服务器返回读写数据时需要使用的item号
    /// 无错误,返回true,否则返回false
    public bool AddItems(string groupName,string[] itemsName,int[] itemsID)
    {
    bool success=true;
    OPCITEMDEF[] ItemDefArray=new OPCITEMDEF[itemsName.Length];
    for(int i=0;i {
    hClientItem=hClientItem+1; //客户项自动加1
    ItemDefArray[i].szAccessPath = ""; // 可选的通道路径,对于Simatiic Net不需要。
    ItemDefArray[i].szItemID = itemsName[i]; // ItemID, see above
    ItemDefArray[i].bActive = 1; // item is active
    ItemDefArray[i].hClient = hClientItem; // client handle ,在OnDataChange中会用到
    ItemDefArray[i].dwBlobSize = 0; // blob size
    ItemDefArray[i].pBlob = IntPtr.Zero; // pointer to blob 
    ItemDefArray[i].vtRequestedDataType = 4; //DWord数据类型
    }
    //初始化输出参数
    IntPtr pResults = IntPtr.Zero;
    IntPtr pErrors = IntPtr.Zero;
    try 
    {
    // 添加项到组
    object grp=((groupStru)hashGroup[groupName]).groupObj;
    ((IOPCItemMgt)grp).AddItems(itemsName.Length,ItemDefArray,out pResults,out pErrors);

    int[] errors = new int[itemsName.Length]; 
    IntPtr pos = pResults;
    Marshal.Copy(pErrors, errors, 0,itemsName.Length);
    for(int i=0;i {
    if (errors[i] == 0)
    {
    OPCITEMRESULT result = (OPCITEMRESULT)Marshal.PtrToStructure(pos, typeof(OPCITEMRESULT));
    itemsID[i] = result.hServer; 
    pos = new IntPtr(pos.ToInt32() + Marshal.SizeOf(typeof(OPCITEMRESULT)));
    }
    else
    {
    String pstrError;
    pIOPCServer.GetErrorString(errors[0],0x407,out pstrError); 
    success=false;
    break;
    }
    }
    SetItenClient(groupName,itemsID,itemsID); //要求始终只有一个组被激活,才不会引起冲突。
    }
    catch (System.Exception err) // catch for error in adding items.
    {
    success=false;
    //error="错误信息:"+error+err.Message;
    }
    finally
    {
    // 释放非托管内存
    if(pResults != IntPtr.Zero)
    {
    Marshal.FreeCoTaskMem(pResults);
    pResults = IntPtr.Zero;
    }
    if(pErrors != IntPtr.Zero)
    {
    Marshal.FreeCoTaskMem(pErrors);
    pErrors = IntPtr.Zero; 
    }
    }
    return success;
    }

    定货号 注释
    6EP1331-1SH02 单相220VAC输入,输出24VDC        1.3A
    6EP1331-2BA00 单相220VAC输入,输出24VDC        2A
    6EP1332-2BA00 单相220VAC输入,输出24VDC        3.8A
    6EP1332-2BA10 单相120/220VAC输入,输出24VDC    2.5A
    6EP1333-2AA00 单相220VAC输入,输出24VDC  5A  工业可并联
    6EP1333-2AA01 单相120/230VAC输入,输出24VDC  5A    工业可并联
    6EP1333-2BA00 单相120VAC/220VAC输入,输出24VDC 5A
    6EP1333-2BA01 单相120VAC/220VAC输入,输出24VDC 5A
    6EP1333-3BA00 单相120VAC/220to500VAC输入,输出24VDC 5A
    6EP1334-2AA00 单相220VAC输入,输出24VDC        10A    工业可并联
    6EP1334-2AA01 单相120/220VAC输入,输出24VDC    10A    工业可并联
    6EP1334-2BA00 单相220VAC输入,输出24VDC        10A
    6EP1334-2BA01 单相220VAC输入,输出24VDC        10A
    6EP1334-3BA00 单相120/220VACto500VAC输入,输出24VDC        10A
    6EP1336-2BA00 单相220VAC输入,输出24VDC        20A
    6EP1336-3BA00 单相220VAC输入,输出24VDC        20A     工业可并联
    6EP1337-3BA00 单相120/230,40A
    6EP1434-2BA00 三相380VAC输入,输出24VDC        10A      工业可并联
    6EP1436-2BA00 三相380VAC输入,输出24VDC        20A      工业可并联
    6EP1332-2BA20 三相380VAC输入,输出24VDC        20A      新型模块式电源
    6EP1332-2BA30 三相380VAC输入,输出24VDC        30A      工业可并联
    6EP1333-2AA02 三相380VAC输入,输出24VDC        40A      工业可并联
    6EP1333-2AA03 三相380VAC输入,输出24VDC        40A      工业可并联
    6EP1252-0AA00 单相230VAC输入,输出41.5V/1.3A
    6EP1252-0AA01 单相230VAC输入,输出41.5V/2A
    6EP1457-3BA00 三相380VAC输入,输出48VDC        20A      工业可并联
    SIYOUNG 电源
    6EP0123-2AA00-0AA0 单相230VAC输入,输出24VDC        2.5A
    6EP0123-2AA00-0AB0 单相230VAC输入,输出24VDC        4A
    6EP0123-3AA00-0AB0 单相230VAC输入,输出24VDC        6A
    6EP0123-4AA00-0AB0 单相230VAC输入,输出24VDC        12A
    SITOP facets
    6EP1331-2BA10 单相120/230VAC输入,输出24VDC        0.5A
    6EP1333-1AL12 单相120/230VAC输入,输出24VDC        5A
    6EP1334-1AL12 单相120/230VAC输入,输出24VDC        10A
    6ES7307-1EA80-0AA0 单相120/230VAC输入,输出24VDC        10A
    6EP1353-2BA00 单相120/230VAC输入,输出24VDC            设定范围3~52DC                      10A
    LOGO! Power 微型电源组
    6EP1332-1SH42 单相220VAC输入,输出24VDC        2.5A
    6EP1332-1SH51 单相220VAC输入,输出24VDC        4A
    SITOP 附加设备
    6EP1961-3BA10 信号模块,输入范围240VAC/6A,只能和模块式SITOP电源共用
    6EP1961-3BA00 缓冲模块,输入24VDC,输出电流40A,可并联,只能和模块式SITOP电源共用
    6EP1961-3BA20 冗余模块,输入24VDC,输出电流40A
    6EP1961-2BA00 诊断模块,输入24VDC,输出电流4*10A

来源:上海赞国
免责声明:地方电气网转载作品均注明出处,本网未注明出处和转载的,是出于传递更多信息之目的,并不意味 着赞同其观点或证实其内容的真实性。如转载作品侵犯作者署名权,或有其他诸如版权、肖像权、知识产权等方面的伤害,并非本网故意为之,在接到相关权利人通知后将立即加以更正。联系电话:0571-87774297。
0571-87774297