如何从C# ADS访问特定的子对象变量

问题描述 投票:0回答:1

我正在使用 Twincat3 和 C# ADS 为 HMI 开发一个项目。

出于结构目的,我想使用 Twincat POO。我是 Twincat 新手,不明白如何使用 ADS 处理程序将嵌套子对象连接到我的 HMI。

我有 1 个父功能块

//Example
FUNCTION_BLOCK FB_Parent
VAR
    iParentVariable: INT;
END_VAR

以及扩展 FB_Parent 的多个子功能块

//Example
FUNCTION_BLOCK FB_Child
VAR
    iChildVariable: INT;
END_VAR

在我的程序中,我有一个 FB_Parent 数组。根据我的自定义 HMI (C#) 的初始化命令,我动态创建新的 FB_Child:

// Example
fbChild := __NEW(FB_Child);
array[0] := fbChild^;
__DELETE(fbChild);

问题是我无法从 HMI (C#) 创建处理程序并访问子变量:

client = new AdsClient
{
    Timeout = 500
};
client.Connect(parameters.AmsNetID, parameters.AdsPort);
handler = client.CreateVariableHandle("PRG_MAIN.arrConveyors[0].iChildVariable");

我如何仍然在 Twincat 中使用 POO 和动态对象创建并通过 ADS 访问 C# 中的子变量?

感谢您的帮助!

我尝试更改数组的定义:

  1. 使用 FB_Parent 指针
  2. 使用接口代替父类

没有任何效果。

c# twincat twincat-ads twincat-ads-.net twincat-hmi
1个回答
0
投票

正如我在评论中所写,我认为 Beckhoff 改变了 ADS 与其 TwinCAT 库的使用方式。作为一个例子,这是我为测试而制作的一个小应用程序,它在一年多前适用于数组。当我现在尝试运行它时,当我想获取类型为

ISymbol
array
时,它会显示“方法未实现”。这也是我不久前在我们的机器使用的自定义应用程序中注意到的,我总是将 PLC 的 NetId 声明为数组,但它在一年多前停止工作,但不幸的是我没有时间查看这并不重要...如果有人有更多线索,请随时发送解决方案或问题可能是什么,我的猜测是 TwinCAT 运行时已更改(出于这个确切原因,我们不更新 ADS nuget)?

NuGet 版本:Beckhoff.TwinCAT.Ads 6.1.203

TwinCAT 版本:4024.32

这是从库抛出的错误,我在这个例子中省略了数组检查: enter image description here 数组成员过去被视为子符号,但现在代码在那里崩溃,如下图所示: enter image description here

作为附加参考,这就是我从目标读取符号的方式,代码被缩短,仅显示所需的方法和属性:

    public IEnumerable<ISymbol>? SymbolCollection
    {
        get;
        private set;
    } = [];

    public void Connect()
    {
        this.adsClient ??= new();
        try
        {
            if (string.IsNullOrEmpty(this.NetId))
            {
                this.adsClient.Connect(AmsNetId.Local, this.Port);
            }
            else
            {
                this.adsClient.Connect(this.NetId, Convert.ToInt32(this.Port));
            }
        }
        catch
        {
        }

        this.adsClient.ConnectionStateChanged += this.OnConnectionStateChanged;
        this.adsClient.AdsStateChanged += this.OnAdsStateChanged;

        this.SymbolCollection = this.GetSymbols();      
    }

    private List<ISymbol>? GetSymbols()
    {
        try
        {
            if (this.adsClient != null && this.adsClient.IsConnected)
            {
                IDynamicSymbolLoader dynamicSymbolLoader = (IDynamicSymbolLoader)SymbolLoaderFactory
                    .Create(this.adsClient, SymbolLoaderSettings.DefaultDynamic);

                return [.. dynamicSymbolLoader.Symbols];
            }
            else
            {
                return default;
            }
        }
        catch
        {
            return null;
        }
    }

另外一点,如果我跳过查看数组,我会得到以下结果,显示的窗口只是应用程序的 UI,它调用上面的代码: enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.