121 lines
3.3 KiB
C#
121 lines
3.3 KiB
C#
|
using System;
|
|||
|
using System.Xml;
|
|||
|
using Aitex.Core.RT.Event;
|
|||
|
using Aitex.Core.RT.IOCore;
|
|||
|
using Aitex.Core.Util;
|
|||
|
|
|||
|
namespace Aitex.Core.RT.Device.Unit
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 心跳包机制
|
|||
|
///
|
|||
|
/// 功能:
|
|||
|
/// 1.C#送出给PLC,如果PLC检测到C#心跳信号停止,则判定C#程序运行异常,从而触发安全逻辑动作.
|
|||
|
/// 2.C#检测PLC返回的心跳包信号,如果检测到PLC心跳信号停止,则判定PLC程序运行异常,从而进行报警处理.
|
|||
|
/// </summary>
|
|||
|
public class IoHeartbeat : BaseDevice, IDevice
|
|||
|
{
|
|||
|
public float Feedback
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _isFloatAioType ? _ai.FloatValue : _ai.Value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public float SetPoint
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _isFloatAioType ? _ao.FloatValue : _ao.Value;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (_isFloatAioType)
|
|||
|
_ao.FloatValue = value;
|
|||
|
else
|
|||
|
{
|
|||
|
_ao.Value = (short)value;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
private int PLC_Heart_Beat_Timeout_ms = 1000* 120;
|
|||
|
//IO
|
|||
|
private AIAccessor _ai = null;
|
|||
|
private AOAccessor _ao = null;
|
|||
|
|
|||
|
private DeviceTimer _updateTimer = new DeviceTimer(); //更新 AO信号 给PLC
|
|||
|
|
|||
|
private int MAX = 0x7FFF;
|
|||
|
private float _prevAiValue = 0;
|
|||
|
|
|||
|
private DeviceTimer _connectTimer = new DeviceTimer();
|
|||
|
private R_TRIG _trigConnectionLost = new R_TRIG();
|
|||
|
private bool _isFloatAioType = false;
|
|||
|
|
|||
|
public IoHeartbeat(string module, XmlElement node, string ioModule = "")
|
|||
|
{
|
|||
|
base.Module = module;
|
|||
|
base.Name = node.GetAttribute("id");
|
|||
|
base.Display = node.GetAttribute("display");
|
|||
|
base.DeviceID = node.GetAttribute("schematicId");
|
|||
|
|
|||
|
_ai = ParseAiNode("ai", node, ioModule);
|
|||
|
_ao = ParseAoNode("ao", node, ioModule);
|
|||
|
|
|||
|
|
|||
|
_isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public bool Initialize()
|
|||
|
{
|
|||
|
_updateTimer.Start(500);
|
|||
|
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public void Terminate()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void Monitor()
|
|||
|
{
|
|||
|
if (Math.Abs(_prevAiValue - Feedback) > 0.01)
|
|||
|
{
|
|||
|
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
|||
|
}
|
|||
|
|
|||
|
_trigConnectionLost.CLK = _connectTimer.IsTimeout();
|
|||
|
if (_trigConnectionLost.Q)
|
|||
|
{
|
|||
|
EV.PostAlarmLog(Module, $"PLC heartbeat check failed");
|
|||
|
}
|
|||
|
|
|||
|
_prevAiValue = Feedback;
|
|||
|
|
|||
|
//如果计时到达,则翻转心跳信号
|
|||
|
if (_updateTimer.IsTimeout())
|
|||
|
{
|
|||
|
int value = (int)SetPoint;
|
|||
|
value++;
|
|||
|
if (value >= MAX)
|
|||
|
{
|
|||
|
value = 0;
|
|||
|
}
|
|||
|
|
|||
|
SetPoint = value;
|
|||
|
|
|||
|
_updateTimer.Start(500); //500 ms
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Reset()
|
|||
|
{
|
|||
|
_connectTimer.Start(PLC_Heart_Beat_Timeout_ms);
|
|||
|
_trigConnectionLost.RST = true;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|