- WeldingCommon/Devices/ACS/ ScannerACS 독립 구현 (Gun 참조 제거) - Scanner EquipmentSetup.RegisterDevices()에 ScannerACS + 모터 등록 - EquipDef.cs MotorIds 추가 - UCScannerMotionViewModel Stage X 조그 필드/커맨드/모니터링 추가 - UCScannerMotion.xaml Stage X Motion 섹션 추가 - SeqComponentTeachingRun MOTF 자리 확보 (_ACS 필드 선언, InitDev() 취득, MOTFStart/CheckMOTFComp 주석 준비) - AuroraEx Device 네임스페이스 충돌 수정 TODO: 이정인 선임 ACS 변수 맵 수신 후 - ScannerACS.Parameter.cs 변수명/버퍼 번호 교체 - MOTFStart() / CheckMOTFComp() 주석 해제 - 축 번호 검증
338 lines
12 KiB
C#
338 lines
12 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Api.Manager;
|
|
using Aurora.View;
|
|
using AuroraACS; // 26.04.06 NDY 추가
|
|
using AuroraLaser;
|
|
using AuroraLaserScanner;
|
|
using HarfBuzzSharp;
|
|
using Microsoft.Office.Interop.Excel;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Input;
|
|
using System.Windows.Threading;
|
|
|
|
namespace WeldingCommon.Views
|
|
{
|
|
public enum eAxisType
|
|
{
|
|
AXIS_X,
|
|
AXIS_Y
|
|
}
|
|
|
|
public enum eJogDirection
|
|
{
|
|
MINUS,
|
|
PLUS
|
|
}
|
|
|
|
public enum eMotionMode
|
|
{
|
|
ABS,
|
|
REL
|
|
};
|
|
|
|
public class UCScannerMotionViewModel : NotifyPropertyChangedBase
|
|
{
|
|
private readonly Logger Log = new Logger("UCScannerMotionViewModel");
|
|
|
|
public ICommand CMD_VisibleChanged { get; }
|
|
public ICommand CMD_SpeedChanged { get; }
|
|
public ICommand CMD_MotionModeChanged { get; }
|
|
public ICommand CMD_JogMove { get; }
|
|
public ICommand CMD_CommandPosMove { get; }
|
|
|
|
private readonly IAuroraEnvironment _Aurora;
|
|
private readonly Scanner _Scanner;
|
|
private readonly Laser _Laser;
|
|
private readonly ScannerConfig _ScannerConfig;
|
|
|
|
private double _ScannerXPos;
|
|
public double ScannerXPos { get => _ScannerXPos; set => SetProperty(ref _ScannerXPos, value); }
|
|
private double _ScannerYPos;
|
|
public double ScannerYPos { get => _ScannerYPos; set => SetProperty(ref _ScannerYPos, value); }
|
|
private bool _IsScannerBusy;
|
|
public bool IsScannerBusy { get => _IsScannerBusy; set => SetProperty(ref _IsScannerBusy, value); }
|
|
|
|
private double _StepValue;
|
|
public double StepValue { get => _StepValue; set => SetProperty(ref _StepValue, value); }
|
|
|
|
private double _CommandPosX;
|
|
public double CommandPosX { get => _CommandPosX; set => SetProperty(ref _CommandPosX, value); }
|
|
private double _CommandPosY;
|
|
public double CommandPosY { get => _CommandPosY; set => SetProperty(ref _CommandPosY, value); }
|
|
|
|
private double _CommandPosLimitMinX;
|
|
public double CommandPosLimitMinX { get => _CommandPosLimitMinX; set => SetProperty(ref _CommandPosLimitMinX, value); }
|
|
private double _CommandPosLimitMaxX;
|
|
public double CommandPosLimitMaxX { get => _CommandPosLimitMaxX; set => SetProperty(ref _CommandPosLimitMaxX, value); }
|
|
|
|
private double _CommandPosLimitMinY;
|
|
public double CommandPosLimitMinY { get => _CommandPosLimitMinY; set => SetProperty(ref _CommandPosLimitMinY, value); }
|
|
private double _CommandPosLimitMaxY;
|
|
public double CommandPosLimitMaxY { get => _CommandPosLimitMaxY; set => SetProperty(ref _CommandPosLimitMaxY, value); }
|
|
|
|
private double _VelocityRate;
|
|
private eMotionMode _MotionMode;
|
|
|
|
private readonly DispatcherTimer _MonitorTimer;
|
|
|
|
// 26.04.06 NDY Stage X 관련 필드 추가 ==================
|
|
private ACSMotor _MotorX;
|
|
|
|
private double _StageXPos;
|
|
public double StageXPos { get => _StageXPos; set => SetProperty(ref _StageXPos, value); }
|
|
|
|
private bool _IsStageXActivated;
|
|
public bool IsStageXActivated { get => _IsStageXActivated; set => SetProperty(ref _IsStageXActivated, value); }
|
|
// ========================================================
|
|
|
|
// PAM, RUW 처럼 2개 이상의 scanner 를 사용하는 경우가 있어, scannerId 를 받는 형태로 생성
|
|
public UCScannerMotionViewModel(IAuroraEnvironment aurora, string scannerId)
|
|
{
|
|
_Aurora = aurora;
|
|
|
|
_Scanner = _Aurora.DeviceManager[scannerId] as Scanner;
|
|
_Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser;
|
|
_ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(scannerId) as ScannerConfig;
|
|
|
|
// 26.04.06 NDY Stage X 모터 연결 추가 ===============
|
|
try { _MotorX = _Aurora.DeviceManager["AxisX2"] as ACSMotor; }
|
|
catch { _MotorX = null; }
|
|
// ====================================================
|
|
|
|
InitVariable();
|
|
|
|
CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
|
|
CMD_SpeedChanged = new DelegateCommand(PerformCmdSpeedChanged);
|
|
CMD_MotionModeChanged = new DelegateCommand(PerformCmdMotionModeChanged);
|
|
CMD_JogMove = new DelegateCommand(PerformCmdJogMove);
|
|
CMD_CommandPosMove = new DelegateCommand(PerformCmdCommandPosMove);
|
|
|
|
_MonitorTimer = new DispatcherTimer();
|
|
_MonitorTimer.Tick += OnMonitoring;
|
|
_MonitorTimer.Interval = TimeSpan.FromMilliseconds(100);
|
|
}
|
|
|
|
private void InitVariable()
|
|
{
|
|
_VelocityRate = 1;
|
|
_MotionMode = eMotionMode.ABS;
|
|
}
|
|
|
|
private void VisibleChanged(object obj)
|
|
{
|
|
bool visible = (bool)obj;
|
|
if (visible)
|
|
{
|
|
Init_XYLimitPos();
|
|
_MonitorTimer.Start();
|
|
}
|
|
else
|
|
{
|
|
_MonitorTimer.Stop();
|
|
}
|
|
}
|
|
|
|
private void Init_XYLimitPos()
|
|
{
|
|
CommandPosLimitMinX = -1 * _ScannerConfig.ScanXSize / 2;
|
|
CommandPosLimitMaxX = _ScannerConfig.ScanXSize / 2;
|
|
CommandPosLimitMinY = -1 * _ScannerConfig.ScanYSize / 2;
|
|
CommandPosLimitMaxY = _ScannerConfig.ScanYSize / 2;
|
|
}
|
|
|
|
private void OnMonitoring(object sender, EventArgs e)
|
|
{
|
|
// 기존 Scanner 모니터링
|
|
double xPos, yPos;
|
|
if (_Scanner != null && _Scanner.IsActivated)
|
|
{
|
|
_Scanner.GetXYPos(out xPos, out yPos);
|
|
ScannerXPos = xPos;
|
|
ScannerYPos = yPos;
|
|
IsScannerBusy = _Scanner.GetBusyStatus();
|
|
}
|
|
else
|
|
{
|
|
ScannerXPos = 0;
|
|
ScannerYPos = 0;
|
|
IsScannerBusy = false;
|
|
}
|
|
|
|
// 26.04.06 NDY Stage X 모니터링 추가 ================
|
|
if (_MotorX != null && _MotorX.IsActivated)
|
|
{
|
|
StageXPos = _MotorX.GetActualPos();
|
|
IsStageXActivated = true;
|
|
}
|
|
else
|
|
{
|
|
IsStageXActivated = false;
|
|
}
|
|
// ====================================================
|
|
}
|
|
|
|
private void PerformCmdSpeedChanged(object commandParameter)
|
|
{
|
|
switch ((string)commandParameter)
|
|
{
|
|
case "Low": _VelocityRate = 0.5; break;
|
|
case "Mid": _VelocityRate = 1; break;
|
|
case "High": _VelocityRate = 1.5; break;
|
|
}
|
|
}
|
|
|
|
private void PerformCmdMotionModeChanged(object commandParameter)
|
|
{
|
|
switch ((string)commandParameter)
|
|
{
|
|
case "ABS": _MotionMode = eMotionMode.ABS; break;
|
|
case "REL": _MotionMode = eMotionMode.REL; break;
|
|
}
|
|
}
|
|
|
|
private void PerformCmdJogMove(object commandParameter)
|
|
{
|
|
var MainSequence = _Aurora.SequenceEntry[CommonSequenceIds.SeqAutoRun].RunState;
|
|
if (MainSequence == SequenceRunState.Running)
|
|
return;
|
|
|
|
switch ((string)commandParameter)
|
|
{
|
|
case "Left": MoveJogXYPos(eAxisType.AXIS_X, eJogDirection.MINUS); break;
|
|
case "Right": MoveJogXYPos(eAxisType.AXIS_X, eJogDirection.PLUS); break;
|
|
case "Up": MoveJogXYPos(eAxisType.AXIS_Y, eJogDirection.PLUS); break;
|
|
case "Down": MoveJogXYPos(eAxisType.AXIS_Y, eJogDirection.MINUS); break;
|
|
case "Home": MoveJogHome(); break;
|
|
|
|
// 26.04.06 NDY Stage X 버튼 추가 =================
|
|
case "Stage_X_Left": MoveStageX(eJogDirection.MINUS); break;
|
|
case "Stage_X_Right": MoveStageX(eJogDirection.PLUS); break;
|
|
// =================================================
|
|
}
|
|
}
|
|
|
|
// 26.04.06 NDY Stage X 이동 메서드 추가 ==================
|
|
private void MoveStageX(eJogDirection direction)
|
|
{
|
|
if (_MotorX == null || !_MotorX.IsActivated) return;
|
|
|
|
// 이미지 기준 방향 반전 적용
|
|
double step = direction == eJogDirection.PLUS ? -StepValue : +StepValue;
|
|
Log.I($"Stage X Move : {step}mm");
|
|
|
|
_MotorX.SetTargetPos(step, TargetPosType.REL);
|
|
_MotorX.Move();
|
|
}
|
|
// =========================================================
|
|
|
|
private void MoveJogXYPos(eAxisType axisType, eJogDirection direction)
|
|
{
|
|
double xPos = 0.0;
|
|
double yPos = 0.0;
|
|
switch (axisType)
|
|
{
|
|
case eAxisType.AXIS_X:
|
|
{
|
|
if (direction == eJogDirection.MINUS) { xPos = StepValue * -1; yPos = 0; }
|
|
else if (direction == eJogDirection.PLUS) { xPos = StepValue; yPos = 0; }
|
|
}
|
|
break;
|
|
case eAxisType.AXIS_Y:
|
|
{
|
|
if (direction == eJogDirection.MINUS) { xPos = 0; yPos = StepValue * -1; }
|
|
else if (direction == eJogDirection.PLUS) { xPos = 0; yPos = StepValue; }
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos))
|
|
{
|
|
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
|
|
return;
|
|
}
|
|
|
|
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
|
|
_Scanner.SetJumpSpeedCtrl(finalVelocity);
|
|
_Scanner.JumpRel(xPos, yPos);
|
|
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
|
|
}
|
|
|
|
private void MoveJogHome()
|
|
{
|
|
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
|
|
_Scanner.SetJumpSpeedCtrl(finalVelocity);
|
|
_Scanner.JumpAbs(0, 0);
|
|
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
|
|
}
|
|
|
|
private void PerformCmdCommandPosMove(object commandParameter)
|
|
{
|
|
switch ((string)commandParameter)
|
|
{
|
|
case "X": MoveCommandXYPos(eAxisType.AXIS_X); break;
|
|
case "Y": MoveCommandXYPos(eAxisType.AXIS_Y); break;
|
|
}
|
|
}
|
|
|
|
private void MoveCommandXYPos(eAxisType axisType)
|
|
{
|
|
double xPos = 0.0;
|
|
double yPos = 0.0;
|
|
switch (axisType)
|
|
{
|
|
case eAxisType.AXIS_X:
|
|
{
|
|
xPos = CommandPosX;
|
|
yPos = _MotionMode == eMotionMode.ABS ? _Scanner.GetCommandPosY() : 0.0;
|
|
}
|
|
break;
|
|
case eAxisType.AXIS_Y:
|
|
{
|
|
xPos = _MotionMode == eMotionMode.ABS ? _Scanner.GetCommandPosX() : 0.0;
|
|
yPos = CommandPosY;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (_MotionMode == eMotionMode.ABS)
|
|
{
|
|
if (CheckOverLimitPos(xPos, yPos))
|
|
{
|
|
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CheckOverLimitPos(ScannerXPos + xPos, ScannerYPos + yPos))
|
|
{
|
|
Log.E("움직이려는 범위가 스캐너 범위를 초과하였습니다.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
double finalVelocity = _ScannerConfig.JumpSpeed * _VelocityRate;
|
|
_Scanner.SetJumpSpeedCtrl(finalVelocity);
|
|
|
|
if (_MotionMode == eMotionMode.ABS)
|
|
_Scanner.JumpAbs(xPos, yPos);
|
|
else
|
|
_Scanner.JumpRel(xPos, yPos);
|
|
|
|
_Scanner.SetJumpSpeedCtrl(_ScannerConfig.JumpSpeed);
|
|
}
|
|
|
|
private bool CheckOverLimitPos(double calcPosX, double calcPosY)
|
|
{
|
|
if (calcPosX < CommandPosLimitMinX || calcPosX > CommandPosLimitMaxX) return true;
|
|
if (calcPosY < CommandPosLimitMinY || calcPosY > CommandPosLimitMaxY) return true;
|
|
return false;
|
|
}
|
|
}
|
|
} |