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

1361 lines
45 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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));
}
}
}