技术论坛

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

返回主题列表
作者 主题
万泉河
至圣

经验值:29190
发帖数:10900
精华帖:131
楼主    2018-07-02 08:47:59
主题:PORTAL编程题,可能与指针和间接寻址有关 精编帖 

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

 

微信公众号:PLC标准化编程,ZHO6371995
lzm
奇侠

经验值:9330
发帖数:1316
精华帖:8
2楼    2018-07-02 09:25:17
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

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

Querer es poder! 修福粒米藏日月 持慧毫芒有乾坤
yming
至圣

经验值:138360
发帖数:23136
精华帖:880
3楼    2018-07-02 10:37:21
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

单独写个变换 FC不行么?

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


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

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

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

学而时习之,不亦说乎?温故而知新,不亦乐乎?
万泉河
至圣

经验值:29190
发帖数:10900
精华帖:131
9楼    2018-07-02 19:41:40
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

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

我打印出来了。 

8543.zip


几分钟内就可以搞定的。 


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

微信公众号:PLC标准化编程,ZHO6371995
威师爷
至圣

经验值:37606
发帖数:5108
精华帖:47
12楼    2018-07-02 20:33:18
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关


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

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

工业起重机防摇摆 QQ:404136820 AntiSwayControl
万泉河
至圣

经验值:29190
发帖数:10900
精华帖:131
14楼    2018-07-02 21:36:01
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

表示看不懂你在做什么。 

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

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

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


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


FB1:


固定调用的时候,FC1:

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


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

微信公众号:PLC标准化编程,ZHO6371995
万泉河
至圣

经验值:29190
发帖数:10900
精华帖:131
23楼    2018-07-03 08:59:44
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

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

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


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


微信公众号:PLC标准化编程,ZHO6371995
*他山之石*
侠士

经验值:1666
发帖数:35
精华帖:0
26楼    2018-07-03 12:41:42
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关
我可以认为这是个寻址问题吗?博途里面有好几种寻址方法的,什么peek.Poke,记不清了
我的奥利奥,只有我来泡
Letham
至圣

经验值:14191
发帖数:2021
精华帖:43
27楼    2018-07-03 13:30:51
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

也做了一个 基本算法和易思特 相同,尽量不使用间接寻址,使用索引寻址。
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


人生就像一场旅行!
万泉河
至圣

经验值:29190
发帖数:10900
精华帖:131
29楼    2018-07-03 15:07:31
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

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

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


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

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

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



微信公众号:PLC标准化编程,ZHO6371995
yming
至圣

经验值:138360
发帖数:23136
精华帖:880
30楼    2018-07-03 18:52:37
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

@Letham 似乎是可以呢。

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

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

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

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

我没有V15


学而时习之,不亦说乎?温故而知新,不亦乐乎?
伊默
至圣

经验值:19234
发帖数:4258
精华帖:118
33楼    2018-07-06 12:48:52
精华帖  精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

既然是I和Q,那么就有绝对地址啊,针对S7-1200/1500可以用PEEK_BOOL和POKE_BOOL指令。

而针对S7-300/400则更简化了!直接用%IX(IDX:= , BIT:= );   %QX(IDX:= , BIT:= ); 这种间接寻址更直观。


以下例程是博途V15版写的, 针对S7-1200和S7-300各写了一个。 

IOTest_Portal_V15.rar

I can do it
Zane
版主

经验值:85161
发帖数:21047
精华帖:399
36楼    2018-07-06 18:16:21
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

花了时间看了各位的程序,也就伊默的程序最贴近万侠的需求了,其他的我觉得都没有理解透彻。


万侠有句话很重要,他的工艺控制块是封装好的,IO定义应该在已有封装块的基础上实现,但伊默的程序和工艺控制块合并了,所以及格线还没到。


加油啊各位!


V14/V15都可以实现!



Zane 注册自动化系统工程师 Always save before download
坏笨笨
侠士

经验值:1689
发帖数:402
精华帖:4
40楼    2018-07-10 13:53:13
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

逻辑上不复杂,倒是怎么样把Io映射到数组要花点心思。如果IO没任何规律,也许只有IO一个一个手动映射了。

Zane
版主

经验值:85161
发帖数:21047
精华帖:399
41楼    2018-07-13 23:42:18
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

手动作映射就失去了实际应用的价值了

Zane 注册自动化系统工程师 Always save before download
伊默
至圣

经验值:19234
发帖数:4258
精华帖:118
42楼    2018-07-15 22:13:34
精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

@万泉河   其实,万版的要求是想:

假定你的工艺FB名称为FB_Technology;

然后在另一个FB块(假设名称为FB_Process)内 添加 Static变量  OptDI : Array[1..2] of FB_Technology;

再用FOR循环类的调用 OptDI[x]


貌似,如果你已经封装好了FB块,在目前的博途环境里,我是找不到这种方法。

但是,你要实现类似的功能,目前能做的工作应该是用 FC + 具有UDT性质的DB块.

I can do it
伊默
至圣

经验值:19234
发帖数:4258
精华帖:118
43楼    2018-07-15 22:19:14
精华帖  精编帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

我写了一个用FC + DB of UDT结构的程序,在附件内。 博途版本V15

另外,也把这三个块用PDF打印出来了,感兴趣的朋友可以看一下。

Prog_PDF.rar

IOTest.rar


I can do it
坐过站
侠士

经验值:1868
发帖数:39
精华帖:1
50楼    2018-09-01 14:05:15
精华帖  主题:回复:PORTAL编程题,可能与指针和间接寻址有关

程序简单,打印出来,感兴趣的可以看一下。

FC1.pdf

虚拟地址表.pdf


您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。