之前在做一个项目时用了很多FB功能块,并且把对应的上位机监控数据放在了IN-OUT接口,结果运行时发现CPU扫描周期很大,接近100ms,控制非常吃力。后来发现是因为在FB的IN-OUT接口使用了UDT类型数据的缘故,因为在IN-OUT接口使用UDT后FB的背景数据块就只保存访问指针,运行时采用指针的方式直接访问接口实参,在FB中每引用一次IN-OUT接口的UDT类型变量元素,程序的工作存储器占用就有40多字节,而普通变量只占用不到10字节。最后没办法把所有IN-OUT接口的UDT拆分到IN和OUT接口,工作存储器马上就降下来了,扫描周期降低了很多,见下图比较。这个问题之前也发帖讨论过。
自从发现上述问题后,我一直不敢再把UDT类型的上位接口放到IN-OUT区了,但是也带来了一些麻烦,比如有的时候需要程序判断上位输入是否合理,如果不合理就通过程序纠正,如果上位接口在IN区就无法在FB内赋值纠正。为了彻底搞清楚这个问题,我最近做了一个测试比较,方法就是创建一个UDT数据类型,包括8个BOOL,2个INT和2个REAL,然后在FB中写三行程序,分别调用三种变量。通过把UDT放到IN接口和IN-OUT接口比较FB占用的装载存储区和工作存储区的大小区别,还通过增加BOOL和INT变量调用比较每增加一次调用占用的装载存储区和工作存储区的大小区别。程序如下
STEP7软件采用5.5SP4,组态CPU为315-2PN/DP V3.2,比较结果如下:
从以上比较可以发现,在IN接口使用UDT时,每增加一次接口元素调用工作存储器只增加8或10字节(因指令和数据类型不同而不同);而在IN-OUT接口UDT时,每增加一次接口元素调用工作存储器增加了46或48字节(因指令和数据类型不同而不同),每次调用比IN接口时多了38字节,同时装载存储器增加的更多。所以得出的结论是在STEP7平台下尽量不要在IN-OUT接口使用UDT数据结构,如果需要使用我最近改进的做法是先把接口数据同步到FB内部变量,在程序调用时使用内部变量替代,只在程序反写接口变量时才使用接口变量,最大限度减少在FB程序内调用接口变量。
目前STEP7平台使用越来越少了,大部分程序都可以用博图来写,那么在博图环境下是否有同样的问题呢?我把上述测试方法在博图V15环境下复制了一遍,同样组态315-2PN/DP 的CPU,结果如下;
通过与STEP7平台比较发现结果差不多,每增加一次调用增加的工作存储器大小是一样的,也就是说对于300系列CPU来说,使用STEP7和博图编程都有这个问题,那么应对方式也是一样的,尽量减少调用频次,因为工作存储器是不可扩展的,调用多了还影响扫描周期。
最后我又在博图V15上组态1500系列CPU做了一次比较,结果如下:
通过比较结果可以发现两者已经没有什么区别了,甚至在IN-OUT区使用时存储器占用还少了一点,说明在1500plc上已经没有这个问题,可以放心大但的去使用了。原来因为300的前车之鉴我在1500下也不敢在IN-OUT区使用UDT数据,下一步就准备把目前的程序块移植到1500上优化一下测试实际结果。