554 lines
16 KiB
C#
554 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Linq;
|
|
using DH.Commons.Base;
|
|
using DH.Commons.Enums;
|
|
using HslCommunication;
|
|
using HslCommunication.Enthernet;
|
|
using HslCommunication.Profinet.XINJE;
|
|
|
|
namespace DH.Devices.PLC
|
|
{
|
|
public class XinJEPLCTcpNet : PLCBase
|
|
{
|
|
private static XinJEPLCTcpNet _instance;
|
|
public static XinJEPLCTcpNet Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null)
|
|
_instance = new XinJEPLCTcpNet();
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
private XinJETcpNet TcpNet = new XinJETcpNet();
|
|
|
|
public override bool PLCConnect()
|
|
{
|
|
try
|
|
{
|
|
TcpNet.IpAddress = IP;
|
|
TcpNet.Port = Port;
|
|
TcpNet.ConnectTimeOut = 5000;
|
|
TcpNet.ReceiveTimeOut = 10000;
|
|
TcpNet.SleepTime = 0;
|
|
TcpNet.AddressStartWithZero = true;
|
|
TcpNet.IsStringReverse = false;
|
|
TcpNet.DataFormat = HslCommunication.Core.DataFormat.ABCD;
|
|
TcpNet.Station = 1;
|
|
TcpNet.Series = XinJESeries.XD;
|
|
|
|
PLCItem itemSpeed = PLCItemList.FirstOrDefault(u => u.Name == "转盘速度");
|
|
if(itemSpeed== null)
|
|
{
|
|
return false;
|
|
}
|
|
OperateResult ret = TcpNet.ConnectServer();
|
|
if (ret.IsSuccess)
|
|
{
|
|
Connected = true;
|
|
MonitorPieces();
|
|
|
|
TurntableOpen(Convert.ToInt32(itemSpeed.Value) , true);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public override ushort ReadShort(string address)
|
|
{
|
|
try
|
|
{
|
|
// 读取Int变量
|
|
var result = TcpNet.ReadInt16(address);
|
|
if (result.IsSuccess)
|
|
{
|
|
return (ushort)result.Content;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public override int ReadInt(string address)
|
|
{
|
|
try
|
|
{
|
|
// 读取Int变量
|
|
var result = TcpNet.ReadInt32(address);
|
|
if (result.IsSuccess)
|
|
{
|
|
return result.Content;
|
|
}
|
|
else
|
|
{
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
public override float ReadFloat(string address)
|
|
{
|
|
try
|
|
{
|
|
// 读取Float变量
|
|
var result = TcpNet.ReadFloat(address);
|
|
if (result.IsSuccess)
|
|
{
|
|
return result.Content;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public override bool ReadBool(string address)
|
|
{
|
|
try
|
|
{
|
|
// 读取Bool变量
|
|
var result = TcpNet.ReadBool(address);
|
|
if (result.IsSuccess)
|
|
{
|
|
return result.Content;
|
|
}
|
|
else
|
|
{
|
|
return false; // 或者可以考虑返回其他的错误标识符
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return false; // 或者返回其他的错误标识符
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 写单独地址 short 值
|
|
/// </summary>
|
|
/// <param name="address">地址</param>
|
|
/// <param name="writeValue">要写入的 int 值</param>
|
|
/// <param name="waitForReply">是否等待回复</param>
|
|
public override bool WriteShort(string address, short writeValue, bool waitForReply = true)
|
|
{
|
|
if (string.IsNullOrEmpty(address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int repeatTime = 3;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start(); // 启动计时
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
var result = TcpNet.Write(address, (short)writeValue);
|
|
if (result.IsSuccess)
|
|
{
|
|
sw.Stop();
|
|
//LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"{Name} {address},写入 {writeValue} 完成,耗时:{sw.ElapsedMilliseconds} ms");
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
} while (repeatTime > 0);
|
|
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 写单独地址 int 值
|
|
/// </summary>
|
|
/// <param name="address">地址</param>
|
|
/// <param name="writeValue">要写入的 int 值</param>
|
|
/// <param name="waitForReply">是否等待回复</param>
|
|
public override bool WriteInt(string address, int writeValue, bool waitForReply = true)
|
|
{
|
|
if (string.IsNullOrEmpty(address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int repeatTime = 3;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start(); // 启动计时
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
var result = TcpNet.Write(address, writeValue);
|
|
if (result.IsSuccess)
|
|
{
|
|
sw.Stop();
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
} while (repeatTime > 0);
|
|
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 写单独地址 Dint 值
|
|
/// </summary>
|
|
/// <param name="address">地址</param>
|
|
/// <param name="writeValue">要写入的 Dint 值</param>
|
|
/// <param name="waitForReply">是否等待回复</param>
|
|
public override bool WriteDInt(string address, int writeValue, bool waitForReply = true)
|
|
{
|
|
if (string.IsNullOrEmpty(address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int repeatTime = 3;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start(); // 启动计时
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
string result = Regex.Replace(address, @"\D", "");
|
|
int r = Convert.ToInt32(result) + 1;
|
|
string address1 = "HD" + r.ToString();
|
|
short high = (short)(writeValue >> 16); // 高 16 位
|
|
short low = (short)(writeValue & 0xFFFF); // 低 16 位
|
|
TcpNet.Write(address1, high);
|
|
Thread.Sleep(10);
|
|
var res = TcpNet.Write(address, low);
|
|
if (res.IsSuccess)
|
|
{
|
|
sw.Stop();
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
} while (repeatTime > 0);
|
|
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 写单独地址 float 值
|
|
/// </summary>
|
|
/// <param name="address">地址</param>
|
|
/// <param name="writeValue">要写入的 float 值</param>
|
|
/// <param name="waitForReply">是否等待回复</param>
|
|
public override bool WriteFloat(string address, float writeValue, bool waitForReply = true)
|
|
{
|
|
if (string.IsNullOrEmpty(address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int repeatTime = 3;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start(); // 启动计时
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
var result = TcpNet.Write(address, writeValue);
|
|
if (result.IsSuccess)
|
|
{
|
|
sw.Stop();
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
} while (repeatTime > 0);
|
|
|
|
sw.Stop();
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 写单独地址 bool 值
|
|
/// </summary>
|
|
/// <param name="address">地址</param>
|
|
/// <param name="writeValue">要写入的 bool 值</param>
|
|
/// <param name="waitForReply">是否等待回复</param>
|
|
public override bool WriteBool(string address, bool writeValue, bool waitForReply = true)
|
|
{
|
|
if (string.IsNullOrEmpty(address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int repeatTime = 3;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start(); // 启动计时
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
var result = TcpNet.Write(address, writeValue);
|
|
if (result.IsSuccess)
|
|
{
|
|
sw.Stop();
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
repeatTime--;
|
|
if (repeatTime <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
} while (repeatTime > 0);
|
|
|
|
sw.Stop();
|
|
Thread.Sleep(10);
|
|
return false;
|
|
}
|
|
|
|
|
|
public override bool PLCDisConnect()
|
|
{
|
|
if (Connected)
|
|
{
|
|
TurntableStop();
|
|
var res = TcpNet.ConnectClose();
|
|
if (res.IsSuccess)
|
|
{
|
|
Connected = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MonitorPieces()
|
|
{
|
|
|
|
ThreadStart ts = new ThreadStart(MonitorPiecesImpl);
|
|
Thread th = new Thread(ts);
|
|
th.Priority = ThreadPriority.AboveNormal;
|
|
th.IsBackground = false;
|
|
th.Start();
|
|
|
|
}
|
|
|
|
|
|
public TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning);
|
|
|
|
private Dictionary<ushort, uint> piecesCountDic = new Dictionary<ushort, uint>();
|
|
private uint piecesCount = 0;
|
|
|
|
/// <summary>
|
|
/// int,int 轴号 捕获位置
|
|
/// </summary>
|
|
public event Action<int, uint> OnNewPieces;
|
|
|
|
public void NewPieces(int axisIndex, uint pieceNumber)
|
|
{
|
|
_taskFactory.StartNew(() =>
|
|
{
|
|
Thread.CurrentThread.Priority = ThreadPriority.Highest;
|
|
|
|
OnNewPieces?.Invoke(axisIndex, pieceNumber);
|
|
});
|
|
}
|
|
/// <summary>
|
|
/// 入料监听
|
|
/// </summary>
|
|
/// <param name="axisIndex"></param>
|
|
private void MonitorPiecesImpl()
|
|
{
|
|
|
|
PLCItem pLCItem= PLCItemList.FirstOrDefault(u => u.Name == "产品计数");
|
|
if (pLCItem == null)
|
|
return;
|
|
DateTime startTime = DateTime.Now;
|
|
DateTime endTime = startTime;
|
|
TimeSpan timeSpan = endTime - startTime;
|
|
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
|
|
//while (CurrentState != DeviceState.DSClose && CurrentState != DeviceState.DSExcept && CurrentState != DeviceState.DSUninit)
|
|
while (Connected)
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
uint tmpPieceNumber = 0;
|
|
sw.Start();
|
|
|
|
var ret = TcpNet.ReadUInt16("D1016");
|
|
|
|
sw.Stop();
|
|
if (ret.IsSuccess)
|
|
{
|
|
tmpPieceNumber = ret.Content;
|
|
}
|
|
|
|
if (ret.IsSuccess && ret.Content > piecesCount)
|
|
{
|
|
sw.Start();
|
|
// Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")} 板卡{station}产品入列触发{tmpPieceNumber}");
|
|
//LogAsync(DateTime.Now, LogLevel.Information, $"转盘{0}产品入列 {piecesCountDic[0]} size:{sum}");
|
|
if (tmpPieceNumber != piecesCount + 1)
|
|
{
|
|
//LogAsync(DateTime.Now, LogLevel.Information, $"入列触发丢失\t{tmpPieceNumber}");
|
|
// Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}\t板卡{station}产品入列触发丢失,{piecesCountDic[station]}\t{tmpPieceNumber}");
|
|
|
|
}
|
|
piecesCount = tmpPieceNumber;
|
|
//NewPieces(ai, piecesCountDic[station]);
|
|
NewPieces(1, piecesCount);
|
|
sw.Stop();
|
|
startTime = DateTime.Now;
|
|
//if (idalarm)
|
|
//{
|
|
// idalarm = false;
|
|
// AlarmVibration(false);
|
|
//}
|
|
|
|
}
|
|
|
|
Thread.Sleep(1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 转盘开启操作
|
|
/// </summary>
|
|
public void TurntableOpen(int speed, bool Direction)
|
|
{
|
|
WriteBool("M122", true);
|
|
Thread.Sleep(10);
|
|
WriteBool("M10", false);
|
|
Thread.Sleep(10);
|
|
//速度
|
|
TcpNet.Write("HD10", (ushort)speed);
|
|
Thread.Sleep(10);
|
|
//方向
|
|
WriteBool("M1", Direction);
|
|
Thread.Sleep(10);
|
|
//使能
|
|
WriteBool("M2", true);
|
|
Thread.Sleep(10);
|
|
//启动
|
|
WriteBool("M0", true);
|
|
Thread.Sleep(10);
|
|
// _mainMotion.CurrentState = DeviceState.DSOpen;
|
|
piecesCount = 0;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 转盘停止操作
|
|
/// </summary>
|
|
public void TurntableStop()
|
|
{
|
|
WriteBool("M122", true);
|
|
Thread.Sleep(50);
|
|
WriteBool("M0", false);
|
|
Thread.Sleep(50);
|
|
WriteBool("M2", false);
|
|
Thread.Sleep(50);
|
|
WriteBool("M50", false);
|
|
piecesCount = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计数清零
|
|
/// </summary>
|
|
public void CountToZero()
|
|
{
|
|
WriteBool("M120", true);
|
|
|
|
}
|
|
}
|
|
}
|