步进电机 挡料地

This commit is contained in:
Admin
2025-04-22 18:03:12 +08:00
parent 74051a4287
commit 33e94b92f9
13 changed files with 1378 additions and 585 deletions

View File

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