Files
2025-11-21 15:50:42 +08:00

539 lines
20 KiB
C#
Raw Permalink 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 HslCommunication;
using HslCommunication.Profinet.Siemens;
using MvCamCtrl.NET;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
namespace WaferAlignment
{
public class Camera
{
private bool _isConnected = false;
public bool IsConnected
{
get { return _isConnected; }
set { _isConnected = value; }
}
private bool _isStarted = false;
public bool IsStarted
{
get { return _isStarted; }
set { _isStarted = value; }
}
public event Action<Bitmap> OutputImageEvent;
private float expo = 12;
private uint imgHeight = 4000;
private MyCamera _dev;
private CancellationTokenSource _startAcqToken;
private CancellationTokenSource _stopAcqToken;
private Task _imageAcquisitionTask;
private static Object BufForDriverLock = new Object();
private IntPtr m_BufForDriver = IntPtr.Zero;
private UInt32 m_nBufSizeForDriver = 0;
private MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
public void Connect()
{
IntPtr devIPtr;
try
{
MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE, ref m_stDeviceList);
if (m_stDeviceList.nDeviceNum > 0)
{
devIPtr = m_stDeviceList.pDeviceInfo[0];
}
else
{
throw new Exception("未找到相机连接!");
}
}
catch (Exception ex)
{
throw new Exception("相机查找失败!");
}
MyCamera.MV_CC_DEVICE_INFO devInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(devIPtr, typeof(MyCamera.MV_CC_DEVICE_INFO));
if (_dev != null)
{
throw new Exception("相机连接失败,原因:该设备实例已存在");
}
_dev = new MyCamera();
if (_dev == null)
{
throw new Exception("相机连接失败,原因:该设备实例化失败");
}
int status = _dev.MV_CC_CreateDevice_NET(ref devInfo);
if (status != MyCamera.MV_OK)
{
throw new Exception(String.Format("相机连接失败,原因:设备创建失败"));
}
status = _dev.MV_CC_OpenDevice_NET();
if (status != MyCamera.MV_OK)
{
throw new Exception(String.Format("相机连接失败,原因:设备启动失败"));
}
int nPacketSize = _dev.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
status = _dev.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
if (status != MyCamera.MV_OK)
{
throw new Exception(String.Format("相机连接失败,原因:获取本地包大小失败"));
}
}
else
{
throw new Exception(String.Format("相机连接失败,原因:获取本地包大小失败"));
}
// 连续采集
int nRet;
nRet = _dev.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
// 手动曝光
nRet = _dev.MV_CC_SetEnumValue_NET("ExposureAuto", (uint)MyCamera.MV_CAM_EXPOSURE_AUTO_MODE.MV_EXPOSURE_AUTO_MODE_OFF);
// 行触发关闭
//nRet = _dev.MV_CC_SetEnumValue_NET("TriggerSelector", 9);
//nRet = _dev.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
// 帧触发打开,软件触发
nRet = _dev.MV_CC_SetEnumValue_NET("TriggerSelector", 6);
nRet = _dev.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
nRet = _dev.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_COUNTER0);
nRet = _dev.MV_CC_SetFloatValue_NET("ExposureTime", expo);
//nRet = _dev.MV_CC_SetIntValue_NET("Width", 1600);
//nRet = _dev.MV_CC_SetIntValue_NET("Height", 1200);
//nRet = _dev.MV_CC_SetIntValue_NET("OffsetX", 1760);
//nRet = _dev.MV_CC_SetIntValue_NET("OffsetY", 1448);
_isConnected = true;
}
public void Disconnect()
{
if (_dev != null)
{
// 关闭设备
_dev.MV_CC_CloseDevice_NET();
_dev.MV_CC_DestroyDevice_NET();
_dev = null;
_isConnected = false;
}
}
public void Start()
{
if (_dev == null)
{
_isStarted = false;
MessageBox.Show("相机启动失败,相机未连接");
return;
}
ImageAcquisitionStart();
m_stFrameInfo.nFrameLen = 0;//取流之前先清除帧长度
m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
_dev.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_COUNTER0);
int nRet = _dev.MV_CC_StartGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
ImageAcquisitionStop();
_isStarted = false;
MessageBox.Show("相机启动失败,清除缓存区失败");
return;
}
_isStarted = true;
}
public void SoftwareGrab()
{
_dev.MV_CC_StopGrabbing_NET();
_dev.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
_dev.MV_CC_StartGrabbing_NET();
_dev.MV_CC_TriggerSoftwareExecute_NET();
}
public void Stop()
{
if (_dev == null)
{
_isStarted = false;
MessageBox.Show("相机停止失败,相机未连接");
return;
}
ImageAcquisitionStop();
int nRet = _dev.MV_CC_StopGrabbing_NET();
if (nRet != MyCamera.MV_OK)
{
_isStarted = false;
MessageBox.Show("相机停止失败");
return;
}
_isStarted = false;
}
private void ImageAcquisitionStart()
{
_startAcqToken = new CancellationTokenSource();
_imageAcquisitionTask = new Task(() => ImageAcquisitionProcess(), _startAcqToken.Token);
_imageAcquisitionTask.Start();
}
private void ImageAcquisitionStop()
{
try
{
_startAcqToken.Cancel();
Thread.Sleep(200);
_imageAcquisitionTask.Wait(_stopAcqToken.Token);
_imageAcquisitionTask.Dispose();
}
catch (OperationCanceledException ex)
{
_imageAcquisitionTask.Dispose();
}
}
private void ImageAcquisitionProcess()
{
_stopAcqToken = new CancellationTokenSource();
MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
while (true)
{
if (_startAcqToken.IsCancellationRequested)
break;
int nRet = _dev.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);
Console.WriteLine("-----------------------Get Image Buffer:" + "Width[" + Convert.ToString(stFrameInfo.stFrameInfo.nWidth) + "] , Height[" + Convert.ToString(stFrameInfo.stFrameInfo.nHeight)
+ "] ,Trigger[" + Convert.ToString(stFrameInfo.stFrameInfo.nTriggerIndex) + "], FrameNum[" + Convert.ToString(stFrameInfo.stFrameInfo.nFrameNum) + "]");
if (nRet == MyCamera.MV_OK)
{
lock (BufForDriverLock)
{
if (m_BufForDriver == IntPtr.Zero || stFrameInfo.stFrameInfo.nFrameLen > m_nBufSizeForDriver)
{
if (m_BufForDriver != IntPtr.Zero)
{
Marshal.Release(m_BufForDriver);
m_BufForDriver = IntPtr.Zero;
}
m_BufForDriver = Marshal.AllocHGlobal((Int32)stFrameInfo.stFrameInfo.nFrameLen);
if (m_BufForDriver == IntPtr.Zero)
{
return;
}
m_nBufSizeForDriver = stFrameInfo.stFrameInfo.nFrameLen;
}
m_stFrameInfo = stFrameInfo.stFrameInfo;
CopyMemory(m_BufForDriver, stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo.nFrameLen);
}
if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType))
{
_dev.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
continue;
}
//从缓存区获取图片
IntPtr pTemp = IntPtr.Zero;
MyCamera.MvGvspPixelType enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
if (m_stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
{
pTemp = m_BufForDriver;
enDstPixelType = m_stFrameInfo.enPixelType;
}
else
{
//ErrorMsgEvent(DeviceName + " -> 图像格式错误");
}
_dev.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
//************************Mono8 转 Bitmap*******************************
Bitmap bmp = new Bitmap(m_stFrameInfo.nWidth, m_stFrameInfo.nHeight, m_stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pTemp);
ColorPalette cp = bmp.Palette;
for (int i = 0; i < 256; i++)
{
cp.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = cp;
OutputImageEvent(bmp);
}
else
{
Thread.Sleep(10);
}
}
_stopAcqToken.Cancel();
}
private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
{
Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000));
if (0x80000000 == nResult)
{
return true;
}
else
{
return false;
}
}
//public Bitmap Trigger()
//{
// if (_dev == null)
// {
// throw new Exception(String.Format("相机触发失败,原因:该设备未连接"));
// }
// _dev.MV_CC_SetEnumValue_NET("TriggerSelector", 6);
// int nRet = _dev.MV_CC_SetCommandValue_NET("TriggerSoftware");
// if (MyCamera.MV_OK != nRet)
// {
// throw new Exception(String.Format("相机触发失败"));
// }
// MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
// nRet = _dev.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);
// if (nRet == MyCamera.MV_OK)
// {
// lock (BufForDriverLock)
// {
// if (m_BufForDriver == IntPtr.Zero || stFrameInfo.stFrameInfo.nFrameLen > m_nBufSizeForDriver)
// {
// if (m_BufForDriver != IntPtr.Zero)
// {
// Marshal.Release(m_BufForDriver);
// m_BufForDriver = IntPtr.Zero;
// }
// m_BufForDriver = Marshal.AllocHGlobal((Int32)stFrameInfo.stFrameInfo.nFrameLen);
// if (m_BufForDriver == IntPtr.Zero)
// {
// return null;
// }
// m_nBufSizeForDriver = stFrameInfo.stFrameInfo.nFrameLen;
// }
// m_stFrameInfo = stFrameInfo.stFrameInfo;
// CopyMemory(m_BufForDriver, stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo.nFrameLen);
// }
// if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType))
// {
// _dev.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
// return null;
// }
// //从缓存区获取图片
// IntPtr pTemp = IntPtr.Zero;
// MyCamera.MvGvspPixelType enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
// if (m_stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
// {
// pTemp = m_BufForDriver;
// enDstPixelType = m_stFrameInfo.enPixelType;
// }
// _dev.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
// //************************Mono8 转 Bitmap*******************************
// Bitmap bmp = new Bitmap(m_stFrameInfo.nWidth, m_stFrameInfo.nHeight, m_stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pTemp);
// ColorPalette cp = bmp.Palette;
// for (int i = 0; i < 256; i++)
// {
// cp.Entries[i] = Color.FromArgb(i, i, i);
// }
// bmp.Palette = cp;
// return bmp;
// }
// else
// {
// return null;
// }
//}
//private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
//{
// Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000));
// if (0x80000000 == nResult)
// {
// return true;
// }
// else
// {
// return false;
// }
//}
}
public class SiemensS7
{
private SiemensS7Net _s7;
private string _ip;
public bool OK { get; private set; }
private System.Timers.Timer _reconnectTimer;
public SiemensS7(string ip)
{
OK = false;
_ip = ip;
_reconnectTimer = new System.Timers.Timer(5000); // 设置定时器为5秒
_reconnectTimer.Elapsed += ReconnectTimerElapsed;
_reconnectTimer.AutoReset = true;
}
//public void Connect()
//{
// _s7 = new SiemensS7Net(SiemensPLCS.S1200);
// _s7.IpAddress = _ip;
// _s7.Port = 102;
// OperateResult operateResult = _s7.ConnectServer();
// if (!operateResult.IsSuccess)
// {
// throw new Exception(string.Format("Siemens S7 S1200客户端连接失败"));
// }
//}
public void Connect()
{
_s7 = new SiemensS7Net(SiemensPLCS.S1200);
_s7.IpAddress = _ip;
_s7.Port = 102;
TryConnect();
}
private void TryConnect()
{
OperateResult operateResult = _s7.ConnectServer();
if (!operateResult.IsSuccess)
{
OK = false;
Console.WriteLine("Siemens S7 S1200客户端连接失败5秒后重试...");
_reconnectTimer.Start(); // 启动定时器
}
else
{
OK = true;
Console.WriteLine("Siemens S7 S1200客户端连接成功");
_reconnectTimer.Stop(); // 停止定时器
}
}
private void ReconnectTimerElapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("尝试重新连接...");
TryConnect();
}
public void Disconnect()
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
OperateResult operateResult = _s7.ConnectClose();
if (!operateResult.IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1200客户端断开失败"));
}
}
public bool GetValue(string address, out bool value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
OperateResult<bool> boolResult = _s7.ReadBool(address);
if (boolResult.IsSuccess)
{
value = boolResult.Content;
return true;
}
else
{
value = false;
return false;
}
}
public void SetValue(string address, bool value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
public void SetValue(string address, int value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
public void SetValue(string address, uint value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
public void SetValue(string address, short value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
public void SetValue(string address, ushort value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
public void SetValue(string address, float value)
{
if (_s7 == null)
{
throw new Exception(string.Format("Siemens S7 S1200通信未连接"));
}
if (!_s7.Write(address, value).IsSuccess)
{
throw new Exception(string.Format("Siemens S7 S1500客户端发送数据失败"));
}
}
}
}