ronkang
倍加福总线
级别: 略有小成
精华主题: 0
发帖数量: 147 个
工控威望: 348 点
下载积分: 914 分
在线时间: 185(小时)
注册时间: 2008-06-24
最后登录: 2024-05-07
查看ronkang的 主题 / 回贴
楼主  发表于: 2021-01-13 13:31
SR20带7台G120XA变频器,走USS通讯,一个子程序中使用7个USS_CTRL指令读写变频器。另一个子程序中使用7个USS_RPM_R指令轮训读取7台变频器电流,现在问题是:
1.两个子程序都在主程序中调用时,USS_RPM_R没有任何错误,但是USS_CTRL平均15秒就会报错,错误代码2。2这个代码不知什么原因引起。
2.主程序中只调用USS_CTRL这个子程序时,7个USS_CTRL指令无任何错误。
请专家指点一下,USS_RPM_R是轮询顺序执行的,应该没有问题,会不会是和USS_CTRL指令冲突了?问题到底出在哪里?有什么解决办法,麻烦大家了
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
1楼  发表于: 2021-01-13 16:08
你这明显要分时中断
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
2楼  发表于: 2021-01-14 15:21
你一个循环周期很容易出现uss_ctrl 和Uss_RPM_R 时间间隔不够,这样就被挂起报错
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
3楼  发表于: 2021-01-14 15:31
IF iAdrOfInsulation =0 THEN
    iAdrOfInsulation :=91;
END_IF
IF bSensorCorrectionHMI THEN
    eCommandNum := 5;
END_IF
IF bParamAlterHMI THEN
    eCommandNum := 7;
END_IF

CASE eCommandNum OF(*SystemTotalData :=1,SubcircuitAnodeToGlobeResistance,ProductParamRead,SubcircuitCathodeToGlobeResistance,SensorCorrection,AddrAlter,ParamAlter*)
SystemTotalData:
    wMBAdr := 16#0320;
    iLen    := 7;
    bReadEnable := TRUE;
    bWriteEnable :=FALSE;
SubcircuitAnodeToGlobeResistance:
    wMBAdr := 16#03E8;
    iLen    := iSubTotal;
    bReadEnable := TRUE;
    bWriteEnable :=FALSE;
ProductParamRead:
    wMBAdr := 16#0510;
    iLen    := 5;
    bReadEnable := TRUE;
    bWriteEnable :=FALSE;
SubcircuitCathodeToGlobeResistance:
    wMBAdr := 16#04B0;
    iLen    := iSubTotal;
    bReadEnable := TRUE;
    bWriteEnable :=FALSE;
SensorCorrection:
    wMBAdr := 16#680;
    wWriteDate    := 16#7;
    bReadEnable := FALSE;
    bWriteEnable :=TRUE;
AddrAlter:
    bReadEnable := FALSE;
    bWriteEnable :=TRUE;
    wMBAdr := 16#1218;
    IF iWantedAdr <>0 THEN
        wWriteDate    := UINT_TO_WORD(iWantedAdr);
    ELSE
        wWriteDate    := 16#5B;
    END_IF
ParamAlter:
    bReadEnable := FALSE;
    bWriteEnable :=TRUE;
    IF bSubcircuitCAlterHMI THEN
        wMBAdr := 16#71A;
        wWriteDate    := UINT_TO_WORD(iWantedSubcircuitAmount);
    END_IF
    IF bAlarmLimitSetHMI THEN
        wMBAdr := 16#71C;
        wWriteDate    := UINT_TO_WORD(iWantedResistanceLimit);
    END_IF
    IF bResistanceCheckRangeSetHMI THEN
        wMBAdr := 16#71E;
        wWriteDate    := UINT_TO_WORD(iWantedResistanceCheckRange);
    END_IF
END_CASE


IF NOT bAlter THEN
    CASE iState OF
    0:    fbMBCom.ReadRegs(Execute := FALSE);
        istate := istate +1;
    1:

        fbMBCom.ReadRegs(
        UnitID := UINT_TO_BYTE(iAdrOfInsulation), (* 站点地址 *)
        Quantity := iLEN,
        MBAddr := wMBAdr,
        CbLength := iLEN*2,
        pMemoryAddr:= ADR(wMemoryDate[1]),
        Execute := TRUE AND bReadEnable ,
        Timeout := t#5s,
        Busy => );
        IF NOT fbMBCom.BUSY THEN
            fbMBCom.ReadRegs(Execute := FALSE);
            IF fbMBCom.Error THEN
                iState :=0;
            ELSE
                istate := istate +1;
            END_IF
        END_IF
    2:
        CASE eCommandNum OF
            1:
                FOR i :=1 TO 7 DO
                    IF i=3 OR i=4 THEN
                    iSysTotalDate := WORD_TO_UINT(wMemoryDate AND 16#3FFF);
                    ELSE
                    iSysTotalDate := WORD_TO_UINT(wMemoryDate);
                    END_IF
                END_FOR
                iSubTotal := iSysTotalDate[2];
                IF wMemoryDate[3].14 THEN
                    bErrList[1] := TRUE;
                ELSE
                    bErrList[1] := FALSE;
                END_IF
                IF wMemoryDate[4].14 THEN
                    bErrList[2] := TRUE;
                ELSE
                    bErrList[2] := FALSE;
                END_IF
            2:
                FOR i :=1 TO 5 DO
                    iProductParam := WORD_TO_INT(wMemoryDate);
                END_FOR
            3:
                FOR i :=1 TO iSubTotal DO
                    iSubP_EarthR := WORD_TO_INT(wMemoryDate AND 16#3FFF);
                    IF wMemoryDate.15 THEN
                        bErrList[2+i] := TRUE;
                    ELSE
                        bErrList[2+i] := TRUE;
                    END_IF
                    IF wMemoryDate.14 THEN
                        bErrList[2+iSubTotal+i] := TRUE;
                    ELSE
                        bErrList[2+iSubTotal+i] := TRUE;
                    END_IF
                END_FOR
            4:
                FOR i :=1 TO iSubTotal DO
                    iSubN_EarthR := WORD_TO_INT(wMemoryDate AND 16#3FFF);
                    IF wMemoryDate.15 THEN
                        bErrList[2+2*iSubTotal+i] := TRUE;
                    ELSE
                        bErrList[2+2*iSubTotal+i] := TRUE;
                    END_IF
                    IF wMemoryDate.14 THEN
                        bErrList[2+3*iSubTotal+i] := TRUE;
                    ELSE
                        bErrList[2+3*iSubTotal+i] := TRUE;
                    END_IF
                END_FOR
        END_CASE
        FOR i := 1 TO 64 DO
            wMemoryDate := 0;
        END_FOR
        istate :=0;
        eCommandNum := eCommandNum +1;
        IF eCommandNum >4 THEN
            eCommandNum :=1;
        END_IF
        bAlter := bStopHmi;(*参数修改ON*)
    END_CASE
ELSE
    CASE istate OF
    0:    fbMBCom.WriteSingleRegister(Execute := FALSE);
        istate := istate +1;
    1:
        fbMBCom.WriteSingleRegister(
            UnitID := UINT_TO_BYTE(iAdrOfInsulation),
            Quantity := 1,
            MBAddr := wMBAdr,
            CbLength := SIZEOF(wWriteDate),
            pMemoryAddr:= ADR(wWriteDate),
            Execute := TRUE AND bWriteEnable,
            Timeout := t#5000ms,
            Busy => );
        IF NOT fbMBCom.BUSY THEN
            fbMBCom.WriteSingleRegister(Execute := FALSE);
            IF fbMBCom.Error THEN
                istate := 0;
            ELSE
                istate :=istate +1;
            END_IF
        END_IF
    2:
        CASE eCommandNum OF
            5:;
            6:
                IF iWantedAdr = BYTE_TO_UINT(fbMBCom.InData.D[4]) THEN
                    iAdrOfInsulation := iWantedAdr;
                END_IF
            7:;
        END_CASE
        bWriteEnable :=FALSE;
        eCommandNum :=1;
        iState :=0;
        bAlter := bStopHmi;(*参数修改OFF*)
    END_CASE
END_IF
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
4楼  发表于: 2021-01-14 15:35
通讯没你想的那么简单,对时间有要求,你的轮询读没问题是每一步都分开了在做,并且,即使你的通讯对象只有一个,也会出现同样的情况,你这存在2中通讯操作就必须在进行另一种的时候中断一种,我的程序是用codesys写的,2种模式切换,但不能同时进行,实际上切换过程时间很短,在确认发出和收到回信再切回去
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
5楼  发表于: 2021-01-15 08:30
引用
引用第7楼ronkang于2021-01-14 19:08发表的  :
楼上兄弟,USS通讯没你说的这么复杂吧。西门子手册也没你说的要中断一个通讯才能启用另一个通讯。只说了USS读写指令同一时刻只能使用一个。

    你对通讯认识还不够,因为你2个指令都是存在询问帧,因此他就像modbus的控制字一样,需要逐条发送,它又不能像CAN那样打包发送,空闲接收。
你这种情况就算同时发送那也只是直接下条覆盖上条,主要还是时间间隔不够,例如:modbus帧间隔是3.5个字符,在一条发送完没间隔完就直接下一条,那么2条会串在一块形成合并帧;
这种帧99.99%的概率是不合法,无法被响应,因为校验通不过。
    另外,你的设备越多数据量越大,你需要做的间隔就越长,波特率本身就是描述通讯速率的,可以计算得出你做程序该有的间隔。


PS: 上面的程序并不复杂,上面是modbus协议,也是读和写。codesys本身就是开放性的,你调用的是一整块功能,它调用可以切入内部调用函数。即使像你那种调用也有时候会写得很复杂,你没用到而已。  比如: 你询问一个设备,设备回的状态可能使你不得不选择N种参数,我上面的就是,读写在上面的case中其实只出现了2次,其他都是数据处理
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
6楼  发表于: 2021-01-15 08:44
我说的中断是广义上的中断,和PLC外部中断不是一个概念,但和定时中断类似,就是你必须先知道与通讯的设备是否成功的完成了上一次,而不是只管发,到时收一堆报错,这种情况当年初学plc就是这样。
拿个最简单的电池SOC can2.0标准协议  只读报文来讲,plc不需要写数据帧,只管读,对象的报文分成4种帧,权重50ms 100ms 200ms 1s  ,一是长度不一样,二是重要程度不一样,那么这四种必须在确定其中一种发送完了才能发另一种,否则极可能出现1s间隔的不重要报文永远发不出去
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
7楼  发表于: 2021-01-17 09:41
程序是很简单,但到实际应用的时候有不确定性,通信原理都是一样,协议也只约定规则,这些规则无非就是限制
紧要
1. 数据帧的开始标志
2. 数据长度;
3. 结束标志;
4. 校验方式;
非紧要,在前面4个重点正确的情况下,后面的一般不会有错
5. 故障码;
6. 最大长度

你的问题可能原因
1.  发送缓存区因相近间隔时间进入过多的数据量,导致发送长度不支持,发送失败;
2.  没有检测握手标志(发送完成标志,接收完成标志),每个通讯功能块都有一个Done 位(双工只注意单个done),新手靠拉长收发时间,中手看标志,老手看综合状态;像485线,你发一帧数据,必须等收到信息完成,或者确实超时才能发下一次询问;
检测的方法最直接是用串口调试工具去监测收发数据的实际状态,这样才能判断错出在哪了,有时候你的数据没问题,而通讯的对方可能有问题,比如,你CPU运行速度1ms周期,而对方在处理不同数据时响应时间不一样,以前测试过一款微型伺服,询问状态响应2ms,控制指令响应时间很长,读数组状态的时候响应时间也很长,所有经常被程序认为是发送超时
写程序前先了解被通讯对象的素质也很重要,先用串口工具测试各种你要用到指令,然后加快收发速度,去测试响应极限,别一上去就干到极限,然后闷逼不知道怎么解决。当确实遇到了问题,那么再回过同用通讯工具采样你发和它发的状态找原因
zhou1211
级别: 略有小成
精华主题: 1 篇
发帖数量: 203 个
工控威望: 359 点
下载积分: 1165 分
在线时间: 64(小时)
注册时间: 2013-11-04
最后登录: 2024-04-12
查看zhou1211的 主题 / 回贴
8楼  发表于: 2021-01-17 11:22
图片:
所以说你根本看不懂我那个程序,那个程序不复杂,里面数据判断占了大部分,真正收发指令只占了很小的一部分,你写一个通讯程序也是一样的,当然,电机控制用固定功能块做的,或者说你只需要固定控制方式,所以显得简单;
我程序里面包含了通讯参数的修改,首先是修改了通讯默认地址,再就是模仿modbus切换控制字写对象的参数,然后根据不同的控制模式解析对应数据
你做通讯感觉才入门,上图是对应实现的功能
大致就是通讯建立,先读出前排2组数据,那2组如果和实际设备有出入则通过下面的写操作修改掉,其余时间是在读取右边2列有效数据,这个设备没有修改软件,所以得做通讯程序去修改报警范围之类的参数,不是每一个给你的设备都会给你配一个参数修改软件,也不是每一个操作工都知道怎么去修改一个设备,尤其是第三方,那么你就必须在你的HMI上开放一个接口去方便修改
[ 此帖被zhou1211在2021-01-17 11:39重新编辑 ]