步进电机 挡料地
This commit is contained in:
@ -1,8 +1,11 @@
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing.Imaging;
|
||||
using AntdUI;
|
||||
using DH.Commons.Base;
|
||||
using DH.Commons.Enums;
|
||||
using DH.Commons.Helper;
|
||||
using DH.Commons.Models;
|
||||
using DH.Devices.Camera;
|
||||
using HalconDotNet;
|
||||
using OpenCvSharp.Extensions;
|
||||
@ -45,23 +48,228 @@ namespace DHSoftware.Views
|
||||
btnSaveImg.Click += BtnSaveImg_Click;
|
||||
btnSavePos.Click += BtnSavePos_Click;
|
||||
sltCameraName.SelectedIndexChanged += SltCameraName_SelectedIndexChanged;
|
||||
btnMotorForward.MouseDown += BtnMotorForward_MouseDown;
|
||||
btnMotorForward.MouseUp += MotorButton_MouseUp;
|
||||
btnMotorReverse.MouseDown += BtnMotorReverse_MouseDown;
|
||||
btnMotorReverse.MouseUp += MotorButton_MouseUp;
|
||||
btnMotorZero.Click += BtnMotorZero_Click;
|
||||
btnSaveMotorPos.Click += BtnSaveMotorPos_Click;
|
||||
panelMotor.Visible = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void BtnSaveMotorPos_Click(object? sender, EventArgs e)
|
||||
{
|
||||
//根据工位查找点位
|
||||
PLCItem? pLCItem = ConfigModel.PLCBaseList?
|
||||
.FirstOrDefault()?
|
||||
.PLCItemList?
|
||||
.Where(it => it.Name == "相机步进位置").FirstOrDefault();
|
||||
if (pLCItem == null)
|
||||
{
|
||||
AntdUI.Message.warn(this, $"未找到相机步进位置地址,请检查该地址是否存在于点位表!", autoClose: 3);
|
||||
return;
|
||||
}
|
||||
|
||||
PLCItem? pLCItem1 = ConfigModel.GlobalList?
|
||||
.FirstOrDefault()?
|
||||
.StartProcessList?
|
||||
.Where(it => it.Name == "相机步进位置").FirstOrDefault();
|
||||
|
||||
if (pLCItem1 == null)
|
||||
{
|
||||
pLCItem1 = new PLCItem();
|
||||
pLCItem1.Name = pLCItem.Name;
|
||||
pLCItem1.Address = pLCItem.Address;
|
||||
pLCItem1.Value = iptMotorPos.Text;
|
||||
pLCItem1.Type = pLCItem.Type;
|
||||
pLCItem1.StartExecute = true;
|
||||
ConfigModel.GlobalList?
|
||||
.FirstOrDefault()?
|
||||
.StartProcessList?.Add(pLCItem1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pLCItem1.Value = iptMotorPos.Text;
|
||||
}
|
||||
|
||||
ConfigHelper.SaveConfig();
|
||||
AntdUI.Message.success(this, "保存成功!", autoClose: 3);
|
||||
}
|
||||
private CancellationTokenSource? _motorCts;
|
||||
private bool _isMotorOperating;
|
||||
private bool _isHoming;
|
||||
|
||||
|
||||
|
||||
private CancellationTokenSource _cts;
|
||||
private bool _isBusy;
|
||||
|
||||
// 电机正转控制
|
||||
private async void BtnMotorForward_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_isBusy = true;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取并处理速度值
|
||||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed == 0)
|
||||
{
|
||||
AntdUI.Message.warn(this, "速度值无效");
|
||||
return;
|
||||
}
|
||||
int actualSpeed = Math.Abs(speed); // 正转取绝对值
|
||||
|
||||
// 启动PLC控制
|
||||
_cts?.Dispose();
|
||||
_cts = new CancellationTokenSource();
|
||||
MainWindow.Instance.PLC.MotorSpeed(actualSpeed);
|
||||
MainWindow.Instance.PLC.MotorTest(true);
|
||||
|
||||
// 实时更新循环
|
||||
while (!_cts.IsCancellationRequested)
|
||||
{
|
||||
var pos = await Task.Run(() => MainWindow.Instance.PLC.ReadMotorRealPos());
|
||||
iptMotorPos.Text = pos.ToString();
|
||||
await Task.Delay(50);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AntdUI.Message.error(this, $"正转异常: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
MainWindow.Instance.PLC.MotorTest(false);
|
||||
_isBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 电机反转控制
|
||||
// 电机反转控制(带原点保护)
|
||||
private async void BtnMotorReverse_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_isBusy = true;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取并处理速度值
|
||||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed == 0)
|
||||
{
|
||||
AntdUI.Message.warn(this, "速度值无效");
|
||||
return;
|
||||
}
|
||||
int actualSpeed = -Math.Abs(speed);
|
||||
|
||||
// 实时位置检查(启动前)
|
||||
int currentPos = MainWindow.Instance.PLC.ReadMotorRealPos();
|
||||
if (currentPos <= 0)
|
||||
{
|
||||
AntdUI.Message.info(this, "已在原点位置");
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动PLC控制
|
||||
_cts?.Dispose();
|
||||
_cts = new CancellationTokenSource();
|
||||
MainWindow.Instance.PLC.MotorSpeed(actualSpeed);
|
||||
MainWindow.Instance.PLC.MotorTest(true);
|
||||
|
||||
// 带保护的实时更新循环
|
||||
while (!_cts.IsCancellationRequested)
|
||||
{
|
||||
currentPos = await Task.Run(() => MainWindow.Instance.PLC.ReadMotorRealPos());
|
||||
|
||||
// 位置边界保护
|
||||
if (currentPos <= 0)
|
||||
{
|
||||
_cts.Cancel();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 更新UI
|
||||
this.Invoke((MethodInvoker)delegate {
|
||||
iptMotorPos.Text = currentPos.ToString();
|
||||
});
|
||||
|
||||
await Task.Delay(50);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AntdUI.Message.error(this, $"反转异常: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
MainWindow.Instance.PLC.MotorTest(false);
|
||||
_isBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 停止控制(正反转共用)
|
||||
private void MotorButton_MouseUp(object sender, MouseEventArgs e) {
|
||||
_cts?.Cancel();
|
||||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||||
}
|
||||
|
||||
// 回零操作
|
||||
private async void BtnMotorZero_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_isBusy) return;
|
||||
_isBusy = true;
|
||||
btnMotorForward.Enabled = btnMotorReverse.Enabled = false;
|
||||
|
||||
try
|
||||
{
|
||||
// 获取速度值
|
||||
if (!int.TryParse(iptMotorSpeed.Text, out int speed) || speed <= 0)
|
||||
{
|
||||
AntdUI.Message.warn(this, "速度值无效");
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行回零
|
||||
MainWindow.Instance.PLC.MotorSpeed(speed);
|
||||
await Task.Run(() => MainWindow.Instance.PLC.MotorToZero(true));
|
||||
|
||||
// 等待回零完成
|
||||
while (MainWindow.Instance.PLC.ReadMotorRealPos() != 0)
|
||||
{
|
||||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
await Task.Run(() => MainWindow.Instance.PLC.MotorToZero(false));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AntdUI.Message.error(this, $"回零失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
btnMotorForward.Enabled = btnMotorReverse.Enabled = true;
|
||||
_isBusy = false;
|
||||
iptMotorPos.Text = MainWindow.Instance.PLC.ReadMotorRealPos().ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private void SltCameraName_SelectedIndexChanged(object sender, IntEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
localizations = VisualLocalization.LoadAll();
|
||||
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SltCameraName_SelectedIndexChanged(object sender, IntEventArgs e)
|
||||
{
|
||||
|
||||
string cameraName= sltCameraName.Text;
|
||||
Do3ThinkCamera = MainWindow.Instance.Cameras.Where(it => it.CameraName == cameraName).FirstOrDefault() ?? new Do3ThinkCamera();
|
||||
VisualLocalization? visual= localizations.Where(it=>it.CameraName==cameraName).FirstOrDefault();
|
||||
if (visual != null)
|
||||
{
|
||||
@ -71,6 +279,14 @@ namespace DHSoftware.Views
|
||||
sltDirection.SelectedIndex = visual.Direction == "正方向" ? 0 : 1;
|
||||
iptSpeed.Text = visual.Speed;
|
||||
}
|
||||
if (Do3ThinkCamera.IsZoomCamera)
|
||||
{
|
||||
panelMotor.Visible=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
panelMotor.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnSavePos_Click(object? sender, EventArgs e)
|
||||
@ -272,6 +488,78 @@ namespace DHSoftware.Views
|
||||
Do3ThinkCamera.Snapshot();
|
||||
}
|
||||
|
||||
private CancellationTokenSource? _rotateCts;
|
||||
private bool _isRotating;
|
||||
/// <summary>
|
||||
/// 统一旋转控制方法
|
||||
/// </summary>
|
||||
private async Task RotateControlAsync(bool direction)
|
||||
{
|
||||
// 防止重复启动
|
||||
if (_isRotating) return;
|
||||
_isRotating = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (!MainWindow.Instance.PLC.Connected)
|
||||
{
|
||||
this.Invoke(() => AntdUI.Message.warn(this, "未连接PLC!", autoClose: 3));
|
||||
return;
|
||||
}
|
||||
|
||||
// 输入验证
|
||||
if (string.IsNullOrEmpty(iptSpeed.Text))
|
||||
{
|
||||
this.Invoke(() => AntdUI.Message.warn(this, "请输入速度!", autoClose: 3));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(iptSpeed.Text, out int speed) || speed <= 0)
|
||||
{
|
||||
this.Invoke(() => AntdUI.Message.warn(this, "速度必须为正整数!", autoClose: 3));
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化取消令牌
|
||||
_rotateCts?.Dispose();
|
||||
_rotateCts = new CancellationTokenSource();
|
||||
|
||||
// 设置PLC参数
|
||||
MainWindow.Instance.PLC.TurnSpeed(speed);
|
||||
MainWindow.Instance.PLC.TurnDirection(direction);
|
||||
MainWindow.Instance.PLC.TurnStart(true);
|
||||
|
||||
// 异步更新循环
|
||||
while (!_rotateCts.IsCancellationRequested)
|
||||
{
|
||||
var position = MainWindow.Instance.PLC.ReadVisionPos();
|
||||
Debug.WriteLine(position.ToString());
|
||||
this.BeginInvoke(() => iptPosition.Text = position.ToString());
|
||||
await Task.Delay(100, _rotateCts.Token);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 正常取消不处理
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Invoke(() => AntdUI.Message.error(this, $"操作异常:{ex.Message}"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保停止转动
|
||||
MainWindow.Instance.PLC.TurnStart(false);
|
||||
var finalPos = MainWindow.Instance.PLC.ReadVisionPos();
|
||||
this.Invoke(() => iptPosition.Text = finalPos.ToString());
|
||||
|
||||
_isRotating = false;
|
||||
_rotateCts?.Dispose();
|
||||
_rotateCts = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 反转抬起
|
||||
/// </summary>
|
||||
@ -279,15 +567,7 @@ namespace DHSoftware.Views
|
||||
/// <param name="e"></param>
|
||||
private void BtnReverse_MouseUp(object? sender, MouseEventArgs e)
|
||||
{
|
||||
if (MainWindow.Instance.PLC.Connected)
|
||||
{
|
||||
MainWindow.Instance.PLC.TurnStart(false);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
AntdUI.Message.warn(this, $"未连接PLC!", autoClose: 3);
|
||||
}
|
||||
_rotateCts?.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -295,38 +575,9 @@ namespace DHSoftware.Views
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnReverse_MouseDown(object? sender, MouseEventArgs e)
|
||||
private async void BtnReverse_MouseDown(object? sender, MouseEventArgs e)
|
||||
{
|
||||
if (MainWindow.Instance.PLC.Connected)
|
||||
{
|
||||
//开启转盘
|
||||
if (string.IsNullOrEmpty(iptSpeed.Text))
|
||||
{
|
||||
AntdUI.Message.warn(this, $"请输入速度!", autoClose: 3);
|
||||
return;
|
||||
}
|
||||
int speed = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bool isValid = int.TryParse(iptSpeed.Text, out speed);
|
||||
if (!isValid)
|
||||
{
|
||||
AntdUI.Message.warn(this, $"输入的速度不是有效值!", autoClose: 3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
MainWindow.Instance.PLC.TurnSpeed(speed);
|
||||
MainWindow.Instance.PLC.TurnDirection(false);
|
||||
MainWindow.Instance.PLC.TurnStart(true);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
AntdUI.Message.warn(this, $"未连接PLC!", autoClose: 3);
|
||||
}
|
||||
await RotateControlAsync(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -336,15 +587,7 @@ namespace DHSoftware.Views
|
||||
/// <param name="e"></param>
|
||||
private void BtnForward_MouseUp(object? sender, MouseEventArgs e)
|
||||
{
|
||||
if (MainWindow.Instance.PLC.Connected)
|
||||
{
|
||||
MainWindow.Instance.PLC.TurnStart(false);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
AntdUI.Message.warn(this, $"未连接PLC!", autoClose: 3);
|
||||
}
|
||||
_rotateCts?.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -352,38 +595,9 @@ namespace DHSoftware.Views
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void BtnForward_MouseDown(object? sender, MouseEventArgs e)
|
||||
private async void BtnForward_MouseDown(object? sender, MouseEventArgs e)
|
||||
{
|
||||
if (MainWindow.Instance.PLC.Connected)
|
||||
{
|
||||
//开启转盘
|
||||
if (string.IsNullOrEmpty(iptSpeed.Text))
|
||||
{
|
||||
AntdUI.Message.warn(this, $"请输入速度!", autoClose: 3);
|
||||
return;
|
||||
}
|
||||
int speed = 0;
|
||||
|
||||
try
|
||||
{
|
||||
bool isValid = int.TryParse(iptSpeed.Text, out speed);
|
||||
if (!isValid)
|
||||
{
|
||||
AntdUI.Message.warn(this, $"输入的速度不是有效值!", autoClose: 3);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
MainWindow.Instance.PLC.TurnSpeed(speed);
|
||||
MainWindow.Instance.PLC.TurnDirection(true);
|
||||
MainWindow.Instance.PLC.TurnStart(true);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
AntdUI.Message.warn(this, $"未连接PLC!", autoClose: 3);
|
||||
}
|
||||
await RotateControlAsync(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -488,23 +702,37 @@ namespace DHSoftware.Views
|
||||
private void OnCameraHImageOutput(DateTime dt, CameraBase camera, MatSet imageSet)
|
||||
{
|
||||
|
||||
imageViewerControl1.Image = imageSet._mat.ToBitmap();
|
||||
HObject obj = OpenCVHelper.MatToHImage(imageSet._mat);
|
||||
HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
|
||||
// 调用 ProcCall 的方法
|
||||
ProcCall.SetInputIconicParamObject("INPUT_Image", hImage); // 将图像输入Proc
|
||||
|
||||
|
||||
this.BeginInvoke(new MethodInvoker(delegate ()
|
||||
{
|
||||
|
||||
imageViewerControl1.Image = imageSet._mat.ToBitmap();
|
||||
if (isLocationing)
|
||||
{
|
||||
HObject obj = OpenCVHelper.MatToHImage(imageSet._mat);
|
||||
HImage hImage = HalconHelper.ConvertHObjectToHImage(obj);
|
||||
// 调用 ProcCall 的方法
|
||||
ProcCall.SetInputIconicParamObject("INPUT_Image", hImage); // 将图像输入Proc
|
||||
|
||||
ProcCall.SetInputIconicParamObject("BackGroundPic", backImage);
|
||||
ProcCall.SetInputIconicParamObject("BackGroundPic", backImage);
|
||||
|
||||
ProcCall.SetInputCtrlParamTuple("DistThreshold", Convert.ToInt32(iptThreshold.Text));
|
||||
ProcCall.Execute();
|
||||
double nNUm = ProcCall.GetOutputCtrlParamTuple("OUTPUT_Flag");
|
||||
ProcCall.SetInputCtrlParamTuple("DistThreshold", Convert.ToInt32(iptThreshold.Text));
|
||||
ProcCall.Execute();
|
||||
double nNUm = ProcCall.GetOutputCtrlParamTuple("OUTPUT_Flag");
|
||||
|
||||
if (nNUm == 0)
|
||||
{
|
||||
MainWindow.Instance.PLC.TurnStart(false);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
if (nNUm == 0)
|
||||
{
|
||||
MainWindow.Instance.PLC.TurnStart(false);
|
||||
iptPosition.Text = MainWindow.Instance.PLC.ReadVisionPos().ToString();
|
||||
isLocationing = false;
|
||||
btnLocalization.Text = "开始定位";
|
||||
btnLocalization.Type = TTypeMini.Primary;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user