Files
DHDHSoftware/DH.Devices.PLC/XinJEPLCTcpNet.cs
T
2025-04-22 18:03:12 +08:00

1361 lines
45 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
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 DH.Commons.Models;
using HslCommunication;
using HslCommunication.Enthernet;
using HslCommunication.Profinet.XINJE;
using OpenCvSharp;
using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
namespace DH.Devices.PLC
{
public class XinJEPLCTcpNet : PLCBase, ILogger
{
private static XinJEPLCTcpNet _instance;
public static XinJEPLCTcpNet Instance
{
get
{
if (_instance == null)
_instance = new XinJEPLCTcpNet();
return _instance;
}
}
public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
public event Action<LogMsg> OnLog;
private XinJETcpNet TcpNet = new XinJETcpNet();
public override bool PLCConnect()
{
try
{
LoggerHelper.LogPath = "D://PROJECTS//Logs//";
LoggerHelper.LogPrefix = "PLC";
TcpNet.IpAddress = IP;
TcpNet.Port = Port;
TcpNet.ConnectTimeOut = 5000;
TcpNet.ReceiveTimeOut = 10000;
TcpNet.SleepTime = 0;
TcpNet.AddressStartWithZero = true;
TcpNet.IsStringReverse = false;
TcpNet.Station = 1;
switch (PLCType)
{
case EnumPLCType.信捷XD网口:
TcpNet.Series = XinJESeries.XD;
TcpNet.DataFormat = HslCommunication.Core.DataFormat.CDAB;
break;
case EnumPLCType.信捷XC网口:
TcpNet.Series = XinJESeries.XC;
TcpNet.DataFormat = HslCommunication.Core.DataFormat.CDAB;
break;
}
OperateResult ret = TcpNet.ConnectServer();
if (ret.IsSuccess)
{
Connected = true;
//初始化流程
InitProcess();
LogAsync(DateTime.Now, LogLevel.Information, $"{IP}:{Port}PLC连接成功");
return true;
}
else
{
Connected = false;
LogAsync(DateTime.Now, LogLevel.Error, $"PLC初始化失败");
return false;
//throw new Exception($"{IP}:{Port}PLC连接失败!");
}
}
catch(Exception ex)
{
Connected = false;
LogAsync(DateTime.Now, LogLevel.Error, $"{IP}:{Port}PLC连接失败!失败原因:{ex.ToString()}");
return false;
//throw new Exception($"{IP}:{Port}PLC连接失败!失败原因:{ex.ToString()}");
}
}
public override Int16 ReadInt16(string address)
{
try
{
if (Connected)
{
// 读取Int变量
var result = TcpNet.ReadInt16(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int16失败,地址{address}");
throw new Exception($"PLC操作读取int16失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取int16失败,地址{address},失败原因:{ex.ToString()}");
}
}
public override Int32 ReadInt32(string address)
{
try
{
if (Connected)
{
// 读取Int变量
var result = TcpNet.ReadInt32(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int32失败,地址{address}");
throw new Exception($"PLC操作读取int32失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取int32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取int32失败,地址{address},失败原因:{ex.ToString()}");
}
}
public override UInt16 ReadUInt16(string address)
{
try
{
if (Connected)
{
// 读取Int变量
var result = TcpNet.ReadUInt16(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint16失败,地址{address}");
throw new Exception($"PLC操作读取uint16失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取uint16失败,地址{address},失败原因:{ex.ToString()}");
}
}
public override UInt32 ReadUInt32(string address)
{
try
{
if (Connected)
{
// 读取Int变量
var result = TcpNet.ReadUInt32(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作uint32失败,地址{address}");
throw new Exception($"PLC操作uint32失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取uint32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取uint32失败,地址{address},失败原因:{ex.ToString()}");
}
}
public override float ReadFloat(string address)
{
try
{
if (Connected)
{
// 读取Float变量
var result = TcpNet.ReadFloat(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取float失败,地址{address}");
throw new Exception($"PLC操作读取float失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取float失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取float失败,地址{address},失败原因:{ex.ToString()}");
}
}
public override bool ReadBool(string address)
{
try
{ if (Connected)
{
// 读取Bool变量
var result = TcpNet.ReadBool(address);
if (result.IsSuccess)
{
return result.Content;
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取bool失败,地址{address}");
throw new Exception($"PLC操作读取bool失败,地址{address}");
}
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
}
catch (Exception ex)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作读取bool失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作读取bool失败,地址{address},失败原因:{ex.ToString()}");
}
}
/// <summary>
/// 写单独地址 uint32 值
/// </summary>
/// <param name="address">地址</param>
/// <param name="writeValue">要写入的 int 值</param>
/// <param name="waitForReply">是否等待回复</param>
public override bool WriteUInt32(string address, UInt32 writeValue, bool waitForReply = true)
{
if (Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入uint32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入uint32失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
return false;
}
/// <summary>
/// 写单独地址 uint16 值
/// </summary>
/// <param name="address">地址</param>
/// <param name="writeValue">要写入的 int 值</param>
/// <param name="waitForReply">是否等待回复</param>
public override bool WriteUInt16(string address, UInt16 writeValue, bool waitForReply = true)
{
if (Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入uint16失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入uint16失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
return false;
}
/// <summary>
/// 写单独地址 int32 值
/// </summary>
/// <param name="address">地址</param>
/// <param name="writeValue">要写入的 int 值</param>
/// <param name="waitForReply">是否等待回复</param>
public override bool WriteInt32(string address, Int32 writeValue, bool waitForReply = true)
{
if (Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入int32失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入int32失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
}
else
{
throw new Exception($"PLC未连接,地址{address}");
}
return false;
}
/// <summary>
/// 写单独地址 int16 值
/// </summary>
/// <param name="address">地址</param>
/// <param name="writeValue">要写入的 int 值</param>
/// <param name="waitForReply">是否等待回复</param>
public override bool WriteInt16(string address, Int16 writeValue, bool waitForReply = true)
{
if (Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
throw new Exception($"PLC操作写入int16失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
}
else
{
throw new Exception($"PLC未连接,地址{address}");
}
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 (Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入float失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入float失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
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(Connected)
{
if (string.IsNullOrEmpty(address))
{
return false;
}
int repeatTime = 3;
do
{
try
{
var result = TcpNet.Write(address, writeValue);
if (result.IsSuccess)
{
return true;
}
}
catch (Exception ex)
{
repeatTime--;
if (repeatTime <= 0)
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC操作写入bool失败,地址{address},失败原因:{ex.ToString()}");
throw new Exception($"PLC操作写入bool失败,地址{address},失败原因:{ex.ToString()}");
}
}
} while (repeatTime > 0);
Thread.Sleep(30);
}
else
{
LogAsync(DateTime.Now, LogLevel.Error, $"PLC未连接,地址{address}");
throw new Exception($"PLC未连接,地址{address}");
}
return false;
}
public override bool PLCDisConnect()
{
if (Connected)
{
var res = TcpNet.ConnectClose();
if (res.IsSuccess)
{
LogAsync(DateTime.Now, LogLevel.Information, $"{IP}:{Port}停止");
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);
});
}
public async Task HeartbeatAsync1()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "心跳地址");
while (Connected)
{
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, true);
await Task.Delay(900); // 非阻塞,等待1秒
}
}
/// <summary>
/// 入料监听
/// </summary>
/// <param name="axisIndex"></param>
private void MonitorPiecesImpl()
{
PLCItem pLCItem= PLCItemList.FirstOrDefault(u => u.Name == "产品计数");
if (pLCItem == null)
return;
string Count = pLCItem.Address;
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");
var ret = TcpNet.ReadUInt32(Count);
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);
}
}
public void InitProcess()
{
//启用心跳
OpenHeartbeat(true);
// LogAsync(DateTime.Now, LogLevel.Information, $"启用心跳");
//状态复位
StatusReset();
//LogAsync(DateTime.Now, LogLevel.Information, $"状态复位");
//关闭定位
VisionPos(false);
// LogAsync(DateTime.Now, LogLevel.Information, $"关闭定位");
//写入流程加载点位配置
InitProcessAction();
//LogAsync(DateTime.Now, LogLevel.Information, $"写入流程加载点位配置");
//计数清零
CountToZero();
// LogAsync(DateTime.Now, LogLevel.Information, $"计数清零");
//停止转盘
TurnStart(false);
//LogAsync(DateTime.Now, LogLevel.Information, $"停止转盘");
//转盘使能
TurnEnable(true);
LogAsync(DateTime.Now, LogLevel.Information, $"启用心跳-状态复位-关闭定位-写入流程加载点位配置-计数清零-停止转盘-转盘使能");
//开启入料监听
MonitorPieces();
}
public void StartProcess()
{
//状态复位
StatusReset();
// LogAsync(DateTime.Now, LogLevel.Information, $"状态复位");
//关闭定位
VisionPos(false);
// LogAsync(DateTime.Now, LogLevel.Information, $"关闭定位");
//写入流程启动点位配置
StartProcessAction();
PLCItem? pLCItem = ConfigModel.GlobalList?
.FirstOrDefault()?
.StartProcessList?
.Where(it => it.Name == "挡料电机回原点速度").FirstOrDefault();
if (pLCItem == null)
{
throw new Exception( $"未找到挡料电机回原点速度地址,请检查该地址是否存在于点位表!");
}
PLCItem? pLCItem1 = ConfigModel.GlobalList?
.FirstOrDefault()?
.StartProcessList?
.Where(it => it.Name == "挡料电机位置").FirstOrDefault();
if (pLCItem1 == null)
{
throw new Exception($"未找到挡料电机位置地址,请检查该地址是否存在于点位表!");
}
FeedingMotor(true, Convert.ToInt32(pLCItem.Value), Convert.ToInt32(pLCItem1.Value));
PLCItem? pLCItemmontor = ConfigModel.GlobalList?
.FirstOrDefault()?
.StartProcessList?
.Where(it => it.Name == "相机步进速度").FirstOrDefault();
if (pLCItemmontor == null)
{
throw new Exception($"未找到相机步进速度地址,请检查该地址是否存在于点位表!");
}
PLCItem? pLCItemmontor1 = ConfigModel.GlobalList?
.FirstOrDefault()?
.StartProcessList?
.Where(it => it.Name == "相机步进位置").FirstOrDefault();
if (pLCItemmontor1 == null)
{
throw new Exception($"未找到相机步进位置地址,请检查该地址是否存在于点位表!");
}
Motor(true, Convert.ToInt32(pLCItemmontor.Value), Convert.ToInt32(pLCItemmontor1.Value));
// if (_PLCConfig?.Enable == true)
//挡料电机操作
// _PLC.FeedingMotor(_PLCConfig.CunToZeroSpeed, _PLCConfig.CunPos, _PLCConfig.CunSpeed, _PLCConfig.CunDirection);
//流程开启操作配置
// ProcessInitialAction();
// if (_PLC?Enabled == true)
//皮带
// _PLC.Belt(true);
// LogAsync(DateTime.Now, LogLevel.Information, $"写入流程加载点位配置");
//计数清零
CountToZero();
LogAsync(DateTime.Now, LogLevel.Information, $"状态复位-关闭定位-写入流程加载点位配置-计数清零");
//转盘启动
TurnStart(true);
}
public void CloseProcess()
{
StatusReset();
VisionPos(false);
CountToZero();
TurnStart(false);
TurnEnable(false);
OpenHeartbeat(false);
PLCDisConnect();
// LogAsync(DateTime.Now, LogLevel.Information, $"PLC断开连接");
}
public void InitProcessAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.InitProcessList?.ToList() ?? new List<PLCItem>());
public void StartProcessAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.StartProcessList?.ToList() ?? new List<PLCItem>());
public void StopProcessAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.StopProcessList?.ToList() ?? new List<PLCItem>());
public void StartResetAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.StartResetList?.ToList() ?? new List<PLCItem>());
public void StopResetAction() =>
ProcessAction(ConfigModel.GlobalList?.FirstOrDefault()?.StopResetList?.ToList() ?? new List<PLCItem>());
// 处理方法:无需再检查 null
private void ProcessAction(List<PLCItem> items)
{
if (items.Count == 0) return;
foreach (var item in items.OrderBy(x => x.StartIndex))
{
switch (item.Type)
{
case EnumPLCDataType.单字整型:
WriteUInt16(item.Address, ushort.Parse(item.Value));
break;
case EnumPLCDataType.双字整型:
WriteUInt32(item.Address, uint.Parse(item.Value));
break;
case EnumPLCDataType.浮点型:
WriteFloat(item.Address, float.Parse(item.Value));
break;
case EnumPLCDataType.布尔型:
WriteBool(item.Address, item.Value.Equals("true", StringComparison.OrdinalIgnoreCase));
break;
}
}
}
/// <summary>
/// 状态复位
/// </summary>
public void StatusReset()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "状态复位");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, false);
}
/// <summary>
/// 开启关闭视觉定位
/// </summary>
public void VisionPos(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "启用定位");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
}
/// <summary>
/// 转盘方向
/// </summary>
/// <param name="b"></param>
public void TurnDirection(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "转盘方向");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
}
/// <summary>
/// 转盘速度
/// </summary>
/// <param name="b"></param>
public void TurnSpeed(int speed)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "转盘速度");
if (pLCItem == null)
return;
WriteUInt16(pLCItem.Address, (ushort)speed);
}
/// <summary>
/// 转盘启停
/// </summary>
public void TurnStart(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "转盘启动");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
piecesCount = 0;
}
/// <summary>
/// 转盘使能
/// </summary>
/// <param name="b"></param>
public void TurnEnable(bool b)
{
PLCItem? DiskOpenItem = PLCItemList.FirstOrDefault(u => u.Name == "转盘使能");
if (DiskOpenItem == null)
return;
WriteBool(DiskOpenItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 计数清零
/// </summary>
public void CountToZero()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "计数清零");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, true);
Thread.Sleep(30);
}
public void RedLight(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "指示灯红");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
}
public void GreenLight(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "指示灯绿");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
}
public void YellowLight(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "指示灯黄");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
}
public void Buzzer(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "蜂鸣器");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
}
public void Motor(bool direction, int speed, int pos)
{
int timeout = 5000;
int elapsedTime = 0;
int checkInterval = 100;
MotorToZero(false);
// 检查是否不在原点,如果不在,则回原点
MotorSpeed(speed); // 速度
Thread.Sleep(300);
// 发送回原点指令
MotorToZero(true);
Thread.Sleep(1000); // 给设备一些时间响应
// 等待回到原点
while (!ReadMotorToZero())
{
if (elapsedTime >= timeout)
{
break;
}
Thread.Sleep(checkInterval);
elapsedTime += checkInterval;
}
// }
// 无论是刚回到原点还是已经在原点,执行目标位置、速度和方向设置
MotorSpeed(speed);
if (direction)
{
MotorClockwise(true); // 顺时针转动
}
else
{
MotorCounterclockwise(true); // 逆时针转动
}
Thread.Sleep(30);
MotorPos(pos); // 目标位置
Thread.Sleep(2000);
}
/// <summary>
/// 挡料电机操作
/// true: 顺时针
/// False: 逆时针
/// </summary>
/// <param name="u"></param>
public void FeedingMotor( bool direction,int speed,int pos)
{
int timeout = 5000;
int elapsedTime = 0;
int checkInterval = 100;
BarrierToZero(false);
// 检查是否不在原点,如果不在,则回原点
BarrierToZeroSpeed(speed); // 速度
Thread.Sleep(300);
// 发送回原点指令
BarrierToZero(true);
Thread.Sleep(1000); // 给设备一些时间响应
// 等待回到原点
while (!ReadBarrierToZero())
{
if (elapsedTime >= timeout)
{
break;
}
Thread.Sleep(checkInterval);
elapsedTime += checkInterval;
}
// 无论是刚回到原点还是已经在原点,执行目标位置、速度和方向设置
BarrierSpeed(speed);
if (direction)
{
BarrierClockwise(true); // 顺时针转动
}
else
{
BarrierCounterclockwise(true); // 逆时针转动
}
Thread.Sleep(30);
BarrierPos(pos); // 目标位置
Thread.Sleep(2000);
}
/// <summary>
/// 转盘清料
/// </summary>
/// <param name="b"></param>
public void TurnClear(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "转盘清料");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 开启心跳
/// </summary>
/// <param name="v"></param>
public void OpenHeartbeat(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "启用心跳");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
Thread.Sleep(30);
if (b)
{
//开启心跳
Task.Run(async () => await HeartbeatAsync1());
}
}
int currentRegister = 0;
public void Blowing(uint productNumber, UInt16 value)
{
int Register = (int)((productNumber - 1) % 30);
currentRegister = 411 + Register;
WriteUInt16($"D{currentRegister}", value);
}
/// <summary>
/// 读取定位脉冲
/// </summary>
/// <returns></returns>
public int ReadVisionPos()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "定位完成脉冲值");
if (pLCItem == null)
return 0;
int value = ReadInt32(pLCItem.Address);
Thread.Sleep(100);
return Math.Abs(value);
}
/// <summary>
/// 挡杆回原点
/// </summary>
public void BarrierToZero(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机回原点");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
}
/// <summary>
/// 变焦相机回原点
/// </summary>
public void ZoomcameraToZero(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "步进电机回原点");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
}
/// <summary>
/// 读取 挡杆回原点状态
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public bool ReadBarrierToZero()
{
//PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机回原点");
//if (pLCItem == null)
//{
// throw new Exception("未找到挡料电机回原点点位");
//}
//挡料电机传感器感应点
return ReadBool("X11");
}
/// <summary>
/// 挡杆回原点速度
/// </summary>
public void BarrierToZeroSpeed(int speed)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机回原点速度");
if (pLCItem == null)
return;
WriteUInt32(pLCItem.Address, (uint)speed);
}
/// <summary>
/// 挡杆位置
/// </summary>
public void BarrierPos(int value)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机位置");
if (pLCItem == null)
return;
WriteUInt16(pLCItem.Address, (ushort)value);
}
/// <summary>
/// 挡杆速度
/// </summary>
public void BarrierSpeed(int value)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机速度");
if (pLCItem == null)
return;
WriteUInt32(pLCItem.Address, (uint)value);
}
/// <summary>
/// 挡杆顺时针
/// </summary>
public void BarrierClockwise(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机顺时针");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 挡杆逆时针
/// </summary>
public void BarrierCounterclockwise(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "挡料电机逆时针");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 相机步进电机回原点
/// </summary>
/// <param name="b"></param>
public void MotorToZero(bool b)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进原点");
if (pLCItem == null)
return;
WriteBool(pLCItem.Address, b);
}
/// <summary>
/// 读取相机步进电机回原点状态
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public bool ReadMotorToZero()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进原点");
if (pLCItem == null)
{
throw new Exception("未找到挡料电机回原点点位");
}
return ReadBool(pLCItem.Address);
}
/// <summary>
/// 相机步进电机位置
/// </summary>
/// <param></param>
public void MotorPos(int value)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进位置");
if (pLCItem == null)
return;
WriteUInt16(pLCItem.Address, (ushort)value);
}
public int ReadMotorRealPos()
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进实时位置");
if (pLCItem == null)
{
throw new Exception("未找到相机步进实时位置");
}
return ReadInt16(pLCItem.Address);
}
/// <summary>
/// 相机步进电机速度
/// </summary>
/// <param name="b"></param>
public void MotorSpeed(int speed)
{
PLCItem? pLCItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进速度");
if (pLCItem == null)
return;
WriteInt32(pLCItem.Address, speed);
}
/// <summary>
/// 相机步进顺时针
/// </summary>
public void MotorClockwise(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进顺时针");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 相机步进逆时针
/// </summary>
public void MotorCounterclockwise(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "相机步进逆时针");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
Thread.Sleep(30);
}
/// <summary>
/// 相机步进点动
/// </summary>
public void MotorTest(bool b)
{
PLCItem? DiskRunItem = PLCItemList.FirstOrDefault(u => u.Name == "点动相机步进");
if (DiskRunItem == null)
return;
WriteBool(DiskRunItem.Address, b);
Thread.Sleep(30);
}
public void LogAsync(LogMsg msg)
{
msg.MsgSource = "PLC";
msg.ThreadId = Thread.CurrentThread.ManagedThreadId;
//OnLog?.BeginInvoke(msg, null, null);
OnLog?.Invoke(msg);
//if (InitialConfig.IsEnableLog)
{
LoggerHelper.LogAsync(msg);
}
}
public void LogAsync(DateTime dt, LogLevel logLevel, string msg)
{
LogAsync(new LogMsg(dt, logLevel, msg));
}
}
}