将 FB1 传递给具有 FB2 的程序,这些程序想要使用 FB1 正在实现的接口
passing FB1 to programs with FB2s that want to use the interface that FB1 is implementing
这是我第一次 post 堆栈溢出,所以这里 ^^。
我正在尝试从“传统”类型的 PLC 编程过渡到 OOP(仍然很新)。我的新项目将有 3 个不同的程序,它们将 运行 一次 运行,所有的都是 运行 在一个主循环中,代码不是太大,因为有一个具有大部分配置且仅通过 ADS 协议将数据传递给 PLC 的独立系统。
我的问题是,在这 3 个程序中,我有许多功能块实例会触发持久数据保存 (FB_WritePersistentData)。我只想要一个 FB_WritePersistent 实例 - 不需要更多实例,更多实例可能只会导致同时写入,我想避免这种情况。
每个程序都有多个功能块,使用接口写入持久数据。
将实现该接口的单个 FB 定义传递到我想要使用该接口的所有功能块的正确方法是什么?我的第一次尝试如下:
- 在 MAIN
中定义 fbWritePersistentData(implements I_PersistentDataStorage)
- 在将要使用此功能块的 3 个程序中具有与 VAR_IN_OUT 相同的 FB
- 使用该接口的 FB 有方法 .FB_Init 提供对
接口 - 依赖注入
- 持久化FB通过VAR_IN_OUT传递给程序中的其他FB,但这会发出一个
TwinCAT 中的警告以及一些页面错误,可能通过使用 VAR_IN_OUT
来解决错误
我如何避免这种情况是通过简单地将持久 FB 传递给实现接口的 FB,如下所示:
fb1 : FB_1(main.fbSavePersistent)
但这不是我想要的,因为感觉,嗯,错了:)
我应该改用 REFERENCE_TO 吗?提前感谢您的帮助。
说明
我认为您在这里感到困惑的是接口的相对应用。在结构化文本接口中,接口被作为 REFERENCES 处理,这意味着它们不需要通过 VAR_IN_OUT 进行专门处理,但只要您在尝试调用之前执行适当的检查,就可以将其视为标准 VAR_INPUT他们。
(正如 Uwe 所说,在设计界面时,您还需要考虑到它们可以从多个来源使用,因此我建议使用一种方法将要处理的数据排入队列记录器)
如果你想做一些事情,比如用辅助记录器替换持久数据记录器,或者将记录器更改为发布者,只要你实现接口,以这种方式实现接口会让生活变得更简单正确地在你的新 FB 中,你可以直接用新的记录器替换旧的记录器,一切仍然正常
例子
我将如何处理这种情况的一个非常基本的示例实现(无逻辑):
PROGRAM MAIN
VAR
Logger1 : fb_PersistentDataLog; // Single data logger
Source1 : fb_DataSource
:=( Logger := Logger1 ); // Data source
Source2 : fb_DataSource
:=( Logger := Logger1 ); // Data source
END_VAR
Source1();
Source2();
Interface i_Logger
METHOD EnqueueData : UDINT // Interface method prototype
FUNCTION_BLOCK fb_PersistentDataLog IMPLEMENTS i_Logger
METHOD EnqueueData : UDINT
// Run code here to enqueue data to logger
FUNCTION_BLOCK fb_DataSource
VAR_INPUT
Logger : i_Logger; // Definition of the interface as an input
END_VAR
IF Logger <> 0 THEN // Check interface reference is valid
Logger.EnqueueData(); // Call interface method
END_IF
这是我第一次 post 堆栈溢出,所以这里 ^^。
我正在尝试从“传统”类型的 PLC 编程过渡到 OOP(仍然很新)。我的新项目将有 3 个不同的程序,它们将 运行 一次 运行,所有的都是 运行 在一个主循环中,代码不是太大,因为有一个具有大部分配置且仅通过 ADS 协议将数据传递给 PLC 的独立系统。
我的问题是,在这 3 个程序中,我有许多功能块实例会触发持久数据保存 (FB_WritePersistentData)。我只想要一个 FB_WritePersistent 实例 - 不需要更多实例,更多实例可能只会导致同时写入,我想避免这种情况。
每个程序都有多个功能块,使用接口写入持久数据。
将实现该接口的单个 FB 定义传递到我想要使用该接口的所有功能块的正确方法是什么?我的第一次尝试如下:
- 在 MAIN 中定义 fbWritePersistentData(implements I_PersistentDataStorage)
- 在将要使用此功能块的 3 个程序中具有与 VAR_IN_OUT 相同的 FB
- 使用该接口的 FB 有方法 .FB_Init 提供对 接口 - 依赖注入
- 持久化FB通过VAR_IN_OUT传递给程序中的其他FB,但这会发出一个 TwinCAT 中的警告以及一些页面错误,可能通过使用 VAR_IN_OUT 来解决错误
我如何避免这种情况是通过简单地将持久 FB 传递给实现接口的 FB,如下所示: fb1 : FB_1(main.fbSavePersistent) 但这不是我想要的,因为感觉,嗯,错了:)
我应该改用 REFERENCE_TO 吗?提前感谢您的帮助。
说明
我认为您在这里感到困惑的是接口的相对应用。在结构化文本接口中,接口被作为 REFERENCES 处理,这意味着它们不需要通过 VAR_IN_OUT 进行专门处理,但只要您在尝试调用之前执行适当的检查,就可以将其视为标准 VAR_INPUT他们。
(正如 Uwe 所说,在设计界面时,您还需要考虑到它们可以从多个来源使用,因此我建议使用一种方法将要处理的数据排入队列记录器)
如果你想做一些事情,比如用辅助记录器替换持久数据记录器,或者将记录器更改为发布者,只要你实现接口,以这种方式实现接口会让生活变得更简单正确地在你的新 FB 中,你可以直接用新的记录器替换旧的记录器,一切仍然正常
例子
我将如何处理这种情况的一个非常基本的示例实现(无逻辑):
PROGRAM MAIN
VAR
Logger1 : fb_PersistentDataLog; // Single data logger
Source1 : fb_DataSource
:=( Logger := Logger1 ); // Data source
Source2 : fb_DataSource
:=( Logger := Logger1 ); // Data source
END_VAR
Source1();
Source2();
Interface i_Logger
METHOD EnqueueData : UDINT // Interface method prototype
FUNCTION_BLOCK fb_PersistentDataLog IMPLEMENTS i_Logger
METHOD EnqueueData : UDINT
// Run code here to enqueue data to logger
FUNCTION_BLOCK fb_DataSource
VAR_INPUT
Logger : i_Logger; // Definition of the interface as an input
END_VAR
IF Logger <> 0 THEN // Check interface reference is valid
Logger.EnqueueData(); // Call interface method
END_IF