diff --git a/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs b/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs
index 507e852..74d4756 100644
--- a/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs
+++ b/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs
@@ -54,6 +54,7 @@ using static WeldingCommon.Vision.Factory.VisionFactory;
using AuroraACS;
using AuroraACS.Views;
using AuroraMotor;
+using WeldingCommon.Views.ACS;
namespace ILSOS_PrismaticScanner
@@ -271,9 +272,10 @@ namespace ILSOS_PrismaticScanner
base.RegisterViews(manager);
// Auto Run
- var MainAutoRun = new MainMenu(CommonViewIds.AutoRun, MenuIcon.GetMenuIcon(eMenuIcon.HOME), PermissionLevel.NONE, false);
- MainAutoRun.AddSubMenu(CommonViewIds.AutoRun, new UCMainAutoRun(new UCMainAutoRunViewModel(AuroraEnv, SequenceIds.SeqAutoRun)));
- manager.RegisterMainMenu(MainAutoRun);
+ // 26.04.06 NDY: Manual 서브로 이동
+ //var MainAutoRun = new MainMenu(CommonViewIds.AutoRun, MenuIcon.GetMenuIcon(eMenuIcon.HOME), PermissionLevel.NONE, false);
+ //MainAutoRun.AddSubMenu(CommonViewIds.AutoRun, new UCMainAutoRun(new UCMainAutoRunViewModel(AuroraEnv, SequenceIds.SeqAutoRun)));
+ //manager.RegisterMainMenu(MainAutoRun);
// Recipe
MainMenu recipe = new MainMenu(CommonViewIds.Recipe, MenuIcon.GetMenuIcon(eMenuIcon.RECIPE), PermissionLevel.NONE, true);
@@ -300,12 +302,17 @@ namespace ILSOS_PrismaticScanner
// Manual
//var manual = new MainMenu(CommonViewIds.Manual, MenuIcon.GetMenuIcon(eMenuIcon.DEVICE), PermissionLevel.LEVEL4, true); // Level4 가 맞으나, 개발때는 None 으로 뒀다가 완료되면 풀자.
var manual = new MainMenu(CommonViewIds.Manual, MenuIcon.GetMenuIcon(eMenuIcon.CAMERA), PermissionLevel.NONE, true);
+ // 26.04.06 NDY 추가: AutoRun을 Manual 서브메뉴로 추가
+ manual.AddSubMenu(CommonViewIds.AutoRun, new UCMainAutoRun(new UCMainAutoRunViewModel(AuroraEnv, SequenceIds.SeqAutoRun))); // 추가
manual.AddSubMenu(CommonViewIds.ScannerOperation, new UCManualScannerOperation(new UCManualScannerOperationViewModel(AuroraEnv, CommonDeviceIds.Scanner, false)));
//manual.AddSubMenu(CommonViewIds.OCT, new UCOCTManualMotion(AuroraEnv, CommonDeviceIds.OCT));
//manual.AddSubMenu(CommonViewIds.LBAD, new UCLBADDevice(AuroraEnv, CommonDeviceIds.LBAD, CommonDeviceIds.IODevice));
//manual.AddSubMenu(CommonViewIds.ConvEdgeObject, new UCConvEdgeObject(AuroraEnv));
manual.AddSubMenu(CommonViewIds.ModelFinder, new UCManualModelFinder(new UCManualModelFinderViewModel(AuroraEnv)));
- #region 26.04.06 ACS 모션 스테이지 메뉴얼 추가 - 진행 예정이였으나, Gun 에 속해서 사용 애매함. View 자체를 전부 가져오지는 못함.
+ #region 26.04.06 ACS 모션 스테이지 메뉴얼 추가 - 진행 예정이였으나, Gun 에 속해서 사용 애매함. View 자체를 전부 가져오지는 못함. - Gun의 view도 common에 복사
+ // Manual 메뉴에 추가
+ manual.AddSubMenu(CommonViewIds.StageManual,
+ new UCStageManual(AuroraEnv, AuroraEnv.DeviceManager));
#endregion
diff --git a/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs b/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs
index e8ae5bd..f5095db 100644
--- a/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs
+++ b/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs
@@ -81,8 +81,11 @@ namespace ILSOS_PrismaticScanner.Sequences
private static PAIX_PrismaticScanner _IO;
// 필드 선언 추가 (다른 필드들 옆에)
- private ScannerACS _ACS; // 26.04.06 NDY - MOTF용 ACS Stage X 제어
+ // 변경 전
+ //private ScannerACS _ACS;
+ // 변경 후
+ private IScannerACS _ACS; // 26.04.06 NDY - MOTF용 ACS Stage X 제어
private Laser _Laser;
private ILaser _LaserDevice;
private LaserTruFiber _LaserTruFiber;
@@ -201,7 +204,10 @@ namespace ILSOS_PrismaticScanner.Sequences
// 26.04.06 NDY 추가: ACS 디바이스 취득 (null-safe)
// 변수 맵 수신 후 MOTFStart() 호출에 사용
- try { _ACS = context.Devices["ACS"] as ScannerACS; }
+ // 변경 전
+ //try { _ACS = context.Devices[DeviceIds.ACS] as ScannerACS; }
+ // 변경 후
+ try { _ACS = context.Devices[DeviceIds.ACS] as IScannerACS; }
catch { _ACS = null; Log.W("ACS 디바이스 취득 실패 (null 처리)"); }
}
private bool CheckDeviceReady(SequenceContext context)
diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.Parameter.cs b/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.Parameter.cs
deleted file mode 100644
index 21ce72d..0000000
--- a/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.Parameter.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs
-using AuroraACS;
-using System.Web.UI.WebControls;
-
-namespace WeldingCommon.Devices.ACS
-{
- public partial class ScannerACS
- {
- // ── 알람 ──────────────────────────────────────────
- const string AlarmReset = "iAlarmreset";
- const string HeavyAlarm = "iAlarm";
- const string LightAlarm = "iLightAlarm";
- const string AlarmCodes = "iPCAlarmNo";
-
- // ── 홈 ───────────────────────────────────────────
- const string iAllAxisHomeComplete = "iPCget_ALLAXIS_HOMECOMP";
-
- // ── MOTF (Mark On The Fly) ────────────────────────
- // TODO: 이정인 선임 ACS 변수 맵 수신 후 실제 변수명으로 교체
- const string iMOTFStart = "iPCset_SCANNER_MOTF_START"; // placeholder
- const string iMOTFComplete = "iPCget_SCANNER_MOTF_COMP"; // placeholder
- const string rMOTFVelocity = "rPCset_SCANNER_MOTF_VEL"; // placeholder
- const string rMOTFAcc = "rPCset_SCANNER_MOTF_ACC"; // placeholder
-
- #region 변수 맵 받으면 작업 순서
- //1. ScannerACS.Parameter.cs
- // → placeholder 변수명을 실제 변수명으로 교체
-
- //2. ScannerACS.cs
- // → 축 번호 검증(ACSMotor 생성 시 넣은 번호)
-
- //3. EquipDef.cs
- // → MotorIds의 eMotorIdx 번호 검증
-
- //4. 빌드 후 실제 장비에서 동작 확인
- #endregion
-
- // ── 레이저 ───────────────────────────────────────
- const string IsLaserOn = "LCI_DEVICE.LaserEnabled";
- const string iLaserUse = "iPCset_LASER_USE";
-
- // ── 축 번호 ──────────────────────────────────────
- const string iXAxisNumber = "iPCget_LCI_ASMASK_X";
-
- // ── 버퍼 ─────────────────────────────────────────
- private enum eBuffer
- {
- All_Axis_Home = 0,
-
- // TODO: Scanner MOTF 버퍼 번호 확인 후 수정
- MOTF_Start = 11,
- }
- }
-}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.cs b/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.cs
deleted file mode 100644
index e863057..0000000
--- a/WeldingComponents/WeldingCommon/Devices/ACS/PrismaticGunACS.cs
+++ /dev/null
@@ -1,185 +0,0 @@
-// WeldingCommon/Devices/ACS/ScannerACS.cs
-using Aurora;
-using Aurora.Api;
-using Aurora.Api.Devices;
-using Aurora.Util.HislogPlus;
-using AuroraACS;
-using ACS.SPiiPlusNET;
-using Hermes;
-using System.Windows;
-using WeldingCommon.Device.ACS;
-using WeldingCommon.Settings;
-
-namespace WeldingCommon.Devices.ACS
-{
- public interface IScannerACS
- {
- bool IsActivated();
-
- // 홈
- bool AllAxisHomeStart();
- bool AllAxisHomeStop();
- bool CheckAllAxisHome();
-
- // MOTF
- bool MOTFStart();
- bool MOTFStop();
- bool CheckMOTFComp();
-
- // 레이저
- bool SetLaserIOUse(bool on);
- bool IsLaserOn();
-
- // 알람
- bool ResetAlarm();
- void AllAxisServoOff();
- }
-
- public partial class ScannerACS : ACSDevice, IScannerACS
- {
- // TODO: Scanner용 Setting ID 확정 후 교체
- private ACSDeviceSetting _setting;
- private ACSMotor MotorStageX; // AxisX2 = Scanner Stage X
-
- public MotionVariable _motorVariable;
-
- public bool HasHeavyAlarm { get; private set; }
- public bool HasLightAlarm { get; private set; }
- public int[] HaveAlarmCodes { get => _HaveAlarmCodes; }
- private int[] _HaveAlarmCodes = new int[11];
-
- public ScannerACS(bool isSimulation, bool useTerminateUMD = false)
- : base(isSimulation, useTerminateUMD)
- {
- _motorVariable = new MotionVariable();
- }
-
- protected override int DoActivate(IDeviceConfig config)
- {
- if (base.DoActivate(config) != E1.OK)
- return E2.ABORTED;
-
- var env = Application.Current.AuroraEnv();
-
- // TODO: Scanner용 SettingIds 확정 후 교체
- // _setting = env.SettingEntry[ScannerSettingIds.ACS] as ACSDeviceSetting;
-
- // Stage X 모터 취득 (null-safe)
- // TODO: 이정인 선임 변수 맵 수신 후 축 번호 검증
- try { MotorStageX = env.DeviceManager[CommonDeviceIds.AxisX2] as ACSMotor; }
- catch { MotorStageX = null; }
-
- SetMonitoringService(UpdateACSParam, 50);
- StartMonitoringService();
-
- return E1.OK;
- }
-
- private void UpdateACSParam()
- {
- // Stage X 상태 갱신
- if (MotorStageX != null)
- {
- _motorVariable.X2AxisPosition = MotorStageX.GetActualPos();
- _motorVariable.X2InPosition = MotorStageX.IsInpos();
- _motorVariable.X2AxisVelocity = MotorStageX.GetFeedbackVelocity();
- _motorVariable.X2AxisAcceleration = MotorStageX.GetAcceleration();
- _motorVariable.IsHome = MotorStageX.GetServoStatus() == 1;
- }
-
- // 알람 상태 갱신
- HasHeavyAlarm = ReadVariableInt(HeavyAlarm) == 1;
- HasLightAlarm = ReadVariableInt(LightAlarm) == 1;
- ReadVariableIntArrRef(AlarmCodes, ref _HaveAlarmCodes,
- ProgramBuffer.ACSC_NONE, 0, 10);
- }
-
- protected override int DoDeactivate()
- {
- StopMonitoringService();
- return base.DoDeactivate();
- }
-
- // ── 홈 ───────────────────────────────────────────
- bool IScannerACS.AllAxisHomeStart()
- {
- if (RunBuffer((ProgramBuffer)eBuffer.All_Axis_Home))
- {
- Log.D("AllAxisHomeStart >> Complete");
- return true;
- }
- Log.D("AllAxisHomeStart >> Fail");
- return false;
- }
-
- bool IScannerACS.AllAxisHomeStop()
- {
- StopBuffer((ProgramBuffer)eBuffer.All_Axis_Home);
- Log.D("AllAxisHomeStop >> Complete");
- return true;
- }
-
- bool IScannerACS.CheckAllAxisHome()
- => ReadVariableInt(iAllAxisHomeComplete) > 0;
-
- // ── MOTF ─────────────────────────────────────────
- // TODO: 이정인 선임 변수 맵 수신 후 버퍼 번호 및 변수명 교체
- bool IScannerACS.MOTFStart()
- {
- if (IsSimul) return true;
- if (RunBuffer((ProgramBuffer)eBuffer.MOTF_Start))
- {
- Log.I("MOTFStart >> Complete");
- return true;
- }
- Log.D("MOTFStart >> Fail");
- return false;
- }
-
- bool IScannerACS.MOTFStop()
- {
- StopBuffer((ProgramBuffer)eBuffer.MOTF_Start);
- Log.D("MOTFStop >> Complete");
- return true;
- }
-
- bool IScannerACS.CheckMOTFComp()
- {
- if (IsSimul) return true;
- return ReadVariableInt(iMOTFComplete) > 0;
- }
-
- // ── 레이저 ───────────────────────────────────────
- bool IScannerACS.SetLaserIOUse(bool on)
- {
- if (WriteRealVariable(iLaserUse, on ? 1 : 0))
- {
- Log.D($"SetLaserIOUse {on} >> Complete");
- return true;
- }
- Log.D("SetLaserIOUse >> Fail");
- return false;
- }
-
- bool IScannerACS.IsLaserOn()
- {
- if (!IsActivated || !IsConnected) return false;
- return ReadVariableInt(IsLaserOn) > 0;
- }
-
- // ── 알람 ─────────────────────────────────────────
- bool IScannerACS.ResetAlarm()
- {
- TerminalCommand("FCLEAR ALL");
- return WriteVariableInt(AlarmReset, 1);
- }
-
- void IScannerACS.AllAxisServoOff()
- {
- if (!IsActivated || !IsConnected) return;
- SetMotorDisableAll();
- }
-
- bool IScannerACS.IsActivated() => IsActivated;
- }
-}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs
new file mode 100644
index 0000000..38d36b0
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs
@@ -0,0 +1,168 @@
+// WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs
+// Gun(PrismaticGunACS.Parameter.cs) 기반으로 Scanner용으로 통합
+// 26.04.06 NDY
+using AuroraACS;
+
+namespace WeldingCommon.Devices.ACS
+{
+ // ── 레이저 출력 타입 ──────────────────────────────────────
+ // Gun의 MainRecipe.eOutType과 동일
+ // partial class 밖에 정의 → IScannerACS 인터페이스에서도 참조 가능
+ public enum eOutType
+ {
+ Analog, // V
+ Interval, // hz
+ }
+
+ public partial class ScannerACS
+ {
+ // ── 알람 ──────────────────────────────────────────
+ // Gun과 동일
+ const string AlarmReset = "iAlarmreset";
+ const string HeavyAlarm = "iAlarm";
+ const string LightAlarm = "iLightAlarm";
+ const string AlarmCodes = "iPCAlarmNo"; // 10개
+
+ // ── 레이저 ───────────────────────────────────────
+ // Gun과 동일
+ const string IsLaserOn = "LCI_DEVICE.LaserEnabled";
+ const string iLaserUse = "iPCset_LASER_USE";
+ const string iAStageLCType = "iPCset_ALINE_LCTYPE";
+
+ // ── 홈 ───────────────────────────────────────────
+ // Gun과 동일
+ const string iAllAxisHomeComplete = "iPCget_ALLAXIS_HOMECOMP";
+
+ // ── 축 번호 ──────────────────────────────────────
+ // Gun과 동일
+ const string iXAxisNumber = "iPCget_LCI_ASMASK_X";
+ const string iYAxisNumber = "iPCget_LCI_ASMASK_Y";
+
+ // ── 레이저 모드 ───────────────────────────────────
+ // Gun과 동일
+ const string iALaserShotMode = "iPCset_ALASER_SHOT_MODE";
+
+ // ── OneShot ───────────────────────────────────────
+ // Gun과 동일
+ const string rOneShotTime = "rPCset_ALINE_SHOT_TIME";
+ const string rOneShotCoreVoltage = "rPCset_ALINE_SHOT_CORE_VOLTAGE";
+ const string rOneShotRingVoltage = "rPCset_ALINE_SHOT_RING_VOLTAGE";
+ const string iOneShotComplete = "iPCget_ALINE_SHOT_COMP";
+
+ // ── LineShot ──────────────────────────────────────
+ // Gun과 동일
+ const string rLineWeldingCoreVoltage = "rPCset_ALINE_LINE_CORE_VOLTAGE";
+ const string rLineWeldingRingVoltage = "rPCset_ALINE_LINE_RING_VOLTAGE";
+ const string rLineWeldingVel = "rPCset_ALINE_LINE_VEL";
+ const string rLineWeldingAcc = "rPCset_ALINE_LINE_ACC";
+ const string rLineWeldingLaserOnX = "rPCset_ALINE_LINE_LASERON_X";
+ const string rLineWeldingLaserOnY = "rPCset_ALINE_LINE_LASERON_Y";
+ const string rLineWeldingLaserOffX = "rPCset_ALINE_LINE_LASEROFF_X";
+ const string rLineWeldingLaserOffY = "rPCset_ALINE_LINE_LASEROFF_Y";
+ const string iLineWeldingComplete = "iPCget_ALINE_LINE_COMP";
+
+ // ── Welding Position 1~8 ──────────────────────────
+ // Gun과 동일
+ const string rWeldingPosition1PosX = "rPCset_ALINE_WeldingPosition1_X";
+ const string rWeldingPosition1PosY = "rPCset_ALINE_WeldingPosition1_Y";
+ const string rWeldingPosition2PosX = "rPCset_ALINE_WeldingPosition2_X";
+ const string rWeldingPosition2PosY = "rPCset_ALINE_WeldingPosition2_Y";
+ const string rWeldingPosition3PosX = "rPCset_ALINE_WeldingPosition3_X";
+ const string rWeldingPosition3PosY = "rPCset_ALINE_WeldingPosition3_Y";
+ const string rWeldingPosition4PosX = "rPCset_ALINE_WeldingPosition4_X";
+ const string rWeldingPosition4PosY = "rPCset_ALINE_WeldingPosition4_Y";
+ const string rWeldingPosition5PosX = "rPCset_ALINE_WeldingPosition5_X";
+ const string rWeldingPosition5PosY = "rPCset_ALINE_WeldingPosition5_Y";
+ const string rWeldingPosition6PosX = "rPCset_ALINE_WeldingPosition6_X";
+ const string rWeldingPosition6PosY = "rPCset_ALINE_WeldingPosition6_Y";
+ const string rWeldingPosition7PosX = "rPCset_ALINE_WeldingPosition7_X";
+ const string rWeldingPosition7PosY = "rPCset_ALINE_WeldingPosition7_Y";
+ const string rWeldingPosition8PosX = "rPCset_ALINE_WeldingPosition8_X";
+ const string rWeldingPosition8PosY = "rPCset_ALINE_WeldingPosition8_Y";
+
+ // ── Welding Arc ───────────────────────────────────
+ // Gun과 동일
+ const string rWeldingEdgePointRad1 = "rPCset_ALINE_EdgePointRad1";
+ const string rWeldingEdgePointRad2 = "rPCset_ALINE_EdgePointRad2";
+ const string rWeldingEdgePointRad3 = "rPCset_ALINE_EdgePointRad3";
+ const string rWeldingEdgePointRad4 = "rPCset_ALINE_EdgePointRad4";
+
+ // ── Welding Power ─────────────────────────────────
+ // Gun과 동일
+ const string rWeldingCorePowerMax = "rPCset_ALINE_WEL_COREPOWER_MAX";
+ const string rWeldingCorePowerMin = "rPCset_ALINE_WEL_COREPOWER_MIN";
+ const string rWeldingRingPowerMax = "rPCset_ALINE_WEL_RINGPOWER_MAX";
+ const string rWeldingRingPowerMin = "rPCset_ALINE_WEL_RINGPOWER_MIN";
+
+ // ── Welding Velocity ──────────────────────────────
+ // Gun과 동일
+ const string rWeldingAcc = "rPCset_ALINE_WEL_ACC";
+ const string rWeldingSVel = "rPCset_ALINE_WEL_SVEL";
+ const string rWeldingCVel = "rPCset_ALINE_WEL_CVEL";
+ const string iWeldingComplete = "iPCget_ALINE_WEL_COMP";
+
+ // ── Welding Position ──────────────────────────────
+ // Gun과 동일
+ const string rWeldingStartPosX = "rPCset_ALINE_WEL_ST_POS_X";
+ const string rWeldingStartPosY = "rPCset_ALINE_WEL_ST_POS_Y";
+ const string rWeldingEndPosX = "rPCset_ALINE_WEL_EN_POS_X";
+ const string rWeldingEndPosY = "rPCset_ALINE_WEL_EN_POS_Y";
+
+ // ── Laser ON/OFF Position ─────────────────────────
+ // Gun과 동일
+ const string rLaserONPosX = "rPCset_ALINE_LASER_ONPOS_X";
+ const string rLaserONOffset = "rPCset_ALINE_LASER_ON_OFFSET";
+ const string rLaserOFFPosX = "rPCset_ALINE_LASER_OFFPOS_X";
+ const string rLaserOFFOffset = "rPCset_ALINE_LASER_OFF_OFFSET";
+
+ // ── Ramping ───────────────────────────────────────
+ // Gun과 동일
+ const string rRampingONOverlapDist = "rPCset_ALINE_RAMP_ON_OVERLAP_DIS";
+ const string rRampingONStartPower = "rPCset_ALINE_RAMP_ON_STARTPOWER";
+ const string rRampingOFFStartPosX = "rPCset_ALINE_RAMP_OFF_STPOS_X";
+ const string rRampingOFFOverlapDist = "rPCset_ALINE_RAMP_OFF_OVERLAP_DIS";
+ const string rRampingOFFEndPower = "rPCset_ALINE_RAMP_OFF_ENDPOWER";
+
+ // ── MOTF (Mark On The Fly) ────────────────────────
+ // Scanner 전용 추가 (Gun에 없음)
+ // TODO: 이정인 선임 ACS 변수 맵 수신 후 실제 변수명으로 교체
+ const string iMOTFStart = "iPCset_SCANNER_MOTF_START"; // placeholder
+ const string iMOTFComplete = "iPCget_SCANNER_MOTF_COMP"; // placeholder
+ const string rMOTFVelocity = "rPCset_SCANNER_MOTF_VEL"; // placeholder
+ const string rMOTFAcc = "rPCset_SCANNER_MOTF_ACC"; // placeholder
+
+ // ── 버퍼 ─────────────────────────────────────────
+ // Gun과 동일 + MOTF 추가
+ private enum eBuffer
+ {
+ All_Axis_Home = 0,
+ AxisX1_Home = 1,
+ AxisX2_Home = 2,
+ AxisY1_Home = 3,
+ AxisY2_Home = 4,
+ AxisZ_Home = 5,
+
+ Welding_Line = 11,
+ Welding_AllRound = 12,
+ Welding_OneShot = 13,
+
+ // TODO: Scanner MOTF 버퍼 번호 확인 후 수정
+ MOTF_Start = 14, // placeholder
+ }
+
+ #region 변수 맵 받으면 작업 순서
+ // 1. ScannerACS.Parameter.cs
+ // → iMOTFStart, iMOTFComplete, rMOTFVelocity, rMOTFAcc placeholder → 실제 변수명 교체
+ // → eBuffer.MOTF_Start 번호 교체
+ // 2. ScannerACS.cs
+ // → 축 번호 검증 (ACSMotor 생성 시 넣은 번호)
+ // 3. EquipDef.cs
+ // → MotorIds의 eMotorIdx 번호 검증
+ // 4. SeqComponentTeachingRun.cs
+ // → _ACS?.MOTFStart() 주석 해제
+ // → CheckMOTFComp() 주석 해제
+ // → CheckDeviceReady() DeviceIds.ACS 주석 해제
+ // 5. 빌드 후 실제 장비에서 동작 확인
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs
new file mode 100644
index 0000000..ea2fdd3
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs
@@ -0,0 +1,588 @@
+// WeldingCommon/Devices/ACS/ScannerACS.cs
+// Gun(PrismaticGunACS.cs) 기반으로 Scanner용으로 통합
+// 변경점:
+// 1. 네임스페이스/클래스명 변경 (PrismaticGunACS → ScannerACS)
+// 2. MOTF 메서드 3개 추가 (MOTFStart/Stop/CheckMOTFComp)
+// 3. 모터 취득 try-catch null-safe 적용
+// 4. TeachingPosition 체크 로직 단순화 (Scanner는 X2축만 사용)
+// 26.04.06 NDY
+using Aurora;
+using Aurora.Api;
+using Aurora.Api.Devices;
+using AuroraACS;
+using ACS.SPiiPlusNET;
+using Hermes;
+using System.Windows;
+using WeldingCommon.Settings;
+using AuroraOCT;
+using WeldingCommon.Device.ACS;
+namespace WeldingCommon.Devices.ACS
+{
+ // ── 인터페이스 ────────────────────────────────────────────────────────────
+ // Gun의 IPrismaticGunACS 기반 + MOTF 3개 추가
+ public interface IScannerACS
+ {
+ bool IsActivated();
+
+ // 홈
+ bool AllAxisHomeStart();
+ bool AllAxisHomeStop();
+ bool CheckAllAxisHome();
+
+ // MOTF (Scanner 전용 추가 - Gun에 없음)
+ // TODO: 이정인 선임 변수 맵 수신 후 주석 해제하여 사용
+ bool MOTFStart();
+ bool MOTFStop();
+ bool CheckMOTFComp();
+
+ // OneShot (Gun과 동일)
+ bool SetOneShot(int msecShotTime, double secPhzShotPulse1, double secPhzShotPulse2);
+ bool OneShotStart();
+ bool OneShotStop();
+ bool CheckOneShotComp();
+
+ // LineShot (Gun과 동일)
+ bool SetLineShot(double corePower, double ringPower,
+ double startPosX, double endPosX,
+ double startPosY, double endPosY,
+ double velocity, double acc);
+ bool LineShotStart();
+ bool LineShotStop();
+ bool CheckLineShotComp();
+
+ // Welding (Gun과 동일)
+ bool SetWeldingVel(double acc, double svel, double cvel);
+ bool SetWeldingPos(double startPosX, double startPosY,
+ double endPosX, double endPosY,
+ double camOffsetX, double camOffsetY);
+ bool SetWeldingArc(double point1, double point2, double point3, double point4);
+ bool SetWeldingType(eOutType type);
+ bool SetWeldingPulse(double coreMaxPower, double coreMinPower,
+ double ringMaxPower, double ringMinPower);
+ bool SetLaserOnOff(double onPosX, double onOffSet,
+ double offPosX, double offOffSet,
+ double camOffsetX, double camOffsetY);
+ bool SetRamppingOffParameter(double pos, double overlap, double endpower,
+ double camOffsetX, double camOffsetY);
+ bool SetRamppingOnParameter(double overlap, double startpower);
+ bool WeldingStart();
+ bool WeldingStop();
+ bool CheckWeldingComp();
+
+ // Teaching Position (Gun과 동일)
+ bool SetWeldingTeachingPosition1(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition2(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition3(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition4(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition5(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition6(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition7(double PosX, double PosY, double camOffsetX, double camOffsetY);
+ bool SetWeldingTeachingPosition8(double PosX, double PosY, double camOffsetX, double camOffsetY);
+
+ // 레이저 (Gun과 동일)
+ bool SetLaserIOUse(bool on);
+ bool SetLCILserOn(bool on);
+ bool SetWeldingAxes(int axisXnum, int axisYnum);
+ bool IsLaserOn();
+
+ // 알람 (Gun과 동일)
+ bool ResetAlarm();
+ void AllAxisServoOff();
+ }
+
+ // ── 구현 ──────────────────────────────────────────────────────────────────
+ public partial class ScannerACS : ACSDevice, IScannerACS
+ {
+ // Gun과 동일한 필드
+ private ACSDeviceSetting _setting;
+
+ // Scanner는 Stage X (X2) 1축만 사용
+ // Gun은 X1, X2, Y1, Y2, Z 5축 사용
+ private ACSMotor MotorStageX; // AxisX2 = Scanner Stage X
+
+ public MotionVariable _motorVariable;
+
+ public bool HasHeavyAlarm { get; private set; }
+ public bool HasLightAlarm { get; private set; }
+ public int[] HaveAlarmCodes { get => _HaveAlarmCodes; }
+ private int[] _HaveAlarmCodes = new int[11];
+
+ public ScannerACS(bool isSimulation, bool useTerminateUMD = false)
+ : base(isSimulation, useTerminateUMD)
+ {
+ _motorVariable = new MotionVariable();
+ }
+
+ protected override int DoActivate(IDeviceConfig config)
+ {
+ if (base.DoActivate(config) != E1.OK)
+ return E2.ABORTED;
+
+ var env = Application.Current.AuroraEnv();
+
+ // TODO: Scanner용 SettingIds 확정 후 교체
+ // Gun: _setting = env.SettingEntry[SettingIds.ACS] as ACSDeviceSetting;
+ // _setting = env.SettingEntry[ScannerSettingIds.ACS] as ACSDeviceSetting;
+
+ // Scanner는 Stage X (X2) 1축만 취득
+ // Gun은 X1, X2, Y1, Y2, Z 전부 취득
+ // null-safe: 변수 맵 수신 전 예외 방지
+ // TODO: 이정인 선임 변수 맵 수신 후 축 번호 검증
+ try { MotorStageX = env.DeviceManager[CommonDeviceIds.AxisX2] as ACSMotor; }
+ catch { MotorStageX = null; }
+
+ SetMonitoringService(UpdateACSParam, 50);
+ StartMonitoringService();
+
+ return E1.OK;
+ }
+
+ private void UpdateACSParam()
+ {
+ // Scanner는 Stage X만 모니터링
+ // Gun은 X1, X2, Y1, Y2, Z 전부 모니터링
+ if (MotorStageX != null)
+ {
+ _motorVariable.X2AxisPosition = MotorStageX.GetActualPos();
+ _motorVariable.X2InPosition = MotorStageX.IsInpos();
+ _motorVariable.X2AxisVelocity = MotorStageX.GetFeedbackVelocity();
+ _motorVariable.X2AxisAcceleration = MotorStageX.GetAcceleration();
+ _motorVariable.IsHome = MotorStageX.GetServoStatus() == 1;
+ }
+
+ // 알람 상태 갱신 (Gun과 동일)
+ HasHeavyAlarm = ReadVariableInt(HeavyAlarm) == 1;
+ HasLightAlarm = ReadVariableInt(LightAlarm) == 1;
+ ReadVariableIntArrRef(AlarmCodes, ref _HaveAlarmCodes, ProgramBuffer.ACSC_NONE, 0, 10);
+ }
+
+ protected override int DoDeactivate()
+ {
+ StopMonitoringService();
+ return base.DoDeactivate();
+ }
+
+ // ── 홈 (Gun과 동일) ───────────────────────────────────────────────────
+ bool IScannerACS.AllAxisHomeStart()
+ {
+ if (RunBuffer((ProgramBuffer)eBuffer.All_Axis_Home))
+ {
+ Log.D("AllAxisHomeStart >> Complete");
+ return true;
+ }
+ Log.D("AllAxisHomeStart >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.AllAxisHomeStop()
+ {
+ StopBuffer((ProgramBuffer)eBuffer.All_Axis_Home);
+ Log.D("AllAxisHomeStop >> Complete");
+ return true;
+ }
+
+ bool IScannerACS.CheckAllAxisHome()
+ => ReadVariableInt(iAllAxisHomeComplete) > 0;
+
+ // ── MOTF (Scanner 전용 추가 - Gun에 없음) ────────────────────────────
+ // TODO: 이정인 선임 변수 맵 수신 후 버퍼 번호 및 변수명 교체
+ bool IScannerACS.MOTFStart()
+ {
+ if (IsSimul) return true;
+ if (RunBuffer((ProgramBuffer)eBuffer.MOTF_Start))
+ {
+ Log.I("MOTFStart >> Complete");
+ return true;
+ }
+ Log.D("MOTFStart >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.MOTFStop()
+ {
+ StopBuffer((ProgramBuffer)eBuffer.MOTF_Start);
+ Log.D("MOTFStop >> Complete");
+ return true;
+ }
+
+ bool IScannerACS.CheckMOTFComp()
+ {
+ if (IsSimul) return true;
+ return ReadVariableInt(iMOTFComplete) > 0;
+ }
+
+ // ── OneShot (Gun과 동일) ──────────────────────────────────────────────
+ bool IScannerACS.SetOneShot(int msecShotTime, double secPhzShotPulse1, double secPhzShotPulse2)
+ {
+ if (WriteRealVariable(rOneShotTime, msecShotTime) &
+ WriteRealVariable(rOneShotCoreVoltage, secPhzShotPulse1) &
+ WriteRealVariable(rOneShotRingVoltage, secPhzShotPulse2))
+ {
+ Log.D("SetOneShot >> Complete");
+ return true;
+ }
+ Log.D("SetOneShot >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.OneShotStart()
+ {
+ if (RunBuffer((ProgramBuffer)eBuffer.Welding_OneShot))
+ {
+ Log.D("OneShotStart >> Complete");
+ return true;
+ }
+ Log.D("OneShotStart >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.OneShotStop()
+ {
+ IScannerACS motion = this;
+ motion.SetLCILserOn(false);
+ StopBuffer((ProgramBuffer)eBuffer.Welding_OneShot);
+ Log.D("OneShotStop >> Complete");
+ return true;
+ }
+
+ bool IScannerACS.CheckOneShotComp()
+ => ReadVariableInt(iOneShotComplete) > 0;
+
+ // ── LineShot (Gun과 동일) ─────────────────────────────────────────────
+ bool IScannerACS.SetLineShot(double corePower, double ringPower,
+ double startPosX, double endPosX,
+ double startPosY, double endPosY,
+ double velocity, double acc)
+ {
+ if (WriteRealVariable(rLineWeldingLaserOnX, startPosX) &
+ WriteRealVariable(rLineWeldingLaserOnY, startPosY) &
+ WriteRealVariable(rLineWeldingLaserOffX, endPosX) &
+ WriteRealVariable(rLineWeldingLaserOffY, endPosY) &
+ WriteRealVariable(rLineWeldingVel, velocity) &
+ WriteRealVariable(rLineWeldingAcc, acc) &
+ WriteRealVariable(rLineWeldingCoreVoltage, corePower) &
+ WriteRealVariable(rLineWeldingRingVoltage, ringPower))
+ {
+ Log.D("SetLineShot >> Complete");
+ return true;
+ }
+ Log.D("SetLineShot >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.LineShotStart()
+ {
+ if (RunBuffer((ProgramBuffer)eBuffer.Welding_Line))
+ {
+ Log.D("LineShotStart >> Complete");
+ return true;
+ }
+ Log.D("LineShotStart >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.LineShotStop()
+ {
+ IScannerACS motion = this;
+ motion.SetLCILserOn(false);
+ StopBuffer((ProgramBuffer)eBuffer.Welding_Line);
+ Log.D("LineShotStop >> Complete");
+ return true;
+ }
+
+ bool IScannerACS.CheckLineShotComp()
+ => ReadVariableInt(iLineWeldingComplete) > 0;
+
+ // ── Welding (Gun과 동일) ──────────────────────────────────────────────
+ bool IScannerACS.WeldingStart()
+ {
+ if (IsSimul) return true;
+ if (RunBuffer((ProgramBuffer)eBuffer.Welding_AllRound))
+ {
+ Log.I("WeldingStart >> Complete");
+ return true;
+ }
+ Log.D("WeldingStart >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.WeldingStop()
+ {
+ IScannerACS motion = this;
+ motion.SetLCILserOn(false);
+ StopBuffer((ProgramBuffer)eBuffer.Welding_AllRound);
+ Log.D("WeldingStop >> Complete");
+ return true;
+ }
+
+ bool IScannerACS.CheckWeldingComp()
+ {
+ if (IsSimul) return true;
+ return ReadVariableInt(iWeldingComplete) > 0;
+ }
+
+ bool IScannerACS.SetWeldingVel(double acc, double svel, double cvel)
+ {
+ if (WriteRealVariable(rWeldingAcc, acc) &
+ WriteRealVariable(rWeldingSVel, svel) &
+ WriteRealVariable(rWeldingCVel, cvel))
+ {
+ Log.D("SetWeldingVel >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingVel >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingPos(double startPosX, double startPosY,
+ double endPosX, double endPosY,
+ double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingStartPosX, startPosX + camOffsetX) &
+ WriteRealVariable(rWeldingStartPosY, startPosY + camOffsetY) &
+ WriteRealVariable(rWeldingEndPosX, endPosX + camOffsetX) &
+ WriteRealVariable(rWeldingEndPosY, endPosY + camOffsetY))
+ {
+ Log.D("SetWeldingPos >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingPos >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingArc(double point1, double point2, double point3, double point4)
+ {
+ if (WriteRealVariable(rWeldingEdgePointRad1, point1) &
+ WriteRealVariable(rWeldingEdgePointRad2, point2) &
+ WriteRealVariable(rWeldingEdgePointRad3, point3) &
+ WriteRealVariable(rWeldingEdgePointRad4, point4))
+ {
+ Log.D("SetWeldingArc >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingArc >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingType(eOutType type)
+ {
+ if (WriteVariableInt(iALaserShotMode, (int)type))
+ {
+ Log.D("SetWeldingType >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingType >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingPulse(double coreMaxPower, double coreMinPower,
+ double ringMaxPower, double ringMinPower)
+ {
+ if (WriteRealVariable(rWeldingCorePowerMax, coreMaxPower) &
+ WriteRealVariable(rWeldingCorePowerMin, coreMinPower) &
+ WriteRealVariable(rWeldingRingPowerMax, ringMaxPower) &
+ WriteRealVariable(rWeldingRingPowerMin, ringMinPower))
+ {
+ Log.D("SetWeldingPulse >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingPulse >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetLaserOnOff(double onPosX, double onOffSet,
+ double offPosX, double offOffSet,
+ double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rLaserONPosX, onPosX + camOffsetX) &
+ WriteRealVariable(rLaserONOffset, onOffSet) &
+ WriteRealVariable(rLaserOFFPosX, offPosX + camOffsetX) &
+ WriteRealVariable(rLaserOFFOffset, offOffSet))
+ {
+ Log.D("SetLaserOnOff >> Complete");
+ return true;
+ }
+ Log.D("SetLaserOnOff >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetRamppingOffParameter(double pos, double overlap, double endpower,
+ double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rRampingOFFStartPosX, pos + camOffsetX) &
+ WriteRealVariable(rRampingOFFOverlapDist, overlap) &
+ WriteRealVariable(rRampingOFFEndPower, endpower))
+ {
+ Log.D("SetRamppingOffParameter >> Complete");
+ return true;
+ }
+ Log.D("SetRamppingOffParameter >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetRamppingOnParameter(double overlap, double startpower)
+ {
+ if (WriteRealVariable(rRampingONOverlapDist, overlap) &
+ WriteRealVariable(rRampingONStartPower, startpower))
+ {
+ Log.D("SetRamppingOnParameter >> Complete");
+ return true;
+ }
+ Log.D("SetRamppingOnParameter >> Fail");
+ return false;
+ }
+
+ // ── Teaching Position (Gun과 동일) ────────────────────────────────────
+ bool IScannerACS.SetWeldingTeachingPosition1(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition1PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition1PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition1 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition1 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition2(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition2PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition2PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition2 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition2 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition3(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition3PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition3PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition3 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition3 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition4(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition4PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition4PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition4 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition4 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition5(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition5PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition5PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition5 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition5 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition6(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition6PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition6PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition6 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition6 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition7(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition7PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition7PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition7 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition7 >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingTeachingPosition8(double PosX, double PosY, double camOffsetX, double camOffsetY)
+ {
+ if (WriteRealVariable(rWeldingPosition8PosX, PosX + camOffsetX) &
+ WriteRealVariable(rWeldingPosition8PosY, PosY + camOffsetY))
+ {
+ Log.D($"SetWeldingTeachingPosition8 ({PosX}/{PosY}) >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingTeachingPosition8 >> Fail");
+ return false;
+ }
+
+ // ── 레이저 (Gun과 동일) ───────────────────────────────────────────────
+ bool IScannerACS.SetLaserIOUse(bool on)
+ {
+ if (WriteRealVariable(iLaserUse, on ? 1 : 0))
+ {
+ Log.D($"SetLaserIOUse {on} >> Complete");
+ return true;
+ }
+ Log.D("SetLaserIOUse >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetLCILserOn(bool on)
+ {
+ if (WriteRealVariable(iAStageLCType, on ? 1 : 0))
+ {
+ Log.D($"SetLCILserOn {on} >> Complete");
+ return true;
+ }
+ Log.D("SetLCILserOn >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.SetWeldingAxes(int axisXnum, int axisYnum)
+ {
+ if (WriteVariableInt(iXAxisNumber, axisXnum) &
+ WriteVariableInt(iYAxisNumber, axisYnum))
+ {
+ Log.D("SetWeldingAxes >> Complete");
+ return true;
+ }
+ Log.D("SetWeldingAxes >> Fail");
+ return false;
+ }
+
+ bool IScannerACS.IsLaserOn()
+ {
+ if (!IsActivated || !IsConnected) return false;
+ return ReadVariableInt(IsLaserOn) > 0;
+ }
+
+ // ── 알람 (Gun과 동일) ─────────────────────────────────────────────────
+ bool IScannerACS.ResetAlarm()
+ {
+ TerminalCommand("FCLEAR ALL");
+ return WriteVariableInt(AlarmReset, 1);
+ }
+
+ void IScannerACS.AllAxisServoOff()
+ {
+ if (!IsActivated || !IsConnected) return;
+ SetMotorDisableAll();
+ }
+
+ bool IScannerACS.IsActivated() => IsActivated;
+ }
+}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/EquipDefCommon.cs b/WeldingComponents/WeldingCommon/EquipDefCommon.cs
index b658615..802e3cb 100644
--- a/WeldingComponents/WeldingCommon/EquipDefCommon.cs
+++ b/WeldingComponents/WeldingCommon/EquipDefCommon.cs
@@ -126,6 +126,7 @@
#region
public const string AxisX2 = "AxisX2"; // 26.04.06 추가
+ public const string ACS = "ACS"; // 26.04.06 추가
#endregion
}
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml
new file mode 100644
index 0000000..84046a1
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml.cs b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml.cs
new file mode 100644
index 0000000..b0474fc
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxses.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+// WeldingCommon/Views/ACS/UCMotorAxses.xaml.cs
+
+
+namespace WeldingCommon.Views.ACS
+{
+ public partial class UCMotorAxses : UserControl
+ {
+ public UCMotorAxses()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxsesViewModel.cs b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxsesViewModel.cs
new file mode 100644
index 0000000..d61b3b2
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCMotorAxsesViewModel.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+// WeldingCommon/Views/ACS/UCMotorAxsesViewModel.cs
+// Gun의 UCMotorAxsesViewModel.cs 기반 → Scanner X축 전용으로 단순화
+// 변경점:
+// - 네임스페이스: ILSOS_PrismaticGun.Views → WeldingCommon.Views.ACS
+// - IPrismaticGunACS → IScannerACS
+// - Y/Z 축 제거, X축만 유지
+// - SequenceIds.MotorInit → Scanner용 시퀀스로 교체 필요 (TODO)
+// 26.04.06 NDY
+using Aurora;
+using Aurora.Api;
+using Aurora.Api.Devices;
+using Aurora.Api.Manager;
+using Aurora.View;
+using AuroraACS;
+using System.Windows;
+using System.Windows.Input;
+using WeldingCommon.Devices.ACS;
+
+namespace WeldingCommon.Views.ACS
+{
+ public class UCMotorAxsesViewModel : NotifyPropertyChangedBase
+ {
+ public ICommand CMD_InitAll { get; }
+ public ICommand CMD_InitStop { get; }
+ public ICommand CMD_ServoOff { get; }
+
+ // Scanner는 X축(Stage X)만 사용
+ // Gun은 X2, Y1, Y2, Z 전부 사용
+ public ACSMotor MotorX { get; set; }
+
+ private IScannerACS _acs;
+
+ public UCMotorAxsesViewModel(IAuroraEnvironment aurora, IDeviceManager devMngr)
+ {
+ CMD_InitAll = new DelegateCommand(InitAllAxses);
+ CMD_InitStop = new DelegateCommand(InitAllStop);
+ CMD_ServoOff = new DelegateCommand(ServoOff);
+
+ // X축만 취득
+ try { MotorX = devMngr[CommonDeviceIds.AxisX2] as ACSMotor; }
+ catch { MotorX = null; }
+
+ // ACS 디바이스 취득
+ try { _acs = devMngr[CommonDeviceIds.ACS] as IScannerACS; }
+ catch { _acs = null; }
+ }
+
+ private void ServoOff(object obj)
+ {
+ _acs?.AllAxisServoOff();
+ }
+
+ private void InitAllAxses(object obj)
+ {
+ if (MessageBox.Show("X축 초기화를 진행하시겠습니까?",
+ "Init", MessageBoxButton.YesNo) == MessageBoxResult.No) return;
+
+ // TODO: Scanner용 MotorInit 시퀀스 등록 후 교체
+ // 현재는 ACS 홈 명령 직접 호출
+ _acs?.AllAxisHomeStart();
+ }
+
+ private void InitAllStop(object obj)
+ {
+ _acs?.AllAxisHomeStop();
+ MotorX?.HomeStop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml
new file mode 100644
index 0000000..ceaa081
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml.cs b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml.cs
new file mode 100644
index 0000000..b7aac77
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManual.xaml.cs
@@ -0,0 +1,51 @@
+// WeldingCommon/Views/ACS/UCStageManual.xaml.cs
+// Gun의 UCStageManual.xaml.cs 기반 → Scanner X축 전용으로 단순화
+// 변경점:
+// - 네임스페이스: ILSOS_PrismaticGun.Views → WeldingCommon.Views.ACS
+// - Y/Z 축 이벤트 제거, X축만 유지
+// - CameraView 제거
+// 26.04.06 NDY
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using Aurora;
+using Aurora.Api.Manager;
+
+namespace WeldingCommon.Views.ACS
+{
+ public partial class UCStageManual : UserControl
+ {
+ UCStageManualViewModel ViewModel = null;
+
+ public UCStageManual()
+ {
+ InitializeComponent();
+ }
+
+ public UCStageManual(IAuroraEnvironment env, IDeviceManager devMngr)
+ {
+ InitializeComponent();
+ ViewModel = new UCStageManualViewModel(env, devMngr);
+ DataContext = ViewModel;
+ }
+
+ // ── X축 조그 이벤트 ────────────────────────────────────────────────────
+ private void BtnXJog_P_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ => ViewModel?.XJogStop(null);
+
+ private void BtnXJog_P_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ => ViewModel?.XJogPlus(null);
+
+ private void BtnXJog_P_MouseLeave(object sender, MouseEventArgs e)
+ => ViewModel?.XJogStop(null);
+
+ private void BtnXJog_M_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ => ViewModel?.XJogStop(null);
+
+ private void BtnXJog_M_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ => ViewModel?.XJogMinus(null);
+
+ private void BtnXJog_M_MouseLeave(object sender, MouseEventArgs e)
+ => ViewModel?.XJogStop(null);
+ }
+}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManualViewModel.cs b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManualViewModel.cs
new file mode 100644
index 0000000..186ab99
--- /dev/null
+++ b/WeldingComponents/WeldingCommon/Views/Manual/ACS/Stage/UCStageManualViewModel.cs
@@ -0,0 +1,244 @@
+// WeldingCommon/Views/ACS/UCStageManualViewModel.cs
+// Gun의 UCStageManualViewModel.cs 기반 → Scanner X축 전용으로 단순화
+// 변경점:
+// - 네임스페이스: ILSOS_PrismaticGun.Views → WeldingCommon.Views.ACS
+// - IPrismaticGunACS → IScannerACS
+// - Y/Z 축 제거, X축만 유지
+// - TeachingPositionSetting 제거
+// - SeqSplitLine, SeqOneShot → IScannerACS 직접 호출로 교체
+// - Camera-Laser Offset 제거
+// - SequenceManagerForMainWelder 제거
+// 26.04.06 NDY
+using Aurora;
+using Aurora.Api;
+using Aurora.Api.Control;
+using Aurora.Api.Devices;
+using Aurora.Api.Manager;
+using Aurora.View;
+using AuroraACS;
+using AuroraMotor;
+using Hermes;
+using System;
+using System.Collections.ObjectModel;
+using System.Reactive.Linq;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
+using WeldingCommon.Data;
+using WeldingCommon.Devices.ACS;
+using JogDirection = AuroraACS.JogDirection;
+using Speed = AuroraACS.Speed;
+
+
+namespace WeldingCommon.Views.ACS
+{
+ public class UCStageManualViewModel : NotifyPropertyChangedBase
+ {
+ // ── ViewModel 참조 ────────────────────────────────────────────────────
+ public UCMotorAxsesViewModel AxsesViewModel
+ {
+ get => _AxsesViewModel;
+ set => SetProperty(ref _AxsesViewModel, value);
+ }
+ private UCMotorAxsesViewModel _AxsesViewModel;
+
+ // ── 커맨드 ────────────────────────────────────────────────────────────
+ public ICommand CMD_VisibleChanged { get; }
+ public ICommand CMD_MoveX { get; }
+ public ICommand CMD_MoveStop { get; }
+ public ICommand CMD_OneShotStart { get; }
+ public ICommand CMD_OneShotStop { get; }
+ public ICommand CMD_AlarmReset { get; }
+ public ICommand CMD_CopyToClipboard { get; }
+
+ // ── 위치 ──────────────────────────────────────────────────────────────
+ public double TargetPosX { get; set; }
+ public double PosX { get => _PosX; set => SetProperty(ref _PosX, value); }
+ private double _PosX;
+
+ // ── 조그 속도 ─────────────────────────────────────────────────────────
+ public double JogSpeed { get; set; } = 10.0;
+
+ // ── OneShot 파라미터 ──────────────────────────────────────────────────
+ public int OneShotTime { get; set; } = 10;
+ public double OneShotCorePower { get; set; } = 0.0;
+ public double OneShotRingPower { get; set; } = 0.0;
+ public bool IsOneShotComp { get => _IsOneShotComp; set => SetProperty(ref _IsOneShotComp, value); }
+ private bool _IsOneShotComp = true;
+
+ // ── 상태 ──────────────────────────────────────────────────────────────
+ public bool IsManualStatus { get => _IsManualStatus; set => SetProperty(ref _IsManualStatus, value); }
+ private bool _IsManualStatus = true;
+
+ // ── Motor Status ──────────────────────────────────────────────────────
+ public ObservableCollection AxisStatus
+ {
+ get => _AxisStatus;
+ set => SetProperty(ref _AxisStatus, value);
+ }
+ private ObservableCollection _AxisStatus = new ObservableCollection();
+
+ // ── 디바이스 ──────────────────────────────────────────────────────────
+ // Scanner는 X축(Stage X)만 사용
+ // Gun은 X1, X2, Y1, Y2, Z 전부 사용
+ private readonly IAuroraEnvironment _env;
+ private IScannerACS _motion;
+ private ScannerACS _acs;
+ private ACSMotor MotorX;
+
+ private readonly DispatcherTimer _timer = new DispatcherTimer();
+
+ // ── 생성자 ────────────────────────────────────────────────────────────
+ public UCStageManualViewModel() { }
+
+ public UCStageManualViewModel(IAuroraEnvironment env, IDeviceManager devMngr)
+ {
+ _env = env;
+ AxsesViewModel = new UCMotorAxsesViewModel(env, devMngr);
+
+ // Scanner는 X축만 취득 (Gun: X1, X2, Y1, Y2, Z)
+ try { MotorX = devMngr[CommonDeviceIds.AxisX2] as ACSMotor; }
+ catch { MotorX = null; }
+
+ // ACS 디바이스 취득
+ try { _motion = _acs = devMngr[CommonDeviceIds.ACS] as ScannerACS; }
+ catch { _motion = _acs = null; }
+
+ // Motor Status 초기화
+ InitMotorStatus();
+
+ // 커맨드 등록
+ CMD_VisibleChanged = new DelegateCommand(VisibleChanged);
+ CMD_MoveX = new DelegateCommand(MoveX);
+ CMD_MoveStop = new DelegateCommand(MoveStop);
+ CMD_OneShotStart = new DelegateCommand(OneShotStart);
+ CMD_OneShotStop = new DelegateCommand(OneShotStop);
+ CMD_AlarmReset = new DelegateCommand(AlarmReset);
+ CMD_CopyToClipboard = new DelegateCommand(OnCopyToClipboard);
+
+ // 모니터링 타이머
+ _timer.Interval = TimeSpan.FromMilliseconds(500);
+ _timer.Tick += Monitoring;
+
+ // 장비 상태 감시
+ _env.EventObservable.AsObservable(CommonEventIds.EVENT_EQUIPMENT_STATUS_CHANGE)
+ .Subscribe(x => IsManualStatus = Status.EquipmentStatus == eEqpStatus.Manual);
+ }
+
+ // ── 모니터링 ──────────────────────────────────────────────────────────
+ private void Monitoring(object sender, EventArgs e)
+ {
+ if (_acs == null || !_acs.IsActivated) return;
+
+ // X축 위치 갱신
+ PosX = _acs._motorVariable.X2AxisPosition;
+
+ // Motor Status 갱신
+ UpdateMotorStatus();
+ }
+
+ private void InitMotorStatus()
+ {
+ if (MotorX == null) return;
+ AxisStatus.Add(new MotorStatus { MotorId = MotorX.DeviceId });
+ }
+
+ private void UpdateMotorStatus()
+ {
+ if (MotorX == null || AxisStatus.Count == 0) return;
+
+ var limit = MotorX.GetPosLimit();
+ AxisStatus[0].LimitMinusPos = limit.Min;
+ AxisStatus[0].LimitPlusPos = limit.Max;
+ AxisStatus[0].AlarmStatus = _acs.HasHeavyAlarm | _acs.HasLightAlarm;
+ AxisStatus[0].ServoStatus = MotorX.IsServoOn();
+ AxisStatus[0].HomeStatus = MotorX.IsHomeCompleted();
+ }
+
+ // ── 커맨드 구현 ───────────────────────────────────────────────────────
+ private void VisibleChanged(object obj)
+ {
+ bool visible = (bool)obj;
+ if (visible) _timer.Start();
+ else _timer.Stop();
+ }
+
+ private void MoveX(object obj)
+ {
+ if (MotorX == null) return;
+ if (MessageBox.Show($"Stage X축을 {TargetPosX}으로 이동하시겠습니까?",
+ "Move", MessageBoxButton.YesNo) == MessageBoxResult.No) return;
+
+ MotorX.SetTargetPos(TargetPosX, TargetPosType.ABS);
+ MotorX.SetMoveVelocityImm(Speed.L);
+ MotorX.Move();
+ }
+
+ private void MoveStop(object obj)
+ {
+ MotorX?.DoStopAll();
+ }
+
+ private void OneShotStart(object obj)
+ {
+ if (_motion == null) return;
+ if (MessageBox.Show("OneShot을 하시겠습니까?",
+ "OneShot", MessageBoxButton.YesNo) == MessageBoxResult.No) return;
+
+ _motion.SetOneShot(OneShotTime, OneShotCorePower, OneShotRingPower);
+ _motion.SetLCILserOn(true);
+ _motion.OneShotStart();
+ IsOneShotComp = false;
+ }
+
+ private void OneShotStop(object obj)
+ {
+ _motion?.OneShotStop();
+ IsOneShotComp = true;
+ }
+
+ private void AlarmReset(object obj)
+ {
+ _motion?.ResetAlarm();
+ }
+
+ private void OnCopyToClipboard(object obj)
+ {
+ var s = obj?.ToString();
+ if (!string.IsNullOrWhiteSpace(s))
+ Clipboard.SetText(s);
+ }
+
+ // ── X축 조그 (code-behind에서 호출) ──────────────────────────────────
+ internal void XJogPlus(object obj)
+ => MotorX?.MoveToSWLimit(JogDirection.plus, Speed.L);
+
+ internal void XJogMinus(object obj)
+ => MotorX?.MoveToSWLimit(JogDirection.minus, Speed.L);
+
+ internal void XJogStop(object obj)
+ => MotorX?.Stop();
+
+ // 같은 파일, 같은 네임스페이스 안에 정의
+ public class MotorStatus : NotifyPropertyChangedBase
+ {
+ public string MotorId { get => _MotorId; set => SetProperty(ref _MotorId, value); }
+ private string _MotorId;
+
+ public double LimitMinusPos { get => _LimitMinusPos; set => SetProperty(ref _LimitMinusPos, value); }
+ private double _LimitMinusPos;
+
+ public double LimitPlusPos { get => _LimitPlusPos; set => SetProperty(ref _LimitPlusPos, value); }
+ private double _LimitPlusPos;
+
+ public bool AlarmStatus { get => _AlarmStatus; set => SetProperty(ref _AlarmStatus, value); }
+ private bool _AlarmStatus;
+
+ public bool ServoStatus { get => _ServoStatus; set => SetProperty(ref _ServoStatus, value); }
+ private bool _ServoStatus;
+
+ public bool HomeStatus { get => _HomeStatus; set => SetProperty(ref _HomeStatus, value); }
+ private bool _HomeStatus;
+ }
+ }
+}
\ No newline at end of file
diff --git a/WeldingComponents/WeldingCommon/WeldingCommon.csproj b/WeldingComponents/WeldingCommon/WeldingCommon.csproj
index 52e81a9..ebd6f5f 100644
--- a/WeldingComponents/WeldingCommon/WeldingCommon.csproj
+++ b/WeldingComponents/WeldingCommon/WeldingCommon.csproj
@@ -210,8 +210,8 @@
-
-
+
+
@@ -321,6 +321,14 @@
UCWorkPos.xaml
+
+ UCMotorAxses.xaml
+
+
+
+ UCStageManual.xaml
+
+
UCManualScannerOperation.xaml
@@ -646,6 +654,14 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile