技术论坛

PORTAL编程题,可能与指针和间接寻址有关

作者 主题
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
主题:【求助】PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 楼主 2018-07-02 08:47:59

portal V15里面编程, 被一个逻辑难倒了。 

我尽量简化, 抽象了一下,简化为一道题目:

假设有10个按钮,(DI地址不连续), 8个指示灯(DO地址也不连续)

现在有逻辑功能,简化为按下1个按钮时, 1个指示灯延时2秒l亮起。 (这是一个封装好的FB块,将来还可以无穷变化, 无穷复杂, 所以不要打改造它的主意)

同时运行的逻辑功能有2套。 所以很容易为其编织一个FB块,系统中调用2次。 


但问题是, 按下哪个按钮,不是确定的, 对应到哪个灯亮, 也不是确定的。 

而是需要在程序的运行中, 比如给两次调用实例, 分别输入参数8:5和4:3.

则当DI8按下时,DO5延时2S亮起。.

DI4按下时, DO3延时2S亮起。 

同一时刻, 另外的其它的DI/DO待命,空闲不用。 


我想象的是,分别建立数组A[10]和B[8], 程序中根据指令的i数值, 把对应的元素A[i]放入到FB的实参, 但高级语言很容易实现的事情, 在PLC里面怎么感觉困难重重, 没有头绪呢?


当然, 我要做的逻辑比这还复杂n倍, 这里只是抽象化表述。 即便实现后, 也还有更复杂的需求冒出。 

*******************************************

看来, 我不做个引子, 只讲题目不行, 都不愿意动手, 只乐意爱那儿夸夸其谈讲愿理去了。

来吧,我打了个程序底子:

8543_V15_1.zip


V13SP1:

8543v13.zip

 


微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  
重要声明:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

帖子链接:http://www.ad.siemens.com.cn/club/bbs/post.aspx?a_id=1492712&b_id=66&s_id=84&num=36

奇侠

经验值: 7384
发帖数: 1269
精华帖: 3
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 1楼 2018-07-02 09:00:14

di和do怎么对应   10对应8????还是有什么条件限制  ,你描述的比较抽象


新手到来 多多指教
以下网友喜欢您的帖子:

  
lzm
奇侠

经验值: 6822
发帖数: 1180
精华帖: 7
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 2楼 2018-07-02 09:25:17

类似“柔性化”控制,事先不知采用哪种控制,根据每个新到的控制要求,挑选适合的控制程序,再调用应用。


Querer es poder! 修福粒米藏日月 持慧毫芒有乾坤
以下网友喜欢您的帖子:

  
至圣

经验值: 80521
发帖数: 17619
精华帖: 603
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 3楼 2018-07-02 10:37:21

单独写个变换 FC不行么?

一旦使用数组,实际上就“指针化”了。


我通常对于 DI/DQ都是在变量表里面逐个定义(EXCEL导入导出)。

编程不涉及具体的DI/DQ。因为编程用的都是符号标签。

需要修改时,只改动变量表标签的具体DI/DQ地址。程序不变。


 
以下网友喜欢您的帖子:

  
H.L
侠圣

经验值: 2883
发帖数: 1776
精华帖: 9
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 4楼 2018-07-02 12:11:16
用2个队列可不可以
 
以下网友喜欢您的帖子:

  
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 楼主 6楼 2018-07-02 14:36:53
以下是引用易思特在2018-07-02 13:18:30的发言 >5楼

这有何难,两个表或者其它数据结构,保存人机接口IO域中指针定义表达式“A:B”中的两个指针值,一个装A,一个装B,这是作为两个接口参数的情况,也可使用一个接口参数形式,需要额外解析。

另建两个DB作数据缓存,将无序的DI一一映射到有序的DB1位元素,再将有序的DB2位元素一一映射到无序的DO。

例:输入处理

DI10-->DB1.ARRAY_DI.0

DI2-->DB1.ARRAY_DI.1

...

DI1-->DB1.ARRAY_DI.9

例:输出处理

与输入处理反向;


输入与输出间的控制逻辑最终抽象简化等效为

DB2.ARRAY_DO[B-1] := (DB1.ARRAY_DI[A-1] & Time_Delay)


用SCL描述此算法过程,应该不难理解。

也另有别法,难度属于幼儿园入园级小班水平,余不赘叙。


您这是相当于把我出的题目, 又口头复述了一遍。 

然并卵。


来真的, 做一下。 V15。


做的都有精华帖可得。 




微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  
至圣

经验值: 31113
发帖数: 4234
精华帖: 33
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 7楼 2018-07-02 18:00:15
以下是引用万泉河在2018-07-02 14:36:53的发言 >6楼

您这是相当于把我出的题目, 又口头复述了一遍。 

然并卵。


来真的, 做一下。 V15。


做的都有精华帖可得。 



以下是引用易思特在2018-07-02 13:18:30的发言 >5楼:这有何难,两个表或...

引用5楼详细内容:

这有何难,两个表或者其它数据结构,保存人机接口IO域中指针定义表达式“A:B”中的两个指针值,一个装A,一个装B,这是作为两个接口参数的情况,也可使用一个接口参数形式,需要额外解析。

另建两个DB作数据缓存,将无序的DI一一映射到有序的DB1位元素,再将有序的DB2位元素一一映射到无序的DO。

例:输入处理

DI10-->DB1.ARRAY_DI.0

DI2-->DB1.ARRAY_DI.1

...

DI1-->DB1.ARRAY_DI.9

例:输出处理

与输入处理反向;


输入与输出间的控制逻辑最终抽象简化等效为

DB2.ARRAY_DO[B-1] := (DB1.ARRAY_DI[A-1] & Time_Delay)


用SCL描述此算法过程,应该不难理解。

也另有别法,难度属于幼儿园入园级小班水平,余不赘叙。


万版!

V14SP1的程序有没有?必须要V15来做?V15还没有安装


工业起重机防摇摆 QQ:404136820 AntiSwayControl
以下网友喜欢您的帖子:

  
至圣

经验值: 80521
发帖数: 17619
精华帖: 603
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 8楼 2018-07-02 19:07:04

估计没戏。

万版想要个关联数据表。博图目前做不到。


 
以下网友喜欢您的帖子:

  
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 楼主 9楼 2018-07-02 19:41:40
以下是引用威师爷在2018-07-02 18:00:15的发言 >7楼

万版!

V14SP1的程序有没有?必须要V15来做?V15还没有安装

以下是引用万泉河在2018-07-02 14:36:53的发言 >6楼:您这是相当于把我出...

引用6楼详细内容:

您这是相当于把我出的题目, 又口头复述了一遍。 

然并卵。


来真的, 做一下。 V15。


做的都有精华帖可得。 



以下是引用易思特在2018-07-02 13:18:30的发言 >5楼:这有何难,两个表或...

引用5楼详细内容:

这有何难,两个表或者其它数据结构,保存人机接口IO域中指针定义表达式“A:B”中的两个指针值,一个装A,一个装B,这是作为两个接口参数的情况,也可使用一个接口参数形式,需要额外解析。

另建两个DB作数据缓存,将无序的DI一一映射到有序的DB1位元素,再将有序的DB2位元素一一映射到无序的DO。

例:输入处理

DI10-->DB1.ARRAY_DI.0

DI2-->DB1.ARRAY_DI.1

...

DI1-->DB1.ARRAY_DI.9

例:输出处理

与输入处理反向;


输入与输出间的控制逻辑最终抽象简化等效为

DB2.ARRAY_DO[B-1] := (DB1.ARRAY_DI[A-1] & Time_Delay)


用SCL描述此算法过程,应该不难理解。

也另有别法,难度属于幼儿园入园级小班水平,余不赘叙。


其实很简单, 一个FB, 一个FC而已。 

我打印出来了。 

8543.zip


几分钟内就可以搞定的。 


为什么用V15? 因为后续的功能, 只有V15可以。 而以下的版本根本不行。 


微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  
至圣

经验值: 31113
发帖数: 4234
精华帖: 33
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 11楼 2018-07-02 20:23:41
以下是引用易思特在2018-07-02 13:18:30的发言 >5楼

这有何难,两个表或者其它数据结构,保存人机接口IO域中指针定义表达式“A:B”中的两个指针值,一个装A,一个装B,这是作为两个接口参数的情况,也可使用一个接口参数形式,需要额外解析。

另建两个DB作数据缓存,将无序的DI一一映射到有序的DB1位元素,再将有序的DB2位元素一一映射到无序的DO。

例:输入处理

DI10-->DB1.ARRAY_DI.0

DI2-->DB1.ARRAY_DI.1

...

DI1-->DB1.ARRAY_DI.9

例:输出处理

与输入处理反向;


输入与输出间的控制逻辑最终抽象简化等效为

DB2.ARRAY_DO[B-1] := (DB1.ARRAY_DI[A-1] & Time_Delay)


用SCL描述此算法过程,应该不难理解。

也另有别法,难度属于幼儿园入园级小班水平,余不赘叙。


好像你认为比较容易?能否把程序捣鼓一下发上来让我见识见识?



工业起重机防摇摆 QQ:404136820 AntiSwayControl
以下网友喜欢您的帖子:

  
至圣

经验值: 31113
发帖数: 4234
精华帖: 33
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 12楼 2018-07-02 20:33:18


万版的意思是要把程序做到灵活应用,编程时不要关注太多东西,在使用时根据定义模板灵活的改变IO地址来满足组态应用,我想很多时候每个项目的IO地址范围都可能不同,有长有短,例如项目A的DI模块地址是I0.0-I3.7 项目B的地址是I6.0-I9.7这样如果是使用指针来定义地址的只需要细微修改地址指针(可以通过HMI来修改)就可以满足项目的兼容应用,如果是绝对寻址就导致工作量比较大了,指针:可以通过灵活应用在程序运行的过程中改变地址。

在TIA现在提倡符号寻址,的确想不到什么好的灵活的方法。特别是1200直接不支持STL了,也不建议使用指针了,这个题目出的比较好,期待各位大神的方案!!!!!


工业起重机防摇摆 QQ:404136820 AntiSwayControl
以下网友喜欢您的帖子:

  
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖


只看楼主 只看精编 楼主 14楼 2018-07-02 21:36:01
以下是引用易思特在2018-07-02 20:23:25的发言 >10楼

array mapping.zip

TIA V14 SP1版本,仅包含数组映射功能,定时功能未加入,有需要计时的请自行编辑修改,其中“8:5”假设由用户在UI上的IO域编辑给定,此给定完全可以设计成一系列序列值,由程序实现自行切换。

表示看不懂你在做什么。 

为什么假设了2S的延时呢?

是假设这里有逻辑关系, 现在举例是延时, 而在实际应用中, 会有更复杂的逻辑关系。 但总的来说,可以封装在一个FB块里面,固定好。 

最终只是接口部分参数化。 


而你把定时都给省了, 那程序还有什么意义呢?


FB1:


固定调用的时候,FC1:

然后现在的目标就是把上面的固定调用改为动态调用, 两次。 


别在我的FB1上动心思, 就只在两次调用中, 用参数方式实现。 


微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  
版主

经验值: 11336
发帖数: 1614
精华帖: 36
回复:PORTAL编程题,可能与指针和间接寻址有关


只看楼主 只看精编 22楼 2018-07-03 08:12:08

还需要指针吗?不需要!


人生就像一场旅行!
以下网友喜欢您的帖子:

  
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖


只看楼主 只看精编 楼主 23楼 2018-07-03 08:59:44
以下是引用易思特在2018-07-02 22:33:32的发言 >21楼

使用了两个DB,DI和DO就是为了降低难度,给上层的ArrayMapping提供方便。

围绕FB1做两次调用, 一次实现8:5, 一次实现4:3.

两次调用都要求是动态调用。 


你一个都不要省略, 就能证明你做的有意义。 



微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  

经验值: 150
发帖数: 21
精华帖: 0
回复:PORTAL编程题,可能与指针和间接寻址有关


只看楼主 只看精编 25楼 2018-07-03 10:50:39
以下是引用易思特在2018-07-02 20:23:25的发言 >10楼

array mapping.zip

TIA V14 SP1版本,仅包含数组映射功能,定时功能未加入,有需要计时的请自行编辑修改,其中“8:5”假设由用户在UI上的IO域编辑给定,此给定完全可以设计成一系列序列值,由程序实现自行切换。


请精华帖版主把精华取消了吧,咱原本就不是冲着精华来的。

再说了,精华不是别人施舍“给”的,而是自己挣的。

也没有动什么脑子,前后不到十分钟的时间,举手之劳,奉送了。

精华不精华的,对咱来说,都是浮云

咱也长了个记性,以后再也不趟这样的浑水了。


你丫挺的,老子跟你死磕到底!
以下网友喜欢您的帖子:

  
侠士

经验值: 1636
发帖数: 43
精华帖: 0
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖


只看楼主 只看精编 26楼 2018-07-03 12:41:42
我可以认为这是个寻址问题吗?博途里面有好几种寻址方法的,什么peek.Poke,记不清了
我的奥利奥,只有我来泡
以下网友喜欢您的帖子:

  
版主

经验值: 11336
发帖数: 1614
精华帖: 36
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖 精编帖 推荐帖


只看楼主 只看精编 27楼 2018-07-03 13:30:51

也做了一个 基本算法和易思特 相同,尽量不使用间接寻址,使用索引寻址。
1500 的数据存储比较大,所以这程序 ,做的比较浪费数据存储;

上位机 通过 字符串数组strParameter 中的输入参数 "XX:Y"来确定 DI/DO的匹配关系,FB程序最多同时可以执行8路DI/DO匹配的过程,通过参数ParNoOfInstance设定 ,默认值是2.

至于 细节方面没有 做很多 就是根据DI和参数"XX:Y"来匹配 相应的输出;

感觉主要精力花在了 参数解析上面。。。。。。。。

UDT 类容


FB 参数区


FB代码

   


 

If #Data.ParNoOfInstance > #MaxInstance Then

    Return;

End_If;


For #Data.LoopIndex := 1 To #Data.ParNoOfInstance Do

   

    Region Decode Input String 

    (*

    Decode the Input And output index from input string like "xx:y"

    *)

        

        #inpStringLen := LEN(#strParameter[#Data.LoopIndex]);

        If #inpStringLen = 0 Then

            #Data.OutNoParameter[#Data.LoopIndex] := TRUE;

           Goto Nxt;

        Else

            #Data.OutNoParameter[#Data.LoopIndex] := FALSE;

        End_If;

        #Data.SplictReturnPostion := FIND(IN1 := #strParameter[#Data.LoopIndex] , IN2 := #SplitCharactor);

        If #Data.SplictReturnPostion = 0 Then

            #Data.OutParameterFormatError[#Data.LoopIndex]  := True;

            Goto Nxt;

        Else

            #Data.OutParameterFormatError[#Data.LoopIndex]  := False;

        End_If;

        

        

        #Data.InputIndex := STRING_TO_INT(LEFT(IN := #strParameter[#Data.LoopIndex] , L := #Data.SplictReturnPostion - 1));

        #Data.OutputIndex := STRING_TO_INT(RIGHT(IN := #strParameter[#Data.LoopIndex] , L := LEN(#strParameter[#Data.LoopIndex] )

                                                     - #Data.SplictReturnPostion));

        

        #Data.OutInputParOutofRange[#Data.LoopIndex]  := #Data.InputIndex > #MaxInput Or #Data.InputIndex <= 0;

        #Data.OutOutputParOutofRange[#Data.LoopIndex]  := #Data.OutputIndex > #MaxOutput Or #Data.OutputIndex <= 0;

        If #Data.OutInputParOutofRange[#Data.LoopIndex]  Or #Data.OutOutputParOutofRange[#Data.LoopIndex]  Then

            #Data.OutParameterOutOfRange[#Data.LoopIndex]  := TRUE;

            Goto Nxt;

        Else

            #Data.OutParameterOutOfRange[#Data.LoopIndex]  := FALSE;

        End_If;

    End_Region

    

    Region Wait for Commond

        #Data.DelayTimer[#Data.LoopIndex](IN := #Data.Input[#Data.InputIndex],

                            PT := #Data.ParDelayTime);

        If Not #Data.Input[#Data.InputIndex] Then

            ;//Correspond input not receieved ,TODO

        ElsIf #Data.Output[#Data.OutputIndex] Then

            ;//The Corresponding output already set,TODO

            

        End_If;

        

        If #Data.DelayTimer[#Data.LoopIndex] .Q Then

            #Data.Output[#Data.OutputIndex] := TRUE;

            #Data.Input[#Data.InputIndex] := FALSE;

        End_If;

    End_Region

   Nxt:;

End_For;


IO缓存DB


 OB1 代码


(*

Copy IO to I/O buffer DB

*)

If "DI_1" Then

    "DB_IO_Buffer".InputBuffer[1] := "DI_1";

End_If;

If "DI_2" Then

    "DB_IO_Buffer".InputBuffer[2] := "DI_2";

End_If;

If "DI_3" Then

    "DB_IO_Buffer".InputBuffer[3] := "DI_3";

End_If;

If "DI_4" Then

    "DB_IO_Buffer".InputBuffer[4] := "DI_4";

End_If;

If "DI_5" Then

    "DB_IO_Buffer".InputBuffer[5] := "DI_5";

End_If;

If "DI_6" Then

    "DB_IO_Buffer".InputBuffer[6] := "DI_6";

End_If;

If "DI_7" Then

    "DB_IO_Buffer".InputBuffer[7] := "DI_7";

End_If;

If "DI_8" Then

    "DB_IO_Buffer".InputBuffer[8] := "DI_8";

End_If;

If "DI_9" Then

    "DB_IO_Buffer".InputBuffer[9] := "DI_9";

End_If;

If "DI_10" Then

    "DB_IO_Buffer".InputBuffer[10] := "DI_10";

End_If;


(*

Call the Program


"Test_DB".Data.ParNoOfInstance should be set ,the default is 2,Max value is 8;

*)

"Test_DB".Data.Input := "DB_IO_Buffer".InputBuffer;


"Test_DB"();


"DB_IO_Buffer".OutputBuffer := "Test_DB".Data.Output;


(*

Copy IO to I/O buffer DB

*)

"DO_1" := "DB_IO_Buffer".OutputBuffer[1];

"DO_2" := "DB_IO_Buffer".OutputBuffer[2];

"DO_3" := "DB_IO_Buffer".OutputBuffer[3];

"DO_4" := "DB_IO_Buffer".OutputBuffer[4];

"DO_5" := "DB_IO_Buffer".OutputBuffer[5];

"DO_6" := "DB_IO_Buffer".OutputBuffer[6];

"DO_7" := "DB_IO_Buffer".OutputBuffer[7];

"DO_8" := "DB_IO_Buffer".OutputBuffer[8];


项目工程

Test.rar



人生就像一场旅行!
推荐帖推荐理由: 不吝分享,这种做法就值得敬仰! 先收藏了慢慢学习! (推荐人:澹澹)
以下网友喜欢您的帖子:

  
侠士

经验值: 1273
发帖数: 86
精华帖: 0
回复:PORTAL编程题,可能与指针和间接寻址有关
推荐帖


只看楼主 只看精编 28楼 2018-07-03 13:39:21

不知道理解的对不对,觉得很简单






以下网友喜欢您的帖子:

  
至圣

经验值: 22426
发帖数: 10002
精华帖: 118
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖


只看楼主 只看精编 楼主 29楼 2018-07-03 15:07:31
以下是引用易思特在2018-07-03 10:50:39的发言 >


请精华帖版主把精华取消了吧,咱原本就不是冲着精华来的。

再说了,精华不是别人施舍“给”的,而是自己挣的。

也没有动什么脑子,前后不到十分钟的时间,举手之劳,奉送了。

精华不精华的,对咱来说,都是浮云

咱也长了个记性,以后再也不趟这样的浑水了。

不用间接寻址, 那做了还有什么意义?

本意是编程的时候不做枚举,你们倒好, 倒在外围给做了详尽的枚举。 


正式应用中, 一个设备的功能块, 当然不可能只有一个DI,一个DO。 

比方说有5个INPUT, 3个OUTPUT。

你们这种思路再如何扩展?




微信公众号:万泉河知识分享
以下网友喜欢您的帖子:

  
至圣

经验值: 80521
发帖数: 17619
精华帖: 603
回复:PORTAL编程题,可能与指针和间接寻址有关
精编帖 推荐帖


只看楼主 只看精编 30楼 2018-07-03 18:52:37

@Letham 似乎是可以呢。

楼主想做成封装、不再改动的。

是不是可以做到 Byte ,Word,Dword,Lword送入Input、送出Output、映射关系通过一个字串DB数组"XX:YY"送入这个FC?

(嘿嘿,不用字符串,博图是没戏,对吧?)

FC内部接口使用Variant 自动辨识 Byte ,Word,Dword,Lword 数据类型。适应不同长度的IO区段。

我没有V15



 
以下网友喜欢您的帖子:

  
  • 上一页
  • 1
  • 下一页
×
扫描打开手机版
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。