【问题标题】:c# OPC client : OPCGroup.SyncWrite sometimes failsc# OPC 客户端:OPCGroup.SyncWrite 有时会失败
【发布时间】:2021-02-16 21:45:20
【问题描述】:

我创建了一个 opc 客户端以连接到 Rockwell Rslinx。我只使用了 OPCgroup.SyncRead 和 SyncWrite。 一切正常,我从 Rockwell plc 编写和读取标签。 为了测试 SyncWrite,我使用了一个正弦波,我在 plc 的趋势页面中正确地看到了它。 此外,当我按下表单上的按钮时,我设置了一个值,直到我按住按钮,当我释放按钮时返回零(比如说一个脉冲)。 该值写入PLC,我可以在趋势中检查它。然后我以表格的形式从PLC读回它。 为此,我用正弦波的值对 array[0] 充电,用脉冲的值对 array[1] 充电。然后将数组传递给 SyncWrite。 所以,正如我所说,一切都很好。 但现在我不得不添加一个新功能。这是一个二阶系统(T(s) 或二阶滤波器)。 我当然使用相同的数组,现在数组 [0] 是过滤器的结果,数组 [1] 又是脉冲。 脉冲从 PLC 读回,现在是扰动系统的力。 为了从正弦波计算切换到滤波,我使用了一个启用滤波或正弦波的按钮。 在这里我发疯了,因为当我切换到过滤器并按下生成要从 PLC 读回的脉冲的按钮时,主要是脉冲没有到达 PLC。 但最奇怪的是,在 array[1] 中我看到了脉冲的值。当我在下面的行中设置中断点时,我在调试中看到了这一点 同步写入

  public static void Write_synchr(RSIOPC r)
    {
      try
        {
          DataToSend.SetValue(r.array_to_send, 1);
          r.RSLinxOPCgroup_w.SyncWrite(1, ref r.SyncServerHandles_w, ref DataToSend, out SyncErrors2);
        }
      catch (Exception e)
        {
          MessageBox.Show(e.ToString(), "Error:  ",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

    }

更奇怪的是,有时我看到它工作,我不知道如何,但并非总是如此。所以我试图纠正,所以我来到了这一点。 当我看到它工作时,有时激活停用滤波器或正弦波的 sw 策略是不同的,但在我看来是错误的。事实上,它并不总是有效。 当它工作时,我可以看到并测试过滤器响应脉冲的行为,这很好。

【问题讨论】:

  • 我使用 OPC 多年,代码和管理总是很耗时。大约 2 年前,我改用 Node-Red。如果您需要一些帮助来设置它,我可以给您一些工作示例。好消息是您不再需要购买 RsLinx!我几乎所有代码都使用 C#,但 Node-Red 可能需要一些 JavaScript,如果您不喜欢 JavaScript 的想法,那么 Node-Red 不适合您。

标签: c# opc


【解决方案1】:

我做了很多测试,发现了这种奇怪的行为。 如果我使用以下

public float test_second_order_filter()
    {
        force[0] = ... the result of the SyncRead to read the value of the pulse ...
        filter[0] = (float) (-(filter[2] * param_filter[2] / param_filter[0]) - (filter[1] * param_filter[1] / param_filter[0]) +
                     +(force[2] * param_force[2] / param_filter[0]) + (force[1] * param_force[1] / param_filter[0]) +
                        +(force[0] * param_force[0] / param_filter[0]));
        filter[2] = filter[1];
        filter[1] = filter[0];
        force[2] = force[1];
        force[1] = force[0];
        return filter[0];
    }

这正是我必须做的,但行为是我上一篇文章中描述的

然后我尝试了一个简化版本:

public float test_second_order_filter()
    {
        force[0] = ... the result of the SyncRead to read the value of the pulse ...
        filter[0] = (float) (force[0] + filter[2]);
        filter[2] = filter[1];
        filter[1] = filter[0];
        force[2] = force[1];
        force[1] = force[0];
        return filter[0];
    }

(这里的公式没有意义)又没办法

然后我尝试了这个:

public float test_second_order_filter()
    {
        force[0] = ... the result of the SyncRead to read the value of the pulse ...
        filter[0] = (float) (force[0] + 1 + filter[2]);
        filter[2] = filter[1];
        filter[1] = filter[0];
        force[2] = force[1];
        force[1] = force[0];
        return filter[0];
    }

(这里的公式没有意义)发生了一些事情,当我按下按钮时,有时脉冲到达 PLC,我看到 PLC 趋势在移动。来自 ....try ... catch 错误在 SyncWrite 中多次出现访问冲突,但代码不会停止并继续做某事。

然后我尝试了这个:

public float test_second_order_filter()
    {
        force[0] = ... the result of the SyncRead to read the value of the pulse ...
        filter[0] = (float) (force[0] + 0.005 + filter[2]);
        filter[2] = filter[1];
        filter[1] = filter[0];
        force[2] = force[1];
        force[1] = force[0];
        return filter[0];
    }

(这里的公式没有意义)现在系统正在运行(...好吧,使用一个没有意义但它有效的公式)。如果我按下按钮,我会在 PLC 中看到从表单中的 PLC 本身读回的脉冲,因此我看到它反映在 force[0] 中。这是我需要做的,但使用第一个代码示例公式。

所以在我看来,与浮动管理有关。我不能使用 double 类型,因为 SyncRead 和 SyncWrite 都返回错误。

参考我的第一篇文章

public static void Write_synchr(RSIOPC r)
{
  try
    {
      DataToSend.SetValue(r.array_to_send, 1);
      r.RSLinxOPCgroup_w.SyncWrite(1, ref r.SyncServerHandles_w, ref DataToSend, out SyncErrors2);
    }
  catch (Exception e)
    {
      MessageBox.Show(e.ToString(), "Error:  ",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

}

在循环中,我将 r.array_to_send[0] 的值设置为 filter[0] 的值,并将 r.array_to_send[1] 的值设置为表单中按钮生成的脉冲值。

我想记住,使用以下公式我完全没有问题

r.array_to_send[0] = (float)(2 * Math.Cos((2 * (1.0 / Time_period[0]) * Math.PI) * t));

问候

【讨论】:

  • 我认为这是由 RsLinx 内存缓存引起的。
  • 我想已经找到原因了。很可能是关于浮点管理的(有很多关于使用浮点数发生灾难性错误的文献)。可能另外在 OPCAuto.dll Rockwell 包装器 (RsiOpcAuto.dll) 中还有一些带有浮点数的东西。
【解决方案2】:

我想已经找到原因了。很可能是关于浮点管理的(有很多关于使用浮点数发生灾难性错误的文献)。此外,OPCAuto.dll Rockwell 包装器 (RsiOpcAuto.dll) 中可能还有一些带有浮点数的东西。我尝试将滤波器计算的结果除以 10(在 PLC 中,我然后乘以 10),然后再除以 100,然后是 1000,最后是 1000'000'000,然后事情变得更好了。我告诉我,在执行 OPCGroup.SyncWrite 时,我有时会收到有关 Rockwell 包装器中的某些访问冲突的错误。当我开始除以 10 的幂时,我收到错误的频率较低。可能解决方案是截断任何计算的结果,特别是在减法时。我读到减法是当近似值导致那些灾难性错误时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 2020-07-24
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多