Compare commits
11 Commits
main
..
07c8e6ec91
| Author | SHA1 | Date | |
|---|---|---|---|
| 07c8e6ec91 | |||
| 31d9f8d6b6 | |||
| 24a905b517 | |||
| 42f8bb7642 | |||
| 165963d337 | |||
| 715d7166bc | |||
| 679320311d | |||
| 6eee4eda24 | |||
| e7341bea87 | |||
| 5dedb1a632 | |||
| dca4b2afac |
@@ -22,6 +22,7 @@ namespace Check.Main.Camera
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 静态全局相机管理器,负责所有相机的生命周期、配置应用和多相机同步
|
/// 静态全局相机管理器,负责所有相机的生命周期、配置应用和多相机同步
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// 222222
|
||||||
public static class CameraManager
|
public static class CameraManager
|
||||||
{
|
{
|
||||||
//1、相机与UI管理----管理每台相机对象和对应的图像显示窗口。
|
//1、相机与UI管理----管理每台相机对象和对应的图像显示窗口。
|
||||||
@@ -692,7 +693,7 @@ namespace Check.Main.Camera
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 【将 SkiaSharp.SKImage 安全地转换为 System.Drawing.Bitmap。
|
/// 【将 SkiaSharp.SKImage 安全地转换为 System.Drawing.Bitmap。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Bitmap ConvertSKImageToBitmap(SKImage skImage)
|
private static Bitmap ConvertSKImageToBitmap(SKImage skImage)
|
||||||
{
|
{
|
||||||
if (skImage == null) return null;
|
if (skImage == null) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -58,13 +58,13 @@ namespace Check.Main.Camera
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void ProcessQueue()
|
private void ProcessQueue()
|
||||||
{
|
{
|
||||||
// 从模型管理器获取此线程专属的YOLO模型
|
//// 从模型管理器获取此线程专属的YOLO模型
|
||||||
var yoloModel = YoloModelManager.GetModel(_modeId);
|
//var yoloModel = YoloModelManager.GetModel(_modeId);
|
||||||
if (yoloModel == null)
|
//if (yoloModel == null)
|
||||||
{
|
//{
|
||||||
ThreadSafeLogger.Log($"[错误] 相机 #{_modeId} 无法获取对应的YOLO模型,处理线程已中止。");
|
// ThreadSafeLogger.Log($"[错误] 相机 #{_modeId} 无法获取对应的YOLO模型,处理线程已中止。");
|
||||||
return; // 如果没有模型,此线程无法工作
|
// return; // 如果没有模型,此线程无法工作
|
||||||
}
|
//}
|
||||||
|
|
||||||
//训练阶段(相机2)
|
//训练阶段(相机2)
|
||||||
var trainer = new LogoTemplateTrainer();
|
var trainer = new LogoTemplateTrainer();
|
||||||
@@ -103,34 +103,32 @@ namespace Check.Main.Camera
|
|||||||
ImageData data = _imageQueue.Take();
|
ImageData data = _imageQueue.Take();
|
||||||
using (data)
|
using (data)
|
||||||
{
|
{
|
||||||
string result = "";
|
|
||||||
using (var skImage = ConvertBitmapToSKImage(data.Image)) // 转换图像格式并管理其生命周期
|
|
||||||
{
|
|
||||||
if (skImage == null) continue;
|
|
||||||
var predictions = yoloModel.RunObjectDetection(skImage);
|
|
||||||
result = predictions.Any() ? "NG" : "OK";
|
|
||||||
|
|
||||||
ThreadSafeLogger.Log($"相机 #{_cameraIndex} 处理产品 #{data.ProductId},检测到 {predictions.Count} 个目标,结果: {result}");
|
//using (var skImage = ConvertBitmapToSKImage(data.Image)) // 转换图像格式并管理其生命周期
|
||||||
|
//{
|
||||||
|
// if (skImage == null) continue;
|
||||||
|
// var predictions = yoloModel.RunObjectDetection(skImage);
|
||||||
|
// string result = predictions.Any() ? "NG" : "OK";
|
||||||
|
|
||||||
// 将处理结果交给协调器进行组装
|
// ThreadSafeLogger.Log($"相机 #{_cameraIndex} 处理产品 #{data.ProductId},检测到 {predictions.Count} 个目标,结果: {result}");
|
||||||
DetectionCoordinator.AssembleProduct(data, result);
|
|
||||||
|
|
||||||
if (OnProcessingCompleted != null)
|
// // 将处理结果交给协调器进行组装
|
||||||
{
|
// DetectionCoordinator.AssembleProduct(data, result);
|
||||||
using (var resultSkImage = skImage.Draw(predictions))
|
|
||||||
{
|
|
||||||
// 4. 触发事件,将绘制好的 resultSkImage 传递出去
|
|
||||||
|
|
||||||
Bitmap bitmap = CameraManager.ConvertSKImageToBitmap(resultSkImage);
|
// if (OnProcessingCompleted != null)
|
||||||
// 所有权在这里被转移
|
// {
|
||||||
OnProcessingCompleted?.Invoke(this, new ProcessingCompletedEventArgs(
|
// using (var resultSkImage = skImage.Draw(predictions))
|
||||||
_cameraIndex,
|
// {
|
||||||
data.ProductId,
|
// // 4. 触发事件,将绘制好的 resultSkImage 传递出去
|
||||||
bitmap
|
// // 所有权在这里被转移
|
||||||
));
|
// OnProcessingCompleted?.Invoke(this, new ProcessingCompletedEventArgs(
|
||||||
}
|
// _cameraIndex,
|
||||||
}
|
// data.ProductId,
|
||||||
}
|
// resultSkImage
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
//***********************************使用Halcon模板匹配进行检测****************************************************
|
//***********************************使用Halcon模板匹配进行检测****************************************************
|
||||||
if (data.Image == null) continue;
|
if (data.Image == null) continue;
|
||||||
@@ -162,7 +160,7 @@ namespace Check.Main.Camera
|
|||||||
|
|
||||||
//score= ProcessImg.ProcessImagesInFolder(filepath,cam);
|
//score= ProcessImg.ProcessImagesInFolder(filepath,cam);
|
||||||
|
|
||||||
//string result = (score > 0.5) ? "OK" : "NG";
|
string result = (score > 0.5) ? "OK" : "NG";
|
||||||
|
|
||||||
ThreadSafeLogger.Log($"相机 #{_cameraIndex} 处理产品 #{data.ProductId},结果: {result},得分: {score}");
|
ThreadSafeLogger.Log($"相机 #{_cameraIndex} 处理产品 #{data.ProductId},结果: {result},得分: {score}");
|
||||||
|
|
||||||
@@ -171,20 +169,12 @@ namespace Check.Main.Camera
|
|||||||
|
|
||||||
|
|
||||||
//给PLC的M90、M91写值(10.10)
|
//给PLC的M90、M91写值(10.10)
|
||||||
if (FrmMain.PlcClient != null && FrmMain.PlcClient.IsConnected)
|
if (FrmMain.PlcClient != null)
|
||||||
{
|
{
|
||||||
if (result == "OK")
|
if (result == "OK")
|
||||||
{
|
{
|
||||||
//吹气到合格框
|
//吹气到合格框
|
||||||
FrmMain.PlcClient.WriteAsync("M90", 1).Wait(); // 写入M90为1
|
FrmMain.PlcClient.WriteBool("90", true); // 写入M90为1
|
||||||
//Thread.Sleep(100);
|
|
||||||
FrmMain.PlcClient.WriteAsync("M90", 0).Wait(); // 写入M90为1
|
|
||||||
|
|
||||||
//var a = FrmMain.PlcClient.ReadAsync("M90");
|
|
||||||
//Console.WriteLine(a);
|
|
||||||
|
|
||||||
//FrmMain.PlcClient.WriteAsync("M91", 0).Wait();
|
|
||||||
|
|
||||||
// 延时复位
|
// 延时复位
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -195,12 +185,7 @@ namespace Check.Main.Camera
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//吹气到不合格框
|
//吹气到不合格框
|
||||||
//FrmMain.PlcClient.WriteAsync("M90", 0).Wait();
|
FrmMain.PlcClient.WriteBool("91", true);// 写入M91为1
|
||||||
FrmMain.PlcClient.WriteAsync("M91", 1).Wait();// 写入M91为1
|
|
||||||
FrmMain.PlcClient.WriteAsync("M91", 0).Wait(); // 写入M90为1
|
|
||||||
|
|
||||||
//var a = FrmMain.PlcClient.ReadAsync("M90");
|
|
||||||
//Console.WriteLine(a);
|
|
||||||
// 延时复位
|
// 延时复位
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@@ -208,10 +193,15 @@ namespace Check.Main.Camera
|
|||||||
//await FrmMain.PlcClient.WriteAsync("M91", 0);
|
//await FrmMain.PlcClient.WriteAsync("M91", 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//完成一次检测进行刷新
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
FrmMain.PlcClient.WriteBool("90", false); //
|
||||||
|
FrmMain.PlcClient.WriteBool("91", false); // 写入M90为1
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThreadSafeLogger.Log("[PLC] 未连接,跳过写入。");
|
ThreadSafeLogger.Log("6,跳过写入。");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<HintPath>..\..\..\HslCommunication-master\HslCommunication.dll</HintPath>
|
<HintPath>..\..\..\HslCommunication-master\HslCommunication.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MvCameraControl.Net">
|
<Reference Include="MvCameraControl.Net">
|
||||||
<HintPath>..\..\..\..\XKRS2025\XKRS2025\CheckDevice\Check.Main\bin\Debug\MvCameraControl.Net.dll</HintPath>
|
<HintPath>..\..\XKRS2025\CheckDevice\Check.Main\bin\Debug\MvCameraControl.Net.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,238 +0,0 @@
|
|||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using Sunny.UI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Check.Main.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 汇川 Easy 系列 PLC 客户端 (Modbus TCP)
|
|
||||||
/// 支持 D/M/X/Y 地址读写,整数、浮点数、字符串
|
|
||||||
/// </summary>
|
|
||||||
public class EasyPlcClient : IDisposable
|
|
||||||
{
|
|
||||||
private readonly TcpClient _tcpClient = new();
|
|
||||||
private NetworkStream _stream;
|
|
||||||
private ushort _transactionId = 0;
|
|
||||||
private readonly SemaphoreSlim _lock = new(1, 1);
|
|
||||||
|
|
||||||
private readonly string _ip;
|
|
||||||
private readonly int _port;
|
|
||||||
private readonly byte _slaveId;
|
|
||||||
|
|
||||||
public EasyPlcClient(string ip, int port = 502, byte slaveId = 1)
|
|
||||||
{
|
|
||||||
_ip = ip;
|
|
||||||
_port = port;
|
|
||||||
_slaveId = slaveId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsConnected => _tcpClient != null && _tcpClient.Connected;//10.11添加
|
|
||||||
|
|
||||||
public async Task ConnectAsync()
|
|
||||||
{
|
|
||||||
await _tcpClient.ConnectAsync(_ip, _port);
|
|
||||||
_stream = _tcpClient.GetStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region ---- 基础 Modbus ----
|
|
||||||
private ushort GetTransactionId() =>
|
|
||||||
unchecked((ushort)Interlocked.Increment(ref Unsafe.As<ushort, int>(ref _transactionId)));
|
|
||||||
|
|
||||||
private async Task<byte[]> SendAndReceiveAsync(byte[] pdu, ushort startAddr, ushort length = 1)
|
|
||||||
{
|
|
||||||
ushort tid = GetTransactionId();
|
|
||||||
ushort lengthField = (ushort)(pdu.Length + 1);
|
|
||||||
byte[] mbap = {
|
|
||||||
(byte)(tid >> 8), (byte)tid,
|
|
||||||
0x00, 0x00, // Protocol = 0
|
|
||||||
(byte)(lengthField >> 8), (byte)lengthField,
|
|
||||||
_slaveId
|
|
||||||
};
|
|
||||||
|
|
||||||
byte[] adu = new byte[mbap.Length + pdu.Length];
|
|
||||||
Buffer.BlockCopy(mbap, 0, adu, 0, mbap.Length);
|
|
||||||
Buffer.BlockCopy(pdu, 0, adu, mbap.Length, pdu.Length);
|
|
||||||
|
|
||||||
await _lock.WaitAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _stream.WriteAsync(adu, 0, adu.Length);
|
|
||||||
|
|
||||||
byte[] header = new byte[7];
|
|
||||||
await _stream.ReadAsync(header, 0, 7);
|
|
||||||
int respLength = (header[4] << 8) + header[5];
|
|
||||||
byte[] resp = new byte[respLength - 1];
|
|
||||||
await _stream.ReadAsync(resp, 0, resp.Length);
|
|
||||||
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
finally { _lock.Release(); }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ---- 地址解析 ----
|
|
||||||
private void ParseAddress(string address, out string area, out ushort offset)
|
|
||||||
{
|
|
||||||
var letters = Regex.Match(address, @"^[A-Za-z]+").Value.ToUpper();
|
|
||||||
var digits = Regex.Match(address, @"\d+").Value;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(letters) || string.IsNullOrEmpty(digits))
|
|
||||||
throw new ArgumentException($"地址 {address} 无效");
|
|
||||||
|
|
||||||
area = letters;
|
|
||||||
offset = (ushort)(ushort.Parse(digits) - 1);
|
|
||||||
|
|
||||||
// 👉 注意:这里的偏移需根据你的 PLC Modbus 地址表调整
|
|
||||||
// 例如 D 区可能是 40001 起,M 区可能是 00001 起
|
|
||||||
// 目前假设 D -> Holding Register, M/Y -> Coil, X -> Discrete Input
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ---- 整数读写 ----
|
|
||||||
public async Task WriteAsync(string address, int value)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
|
|
||||||
switch (area)
|
|
||||||
{
|
|
||||||
case "D": // 写寄存器
|
|
||||||
byte[] pdu = {
|
|
||||||
0x06,
|
|
||||||
(byte)(offset >> 8), (byte)offset,
|
|
||||||
(byte)(value >> 8), (byte)value
|
|
||||||
};
|
|
||||||
await SendAndReceiveAsync(pdu, offset);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "M":
|
|
||||||
case "Y": // 写单线圈
|
|
||||||
byte[] coil = {
|
|
||||||
0x05,
|
|
||||||
(byte)(offset >> 8), (byte)offset,
|
|
||||||
(byte)(value != 0 ? 0xFF : 0x00), 0x00
|
|
||||||
};
|
|
||||||
await SendAndReceiveAsync(coil, offset);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException($"写 {area} 区未支持");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> ReadAsync(string address)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
|
|
||||||
switch (area)
|
|
||||||
{
|
|
||||||
case "D": // Holding Register
|
|
||||||
byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
|
|
||||||
var resp = await SendAndReceiveAsync(pdu, offset);
|
|
||||||
return (resp[1] << 8) + resp[2];
|
|
||||||
|
|
||||||
case "M":
|
|
||||||
case "Y": // Coils
|
|
||||||
byte[] pdu1 = { 0x01, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
|
|
||||||
var resp1 = await SendAndReceiveAsync(pdu1, offset);
|
|
||||||
return (resp1[2] & 0x01) != 0 ? 1 : 0;
|
|
||||||
|
|
||||||
case "X": // Inputs
|
|
||||||
byte[] pdu2 = { 0x02, (byte)(offset >> 8), (byte)offset, 0x00, 0x01 };
|
|
||||||
var resp2 = await SendAndReceiveAsync(pdu2, offset);
|
|
||||||
return (resp2[2] & 0x01) != 0 ? 1 : 0;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException($"读 {area} 区未支持");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ---- 浮点读写 (2寄存器) ----
|
|
||||||
public async Task WriteFloatAsync(string address, float value)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
if (area != "D") throw new NotSupportedException("浮点仅支持 D 区");
|
|
||||||
|
|
||||||
byte[] bytes = BitConverter.GetBytes(value);
|
|
||||||
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
|
|
||||||
|
|
||||||
byte[] pdu = {
|
|
||||||
0x10,
|
|
||||||
(byte)(offset >> 8), (byte)offset,
|
|
||||||
0x00, 0x02,
|
|
||||||
0x04,
|
|
||||||
bytes[0], bytes[1], bytes[2], bytes[3]
|
|
||||||
};
|
|
||||||
await SendAndReceiveAsync(pdu, offset, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<float> ReadFloatAsync(string address)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
if (area != "D") throw new NotSupportedException("浮点仅支持 D 区");
|
|
||||||
|
|
||||||
byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, 0x00, 0x02 };
|
|
||||||
var resp = await SendAndReceiveAsync(pdu, offset, 2);
|
|
||||||
|
|
||||||
byte[] data = { resp[1], resp[2], resp[3], resp[4] };
|
|
||||||
if (BitConverter.IsLittleEndian) Array.Reverse(data);
|
|
||||||
|
|
||||||
return BitConverter.ToSingle(data, 0);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ---- 字符串读写 ----
|
|
||||||
public async Task WriteStringAsync(string address, string value, int maxLength)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
if (area != "D") throw new NotSupportedException("字符串仅支持 D 区");
|
|
||||||
|
|
||||||
byte[] strBytes = Encoding.ASCII.GetBytes(value);
|
|
||||||
if (strBytes.Length > maxLength) Array.Resize(ref strBytes, maxLength);
|
|
||||||
|
|
||||||
// 每寄存器2字节
|
|
||||||
int regCount = (strBytes.Length + 1) / 2;
|
|
||||||
byte[] data = new byte[regCount * 2];
|
|
||||||
Array.Copy(strBytes, data, strBytes.Length);
|
|
||||||
|
|
||||||
byte[] pdu = new byte[7 + data.Length];
|
|
||||||
pdu[0] = 0x10;
|
|
||||||
pdu[1] = (byte)(offset >> 8); pdu[2] = (byte)offset;
|
|
||||||
pdu[3] = (byte)(regCount >> 8); pdu[4] = (byte)regCount;
|
|
||||||
pdu[5] = (byte)(data.Length);
|
|
||||||
Buffer.BlockCopy(data, 0, pdu, 6, data.Length);
|
|
||||||
|
|
||||||
await SendAndReceiveAsync(pdu, offset, (ushort)regCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReadStringAsync(string address, int length)
|
|
||||||
{
|
|
||||||
ParseAddress(address, out string area, out ushort offset);
|
|
||||||
if (area != "D") throw new NotSupportedException("字符串仅支持 D 区");
|
|
||||||
|
|
||||||
int regCount = (length + 1) / 2;
|
|
||||||
byte[] pdu = { 0x03, (byte)(offset >> 8), (byte)offset, (byte)(regCount >> 8), (byte)regCount };
|
|
||||||
var resp = await SendAndReceiveAsync(pdu, offset, (ushort)regCount);
|
|
||||||
|
|
||||||
byte[] data = new byte[resp[0]];
|
|
||||||
Array.Copy(resp, 1, data, 0, data.Length);
|
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(data).TrimEnd('\0');
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_stream?.Dispose();
|
|
||||||
_tcpClient?.Close();
|
|
||||||
_lock?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
using HslCommunication;
|
||||||
|
using HslCommunication.ModBus;
|
||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
// ModbusTcp读写服务类,线程安全,互斥锁
|
||||||
|
namespace Check.Main.Common
|
||||||
|
{
|
||||||
|
public class ModbusTcpService
|
||||||
|
{
|
||||||
|
private readonly TcpClient _tcpClient = new();
|
||||||
|
private readonly ModbusTcpNet _plc;
|
||||||
|
private readonly object _lock = new();
|
||||||
|
public bool IsConnected => _tcpClient != null && _tcpClient.Connected;//
|
||||||
|
//
|
||||||
|
public ModbusTcpService(string ip, int port = 502, byte station = 1)
|
||||||
|
{
|
||||||
|
_plc = new ModbusTcpNet(ip, port, station)
|
||||||
|
{
|
||||||
|
// CDAB 格式:PLC的不同品牌的modelbus TCP存在正反高低位。如果读写异常。删掉或者补充下面这句函数进行修复
|
||||||
|
DataFormat = HslCommunication.Core.DataFormat.CDAB
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 32 位整数
|
||||||
|
public OperateResult<int> ReadInt32(string address)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.ReadInt32(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入 32 位整数(int)
|
||||||
|
public OperateResult WriteInt32(string address, int value)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.Write(address, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 16 位整数(short)
|
||||||
|
public OperateResult<short> ReadInt16(string address)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.ReadInt16(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入 16 位整数(short)
|
||||||
|
public OperateResult WriteInt16(string address, short value)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.Write(address, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 读取布尔量
|
||||||
|
public OperateResult<bool> ReadBool(string address)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.ReadBool(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入布尔量
|
||||||
|
public OperateResult WriteBool(string address, bool value)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.Write(address, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取浮点数(float)
|
||||||
|
public OperateResult<float> ReadFloat(string address)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.ReadFloat(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入浮点数(float)
|
||||||
|
public OperateResult WriteFloat(string address, float value)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _plc.Write(address, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭连接
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_plc.ConnectClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ namespace Check.Main
|
|||||||
public partial class FrmMain : Form
|
public partial class FrmMain : Form
|
||||||
{
|
{
|
||||||
// private FrmCamConfig _formCameraConfig;
|
// private FrmCamConfig _formCameraConfig;
|
||||||
public static EasyPlcClient PlcClient;//定义全局PLC对象 --- 10.10添加①
|
public static ModbusTcpService PlcClient;//定义全局PLC对象 --- 10.10添加①
|
||||||
|
|
||||||
private FrmConfig _frmConfig;
|
private FrmConfig _frmConfig;
|
||||||
private FrmLog _formLog;
|
private FrmLog _formLog;
|
||||||
@@ -47,8 +47,8 @@ namespace Check.Main
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlcClient = new EasyPlcClient("192.168.1.88", 502);
|
PlcClient = new ModbusTcpService("192.168.1.88", 502);
|
||||||
await PlcClient.ConnectAsync();
|
// await PlcClient.ConnectAsync();
|
||||||
ThreadSafeLogger.Log("[PLC] 已成功连接到汇川PLC");
|
ThreadSafeLogger.Log("[PLC] 已成功连接到汇川PLC");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -62,8 +62,8 @@ namespace Check.Main
|
|||||||
// 初始化PLC连接-----10.10添加
|
// 初始化PLC连接-----10.10添加
|
||||||
await InitPlcConnection();
|
await InitPlcConnection();
|
||||||
|
|
||||||
EasyPlcClient easyPlcClient = new EasyPlcClient("127.0.0.1", 502, 1);
|
ModbusTcpService easyPlcClient = new ModbusTcpService("192.168.1.88", 502, 1);
|
||||||
easyPlcClient.ConnectAsync();
|
//easyPlcClient.ConnectAsync();
|
||||||
_frmConfig = new FrmConfig { Text = "主程序配置" };
|
_frmConfig = new FrmConfig { Text = "主程序配置" };
|
||||||
_formLog = new FrmLog { Text = "运行日志" };
|
_formLog = new FrmLog { Text = "运行日志" };
|
||||||
_formStatistics = new FormStatistics { Text = "生产统计" };
|
_formStatistics = new FormStatistics { Text = "生产统计" };
|
||||||
|
|||||||
@@ -18,16 +18,16 @@ namespace Check.Main.Infer
|
|||||||
[Description("GPU")]
|
[Description("GPU")]
|
||||||
GPU,
|
GPU,
|
||||||
|
|
||||||
[Description("VPU")]
|
//[Description("VPU")]
|
||||||
VPU,
|
//VPU,
|
||||||
}
|
}
|
||||||
public enum ModelVersion
|
public enum AlgorithmType
|
||||||
{
|
{
|
||||||
[Description("v8")]
|
[Description("传统算法")]
|
||||||
V8 = 0,
|
Tradition = 0,
|
||||||
|
|
||||||
[Description("v11")]
|
[Description("深度学习")]
|
||||||
V11,
|
DeepLearning,
|
||||||
}
|
}
|
||||||
public enum CheckModelType
|
public enum CheckModelType
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ namespace Check.Main.Infer
|
|||||||
private string _name = "New Model";
|
private string _name = "New Model";
|
||||||
private string _path = "";
|
private string _path = "";
|
||||||
private DetectDevice _checkDevice=DetectDevice.CPU;
|
private DetectDevice _checkDevice=DetectDevice.CPU;
|
||||||
private ModelVersion _mVersion=ModelVersion.V8;
|
private AlgorithmType _mAType = AlgorithmType.Tradition;
|
||||||
private CheckModelType _mType = CheckModelType.Classification;
|
private CheckModelType _mType = CheckModelType.Classification;
|
||||||
private bool _isEnabled = true;
|
private bool _isEnabled = true;
|
||||||
|
|
||||||
@@ -81,12 +81,12 @@ namespace Check.Main.Infer
|
|||||||
set { if (_checkDevice != value) { _checkDevice = value; OnPropertyChanged(); } }
|
set { if (_checkDevice != value) { _checkDevice = value; OnPropertyChanged(); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Category("基本信息"), DisplayName("模型版本"), Description("推理模型的版本。")]
|
[Category("基本信息"), DisplayName("算法类型"), Description("所使用的算法的类型。")]
|
||||||
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
|
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
|
||||||
public ModelVersion MVersion
|
public AlgorithmType M_AType
|
||||||
{
|
{
|
||||||
get => _mVersion;
|
get => _mAType;
|
||||||
set { if (_mVersion != value) { _mVersion = value; OnPropertyChanged(); } }
|
set { if (_mAType != value) { _mAType = value; OnPropertyChanged(); } }
|
||||||
}
|
}
|
||||||
[Category("基本信息"), DisplayName("模型类型"), Description("推理模型的类型。")]
|
[Category("基本信息"), DisplayName("模型类型"), Description("推理模型的类型。")]
|
||||||
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
|
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
//cyf
|
||||||
public class ProcessImg
|
public class ProcessImg
|
||||||
{
|
{
|
||||||
// 对单个图像进行模板匹配
|
// 对单个图像进行模板匹配
|
||||||
|
|||||||
Reference in New Issue
Block a user