From b2589be67d29224d7f0c3dd85a2e57834e476cf2 Mon Sep 17 00:00:00 2001 From: RnD_Welder Date: Tue, 14 Apr 2026 20:44:08 +0900 Subject: [PATCH] =?UTF-8?q?feat:260414=5F=ED=98=84=EC=9E=A5=EC=86=8C?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AuroraDevices/AuroraACS/ACSDevice.cs | 4 +- .../AuroraLaser/Coherent/Arm/LaserArm.cs | 2 +- .../Device/ACS/PrismaticGunACS.Parameter.cs | 3 +- .../Device/ACS/PrismaticGunACS.cs | 6 +- .../ILSOS_PrismaticScanner/EquipmentSetup.cs | 97 +- .../Manual/SeqComponentTeachingRun.cs | 756 ++++++-- .../Sequences/Monitoring/SeqAlarmMonitor.cs | 21 +- .../Sequences/SeqAutoRunPrismaticScanner.cs | 1566 ++++------------- .../Views/Main/UCMainAutoRunViewModel.cs | 2 +- .../WeldingCommon/CommonEquipmentSetup.cs | 8 +- .../Devices/ACS/ScannerACS.Parameter.cs | 114 ++ .../WeldingCommon/Devices/ACS/ScannerACS.cs | 20 +- .../WeldingCommon/EquipDefCommon.cs | 6 +- .../Calibration/SeqScannerCalibration.cs | 1 + .../Sequences/Gun/SeqMotorInit.cs | 38 +- .../StageA/SeqTeachingPosMoveStageA.cs | 8 +- .../Sequences/Main/SeqScoutNormal.cs | 2 +- .../Sequences/Main/SeqUploadWeldingList.cs | 46 +- .../Calibration/UCScannerCalibration.xaml | 4 +- .../UCScannerCalibrationViewModel.cs | 24 +- .../UCManualScannerOperationViewModel.cs | 2 +- .../Scanner/UCScannerLaserControlViewModel.cs | 61 +- .../Views/Manual/Scanner/UCScannerMotion.xaml | 57 +- .../Scanner/UCScannerMotionViewModel.cs | 34 + .../UCScannerObjectTeachingControlBox.xaml | 43 +- ...cannerObjectTeachingControlBoxViewModel.cs | 32 +- 26 files changed, 1322 insertions(+), 1635 deletions(-) diff --git a/AuroraDevices/AuroraACS/ACSDevice.cs b/AuroraDevices/AuroraACS/ACSDevice.cs index aa0b3f8..7f46bfa 100644 --- a/AuroraDevices/AuroraACS/ACSDevice.cs +++ b/AuroraDevices/AuroraACS/ACSDevice.cs @@ -643,7 +643,7 @@ namespace AuroraACS return intValue; } - Log.E($"ReadVariable {VariableName} Error : " + result); + //Log.E($"ReadVariable {VariableName} Error : " + result); // 잠시 주석 26.04.14 - 로그 많이 찍힘 - VariableName 확인 필요 return 0; } @@ -773,7 +773,7 @@ namespace AuroraACS } } catch (Exception exc) { if (!IsSimul) { - Log.E($"ReadVariable {VariableName} Exception : " + exc.Message); + //Log.E($"ReadVariable {VariableName} Exception : " + exc.Message); // 26.04.14 잠시 주석 - 로그가 너무 많이 찍힘 VariableName 확인 필요 return null; } return null; diff --git a/AuroraDevices/AuroraLaser/Coherent/Arm/LaserArm.cs b/AuroraDevices/AuroraLaser/Coherent/Arm/LaserArm.cs index 7ded89d..a016a0b 100644 --- a/AuroraDevices/AuroraLaser/Coherent/Arm/LaserArm.cs +++ b/AuroraDevices/AuroraLaser/Coherent/Arm/LaserArm.cs @@ -395,7 +395,7 @@ namespace AuroraLaser ReadNode[nTargetCommand + 1].dRet = dData * 0.25; } else { //To Do : AlarmLog 수정할 것 - Logger.E("LASER_POWER Invalid Data received " + strReceiveMsgTotal); + Logger.E("LASER_POWER Invalid Data received " + strReceiveMsgTotal); // 04 14 //UtilUnit.logUnit.SetLog(LogUnit.eLogType.DEBUG, MethodBase.GetCurrentMethod().Name, "LASER_POWER Invalid Data received " + strReceiveMsgTotal); } diff --git a/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.Parameter.cs b/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.Parameter.cs index ab5c113..e3e8200 100644 --- a/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.Parameter.cs +++ b/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.Parameter.cs @@ -7,7 +7,8 @@ using System.Threading.Tasks; namespace ILSOS_PrismaticGun.Device.ACS { public partial class PrismaticGunACS - { const string AlarmReset = "iAlarmreset"; + { + const string AlarmReset = "iAlarmreset"; const string HeavyAlarm = "iAlarm"; const string LightAlarm = "iLightAlarm"; const string AlarmCodes = "iPCAlarmNo"; // 10개 diff --git a/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.cs b/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.cs index 2bc7237..00e4acd 100644 --- a/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.cs +++ b/Machines/ILSOS_PrismaticGun/Device/ACS/PrismaticGunACS.cs @@ -106,10 +106,10 @@ namespace ILSOS_PrismaticGun.Device.ACS _calibration = env.SettingEntry[CommonSettingIds.LaserPowerCalParam] as LaserPowerCalParam; _teachingSetting = env.SettingEntry[SettingIds.TeachingPos] as TeachingPositionSetting; - MotorX1 = env.DeviceManager[MotorIds.AxisX1] as ACSMotor; + //MotorX1 = env.DeviceManager[MotorIds.AxisX1] as ACSMotor; MotorX2 = env.DeviceManager[MotorIds.AxisX2] as ACSMotor; - MotorY1 = env.DeviceManager[MotorIds.AxisY1] as ACSMotor; - MotorY2 = env.DeviceManager[MotorIds.AxisY2] as ACSMotor; + //MotorY1 = env.DeviceManager[MotorIds.AxisY1] as ACSMotor; + //MotorY2 = env.DeviceManager[MotorIds.AxisY2] as ACSMotor; MotorZ = env.DeviceManager[MotorIds.AxisZ] as ACSMotor; diff --git a/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs b/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs index f4d7f00..1b86372 100644 --- a/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs +++ b/Machines/ILSOS_PrismaticScanner/EquipmentSetup.cs @@ -98,17 +98,17 @@ namespace ILSOS_PrismaticScanner await ActivateDevices(); } - AuroraEx.RegisterRmsHandler(); - AuroraEnv.RecipeManager.RmsHandler().RegistryDeviceHandler(AuroraEnv); - AuroraEnv.RecipeManager.RmsHandler().Start(); + //AuroraEx.RegisterRmsHandler(); + //AuroraEnv.RecipeManager.RmsHandler().RegistryDeviceHandler(AuroraEnv); + //AuroraEnv.RecipeManager.RmsHandler().Start(); // [Singleton Instance] Recipe Change History - AuroraEnv.RecipeManager.RchHandler().RegistryDeviceHandler(AuroraEnv); + //AuroraEnv.RecipeManager.RchHandler().RegistryDeviceHandler(AuroraEnv); //AlarmMonitroing Seq Start - AuroraEnv.SequenceEntry[SequenceIds.SeqAlarmMonitor].Start(); - AuroraEnv.SequenceEntry[SequenceIds.SeqStatusMonitor].Start(); - AuroraEnv.SequenceEntry[CommonSequenceIds.PLCMonitor].Start(); + //AuroraEnv.SequenceEntry[SequenceIds.SeqAlarmMonitor].Start(); + //AuroraEnv.SequenceEntry[SequenceIds.SeqStatusMonitor].Start(); + //AuroraEnv.SequenceEntry[CommonSequenceIds.PLCMonitor].Start(); base.OnStartUp(); @@ -116,9 +116,9 @@ namespace ILSOS_PrismaticScanner public override void OnShutDown() { // 모니터링 시퀀스 먼저 종료 - AuroraEnv.SequenceEntry[SequenceIds.SeqAlarmMonitor].Stop(); - AuroraEnv.SequenceEntry[SequenceIds.SeqStatusMonitor].Stop(); - AuroraEnv.SequenceEntry[CommonSequenceIds.PLCMonitor].Stop(); + //AuroraEnv.SequenceEntry[SequenceIds.SeqAlarmMonitor].Stop(); + //AuroraEnv.SequenceEntry[SequenceIds.SeqStatusMonitor].Stop(); + //AuroraEnv.SequenceEntry[CommonSequenceIds.PLCMonitor].Stop(); Thread.Sleep(200); base.OnShutDown(); @@ -145,24 +145,6 @@ namespace ILSOS_PrismaticScanner var isSimul = ApplicationExt.IsSimulation; - //registry.Register(CommonDeviceIds.OCT, () => new OCT(CommonDeviceIds.OCT, isSimul), new OCTConfig(), - // device => new UCOCTDevice() { DataContext = new UCOCTDeviceViewModel(AuroraEnv, CommonDeviceIds.OCT) }); - //registry.Register(CommonDeviceIds.LBAD, () => new LBAD(CommonDeviceIds.LBAD, isSimul), new LBADConfig()); - //registry.Register(CommonDeviceIds.CellTracker, () => new CellTracker(CommonDeviceIds.CellTracker, eCellTrackerType.Daekhon, isSimul), new CellTrackerConfig(), - // device => new UCCellTrackerDevice() { DataContext = new UCCellTrackerDeviceViewModel(AuroraEnv, CommonDeviceIds.CellTracker) }); - - - //IODevice는 AjinIO가 아니라 IOUnit으로 받아오는것으로 수정해야 함 - registry.Register(CommonDeviceIds.IODevice, () => new PAIX_PrismaticScanner(AuroraEnv, CommonDeviceIds.IODevice, isSimul), new IOUnitConfig()); - registry.Register(CommonDeviceIds.Laser, () => new Laser(CommonDeviceIds.Laser, isSimul), new LaserConfig(), - device => new UCLaserDevice() { DataContext = new UCLaserDeviceViewModel(AuroraEnv, CommonDeviceIds.Laser) }); - - var _plc = new PLCControllerPrismaticScanner(CommonDeviceIds.PLCDevice, ePLCNetType.MXComponent, ApplicationExt.IsSimulation, PLCMMapFileType.CSV, AuroraEnv); - registry.Register(CommonDeviceIds.PLCDevice, - () => _plc, PLCMxComponentConfig.GetDefaultConfig(), - device => new UCPLCDevice() { DataContext = new UCPLCDeviceViewModel(AuroraEnv, _plc) }); - - AlarmManager.Init(AuroraEnv); @@ -177,16 +159,6 @@ namespace ILSOS_PrismaticScanner new ACSMotorConfig(MotorIds.AxisX2), motor => new UCACSMotor(AuroraEnv.DeviceManager, motor.DeviceId)); - //var motorY1 = new ACSMotor(MotorIds.AxisY1, ACS, 3, (int)MotorIds.eMotorIdx.AxisY1); - //registry.Register(MotorIds.AxisY1, () => motorY1, - // new ACSMotorConfig(MotorIds.AxisY1), - // motor => new UCACSMotor(AuroraEnv.DeviceManager, motor.DeviceId)); - - //var motorY2 = new ACSMotor(MotorIds.AxisY2, ACS, 4, (int)MotorIds.eMotorIdx.AxisY2); - //registry.Register(MotorIds.AxisY2, () => motorY2, - // new ACSMotorConfig(MotorIds.AxisY2), - // motor => new UCACSMotor(AuroraEnv.DeviceManager, motor.DeviceId)); - var motorZ = new ACSMotor(MotorIds.AxisZ, ACS, 4, (int)MotorIds.eMotorIdx.AxisZ); registry.Register(MotorIds.AxisZ, () => motorZ, new ACSMotorConfig(MotorIds.AxisZ), @@ -197,8 +169,8 @@ namespace ILSOS_PrismaticScanner { if (device.DeviceId == DeviceIds.ACS || device.DeviceId == MotorIds.AxisX2 || - device.DeviceId == MotorIds.AxisY1 || - device.DeviceId == MotorIds.AxisY2 || + //device.DeviceId == MotorIds.AxisY1 || + //device.DeviceId == MotorIds.AxisY2 || device.DeviceId == MotorIds.AxisZ) { device.DevGroup = "ACS"; @@ -206,47 +178,12 @@ namespace ILSOS_PrismaticScanner } // ────────────────────────────────────────────────────────────────── - // ── 26.04.06 NDY 추가: 인터락 ───────────────────────────────────── - // TODO: PLCControllerPrismaticScanner에 IsDoorOpen, IsEMO 있는지 확인 필요 - 없는 것 확인 완료 - //PLC_DOOR_INTERLOCK = 6, // ← 도어 인터락 - //PLC_EMO_STATUS = 7, // ← EMO - AddMotionInterlockCheck(_plc); - // ────────────────────────────────────────────────────────────────── + #endregion } // 인터락 - private void AddMotionInterlockCheck(PLCControllerPrismaticScanner plc) - { - var motorIds = new[] { - MotorIds.AxisX2, - MotorIds.AxisY1, - MotorIds.AxisY2, - MotorIds.AxisZ - }; - foreach (var motorId in motorIds) - { - try - { - var motor = AuroraEnv.DeviceManager[motorId] as ACSMotor; - if (motor == null) continue; - - //motor.AddInterlockCheck(("MotorInPos", - // () => !motor.ReadInposition())); - //motor.AddInterlockCheck(("IsDoorOpen", - // () => plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_DOOR_INTERLOCK).data)); - //motor.AddInterlockCheck(("IsEMO", - // () => plc.ReadBit(PLCControllerPrismaticScanner.eBitInput.PLC_EMO_STATUS).data)); - - //*** 인터락은 이정인 선임께 ACSMotor에 AddInterlockCheck가 있는지 확인 후 진행 - } - catch (Exception ex) - { - Log.W($"AddMotionInterlockCheck [{motorId}] 실패: {ex.Message}"); - } - } - } public override void RegisterRecipes(RecipeRegister register) { register(CommonRecipeIds.ScannerObjectTeaching, new ScannerObjectTeachingRecipe(), @@ -332,10 +269,10 @@ namespace ILSOS_PrismaticScanner base.RegisterViews(manager); // Auto Run - // 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); + // 26.04.06 NDY: Manual 서브로 이동 - 26.04.14 주석이였으나 - 주석 해제 + 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); diff --git a/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs b/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs index 1fc1a2f..fb43ec8 100644 --- a/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs +++ b/Machines/ILSOS_PrismaticScanner/Sequences/Manual/SeqComponentTeachingRun.cs @@ -35,7 +35,7 @@ using VisionCommon; using WeldingCommon; using WeldingCommon.Alarm; using WeldingCommon.Data; -using WeldingCommon.Devices.ACS; // 26.04.06 +using WeldingCommon.Devices.ACS; // 26.04.06 using WeldingCommon.Sequences; using WeldingCommon.Settings; using WeldingCommon.Utils; @@ -51,25 +51,29 @@ namespace ILSOS_PrismaticScanner.Sequences { static readonly Logger Log = new Logger("SeqComponentTeachingRun"); - const string SEQ_ENTER = "SEQ_ENTER"; // inputParam 으로 받자. - const string SEQ_CHECK_INIT_CONDITION = "Check Init Condition"; // Check Init Condition + const string SEQ_ENTER = "[SeqComponentTeachingRun] SEQ_ENTER"; // inputParam 으로 받자. + const string SEQ_CHECK_INIT_CONDITION = "[SeqComponentTeachingRun] Check Init Condition"; // Check Init Condition - const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "Set Sequence Param (UploadWeldingList Seq)"; - const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "Process (UploadWeldingList Seq)"; - const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "Get Sequence Result (UploadWeldingList Seq)"; + const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqComponentTeachingRun] Set Sequence Param (UploadWeldingList Seq)"; + const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqComponentTeachingRun] Process (UploadWeldingList Seq)"; + const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "[SeqComponentTeachingRun] Get Sequence Result (UploadWeldingList Seq)"; + const string SEQ_SET_BLOW_ON = "[SeqComponentTeachingRun] Set Blow On"; + const string SEQ_SET_BLOW_OFF = "[SeqComponentTeachingRun] Set Blow Off"; - const string SEQ_COMPLETE = "SEQ_COMPLETE"; // 완료 + const string SEQ_SAVE_RESULT_DATA = "[SeqComponentTeachingRun] Save Result Data"; - const string SEQ_START_WELDING = "Start All Welding"; - const string SEQ_DO_COMPONENT_WELDING = "Do Component Welding"; - const string SEQ_ACS_MOTION_SET = "Set ACS Motion Parameter"; - const string SEQ_ACS_MOTION_START = "ACS Motion Start"; - const string SEQ_CHECK_MOTION_END = "Check ACS Motion Complete"; + const string SEQ_COMPLETE = "[SeqComponentTeachingRun] SEQ_COMPLETE"; // 완료 + + const string SEQ_UPDATE_COMPONENT_WELDING_PARAMETERS = "[SeqComponentTeachingRun] Update Component Welding Parameters"; + const string SEQ_START_WELDING = "[SeqComponentTeachingRun] Start All Welding"; + const string SEQ_DO_COMPONENT_WELDING = "[SeqComponentTeachingRun] Do Component Welding"; + const string SEQ_CHECK_END_LIST = "[SeqComponentTeachingRun] Check End List"; + const string SEQ_END_WELDING = "[SeqComponentTeachingRun] End All Welding"; #region 260408 NDY 노드 추가 // Builder()에 노드 추가 - const string SEQ_STANDBY_MOTION = "Move Stage To Origin"; - const string SEQ_STANDBY_SCANNER = "Encoder Reset"; + //const string SEQ_MOVE_STAGE_ORIGIN = "[SeqComponentTeachingRun] Move Stage To Origin"; + //const string SEQ_ENCODER_RESET = "[SeqComponentTeachingRun] Encoder Reset"; #endregion const int timeoutSeconds = 10; @@ -82,6 +86,7 @@ namespace ILSOS_PrismaticScanner.Sequences private SeqTeachingRun_InitParam _InitParam; private static Scanner _Scanner; + private static PAIX_PrismaticScanner _IO; // 필드 선언 추가 (다른 필드들 옆에) // 변경 전 @@ -90,7 +95,13 @@ namespace ILSOS_PrismaticScanner.Sequences // 변경 후 private IScannerACS _ACS; // 26.04.06 NDY - MOTF용 ACS Stage X 제어 - private static ACSMotor _AxisX, _AxisZ; // 26.04.08 NDY - MOTF용 Stage X 축 + private static ACSMotor _AxisX; // 26.04.08 NDY - MOTF용 Stage X 축 + + private Laser _Laser; + private ILaser _LaserDevice; + private LaserTruFiber _LaserTruFiber; + private LaserPowerCalParam _LaserPowerCalParam; + private PLCControllerPrismaticScanner _plc; private SystemParameter _SystemParameter; private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언 @@ -101,48 +112,69 @@ namespace ILSOS_PrismaticScanner.Sequences private List _SelectedObjectList; + private Queue> _DivideObjectsQueue; private List _TargetObjects; private static DateTime _SequenceCompleteTime; // 시퀸스 시간 private static TimeSpan _MeasurementSpanTime; //측정 시간 private static TimeSpan _ScannerSaveLogTime; private static DateTime _partialWeldingStartTime; + private static List _FlattenRecipes; + private static int _CountWeldingObject; // 트럼프 레시피에서 부분 용접 할 Ojbect의 개수 + private static int _CurrentobjectIndex; + private static int _BeforeObjectIndex; + private static int _BeforeProgramNo; // 이전 트럼프 레이저 용접 번호 + private static int _BeforeParameterNo; // + private static int _CenterBeamPower; + private static int _RingBeamPower; + private static bool _LaserPowerControlByRatio = false; + private static int _CenterRingRatio; // Center Ring의 파워 비율 + private static double _LaserPowerRatio; // Laser에서 출력 파워 비율 public SequenceBuilder Builder() { var sb = new SequenceBuilder(1000, true); + ////var sb = new SequenceBuilder(1000, false); // With log sb.AddAction(SEQ_ENTER, Sequence_Enter); sb.AddAction(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기 - #region 26.04.08 추가된 노드 NDY - // 26.04.08 필드 좌표 0,0으로 스테이지 이동 시퀸스 + EncoderReset 호출 - sb.AddAction(SEQ_STANDBY_MOTION, SetStandbyMotion); - sb.AddAction(SEQ_STANDBY_SCANNER, SetStandbyScanner); + sb.AddAction(SEQ_SET_BLOW_ON, SetBlowOn); + #region 26.04.08 추가된 노드 NDY + // 26.04.08 필드 좌표 0,0으로 스테이지 이동 시퀸스 + EncoderReset 호출 + //sb.AddAction(SEQ_MOVE_STAGE_ORIGIN, MoveStageToOrigin); + //sb.AddAction(SEQ_ENCODER_RESET, EncoderReset); #endregion + sb.AddAction(SEQ_START_WELDING, StartWelding); + sb.AddDecision(SEQ_CHECK_END_LIST, CheckEndList); + sb.AddAction(SEQ_UPDATE_COMPONENT_WELDING_PARAMETERS, UpdateComponentWeldingParameters); sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams); sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, CommonSequenceManager.GetSeqBuilder_SeqUploadWeldingList()); sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult); sb.AddAction(SEQ_DO_COMPONENT_WELDING, DoComponentWelding); - sb.AddAction(SEQ_ACS_MOTION_SET, SetMotion); - sb.AddAction(SEQ_ACS_MOTION_START, StartMotion); - sb.AddAction(SEQ_CHECK_MOTION_END, EndWelding); + sb.AddAction(SEQ_END_WELDING, EndWelding); + sb.AddAction(SEQ_SET_BLOW_OFF, SetBlowOff); + sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함. sb.AddAction(SEQ_COMPLETE, Complete); - sb.Flows(sb.Init - > sb[SEQ_ENTER] - > sb[SEQ_CHECK_INIT_CONDITION] - > sb[SEQ_STANDBY_MOTION] - > sb[SEQ_STANDBY_SCANNER] - > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] - > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] - > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ] - > sb[SEQ_DO_COMPONENT_WELDING] - > sb[SEQ_ACS_MOTION_SET] - > sb[SEQ_ACS_MOTION_START] - > sb[SEQ_CHECK_MOTION_END] - > sb[SEQ_COMPLETE] - > sb.Final); + // 기존 흐름에서 SET_BLOW_ON → START_WELDING 사이에 끼워넣기 + #region 기존 흐름 26.04.08 + sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_SET_BLOW_ON] + > sb[SEQ_START_WELDING] > sb[SEQ_CHECK_END_LIST]); + #endregion + #region 2개 노드 추가한 흐름 26.04.08 + //sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_SET_BLOW_ON] + // > sb[SEQ_MOVE_STAGE_ORIGIN] // ← 추가 + // > sb[SEQ_ENCODER_RESET] // ← 추가 + // > sb[SEQ_START_WELDING] > sb[SEQ_CHECK_END_LIST]); + #endregion + + // 아래 두 흐름은 기존 그대로 유지 + sb.Flows(sb[SEQ_CHECK_END_LIST] > sb[SEQ_UPDATE_COMPONENT_WELDING_PARAMETERS] + > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ] + > sb[SEQ_DO_COMPONENT_WELDING] > sb[SEQ_CHECK_END_LIST]); + sb.Flows(sb[SEQ_CHECK_END_LIST] > sb[SEQ_END_WELDING] > sb[SEQ_SET_BLOW_OFF] + > sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_COMPLETE] > sb.Final); sb.OnStopped(OnStopped); sb.OnForceError(OnForceError); @@ -152,123 +184,23 @@ namespace ILSOS_PrismaticScanner.Sequences return sb; } - - - private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) - { - Log.I("===== SeqTeachingRun Sequence_Enter 진입 ====="); // 임시 추가 - Log.I("SeqTeachingRun Start"); - - _InitParam = param.Param as SeqTeachingRun_InitParam; - _SystemParameter = context.Settings[CommonSettingIds.SystemParameter] as SystemParameter; - _SequenceSetting = context.Settings[CommonSettingIds.Sequence] as SequenceSetting; - - _Scanner = context.Devices[DeviceIds.Scanner] as Scanner; - if (_Scanner == null) { MessageUtil.ShowErrorToast("Scanner not Ready", Log); return null; } - - _ACS = context.Devices[DeviceIds.ACS] as ScannerACS; - if (_ACS == null) { MessageUtil.ShowErrorToast("ACS not Ready", Log); return null; } - - _AxisX = context.Devices[CommonDeviceIds.AxisX2] as ACSMotor; - if (_AxisX == null) { MessageUtil.ShowErrorToast("AxisX not Ready", Log); return null; } - - _AxisZ = context.Devices[CommonDeviceIds.AxisZ] as ACSMotor; - if (_AxisZ == null) { MessageUtil.ShowErrorToast("AxisZ not Ready", Log); return null; } - - //Check Device - if (!CheckDeviceReady(context)) { - AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_DeviceNotReady); - Log.E("The devices are not active."); - return null; - } - - return SequenceAction.Ok(); - } - private bool CheckDeviceReady(SequenceContext context) - { - List deviceListToCheck = new List() { DeviceIds.ACS, CommonDeviceIds.Scanner, CommonDeviceIds.AxisX2, CommonDeviceIds.AxisZ }; - //List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.IODevice,DeviceIds.ACS }; 변수 맵 수신 후 ACS 주석 해제 위에 주석 처리 - bool isAllDeviceActivated = true; - foreach (string item in deviceListToCheck) { - if (!context.Devices[item].IsActivated) { - isAllDeviceActivated = isAllDeviceActivated && false; - } - } - - return isAllDeviceActivated; - } - - private SequenceActionResult CheckInitCondition(SequenceContext context, string id, SequenceActionResult param) - { - bool boolian = AlarmManager.HasAlarmLevelHigh(); - if (boolian) { - Log.E($"Clear Heavy Alarms For Welding!"); - MessageUtil.ShowWarningToast(string.Format("Clear Heavy Alarms For Welding!")); - return null; - } - - _ScannerSaveLogTime = TimeSpan.Zero; - - var startTime = DateTime.Now; - context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime); - - Log.D("ComponentTeachingRun Sequence CheckInitCondition"); - return SequenceAction.Ok(); - } - #region 26.04.08 NDY - private SequenceActionResult SetStandbyMotion(SequenceContext context, string id, SequenceActionResult param) + private SequenceActionResult EncoderReset(SequenceContext context, string id, SequenceActionResult param) { - if (_AxisX == null) { - Log.W("[MoveStageToOrigin] AxisX2 null - 스킵"); + if (_ACS == null) + { + Log.W("[EncoderReset] ACS null - 스킵"); return SequenceAction.Ok(); } - Log.I("[MoveStageToOrigin] Stage X → 0 이동 시작"); - - // (스캐너의 0,0 && 용접 대상의 시작 위치) >> X축을 이동 - _AxisX.SetTargetPos(0, TargetPosType.ABS); - _AxisX.SetMoveVelocityImm(AuroraACS.Speed.M); - _AxisX.AccelerationImm(AuroraACS.Speed.M); - _AxisX.DecelerationImm(AuroraACS.Speed.M); - _AxisX.JerkImm(AuroraACS.Speed.M); - _AxisX.Move(); - - // Laser FocusPosition Move - _AxisZ.SetTargetPos(0, TargetPosType.ABS); - _AxisZ.SetMoveVelocityImm(AuroraACS.Speed.M); - _AxisZ.AccelerationImm(AuroraACS.Speed.M); - _AxisZ.DecelerationImm(AuroraACS.Speed.M); - _AxisZ.JerkImm(AuroraACS.Speed.M); - _AxisZ.Move(); - - var res = context.RetryUntilSuccess( - () => _AxisX.IsReachedTargetPosition(0) && _AxisZ.IsReachedTargetPosition(0), - 30 * 1000, 20, true); - - if (res == E2.TIMEOUT) { Log.E("[MoveStageToOrigin] TIMEOUT"); return null; } - else if (res == E2.CANCELLED) { Log.E("[MoveStageToOrigin] CANCELLED"); return null; } - - Log.I("[MoveStageToOrigin] Stage X = 0 도달 완료"); - return SequenceAction.Ok(); - - } - private SequenceActionResult SetStandbyScanner(SequenceContext context, string id, SequenceActionResult param) - { - // Scanner Default Setting - var mainPage = CommonHelper.GetMainPage(); - _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; - _WeldingScannerListNo = eListNo.LIST1; - _SelectedObjectList = FindObjects(); - //Vision Correction File 선택 - _Scanner.SelectCorrectionTable(2); - - if (!_Scanner.Config.UseMarkingOnTheFly) { + if (!_Scanner.Config.UseMarkingOnTheFly) + { Log.W("[EncoderReset] MOTF 비활성화 - 스킵"); return SequenceAction.Ok(); } Log.I("[EncoderReset] 시작"); + // SeqUploadWeldingList.MarkingOnTheFlyOn 패턴 _Scanner.SetFlyX(_Scanner.Config.MarkingOnTheFlyEncoderResolutionX); Log.I($"[EncoderReset] SetFlyX: {_Scanner.Config.MarkingOnTheFlyEncoderResolutionX}"); @@ -282,36 +214,398 @@ namespace ILSOS_PrismaticScanner.Sequences Log.I("[EncoderReset] 완료 - Stage(0) = Scanner(0) 동기화"); return SequenceAction.Ok(); } - //SeqTeachingPosMoveStageA패턴 참고 - 기존 GUN 프로젝트 시퀸스 + //SeqTeachingPosMoveStageA패턴 참고 - 기존 GUN 프로젝트 시퀸스 + private SequenceActionResult MoveStageToOrigin(SequenceContext context, string id, SequenceActionResult param) + { + if (_AxisX == null) + { + Log.W("[MoveStageToOrigin] AxisX2 null - 스킵"); + return SequenceAction.Ok(); + } + + Log.I("[MoveStageToOrigin] Stage X → 0 이동 시작"); + + // SeqTeachingPosMoveStageA.MoveXYStage 패턴 + _AxisX.SetTargetPos(0, TargetPosType.ABS); + _AxisX.SetMoveVelocityImm(AuroraACS.Speed.M); + _AxisX.AccelerationImm(AuroraACS.Speed.M); + _AxisX.DecelerationImm(AuroraACS.Speed.M); + _AxisX.JerkImm(AuroraACS.Speed.M); + _AxisX.Move(); + + var res = context.RetryUntilSuccess( + () => _AxisX.IsReachedTargetPosition(0), + 30 * 1000, 20, true); + + if (res == E2.TIMEOUT) { Log.E("[MoveStageToOrigin] TIMEOUT"); return null; } + if (res == E2.CANCELLED) { Log.E("[MoveStageToOrigin] CANCELLED"); return null; } + + Log.I("[MoveStageToOrigin] Stage X = 0 도달 완료"); + return SequenceAction.Ok(); + + } + #endregion + private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) + { + Log.I("===== SeqTeachingRun Sequence_Enter 진입 ====="); // 임시 추가 + Log.I("SeqTeachingRun Start"); + + _InitParam = param.Param as SeqTeachingRun_InitParam; + _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); + + //_Laser = context.GetLaser(); + //_Laser.GetLaserDevice(ref _LaserDevice); + //_LaserTruFiber = _LaserDevice as LaserTruFiber; + + //if (_plc == null) + // _plc = context.Devices[DeviceIds.PLCDevice] as PLCControllerPrismaticScanner; + + // Laser 시퀀스 Running. 안 넣어줘도 됨. + //_LaserTruFiber.SetIsSeqRunning(true); + + _LaserPowerCalParam = context.GetSetting(CommonSettingIds.LaserPowerCalParam);//우선 AuroraRecipe로 상속받아서 함수 사용하도록 함 + //laserPowerCalParam 초기화(CSV 파일 불러오기) + _LaserPowerCalParam.Initialize(_LaserPowerCalParam.PowerCalibrationCenterBeamCSVFile, _LaserPowerCalParam.PowerCalibrationRingBeamCSVFile); + + _SequenceSetting = context.Settings[CommonSettingIds.Sequence] as SequenceSetting; + InitDev(context); + if (!CheckDeviceReady(context)) + { //Check Device + AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_DeviceNotReady); + Log.E("The devices are not active."); + return null; + } + + if (InitSequenceVariable(context) == false) + { + AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_InitVariableError); + return null; + } + + + return SequenceAction.Ok(); + } + private void InitDev(SequenceContext context) + { + //Device Init + _Scanner = context.GetLaserScanner(); + //_IO = context.Devices[CommonDeviceIds.IODevice] as PAIX_PrismaticScanner; + + // 26.04.06 NDY 추가: ACS 디바이스 취득 (null-safe) + // 변수 맵 수신 후 MOTFStart() 호출에 사용 + // 변경 전 + //try { _ACS = context.Devices[DeviceIds.ACS] as ScannerACS; } + // 변경 후 + try { _ACS = context.Devices[DeviceIds.ACS] as IScannerACS; } + catch { _ACS = null; Log.W("ACS 디바이스 취득 실패 (null 처리)"); } + + //26.04.08 NDY 추가 _AxisX 가져오기 + try { _AxisX = context.Devices[CommonDeviceIds.AxisX2] as ACSMotor; } + catch { _AxisX = null; Log.W("AxisX2 취득 실패"); } + } + private bool CheckDeviceReady(SequenceContext context) + { + List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.IODevice }; + //List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.IODevice,DeviceIds.ACS }; 변수 맵 수신 후 ACS 주석 해제 위에 주석 처리 + bool isAllDeviceActivated = true; + foreach (string item in deviceListToCheck) + { + if (!context.Devices[item].IsActivated) + { + isAllDeviceActivated = isAllDeviceActivated && false; + } + } + + return isAllDeviceActivated; + } + private bool InitSequenceVariable(SequenceContext context) + { + var mainPage = CommonHelper.GetMainPage(); + _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; + + _WeldingScannerListNo = eListNo.LIST1; + + _SelectedObjectList = FindObjects(); + + return true; + } private List FindObjects() { - if (_InitParam.IsUseExternalObjects) { + if (_InitParam.IsUseExternalObjects) + { return _InitParam.ExternalObjects; - } else if (_InitParam.IsObjectSelectAll) { + } + else if (_InitParam.IsObjectSelectAll) + { return _ScannerCanvasUserCtrl.Model.ActiveLayer.Objects; - } else { + } + else + { return _ScannerCanvasUserCtrl.Canvas.Model.SelectedObjects; } + + } + + private SequenceActionResult CheckInitCondition(SequenceContext context, string id, SequenceActionResult param) + { + if (!CheckCondition()) + { + AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_CheckInitCondition); + Log.E("Condition is not in state to start sequence."); + context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false); + return null; + } + + _CurrentobjectIndex = 0; + _BeforeObjectIndex = 0; + _CountWeldingObject = 0; + _BeforeParameterNo = -1; + _BeforeProgramNo = -1; + _ScannerSaveLogTime = TimeSpan.Zero; + + _FlattenRecipes = new List(); // 레시피 초기화 + UnpackRecipes(_SelectedObjectList); + var startTime = DateTime.Now; + context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime); + + Log.D("ComponentTeachingRun Sequence CheckInitCondition"); + return SequenceAction.Ok(); + } + private bool CheckCondition() + { + if (CheckCondition_Interlock()) + { + if (InitializeDeviceStatus()) + { + return true; + } + } + return false; + } + + private bool CheckCondition_Interlock() + { + //// PLC, Data, IO 등 Interlock checking + bool boolian = AlarmManager.HasAlarmLevelHigh(); + if (boolian) + { + Log.E($"Clear Heavy Alarms For Welding!"); + MessageUtil.ShowWarningToast(string.Format("Clear Heavy Alarms For Welding!")); + return false; + } + boolian = AlarmManager.IsPlcDoorOpen(); + if (boolian) + { + Log.E($"PLC Door Opened!! Can't Weld Now."); + MessageUtil.ShowWarningToast(string.Format("Close Door ! Clear PLC DoorInterlock!")); + return false; + } + + boolian = AlarmManager.IsPlcEmoAlarm(); + if (boolian) + { + Log.E($"PLC EMO Pushed!! Can't Weld Now."); + MessageUtil.ShowWarningToast(string.Format("Clear PLC EMO Status!")); + return false; + } + return true; + } + + private bool InitializeDeviceStatus() + { + //Vision Correction File 선택 + _Scanner.SelectCorrectionTable(2); + return true; + } + + private SequenceActionResult SetBlowOn(SequenceContext context, string id, SequenceActionResult param) + { + if (_InitParam.UseBlow == false) + { + return SequenceAction.Ok(); + } + + int intervalTime = _InitParam.IntervalTimeBlowOn; + //_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingN2BlowSol), true); + Thread.Sleep(intervalTime); + + Log.D(string.Format($"[ComponentTeachingRun] Blow ON Complete")); + + return SequenceAction.Ok(); + } + + private void SaveScannerRecordFileForamt() + { + if (_Scanner.Config.UseRecordSignal) + { + DateTime startTime = DateTime.Now; + _Scanner.SaveStackRecord("Normal"); + _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); + } } - #endregion + private SequenceActionResult StartWelding(SequenceContext context, string id, SequenceActionResult param) + { + Log.D(string.Format($"[ComponentTeachingRun] Start Component Welding")); + _SequenceCompleteTime = DateTime.Now; + // Laser 판넬 On + //_IO.WriteDoBit(PAIX_PrismaticScanner.ePrismaticDOAddress.CCCAPLaserOnLampOn, true); + _DivideObjectsQueue = SplitBySerialize(_FlattenRecipes); + Log.I($"Divided DrawObjects List Count[{_DivideObjectsQueue.Count}]"); + + return SequenceAction.Ok(); + } + + // 펼쳐진 객체(_FlattenRecipes)를 여러개의 스캔 파라미터에 따라 여러개로 나눈다 + public static Queue> SplitBySerialize(List source) + { + var result = new Queue>(); + if (source == null || source.Count == 0) + return result; + + List current = null; + int? currentId = null; + + foreach (var item in source) + { + if (current == null || currentId.Value != item.ScannerParamID) + { + current = new List(); + result.Enqueue(current); + currentId = item.ScannerParamID; + } + + current.Add(item); + } + + return result; + } + + private string CheckEndList(SequenceContext context, string id, ICollection branches, SequenceActionResult param) + { + if (_DivideObjectsQueue.Count == 0) + return SEQ_END_WELDING; + + // 파일 저장 변수 초기화 + if (_Scanner.Config.UseRecordSignal) + { + DateTime startTime = DateTime.Now; + _Scanner.InitializeRecord(); + _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); + } + + return SEQ_UPDATE_COMPONENT_WELDING_PARAMETERS; + + } + + private SequenceActionResult UpdateComponentWeldingParameters(SequenceContext context, string id, SequenceActionResult param) + { + _partialWeldingStartTime = DateTime.Now; + //var currentDivideObject = _DivideObjectsQueue.Peek(); + //int paramIndex = currentDivideObject[0].ScannerParamID - 1; + //Log.I($"Remain Divided DrawObjects Count[{currentDivideObject.Count}] / ParameterNo[{paramIndex + 1}]"); + + //int SlotNo = _plc.ReadWord(eWordInput.PLC_CURRENT_SLOT_NO).data; + //if (SlotNo <= 0) + // SlotNo = 1; + //// 결과 Data 를 업데이트 함. + //var power = Status.GetProcessingWeldingData().UploadProcessDatas.Where(data => data.DataName == $"Power_{SlotNo}_{_SequenceSetting.LastPageNo}").FirstOrDefault(); + + //#region 26.04.08 NDY 캘리브레이션 노드 추가 테스트를 위해서 잠시 예외처리 코드 추가 + //if (power != null) + // power.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower1 + // + ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower2; + //#endregion + //// 26.04.08 NDY 주석처리 - power null 예외 방지 (위 null 체크로 대체) + ////power.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower1 + ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower2; + + + //var velocity = Status.GetProcessingWeldingData().UploadProcessDatas.Where(data => data.DataName == $"Velocity_{SlotNo}_{_SequenceSetting.LastPageNo}").FirstOrDefault(); + //#region 26.04.08 NDY velocity null에 대한 예외 처리 + //if (velocity != null) + // velocity.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].MarkSpeed; + //#endregion + //// 26.04.08 NDY 주석처리 - velocity null 예외 방지 (위 null 체크로 대체) + ////velocity.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].MarkSpeed; + + + //// 26.04.08 NDY - FDC 데이터 상신 -기존 코드 주석처리 + ////_plc.UploadReportDatas(Status.GetProcessingWeldingData().UploadProcessDatas); + //// 26.04.08 NDY - FDC 상신도 데이터 있을 때만 - 테스트 목적 예외 처리 추가 + //if (Status.GetProcessingWeldingData().UploadProcessDatas.Count > 0) + // _plc.UploadReportDatas(Status.GetProcessingWeldingData().UploadProcessDatas); + + //_CenterBeamPower = (int)ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower1; + //_RingBeamPower = (int)ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower2; + //_CenterRingRatio = 0; + + //if (_CenterBeamPower == 0 && _RingBeamPower == 0) + // _CenterRingRatio = 100; + //else + // _CenterRingRatio = (int)Math.Round((double)(100 * _CenterBeamPower) / (double)(_CenterBeamPower + _RingBeamPower), 0); // Discrete 한 값이라서 Ring은 오차 발생 + + ////if (_Laser.Config.TruFiberType == eTruFiberType.TruFiberP) + ////{ + // _CenterBeamPower = _LaserPowerCalParam.CalibrateWattToWatt(_CenterBeamPower, (uint)LaserPowerCalParam.beamMode.Center); + // _RingBeamPower = _LaserPowerCalParam.CalibrateWattToWatt(_RingBeamPower, (uint)LaserPowerCalParam.beamMode.Ring); + ////} + //// Ready 상태 변경 확인(Complete 상태에서 Laser Ready로 변환되기까지 시간이 걸림) + //// 여기서는 왜 IW03과 Center를 비교하는 것인지.... 아직 값을 써주지 않았으므로 레이저 출사 가능 여부만 확인하면 되지 않을까. + //var res = context.RetryUntilSuccess(_Laser.GetLaserReady, timeoutSeconds * 1000, 1); + + //if (res == E2.TIMEOUT) + //{ + // Log.E(string.Format($"[Page Change Req] Laser Program Ready Timeout When LaserReady")); + // return null; + //} + //Log.D(string.Format($"[Page Change Req] Laser Program Ready OK")); + + //// Laser Program Parameters 설정(Laser Ready 상태는 용접 직전에 확인) + //List<(int, int, bool)> datas = new List<(int, int, bool)>(); + //datas.Add((csWriteNodeNo.IW03, _CenterBeamPower, true)); + //datas.Add((csWriteNodeNo.IW04, _RingBeamPower, true)); + //datas.Add((csWriteNodeNo.IW05, _CenterRingRatio, true)); + + //// 업데이트 될 경우, 프로그램 전환을 위한 프로그램 종료 시퀸스 진행됨. + //if (_LaserTruFiber.UpdatesDatasIfChanged(datas)) + //{ + + // // 프로그램이 종료 될 때까지 대기. + // res = context.RetryUntilSuccess(_LaserTruFiber.GetProgramCompleted, timeoutSeconds * 1000, 10); + + // if (res == E2.TIMEOUT) + // { + // Log.E(string.Format($"[Page Change Req] Laser Program Completed Timeout When Parameter Changes")); + // return null; + // } + // Log.D(string.Format($"[Page Change Req] Laser Program Completed OK When Data Updated")); + //} + + return SequenceAction.Ok(); + } private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.UPLOADING_WELD_LIST); // TeachingRun에는 용접 시퀀스만 정의해서 Auto Run에서도 사용하므로 Offset 넣어줘야 함 - SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() { + SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() + { NeedSetLaserTiming = _InitParam.NeedSetLaserTiming, IncludeListStartEnd = true, CellMeasureCenterOffsetX = _SystemParameter.CellPosMeasureCenterOffsetX + _InitParam.CellCenterOffsetX, CellMeasureCenterOffsetY = _SystemParameter.CellPosMeasureCenterOffsetY + _InitParam.CellCenterOffsetY, - SelectedDrawObjectList = _SelectedObjectList, + SelectedDrawObjectList = _DivideObjectsQueue.Peek(), WeldingScannerListNo = _WeldingScannerListNo, }; + var _PageNo = _SequenceSetting.LastPageNo; + + Log.W($"page {_PageNo}({Status.GetProcessingWeldingData().CellId}) : Cell Offset Value Check ; X : {_SystemParameter.CellPosMeasureCenterOffsetX} + {_InitParam.CellCenterOffsetX} ; Y : {_SystemParameter.CellPosMeasureCenterOffsetY} + {_InitParam.CellCenterOffsetY}"); + Log.D(string.Format($"[ComponentTeachingRun] Set UploadWelindList Seq Param")); + return SequenceAction.Ok(seqParams); } @@ -320,7 +614,8 @@ namespace ILSOS_PrismaticScanner.Sequences Log.D(string.Format($"[ComponentTeachingRun] Get UploadWelindList Seq Param")); var resultOutParam = param.Param as SeqUploadWeldingList_OutParam; - if (resultOutParam.Success == false) { + if (resultOutParam.Success == false) + { Log.E(string.Format($"[ComponentTeachingRun] Failed UploadWeldingList Sequence")); return null; } @@ -331,7 +626,33 @@ namespace ILSOS_PrismaticScanner.Sequences private SequenceActionResult DoComponentWelding(SequenceContext context, string id, SequenceActionResult param) { - Log.I("ExecuteList Start"); + _DivideObjectsQueue.Dequeue(); + Log.I("UploadWeldingList Complete"); + Log.D(string.Format($"[ComponentTeachingRun] Component Welding Start idx :({_BeforeObjectIndex} ~ {_BeforeObjectIndex + _CountWeldingObject - 1})")); + + #region PSTART_DYN 사용시 참고 + //// PSTART_DYN에서는 레이저가 활성화되었는지 확인하여야 함. 하지만, PSTART_STATICALLY에서는 굳이 확인할 필요 없음. (이전에 확인해줄 것이므로) + // var res = context.RetryUntilSuccess(_LaserTruFiber.GetProgramActive, timeoutSeconds * 1000, 1); + //if (res == E2.TIMEOUT) + //{ + // Log.E(string.Format($"[ComponentTeachingRun] Laser Program Active Timeout")); + // return null; + //} + #endregion + + //Log.D(string.Format($"[ComponentTeachingRun] Check LaserReadyResponse")); + //// 만일 프로그램이 정상적으로 종료 및 변경 원할 경우, 레이저 스레드에서 Ready 상태로 만들어주고 있을 것임. + //// Ready 상태 변경 확인 + //var res = context.RetryUntilSuccess(LaserReadyResponse, timeoutSeconds * 1000, 10); + //if (res == E2.TIMEOUT) + //{ + // Log.E(string.Format($"[ComponentTeachingRun] Laser Program Ready Timeout When LaserReadyResponse")); + // return null; + //} + //Log.D(string.Format($"[ComponentTeachingRun] Laser Program Ready OK When ReadyResponse")); + + //Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD); + Log.I($"Welding List Space : {_Scanner.GetListSpace()}"); DateTime weldingTime = DateTime.Now; _Scanner.ExecuteList(_WeldingScannerListNo); @@ -346,14 +667,32 @@ namespace ILSOS_PrismaticScanner.Sequences + _Scanner.WaitForListTaskCompleted(_SystemParameter.WeldLinesTaskTimeOut); // ── 26.04.06 NDY 추가: ACS 완료 대기 ───────────────── // TODO: 변수 맵 수신 후 활성화 // while (!_ACS.CheckMOTFComp()) { Thread.Sleep(10); } // ──────────────────────────────────────────────────── + _MeasurementSpanTime = DateTime.Now.Subtract(weldingTime); + Log.D(string.Format($"[ComponentTeachingRun] Component Welding Complete Time : {_MeasurementSpanTime.TotalMilliseconds}")); - if (_Scanner.Config.UseRecordSignal) { + #region PSTART_DYN 사용시 참고 + //// 굳이 확인할 필요가 없을 듯 함.PSTAT_STATICALLY 활용시. + //res = context.RetryUntilSuccess(_LaserTruFiber.GetProgramCompleted, timeoutSeconds * 1000, 1); + + //if (res == E2.TIMEOUT) + //{ + // Log.E(string.Format($"[ComponentTeachingRun] Laser Program Complete Timeout")); + // return null; + //} + #endregion + + Log.D(string.Format($"[ComponentTeachingRun] Laser Program Complete OK")); + + + if (_Scanner.Config.UseRecordSignal) + { DateTime startTime = DateTime.Now; _Scanner.StackRecord(); _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); @@ -368,35 +707,17 @@ namespace ILSOS_PrismaticScanner.Sequences _ScannerCanvasUserCtrl.TimeLabelUpdate(_MeasurementSpanTime.TotalMilliseconds, PartialTactTime.TotalMilliseconds); - return SequenceAction.Ok(); - } - - private SequenceActionResult SetMotion(SequenceContext context, string id, SequenceActionResult param) - { - // 메뉴얼 화면에서 셋팅이 필요해보임 - _ACS.SetMOTFParams(0, 0, 0, 0, 0); - return SequenceAction.Ok(); - } - - private SequenceActionResult StartMotion(SequenceContext context, string id, SequenceActionResult param) - { - _ACS.MOTFStart(); - // 모션 동작시키고 바로 확인하면 그냥 빠져나올 것 같음 - var res = context.Wait(1000, 100); - if (res == E2.TIMEOUT) ; - else if (res == E2.CANCELLED) { Log.E("[MOTF] Motion CANCELLED"); return null; } - - res = context.RetryUntilSuccess(() => _ACS.CheckMOTFComp(), 1000 * 20, 100, true); - if (res == E2.TIMEOUT) { Log.E("[MOTF] Motion TIMEOUT"); return null; } - else if (res == E2.CANCELLED) { Log.E("[MOTF] Motion CANCELLED"); return null; } + //// 용접 끝난 후, 초기화 시킴 + //var UploadDatas = Status.GetProcessingWeldingData().UploadProcessDatas; + //foreach (var data in UploadDatas) + // data.Clear(); + //_plc.UploadReportDatas(UploadDatas); return SequenceAction.Ok(); } + private SequenceActionResult EndWelding(SequenceContext context, string id, SequenceActionResult param) { - _Scanner.WaitForListTaskCompleted(_SystemParameter.WeldLinesTaskTimeOut); - Log.I("ExecuteList Complete"); - _MeasurementSpanTime = DateTime.Now.Subtract(_SequenceCompleteTime); Log.D(string.Format($"[TactTime] Complete All Component Weld : {_MeasurementSpanTime.TotalMilliseconds}")); @@ -406,6 +727,9 @@ namespace ILSOS_PrismaticScanner.Sequences _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); _Scanner.JumpAbs(0, 0, eFunctionType.COMMAND); + // Laser 판넬 Off + //_IO.WriteDoBit(PAIX_PrismaticScanner.ePrismaticDOAddress.CCCAPLaserOnLampOn, false); + var mesurementTime = DateTime.Now; //용접 완료 후 CorrectionFile Vision으로 원복 @@ -417,12 +741,36 @@ namespace ILSOS_PrismaticScanner.Sequences return SequenceAction.Ok(); } + private SequenceActionResult SetBlowOff(SequenceContext context, string id, SequenceActionResult param) + { + if (_InitParam.UseBlow == false) + { + return SequenceAction.Ok(); + } + + int intervalTime = _InitParam.IntervalTimeBlowOff; + Thread.Sleep(intervalTime); + + //_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePDOAddress.SeamWeldingN2BlowSol), false); + + Log.D(string.Format($"[ComponentTeachingRun] Blow OFF Complete")); + + return SequenceAction.Ok(); + } + + private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param) + { + context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true); + return SequenceAction.Ok(); + } + private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) { context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); SeqTeachingRun_OutParam result = new SeqTeachingRun_OutParam() { Success = seqResult }; - if (seqResult == false) { + if (seqResult == false) + { AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_ResultFailed); } @@ -430,15 +778,28 @@ namespace ILSOS_PrismaticScanner.Sequences return SequenceAction.Ok(result); } - private void SaveScannerRecordFileForamt() + private static void UnpackRecipes(List recipes) { - if (_Scanner.Config.UseRecordSignal) { - DateTime startTime = DateTime.Now; - _Scanner.SaveStackRecord("Normal"); - _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); + // Recipe를 재귀적으로 탐색해서 List로 재구성하는 함수 + if (recipes == null) + return; + + for (int i = 0; i < recipes.Count; i++) + { + if (recipes[i] is Group) + { + Group subGroup = recipes[i] as Group; + List subrecipes = subGroup.SubObjects as List; + UnpackRecipes(subrecipes); + } + else + { + _FlattenRecipes.Add(recipes[i]); + } } } + private void OnForceError(SequenceContext context, string arg2) { // Scanner Log 저장 @@ -451,6 +812,9 @@ namespace ILSOS_PrismaticScanner.Sequences _Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND); _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); + // TruFiber레이저 Ready로 변경 + ForceLaserReady(); + //Scanner 원점 복귀 // 복귀 시 Scanner Busy 상태일 수 있으므로 진행중인 작업이 끝날 때까지 대기 Thread.Sleep(10); @@ -472,15 +836,41 @@ namespace ILSOS_PrismaticScanner.Sequences _Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND); _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); + // TruFiber레이저 Ready로 변경 + ForceLaserReady(); + //Scanner 원점 복귀 // 복귀 시 Scanner Busy 상태일 수 있으므로 진행중인 작업이 끝날 때까지 대기 Thread.Sleep(10); _Scanner.JumpAbs(0, 0, eFunctionType.COMMAND); Thread.Sleep(10); + // Laser 판넬 Off + //_IO.WriteDoBit(PAIX_PrismaticScanner.ePrismaticDOAddress.CCCAPLaserOnLampOn, false); Log.I("SequenceAction Ok : OnStopped"); } + + + + private void ForceLaserReady() + { + // 트럼프 레이저에서 PStartDyn, Prog_Stop을 감시하여 강제로 Ready 상태로 만드는 함수 + if (_Laser.IsSimul) + { + return; + } + + //// PSTART_STATICAL 에서는 필요 없어보임. + //_LaserTruFiber.SetProgEnd(); + + // Laser 판넬 Off + //_IO.WriteDoBit(PAIX_PrismaticScanner.ePrismaticDOAddress.CCCAPLaserOnLampOn, false); + + Log.I("SequenceAction Ok : Set Laser Ready"); + + } + } // TODO: UseStream 으로 TeachingRun 을 할 필요가 있을까?? 확인 필요 diff --git a/Machines/ILSOS_PrismaticScanner/Sequences/Monitoring/SeqAlarmMonitor.cs b/Machines/ILSOS_PrismaticScanner/Sequences/Monitoring/SeqAlarmMonitor.cs index 9becb69..7a3250a 100644 --- a/Machines/ILSOS_PrismaticScanner/Sequences/Monitoring/SeqAlarmMonitor.cs +++ b/Machines/ILSOS_PrismaticScanner/Sequences/Monitoring/SeqAlarmMonitor.cs @@ -106,7 +106,8 @@ namespace WeldingCommon.Sequences if (_SequenceSetting.ScannerActivated) _Scanner = context.GetLaserScanner(); - if (_SequenceSetting.LaserActivated) { + if (_SequenceSetting.LaserActivated) + { _Laser = context.GetLaser(); _LaserTruFiber = _Laser.getCore() as LaserTruFiber; } @@ -282,16 +283,24 @@ namespace WeldingCommon.Sequences } } else { _LaserTruFiber = _Laser.getCore() as LaserTruFiber; - // Laser OPCUA로 연결한 경우 - if (_LaserTruFiber.GetEStopOpen()) { + //// Laser OPCUA로 연결한 경우 + + //#region 26.04.14 삭제 할 것 + if (_LaserTruFiber == null) return SequenceAction.Ok();; // 강제 OK + //#endregion + if (_LaserTruFiber.GetEStopOpen()) + { AlarmManager.Alarm(AlarmCode_PrismaticScanner.ALARM_DEVICE_IO_LASER_EMO); } - if (_LaserTruFiber.GetFaultLaser()) { - string alarmCode = $"{Convert.ToString(_LaserTruFiber.GetLastMessageCompID(),16).ToUpper().PadLeft(2,'0')}{Convert.ToString(_LaserTruFiber.GetLastMessageCompNum(),16).ToUpper().PadLeft(2,'0')} {Convert.ToString(_LaserTruFiber.GetLastMessageMsgCode(),16).ToUpper().PadLeft(2,'0')}"; + if (_LaserTruFiber.GetFaultLaser()) + { + string alarmCode = $"{Convert.ToString(_LaserTruFiber.GetLastMessageCompID(), 16).ToUpper().PadLeft(2, '0')}{Convert.ToString(_LaserTruFiber.GetLastMessageCompNum(), 16).ToUpper().PadLeft(2, '0')} {Convert.ToString(_LaserTruFiber.GetLastMessageMsgCode(), 16).ToUpper().PadLeft(2, '0')}"; string alarmDescription = $" {_LaserTruFiber.GetLastMessageShortText()}"; AlarmManager.ChangeAlarmDescription(AlarmCode_PrismaticScanner.ALARM_DEVICE_LASER_ERROR_MSG, alarmCode + alarmDescription); - } else if (_LaserTruFiber.GetMonitoring()) { + } + else if (_LaserTruFiber.GetMonitoring()) + { string alarmCode = $"{Convert.ToString(_LaserTruFiber.GetLastMessageCompID(), 16).ToUpper().PadLeft(2, '0')}{Convert.ToString(_LaserTruFiber.GetLastMessageCompNum(), 16).ToUpper().PadLeft(2, '0')} {Convert.ToString(_LaserTruFiber.GetLastMessageMsgCode(), 16).ToUpper().PadLeft(2, '0')}"; string alarmDescription = $" {_LaserTruFiber.GetLastMessageShortText()}"; AlarmManager.ChangeAlarmDescription(AlarmCode_PrismaticScanner.ALARM_DEVICE_LASER_WARNING_MSG, alarmCode + alarmDescription); diff --git a/Machines/ILSOS_PrismaticScanner/Sequences/SeqAutoRunPrismaticScanner.cs b/Machines/ILSOS_PrismaticScanner/Sequences/SeqAutoRunPrismaticScanner.cs index 368cf45..36f3488 100644 --- a/Machines/ILSOS_PrismaticScanner/Sequences/SeqAutoRunPrismaticScanner.cs +++ b/Machines/ILSOS_PrismaticScanner/Sequences/SeqAutoRunPrismaticScanner.cs @@ -73,1061 +73,153 @@ namespace ILSOS_PrismaticScanner.Sequences /// /// 각형 스캐너 타입 자동 운전을 위한 시퀸스 /// - class SeqAutoRunPrismaticScanner + public class SeqAutoRunPrismaticScanner { static readonly Logger Log = new Logger("SeqAutoRunPrismaticScanner"); - #region 시퀸스 변수명 const string SEQ_ENTER = "SEQ_ENTER"; // inputParam 으로 받자. const string SEQ_CHECK_INIT_CONDITION = "Check Init Condition"; // Check Init Condition - const string SEQ_FORK_CHECK_SEQ_SETTING = "Fork Check Seq Setting"; + const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "Set Sequence Param (UploadWeldingList Seq)"; + const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "Process (UploadWeldingList Seq)"; + const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "Get Sequence Result (UploadWeldingList Seq)"; - const string SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ = "Set Sequence Param (ExecutePlcPageChangeOrWeldRequestInterface Seq)"; - const string SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST = "Process (Wait Page Change Request Or Weld Request)"; - const string SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ = "Get Sequence Result (ExecutePlcPageChangeOrWeldRequestInterface Seq)"; - - const string SEQ_CHECK_CELL_INFO_RECEIVE = "Check Cell Info Receive"; // 셀 정보 수신 확인 - const string SEQ_CHECK_WELDDING_RETRY = "Check Welding Retry"; - const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "Get Sequence Result (ReceiveCellInfo Seq)"; - const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "Process (ReceiveCellInfo Seq)"; - const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "Set Sequence Param (ReceiveCellInfo Seq)"; - const string SEQ_JOIN_CELL_INFO_RECEIVE = "Complete Check Cell Info Receive"; - - const string SEQ_CHECK_VISION_COMPENSION_USE = "Check Vision Compensation Use"; // 비전 보상 사용 확인 - const string SEQ_DO_VISION_JOB = "Do Vision Job"; // 비전 작업 진행 - const string SEQ_JOIN_VISION_COMPENSION = "Complete Vision Compensation"; - const string SEQ_CHECK_SAVE_WELD_IMAGE = "Check Save Weld Image"; - const string SEQ_SAVE_WELD_IMAGE = "Save Weld Image"; // 용접 후 이미지 저장 - - const string SEQ_JOIN_CHECK_SEQ_SETTING = "Join Check Seq Setting"; - - const string SEQ_SEND_EVENT_SENDER = "Event Sender"; // Image Q 저장 - const string SEQ_SEND_EVENT_SENDER2 = "Event Sender2"; // Image Q 저장 - - const string SEQ_EVENT_Q_SAVE_FILE = "EventQ Save File"; - const string SEQ_SAVE_IMAGES = "Save Images"; - - const string SEQ_CHECK_VISION_COMPLETE = "Check Vision Complete"; - const string SEQ_NG_RESULT_PROCESS = "Ng Result Process"; - - const string SEQ_GENERATE_WELDING_OBJECT = "Generate Welding Object"; // 용접 객체 생성 - const string SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ = "Set Params Component Teachingrun Seq"; // 용접 리스트 업로드 파라미터 설정 - const string SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ = "Process (Component Teachingrun Seq)"; // 용접 리스트 업로드 시퀀스 처리 - const string SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ = "Get Result Component Teachingrun Seq"; // 용접 리스트 업로드 결과 가져오기 - - const string SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Get Sequence Result (PLC Weld Complete Interface Seq)"; - const string SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Process (PLC Weld Complete Interface Seq)"; - const string SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Set Sequence Param (PLC Weld Complete Interface Seq)"; - - const string SEQ_SAVE_RESULT_DATA = "Save Result Data"; // 결과 데이터 저장 const string SEQ_COMPLETE = "SEQ_COMPLETE"; // 완료 + + const string SEQ_START_WELDING = "Start All Welding"; + const string SEQ_DO_COMPONENT_WELDING = "Do Component Welding"; + const string SEQ_ACS_MOTION_SET = "Set ACS Motion Parameter"; + const string SEQ_ACS_MOTION_START = "ACS Motion Start"; + const string SEQ_CHECK_MOTION_END = "Check ACS Motion Complete"; + + #region 260408 NDY 노드 추가 + // Builder()에 노드 추가 + const string SEQ_STANDBY_MOTION = "Move Stage To Origin"; + const string SEQ_STANDBY_SCANNER = "Encoder Reset"; #endregion + const int timeoutSeconds = 10; static class ContextKey { public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunPrismaticScanner"; public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunPrismaticScanner"; } - #region 변수 정의 - // 디바이스 정의 - private Scanner _Scanner; - private Laser _Laser; - private PLCControllerPrismaticScanner _PLC; - private IODevice _IO; - private LightDevice _Light; - #region 26.04.09 NDY ACS와 축도 가져와야하지 않을까 ? - private ScannerACS ScannerACS; - #endregion + private SeqTeachingRun_InitParam _InitParam; + + private static Scanner _Scanner; + + // 필드 선언 추가 (다른 필드들 옆에) + // 변경 전 + //private ScannerACS _ACS; + + + // 변경 후 + private IScannerACS _ACS; // 26.04.06 NDY - MOTF용 ACS Stage X 제어 + private static ACSMotor _AxisX, _AxisZ; // 26.04.08 NDY - MOTF용 Stage X 축 - // 비전 정의 - private CameraAgentBase _CameraAgent; - private ICameraDisplay _CameraDisplay; - private PatternAgentBase _PatternAgent; - private List _Patterns; - private PatternInfo _PatternInfo; - private PatternResult _PatternResult; - private FieldScanParams _FieldScanParams; - private object _GrabImage; - private MIL_ID _GrabImageMilId; - private int _RetryCount = 0; - private double _OffsetXfromModelFinder = 0; - private double _OffsetYfromModelFinder = 0; - // 시스템 및 용접 파라미터 정의 private SystemParameter _SystemParameter; - private static SequenceSetting _SequenceSetting; private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언 - private List _SelectedDrawObjectList; - private static List _UnpackDrawObject; - private SeqAutoRunPrismaticScanner_InitParam _InitParam; + private static SequenceSetting _SequenceSetting; - // 생산 데이터 정의 - private uint _TodayProduct; - private uint _TotalProduct; + private eListNo _WeldingScannerListNo; - private DateTime _AutoRunStartTime; - private DateTime _WeldStartTime; - private DateTime _WeldEndTime; - private TimeSpan _WeldSpanTime; - private TimeSpan _InterfaceSpanTime; - private DateTime _InterfaceStartTime; - private string _LotId = "N/A"; - private string _CellId = "N/A"; - const int timeoutSeconds = 10; - - private bool _FirstUpdateStep = true; - private bool _IsWeldingRetry = false; - private int _CurrentWeldingStep = 0; - private int _TotalWeldingStep = 0; - private int _PreviousTotalWeldingStep = 0; - private int _PageNo = 1; - private MIL_ID _ResultImageMilId; - private bool _SuccessVisionResult = false; - const int PLC_TIMEOUT = 60; // sec, Timeout은 시퀀스 정지가 아니라 타임아웃 시간마다 로그만 남기도록 한다 - - public string EVENT_TRIGGER_SAVE_FILE = "EventTriggerSaveFile"; - - // 공정 시간 측정 - private static DateTime _WeldReqTime; - private static DateTime _WeldComTime; - - private List lightValues = new List { 255, 255, 255, 255 }; - - private (double X, double Y) TargetObjectCenterPosition = (X: 0.0, Y: 0.0); - #endregion + private List _SelectedObjectList; + private List _TargetObjects; + private static DateTime _SequenceCompleteTime; // 시퀸스 시간 + private static TimeSpan _MeasurementSpanTime; //측정 시간 + private static TimeSpan _ScannerSaveLogTime; + private static DateTime _partialWeldingStartTime; public SequenceBuilder Builder() { var sb = new SequenceBuilder(1000, true); - ////var sb = new SequenceBuilder(1000, false); // With log sb.AddAction(SEQ_ENTER, Sequence_Enter); - sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기 + sb.AddAction(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기 + #region 26.04.08 추가된 노드 NDY + // 26.04.08 필드 좌표 0,0으로 스테이지 이동 시퀸스 + EncoderReset 호출 + sb.AddAction(SEQ_STANDBY_MOTION, SetStandbyMotion); + sb.AddAction(SEQ_STANDBY_SCANNER, SetStandbyScanner); + #endregion - ///// PLC_USE_PAGE_CHANGE_INTERFACE - sb.AddAction(SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ, SetPlcPageChangeOrWeldRequest_SeqParams); - sb.AddSubsequence(SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST, SequenceManager.GetSeqBuilder_SeqWaitWeldOrChangePage()); - sb.AddAction(SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ, GetPlcPageChangeOrWeldRequest_SeqParams); - - ///// Fork - sb.AddFork(SEQ_FORK_CHECK_SEQ_SETTING); - - ///// Check & Cell Load - sb.AddDecision(SEQ_CHECK_CELL_INFO_RECEIVE, CheckCellInfoReceive); - sb.AddDecision(SEQ_CHECK_WELDDING_RETRY, CheckWeldingRetry); - sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams); - sb.AddSubsequence(SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ, SequenceManager.GetSeqBuilder_SeqReceiveCellInfo()); - sb.AddAction(SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ, GetReceiveCellInfo_SeqResult); - sb.AddAction(SEQ_JOIN_CELL_INFO_RECEIVE, JoinCellInfoReceive); - - ///// Check & Use Model Finder - sb.AddDecision(SEQ_CHECK_VISION_COMPENSION_USE, CheckVisionCompensationUse); - sb.AddAction(SEQ_DO_VISION_JOB, DoVisionJob); - sb.AddAction(SEQ_JOIN_VISION_COMPENSION, JoinVisionCompensation); - sb.AddDecision(SEQ_CHECK_SAVE_WELD_IMAGE, CheckSaveWeldImage); - sb.AddAction(SEQ_SAVE_WELD_IMAGE, SaveWeldImage); - - ///// Event Q - sb.AddEventSender(SEQ_SEND_EVENT_SENDER, SendEvent); - sb.AddEventSender(SEQ_SEND_EVENT_SENDER2, SendEvent); - sb.AddEventQ(SEQ_EVENT_Q_SAVE_FILE, 2); - sb.AddAction(SEQ_SAVE_IMAGES, SaveImagesEvent); - - ///// Join - sb.AddJoin(SEQ_JOIN_CHECK_SEQ_SETTING); - sb.AddDecision(SEQ_CHECK_VISION_COMPLETE, CheckVisionComplete); - sb.AddAction(SEQ_NG_RESULT_PROCESS, NgResultProcess); - - ///// Weld Start / Complete - sb.AddAction(SEQ_GENERATE_WELDING_OBJECT, GenerateWeldingObject); - sb.AddAction(SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ, SetComponentTeachingrun_SeqParams); - sb.AddSubsequence(SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ, SequenceManager.GetSeqBuilder_SeqComponentTeachingRun()); - sb.AddAction(SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ, GetComponentTeachingrun_SeqResult); - - ///// Check Welding Retry Request; - sb.AddAction(SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ, SetPlcWeldCompleteInterface_SeqParams); - sb.AddSubsequence(SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ, SequenceManager.GetSeqBuilder_SeqExecutePlcBitInterface()); - sb.AddAction(SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ, GetPlcWeldCompleteInterface_SeqParams); - - sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함. + sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams); + sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, CommonSequenceManager.GetSeqBuilder_SeqUploadWeldingList()); + sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult); + sb.AddAction(SEQ_DO_COMPONENT_WELDING, DoComponentWelding); + sb.AddAction(SEQ_ACS_MOTION_SET, SetMotion); + sb.AddAction(SEQ_ACS_MOTION_START, StartMotion); + sb.AddAction(SEQ_CHECK_MOTION_END, EndWelding); sb.AddAction(SEQ_COMPLETE, Complete); - // [Action] 초기 세팅 - sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] - // [Decision] PLC에서 페이지 변경 및 용접 요청 들어온 경우 - > sb[SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ] > sb[SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST] > sb[SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ] - //// Fork1 - // [Decision] 셀 ID를 받을 수 있는 설정인 경우 - > sb[SEQ_FORK_CHECK_SEQ_SETTING]); - sb.Flows(sb[SEQ_FORK_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_CELL_INFO_RECEIVE] > sb[SEQ_CHECK_WELDDING_RETRY] > sb[SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_JOIN_CELL_INFO_RECEIVE] - //// Join - > sb[SEQ_JOIN_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_VISION_COMPLETE]); - // 비전 실패 - sb.Flows(sb[SEQ_CHECK_VISION_COMPLETE] > sb[SEQ_NG_RESULT_PROCESS] > sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ]); - // 비전 성공 - sb.Flows(sb[SEQ_CHECK_VISION_COMPLETE] > sb[SEQ_GENERATE_WELDING_OBJECT] - //// [Action] 용접 시작 - > sb[SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_CHECK_SAVE_WELD_IMAGE] > sb[SEQ_SAVE_WELD_IMAGE] > sb[SEQ_SEND_EVENT_SENDER2].Send(EVENT_TRIGGER_SAVE_FILE) - //// [Decision] 용접 완료 혹은 재시작 (GET_PARAMS 에서 진행) - > sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ] > sb[SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ] > sb[SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ] - // [Action] 결과값 입력 - > sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ]); + sb.Flows(sb.Init + > sb[SEQ_ENTER] + > sb[SEQ_CHECK_INIT_CONDITION] + > sb[SEQ_STANDBY_MOTION] + > sb[SEQ_STANDBY_SCANNER] + > sb[SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ] + > sb[SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ] + > sb[SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ] + > sb[SEQ_DO_COMPONENT_WELDING] + > sb[SEQ_ACS_MOTION_SET] + > sb[SEQ_ACS_MOTION_START] + > sb[SEQ_CHECK_MOTION_END] + > sb[SEQ_COMPLETE] + > sb.Final); - ///// Fork2 & Join - // [Decision] 비전 보상이 필요한 경우 - // [Decision] OFFSET 입력 혹은 재시도 결정 - sb.Flows(sb[SEQ_FORK_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_VISION_COMPENSION_USE] > sb[SEQ_DO_VISION_JOB] > sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_JOIN_VISION_COMPENSION] > sb[SEQ_JOIN_CHECK_SEQ_SETTING]); - // Scout Image Save Event Seq - sb.Flows(sb[SEQ_EVENT_Q_SAVE_FILE].On(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_SAVE_IMAGES] > sb.FlowFinal); - - // SEQ_CHECK_INIT_CONDITION - sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final); - // SEQ_CHECK_CELL_INFO_RECEIVE - sb.Flows(sb[SEQ_CHECK_CELL_INFO_RECEIVE] > sb[SEQ_JOIN_CELL_INFO_RECEIVE]); - sb.Flows(sb[SEQ_CHECK_WELDDING_RETRY] > sb[SEQ_JOIN_CELL_INFO_RECEIVE]); - - // SEQ_CHECK_VISION_COMPENSION_USE - sb.Flows(sb[SEQ_CHECK_VISION_COMPENSION_USE] > sb[SEQ_JOIN_VISION_COMPENSION]); - sb.Flows(sb[SEQ_CHECK_SAVE_WELD_IMAGE] > sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ]); - - sb.OnForceError(OnForceError); sb.OnStopped(OnStopped); + sb.OnForceError(OnForceError); + //sb.Draw("SeqAutoRunPrismaticScanner.pdf"); return sb; } - private string CheckWeldingRetry(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - if (_IsWeldingRetry) return SEQ_JOIN_CELL_INFO_RECEIVE; - else return SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ; - } - #region 시퀸스 함수 - - #region 1. 디바이스 및 변수 상태 확인 private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) { - Log.I("SeqAutoRunPrismaticScanner Start"); + Log.I("===== SeqTeachingRun Sequence_Enter 진입 ====="); // 임시 추가 + Log.I("SeqTeachingRun Start"); - _InitParam = param.Param as SeqAutoRunPrismaticScanner_InitParam; - _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); - _SequenceSetting = context.GetSetting(CommonSettingIds.Sequence); + _InitParam = param.Param as SeqTeachingRun_InitParam; + _SystemParameter = context.Settings[CommonSettingIds.SystemParameter] as SystemParameter; + _SequenceSetting = context.Settings[CommonSettingIds.Sequence] as SequenceSetting; - InitDev(context); - if (!CheckDeviceReady(context)) { - AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_DeviceNotReady); + _Scanner = context.Devices[DeviceIds.Scanner] as Scanner; + if (_Scanner == null) { MessageUtil.ShowErrorToast("Scanner not Ready", Log); return null; } + + _ACS = context.Devices[DeviceIds.ACS] as ScannerACS; + if (_ACS == null) { MessageUtil.ShowErrorToast("ACS not Ready", Log); return null; } + + _AxisX = context.Devices[CommonDeviceIds.AxisX2] as ACSMotor; + if (_AxisX == null) { MessageUtil.ShowErrorToast("AxisX not Ready", Log); return null; } + + _AxisZ = context.Devices[CommonDeviceIds.AxisZ] as ACSMotor; + if (_AxisZ == null) { MessageUtil.ShowErrorToast("AxisZ not Ready", Log); return null; } + + //Check Device + if (!CheckDeviceReady(context)) + { + AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_DeviceNotReady); Log.E("The devices are not active."); return null; } - if (InitSequenceVariable(context) == false) { - AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_InitVariableError); - return null; - } - - // Setting 값 - _PageNo = _SequenceSetting.LastPageNo; - Log.I($"Previous Page No is {_PageNo}"); - Log.I($"Sequence Setting Info is 1) ImageAcquire : {_SequenceSetting.UseImageAcquire}, 2) UseCellOffset : {_SequenceSetting.UseCellOffset}."); - return SequenceAction.Ok(); } - - private string CheckInitCondition(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION); - - if (!CheckCondition(context)) { - AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition); - Log.E("Condition is not in state to start sequence."); - context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false); - return SEQ_COMPLETE; - } - - var startTime = DateTime.Now; - context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime); - - // 자동 운전 시, 비전 보상 유무에 따른 조명 값 변경 - if (_SequenceSetting.UseCellOffset) UpdateAutoLightValue(_SequenceSetting.CompensationLightValue); - else UpdateAutoLightValue(_SequenceSetting.LightValue); - - // Light ALL ON - if (!_Light.CheckLightOnAndValue(lightValues[0])) { - _Light.SetLightValue(lightValues); - Log.I($"Light All On !"); - } - - // 레이저 레디 상태가 아니면, 레디 시켜야 함. - if (!_Laser.GetLaserReady()) { - _Laser.LaserOn(); - Log.I($"Start Laser ON in CheckInitCondition"); - } - - // 너무 빨리 되어서 문제인 것인가 ? - var res = context.RetryUntilSuccess(_Laser.GetLaserReady, timeoutSeconds * 1000, 10); - if (res == E2.TIMEOUT) { - Log.E("Laser Ready Fail When Autorun"); - return null; - } - - InitializePlcBits(); - - // CheckInitCondition 완료된다면.. - _PLC.WriteBit(eBitOutput.PC_AUTO_STATUS, true); - _PLC.WriteWord(eWordOutput.PC_PAGE_NO, (short)_PageNo); - - Log.I("Complete CheckInitCondition."); - - return SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ; - } - #endregion - - #region 2. Page 변경 시퀸스 ~ 3. Weld Req 시퀸스 - private SequenceActionResult SetPlcPageChangeOrWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - Log.I(string.Format("PLC Interface(PageChange, WeldReq) Start; (REQ,ACK); ({0},{1});({2},{3})", - (int)eBitInput.PLC_PAGE_CHANGE_REQ, (int)eBitOutput.PC_PAGE_CHANGE_COMPLETE, (int)eBitInput.PLC_WELD_READY_REQ, (int)eBitOutput.PC_WELD_READY_ACK)); - - Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL); - - // PLC 인터페이스 전까지 테스트 - SeqWaitWeldOrChangePage_InitParam seqParams = new SeqWaitWeldOrChangePage_InitParam() { - CurrentPageNo = (short)_PageNo, - NeedPageNo = _SequenceSetting.UsePageChangeMode, - TimeoutSec = 10, - Models = _ScannerCanvasUserCtrl.Model - }; - return SequenceAction.Ok(seqParams); - } - - private SequenceActionResult GetPlcPageChangeOrWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - // PageChangeOrWeldRequest 탈출 조건은 Weld Request가 동작했을 때임 - // 해당 단계까지 왔다면 용접 요청까지 받은 상태 - var resultOutParam = param.Param as SeqWaitWeldOrChangePage_OutParam; - _WeldReqTime = resultOutParam._WeldReqTime; - if (resultOutParam.Success == false) { - Log.E("Failed Page Change & Weld Request Interface"); - return null; - } - - Log.I($"Complete Page Change & Weld Request Interface"); - - // 처음 인터페이스할 때, Word Data 받아옴. - _PreviousTotalWeldingStep = _TotalWeldingStep; - _PageNo = resultOutParam.PLCPageNo; - // Total은 항상 같으므로 상관 없을 듯. - _TotalWeldingStep = Convert.ToInt16(_PLC.ReadWord(eWordInput.PLC_STEP_NO).data); - - _SequenceSetting.LastPageNo = _PageNo; - context.Settings.Save(CommonSettingIds.Sequence, _SequenceSetting, "SeqAutoRunPrismaticScanner_New"); - - // 용접 전에 NG 및 FDC 정보를 초기화한다. - Status.GetProcessingWeldingData().IsVisionNG = false; - _PLC.WriteBit(eBitOutput.PC_WELD_NG_JUDGE, false); - var UploadDatas = Status.GetProcessingWeldingData().UploadProcessDatas; - foreach (var data in UploadDatas) - data.Clear(); - _PLC.UploadReportDatas(UploadDatas); - - // PLC에게 값을 써주어야 함. - //_PLC.WriteWord((int)eWordOutput.PC_PAGE_NO, (short)_PageNo, PLCBase.ePLCDevice.D); - - Log.I(string.Format("Read Words; Page No: {0}; Step No: {1}", _PageNo, _TotalWeldingStep)); - - if (_PageNo > _ScannerCanvasUserCtrl.Model.Layers.Count() && _PageNo > 0) { - Log.E(string.Format("Page No isn't proper. ;Page No : {0}; Layers Count: {1}", _PageNo, _ScannerCanvasUserCtrl.Model.Layers.Count())); - return null; - } - - Status.GetProcessingWeldingData().CellId = _PLC.CellId(); - Status.GetProcessingWeldingData().LotId = _PLC.LotId(); - - if (_FirstUpdateStep) { - _FirstUpdateStep = false; - return SequenceAction.Ok(); - } - if (_PreviousTotalWeldingStep != _TotalWeldingStep) { - Log.E(string.Format("SeqCheckWeldingComplete Error;Changed Step No; Prev: {0}; Current: {1}", _PreviousTotalWeldingStep, _TotalWeldingStep)); - return null; - } - - return SequenceAction.Ok(); - } - #endregion - - #region 3. 용접 요청 인터페이스 (PLC <-> PC) - private SequenceActionResult SetPlcWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - Log.I(string.Format("Test1; REQ: {0}; ACK: {1}", (int)eBitInput.PLC_WELD_READY_REQ, (int)eBitOutput.PC_WELD_READY_ACK)); - - // PLC 인터페이스 전까지 테스트 - SeqExecutePlcBitInterface_InitParam seqParams = new SeqExecutePlcBitInterface_InitParam() { - GetAddress = eCommonBitInput.PLC_WELD_READY_REQ, - SetAddress = eCommonBitOutput.PC_WELD_READY_ACK, - TimeoutSec = 60, - FirstTimeoutSec = 6 * 60 * 60, // 2시간동안 대기, - IsSetMode = false - }; - return SequenceAction.Ok(seqParams); - } - - private SequenceActionResult GetPlcWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - // PLC 인터페이스 전까지 테스트 - var resultOutParam = param.Param as SeqExecutePlcBitInterface_OutParam; - if (resultOutParam.Success == false) { - return null; - } - - return SequenceAction.Ok(); - } - #endregion - - #region 4.1. 셀 데이터 받기 - private string CheckCellInfoReceive(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - if (_SequenceSetting.UseCellReport) { - Log.I(string.Format("Check Cell Info Receive")); - return SEQ_CHECK_WELDDING_RETRY; - } - else { - Log.I(string.Format("Pass Cell Info Receive")); - return SEQ_JOIN_CELL_INFO_RECEIVE; - } - } - - private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() { - }; - return SequenceAction.Ok(seqParams); - } - - private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param) - { - var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam; - if (resultOutParam.Success == false) { - return null; - } - - return SequenceAction.Ok(); - } - - private SequenceActionResult JoinCellInfoReceive(SequenceContext context, string id, SequenceActionResult param) - { - return SequenceAction.Ok(); - } - #endregion - - #region 4.2. 비전 보상 진행 - private string CheckVisionCompensationUse(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - if (_SequenceSetting.UseImageAcquire) { - Log.I(string.Format("Use Image Acquire")); - - // 비전 보상 유무에 따른 조명 값 변경 - if (_SequenceSetting.UseCellOffset) UpdateAutoLightValue(_SequenceSetting.CompensationLightValue); - else UpdateAutoLightValue(_SequenceSetting.LightValue); - - if (!_Light.CheckLightOnAndValue(lightValues[0])) { - _Light.SetLightValue(lightValues); - Log.I($"Light All On !"); - } - - return SEQ_DO_VISION_JOB; - } - else { - // Welding Object로 넘겨주기 전에는 Offset 값을 써주어야 됨 !! - _RetryCount = 0; - _OffsetXfromModelFinder = 0; - _OffsetYfromModelFinder = 0; - Log.I(string.Format("Unuse Image Acquire")); - return SEQ_JOIN_VISION_COMPENSION; - } - } - private static SeqVisionData_Param visionParam; - private SequenceActionResult DoVisionJob(SequenceContext context, string id, SequenceActionResult param) - { - // 1. Pattern은 0번부터 시작이며, Page 숫자 OR 그 이상으로 Pattern이 있어야 함. - _PatternInfo = _Patterns[_PageNo - 1]; - - // 2.1. 스캐너 이동을 객체 기반의 중앙 기반 이동 - FindObjectsCenter(out TargetObjectCenterPosition.X, out TargetObjectCenterPosition.Y); - Log.I(string.Format($"Move Scanner - ScannerPosX : {TargetObjectCenterPosition.X},ScannerPosY : {TargetObjectCenterPosition.Y} ")); - _Scanner.JumpAbs(TargetObjectCenterPosition.X, TargetObjectCenterPosition.Y); - - // 2.2. 이동까지 기다려주어야 함. - //250701 Vision Image 흔들림으로 인해 20ms로 변경 - Thread.Sleep(20); - - // 3.1. CameraDisplay의 Overlay된 것들 모두 클리어해줌. - _CameraDisplay.ClearMeasureGraphics(); - _CameraDisplay.ClearFindGraphics(); - _CameraDisplay.ClearTrainGraphics(); - - // 3.2. StopLive GrabSync를 통해서 이미지를 취득함. - object image = null; - _CameraAgent.StopLive(); - _CameraAgent.GrabSync(_CameraDisplay, ref image); - - // 4. 패턴 찾기 및 Score 기반으로 용접 여부 판단 변수 업데이트 - bool isHigherLimitScore = false; - - // 첫 번째 Offset 값을 사용하고 싶을 경우 UseExistOffset 활용할 것. 그러나 활용도는 매우 낮을 듯 함. 250701 기준 EL도 사용하지 않음. - if (_SequenceSetting.UseExistOffset && _PageNo != 1) { - Log.I(string.Format($"UseExistOffset : X(mm) : {_OffsetXfromModelFinder}, Y(mm) : {_OffsetYfromModelFinder}")); - if (_PatternResult != null && _PatternResult.Status == eFoundStatus.FoundOK) - isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.FirstLimitScore, _PatternInfo.PatternType); - } - else { - _PatternResult = _PatternAgent.Find(_PatternInfo, image, _CameraDisplay); - Log.I(string.Format($"First Model Find : {_PatternResult.Status.ToString()}")); - - // 첫 번째 실패하면, 한 번 더 찾을 수 있는 로직 구성. (UseSubPatternOnFailure 사용) - if (_PatternResult.Status != eFoundStatus.FoundOK && _SequenceSetting.UseSubPatternOnFailure) { - _PatternInfo = _Patterns[_PageNo - 1 + _TotalWeldingStep]; - _PatternResult = _PatternAgent.Find(_PatternInfo, image, _CameraDisplay); - Log.I(string.Format($"Second Model Find : {_PatternResult.Status.ToString()}")); - - if (_PatternResult.Status == eFoundStatus.FoundOK) - isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.SecondLimitScore, _PatternInfo.PatternType); - } - else { - if (_PatternResult.Status == eFoundStatus.FoundOK) - isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.FirstLimitScore, _PatternInfo.PatternType); - } - } - - // 4.1. 패턴 Found 여부 업데이트 - if (_PatternResult != null && _PatternResult.Status == eFoundStatus.FoundOK) - Status.GetProcessingWeldingData().IsVisionNG = false; - else - Status.GetProcessingWeldingData().IsVisionNG = true; - - // 5. 이미지 저장 관련 EventQueue 사용을 위한 Parameter 생성 - MIL_ID temp1; - MIL_ID temp2; - - // 5.1. 만약, Draw 중 문제 생길 경우 Log Error 발생하도록 수정 - try { - if (!Status.GetProcessingWeldingData().IsVisionNG) - _PatternAgent.Draw(_PatternInfo, _PatternResult, _CameraDisplay); - - temp1 = MilEnvironment.CloneImage((MIL_ID)image); - temp2 = MilEnvironment.GetOverlayImage((IMilCameraDisplay)_CameraDisplay); - Log.I($"Vision Draw Successed."); - } - catch (Exception ex) { - temp1 = MIL.M_NULL; - temp2 = MIL.M_NULL; - Log.E($"Vision Draw Error Occured !!!!!!;{ex.Message}"); - } - - // 6. Offset 값 추출 및 인터락 체크 - if (!Status.GetProcessingWeldingData().IsVisionNG) { - // 6.1. 보상 필요할 경우 Offset 값 구하기 - if (_SequenceSetting.UseCellOffset) { - double offsetX = 0; - double offsetY = 0; - - #region 기존 Offset 값 추출 코드. 뒤 코드 가독성이 좋아보여서 수정하였음. 문제 시 해당 코드 사용 - //foreach (BaseResult baseResult in _PatternResult.Results) { - // if (_PatternInfo.PatternType == ePatternType.ImageModelFinder || _PatternInfo.PatternType == ePatternType.ShapeModelFinder) { - // var result = baseResult as ModelFinderResult; - // offsetX = result.ImagePosition.X; - // offsetY = result.ImagePosition.Y; - // } else if (_PatternInfo.PatternType == ePatternType.PatternMatching) { - // var result = baseResult as PatternMatchingResult; - // offsetX = result.ImagePosition.X; - // offsetY = result.ImagePosition.Y; - // } else { - // Log.E("Pattern Type is not proper !!! "); - // return null; - // } - // break; - //} - #endregion - - // 6.1.1. 첫 번째 결과를 보상 값으로 활용함. 해당 구문 활용하여 추후 Score가 제일 높은 것을 고를 수도 있을 듯 함. - BaseResult baseResult = _PatternResult.Results.FirstOrDefault(); - - if (baseResult != null) { - switch (_PatternInfo.PatternType) { - case ePatternType.ImageModelFinder: - case ePatternType.ShapeModelFinder: - offsetX = (baseResult as ModelFinderResult).ImagePosition.X; - offsetY = (baseResult as ModelFinderResult).ImagePosition.Y; - break; - case ePatternType.PatternMatching: - offsetX = (baseResult as PatternMatchingResult).ImagePosition.X; - offsetY = (baseResult as PatternMatchingResult).ImagePosition.Y; - break; - default: - Log.E("Pattern Type is not proper !!! "); - return null; - } - } - - TranslateImageToField(offsetX, offsetY, out double _PatternOffsetX, out double _PatternOffsetY); - - // 6.1.2. Offset 값의 Distance 및 Score 따른 보상 진행 여부 결정 - double distance = Math.Sqrt(_PatternOffsetX * _PatternOffsetX + _PatternOffsetY * _PatternOffsetY); - if (distance < _SequenceSetting.CellOffsetLimit || isHigherLimitScore) { - _OffsetXfromModelFinder = _PatternOffsetX; - _OffsetYfromModelFinder = _PatternOffsetY; - _SuccessVisionResult = true; - Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; Can Compensate ; - PatternOffsetX(mm) : {_PatternOffsetX}, PatternOffsetY(mm) : {_PatternOffsetY}, Distance(mm) : {distance}, Vision Offset OK")); - } - else { - _OffsetXfromModelFinder = 0; - _OffsetYfromModelFinder = 0; - _SuccessVisionResult = false; - Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; Can't Compensate ; - PatternOffsetX(mm) : {_PatternOffsetX}, PatternOffsetY(mm) : {_PatternOffsetY}, Distance(mm) : {distance}, Vision Offset Fail")); - } - } - - } - else { - _OffsetXfromModelFinder = 0; - _OffsetYfromModelFinder = 0; - Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; OR Not Found ;")); - } - - - visionParam = new SeqVisionData_Param { - originalImageID = temp1, - overlayImageID = temp2, - IsSuccess = !Status.GetProcessingWeldingData().IsVisionNG, - VisionData_Foler = _SequenceSetting.VisionFolderName, - CellId = Status.GetProcessingWeldingData().CellId, - }; - - // 7. 필요시 해당 구문 테스트 필요 - //_CameraAgent.StartLive(_CameraDisplay); - - return SequenceAction.Ok(visionParam); - } - private bool IsHigherLimitScore(double limitScore, ePatternType patternType) - { - double Score = -1; - - #region 기존 코드. 이 후 코드가 가독성이 좋아보여서 수정. 필요 시, 사용할 것. - //foreach (BaseResult baseResult in _PatternResult.Results) { - // if (_PatternInfo.PatternType == ePatternType.ImageModelFinder || _PatternInfo.PatternType == ePatternType.ShapeModelFinder) { - // var result = baseResult as ModelFinderResult; - // Score = result.Score; - // } else if (_PatternInfo.PatternType == ePatternType.PatternMatching) { - // var result = baseResult as PatternMatchingResult; - // Score = result.Score; - // } - // break; - //} - #endregion - - Score = GetPatternScore(patternType); - Log.I(string.Format($"Extract Score : {Score}; Limit Score : {limitScore}")); - - if (Score.Equals(double.NaN)) { - Log.I(string.Format($"Fail Extract Score : Pattern Find Logic Mismatch")); - return false; - } - - return Score > limitScore ? true : false; - } - private double GetPatternScore(ePatternType patternType) - { - BaseResult baseResult = _PatternResult?.Results?.FirstOrDefault(); - - if (baseResult != null) { - switch (patternType) { - case ePatternType.ImageModelFinder: - case ePatternType.ShapeModelFinder: - return (baseResult as ModelFinderResult).Score; - case ePatternType.PatternMatching: - return (baseResult as PatternMatchingResult).Score; - default: - Log.E("Pattern Type is not proper !!! "); - return double.NaN; - } - } - return double.NaN; - } - private SequenceActionResult SaveImagesEvent(SequenceContext context, string id, SequenceActionResult param) - { - if (visionParam is SeqVisionData_Param result && result != null) { - var currentDate = DateTime.Now; - string SequenceSettingFilePath = result.VisionData_Foler; - - var FinalFilePath = Path.Combine(SequenceSettingFilePath, currentDate.ToString("yyyy"), currentDate.ToString("MM"), currentDate.ToString("dd")); - if (!Directory.Exists(FinalFilePath)) { - Directory.CreateDirectory(FinalFilePath); - } - - string SuccessStatus = result.IsSuccess ? "OK" : "NG"; - string CurrentTimeStamp = DateTime.Now.ToString("HHmmss"); - string rawFileName = $"{FinalFilePath}\\Raw\\Page{_PageNo.ToString()}\\{SuccessStatus}\\{CurrentTimeStamp}_{result.CellId}.png"; - string resultFileName = $"{FinalFilePath}\\Result\\Page{_PageNo.ToString()}\\{SuccessStatus}\\{CurrentTimeStamp}_{result.CellId}.png"; - - if (result.originalImageID != MIL.M_NULL) { - ImageUtil.SaveFieldScanImageJPG(result.originalImageID, rawFileName, 10); - MilEnvironment.FreeImage(result.originalImageID); - result.originalImageID = MIL.M_NULL; - Log.D($"Update Q Raw Image Complete;{rawFileName}"); - } - else { - Log.E($"Update Q Raw Image Failed;{rawFileName};rawImage Is Null.."); - } - if (result.overlayImageID != MIL.M_NULL) { - ImageUtil.SaveFieldScanImageJPG(result.overlayImageID, resultFileName, 10); - MilEnvironment.FreeImage(result.overlayImageID); - result.overlayImageID = MIL.M_NULL; - Log.D($"Update Q Overlay Image Complete;{resultFileName}"); - } - else { - Log.E($"Update Q Overlay Image Failed;{resultFileName};resultImage Is Null"); - } - } - else - Log.E("SeqVisionData_Param is null >> Image Save Fail"); - - - return SequenceAction.Ok(); - } - private string CheckSaveWeldImage(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - if (_SequenceSetting.UseWeldResultImage) { - return SEQ_SAVE_WELD_IMAGE; - } - else { - return SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ; - } - } - - private SequenceActionResult SaveWeldImage(SequenceContext context, string id, SequenceActionResult param) - { - // WeldResult이미지는 EventQ 저장 버그가 발생하였는데 원인 파악중. - double ScannerPosX = 0, ScannerPosY = 0; - - // 용접 이후에 용접 전에 찍은 이미지와 동일한 위치로 용접을 진행해야 함 - // 객체 기반의 중앙 기반 - FindObjectsCenter(out ScannerPosX, out ScannerPosY); - Log.I(string.Format($"Move Scanner - ScannerPosX : {ScannerPosX},ScannerPosY : {ScannerPosY} ")); - _Scanner.JumpAbs(ScannerPosX, ScannerPosY); - - // 이동까지 기다려주어야 함. - Thread.Sleep(20); // EL Welder에서 10ms로 설정 시 이동중에 이미지가 촬영되어 대기시간 증가 - - _CameraDisplay.ClearMeasureGraphics(); - _CameraDisplay.ClearFindGraphics(); - _CameraDisplay.ClearTrainGraphics(); - - object image = null; - _CameraAgent.StopLive(); - _CameraAgent.GrabSync(_CameraDisplay, ref image); - - if (_PatternResult?.Status == eFoundStatus.FoundOK) { - _PatternAgent.Draw(_PatternInfo, _PatternResult, _CameraDisplay); - } - - MIL_ID temp1; - MIL_ID temp2; - try { - // 성공하든 아니든 이미지를 남겨보자. - temp1 = MilEnvironment.CloneImage((MIL_ID)image); - temp2 = MilEnvironment.GetOverlayImage((IMilCameraDisplay)_CameraDisplay); - } - catch (Exception ex) { - temp1 = MIL.M_NULL; - temp2 = MIL.M_NULL; - Log.FuncE($"Vision Draw Error Occured !!!!!!;{ex.Message}"); - } - - visionParam = new SeqVisionData_Param { - originalImageID = temp1, - overlayImageID = temp2, - IsSuccess = !Status.GetProcessingWeldingData().IsVisionNG, - VisionData_Foler = _SequenceSetting.WeldResultFolderName, - CellId = Status.GetProcessingWeldingData().CellId, - }; - return SequenceAction.Ok(visionParam); - - } - - private object SendEvent(SequenceContext context, string id, SequenceActionResult param) - { - var seqParam = param.Param as SeqVisionData_Param; - return SequenceAction.Ok(seqParam); - } - private SequenceActionResult JoinVisionCompensation(SequenceContext context, string id, SequenceActionResult param) - { - return SequenceAction.Ok(); - } - #endregion - - private string CheckVisionComplete(SequenceContext context, string id, ICollection branches, SequenceActionResult param) - { - var visionComplete = !Status.GetProcessingWeldingData().IsVisionNG && _SuccessVisionResult && _SequenceSetting.UseCellOffset; - var WeldingSkip = !visionComplete && _SequenceSetting.UseNgCellSkip; - if (WeldingSkip) { - Log.I($"Vision Compension Complete[{!Status.GetProcessingWeldingData().IsVisionNG}] / Vision Result[{_SuccessVisionResult}] / UseCellOffset[{_SequenceSetting.UseCellOffset}]"); - return SEQ_NG_RESULT_PROCESS; - } - - // 성공했거나, Vision Offset을 사용 안하면 다음 스텝으로 - return SEQ_GENERATE_WELDING_OBJECT; - } - - private SequenceActionResult NgResultProcess(SequenceContext context, string id, SequenceActionResult param) - { - // 이미 NG 처리는 했고, PLC에서 로직상 BUSY는 토글되야 한다고 해서 넣어줌 - _PLC.WriteBit(eBitOutput.PC_WELD_NG_JUDGE, Status.GetProcessingWeldingData().IsVisionNG); - _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, true); - Thread.Sleep(100); - _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false); - return SequenceAction.Ok(); - } - - #region 5. 용접 진행 - private SequenceActionResult GenerateWeldingObject(SequenceContext context, string id, SequenceActionResult param) - { - _SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[_PageNo - 1].Objects; - - return SequenceAction.Ok(); - } - - private SequenceActionResult SetComponentTeachingrun_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, true); - - Log.I(string.Format("Weld Busy On ! Set ComponentTeachingrun Start.")); - - _WeldStartTime = DateTime.Now; - Status.GetProcessingWeldingData().WeldingStartTime = _WeldStartTime; - - var currentModelInfo = EquipmentSpecificModelUtil.GetCurrentRecipeEquipmentSpecificModel(); - if (currentModelInfo.equipmentSpecificModel == null) { - MessageUtil.ShowWarningToast(string.Format("선택된 model 이 없습니다.", "Laser On")); - return null; - } - - var intervalTimeBlowOn = 0; - var intervalTimeBlowOff = 0; - - if (currentModelInfo.equipmentSpecificModel.UseBlow) { - intervalTimeBlowOn = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOn; - intervalTimeBlowOff = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOff; - } - - Log.I(string.Format("Set ComponentTeachingrun Immediately!")); - - // Object를 만들어 - SeqTeachingRun_InitParam seqParam = new SeqTeachingRun_InitParam() { - IsUseExternalObjects = true, - ExternalObjects = _SelectedDrawObjectList, - - //UseStream = _EquipmentInfo.UseStream, - UseStream = currentModelInfo.equipmentSpecificModel.UseStream, - - UseBlow = currentModelInfo.equipmentSpecificModel.UseBlow, - IntervalTimeBlowOn = intervalTimeBlowOn, - IntervalTimeBlowOff = intervalTimeBlowOff, - - NeedSetLaserTiming = true, - CellCenterOffsetX = _OffsetXfromModelFinder, - CellCenterOffsetY = _OffsetYfromModelFinder - }; - - Log.I(string.Format("Set ComponentTeachingrun Complete!")); - - return SequenceAction.Ok(seqParam); - } - - private SequenceActionResult GetComponentTeachingrun_SeqResult(SequenceContext context, string id, SequenceActionResult param) - { - var resultOutParam = param.Param as SeqTeachingRun_OutParam; - Log.I(string.Format("Get ComponentTeachingrun Complete!")); - - if (resultOutParam.Success == false) { - Log.I(string.Format("SeqComponentTeachingrun Complete Error;Success Failed.")); - return null; - } - else Log.I(string.Format("SeqComponentTeachingrun Complete Success;Welding Complete!")); - - int bitRet = _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false); - Log.I("Weld Busy OFF!"); - - _WeldEndTime = DateTime.Now; - _WeldSpanTime = _WeldEndTime.Subtract(_WeldStartTime); - - Log.I($"[TactTime] Page({_PageNo}) Total Welding Time : {_WeldSpanTime.TotalMilliseconds}msec"); - - return SequenceAction.Ok(); - } - - private SequenceActionResult GetPlcWeldCompleteInterface_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - var resultOutParam = param.Param as SeqExecutePlcBitInterface_OutParam; - if (resultOutParam.Success == false) { - Log.I(string.Format("SeqCheckWeldingComplete Error;Success Failed.")); - return null; - } - else Log.I(string.Format("SeqCheckWeldingComplete Success;Welding Complete!")); - - _WeldComTime = DateTime.Now; - Log.I($"***** 공정 시간 WeldPage No : {_PageNo} WeldRequest ~ WeldComplete : {_WeldComTime.Subtract(_WeldReqTime).TotalMilliseconds}ms"); - _CurrentWeldingStep++; - - if (_CurrentWeldingStep >= _TotalWeldingStep) { - Log.I(string.Format("Need to Update the Cell Info;{0}/{1}", _CurrentWeldingStep, _TotalWeldingStep)); - _IsWeldingRetry = false; - _CurrentWeldingStep = 0; - Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL); - UpdateProductCount(context); - UpdateProductInfoForView(); - } - else { - Log.I(string.Format("Update Welding Step;{0}/{1}", _CurrentWeldingStep, _TotalWeldingStep)); - _IsWeldingRetry = true; - } - - return SequenceAction.Ok(); - } - - private SequenceActionResult SetPlcWeldCompleteInterface_SeqParams(SequenceContext context, string id, SequenceActionResult param) - { - Log.I(string.Format("SeqCheckWeldingComplete Set Parameters")); - - SeqExecutePlcBitInterface_InitParam seqParams = new SeqExecutePlcBitInterface_InitParam() { - GetAddress = (eCommonBitInput)eBitInput.PLC_WELD_COMPLETE_ACK, - SetAddress = (eCommonBitOutput)eBitOutput.PC_WELD_COMPLETE, - TimeoutSec = 60, - FirstTimeoutSec = 60, - IsSetMode = true - }; - return SequenceAction.Ok(seqParams); - } - #endregion - - #region 6. 데이터 쓰기 및 종료 - private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param) - { - Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT); - - DataTable table = new DataTable("CellHistory"); - table.Columns.Add("time", typeof(string)); - table.Columns.Add("Cell Id", typeof(string)); - table.Columns.Add("Pre Compensation X", typeof(double)); - table.Columns.Add("Pre Compensation Y", typeof(double)); - table.Columns.Add("Post Compensation X", typeof(double)); - table.Columns.Add("Post Compensation Y", typeof(double)); - table.Columns.Add("(Pre - Post) X", typeof(double)); - table.Columns.Add("(Pre - Post) Y", typeof(double)); - table.Columns.Add("(Pre - Post) RMS", typeof(double)); - table.Columns.Add("Score", typeof(double)); - - var SystemSetting = context.Settings[CommonSettingIds.SystemParameter] as SystemParameter; - - var DrawingObjectCenterX = TargetObjectCenterPosition.X; - var DrawingObjectCenterY = TargetObjectCenterPosition.Y; - - var FindObjectCenterX = _OffsetXfromModelFinder; - var FindObjectCenterY = _OffsetYfromModelFinder; - - var CompensionGapX = DrawingObjectCenterX - FindObjectCenterX; - var CompensionGapY = DrawingObjectCenterY - FindObjectCenterY; - - table.Rows.Add(DateTime.Now.ToString("HH:mm:ss"), - Status.GetProcessingWeldingData().CellId, - DrawingObjectCenterX, DrawingObjectCenterY, - FindObjectCenterX, FindObjectCenterY, - CompensionGapX, CompensionGapY, - Math.Sqrt(CompensionGapX * CompensionGapX + CompensionGapY * CompensionGapY), - GetPatternScore(_PatternInfo.PatternType)); - - string today = DateTime.Now.ToString("yyyyMMdd", CultureInfo.InvariantCulture); - string safeName = $"CellInfo_{today}.csv"; - - CSV_Manager.GetInstance().Save_DataTableToCsv(SystemSetting.CellHistoryFolderPath, safeName, table); - - context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true); - return SequenceAction.Ok(); - } - - private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) - { - RestoreDeviceStatus(); - - context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); - SeqAutoRunPrismaticScanner_OutParam result = new SeqAutoRunPrismaticScanner_OutParam() { Success = seqResult }; - - if (seqResult == false) { - AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_ResultFailed); - } - Status.SetWorkingPosition(eWorkingPosition.DONE); - - return SequenceAction.Ok(result); - } - #endregion - - #endregion - - #region 구동 함수 - - private bool InitSequenceVariable(SequenceContext context) - { - // TODO: [장비구현필요] Initialize Variable 추가 - FovInfo _fovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault(); - _PatternAgent = FovPatternAgentManager.GetAgent(_fovInfo.ToSubSysInfo()); - _Patterns = _PatternAgent.GetMainPatterns(_fovInfo); - _PatternInfo = _Patterns[_InitParam.VisionRecipeNo]; - _CameraDisplay = CameraDisplayManager.GetDisplay(_fovInfo, eDisplayType.Machine_A); - _CameraAgent = CameraAgentManager.GetCameraAgent(_fovInfo); - _FieldScanParams = FieldScanParams.GetInstance(); - _RetryCount = 0; - - var mainPage = CommonHelper.GetMainPage(); - _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; - // PLC에게 받는 PageNo는 1부터 시작 ! - _PageNo = 1; - _CurrentWeldingStep = 0; - _PreviousTotalWeldingStep = 0; - _TotalWeldingStep = 0; - _OffsetXfromModelFinder = 0; - _OffsetYfromModelFinder = 0; - - _IsWeldingRetry = false; - _FirstUpdateStep = true; - - return true; - } - - private void InitDev(SequenceContext context) - { - //Device Init - _Scanner = context.GetLaserScanner(); - _Laser = context.GetLaser(); - _PLC = context.GetPLC() as PLCControllerPrismaticScanner; - _Light = context.GetLight(); - - #region 26.04.09 - // 26.04.09 NDY - ScannerACS = context.Devices.GetDevice(CommonDeviceIds.ACS) as ScannerACS; - #endregion - } - private bool CheckDeviceReady(SequenceContext context) { - List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.PLCDevice }; + List deviceListToCheck = new List() { DeviceIds.ACS, CommonDeviceIds.Scanner, CommonDeviceIds.AxisX2, CommonDeviceIds.AxisZ }; + //List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.IODevice,DeviceIds.ACS }; 변수 맵 수신 후 ACS 주석 해제 위에 주석 처리 bool isAllDeviceActivated = true; - foreach (string item in deviceListToCheck) { - if (!context.Devices[item].IsActivated) { + foreach (string item in deviceListToCheck) + { + if (!context.Devices[item].IsActivated) + { isAllDeviceActivated = isAllDeviceActivated && false; } } @@ -1135,235 +227,321 @@ namespace ILSOS_PrismaticScanner.Sequences return isAllDeviceActivated; } - private bool CheckCondition(SequenceContext context) + private SequenceActionResult CheckInitCondition(SequenceContext context, string id, SequenceActionResult param) { - if (CheckCondition_Interlock()) { - if (InitializeDeviceStatus(context)) { - return true; - } + bool boolian = AlarmManager.HasAlarmLevelHigh(); + if (boolian) + { + Log.E($"Clear Heavy Alarms For Welding!"); + MessageUtil.ShowWarningToast(string.Format("Clear Heavy Alarms For Welding!")); + return null; } - return false; + + _ScannerSaveLogTime = TimeSpan.Zero; + + var startTime = DateTime.Now; + context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime); + + Log.D("ComponentTeachingRun Sequence CheckInitCondition"); + return SequenceAction.Ok(); } - private bool CheckCondition_Interlock() + #region 26.04.08 NDY + private SequenceActionResult SetStandbyMotion(SequenceContext context, string id, SequenceActionResult param) { - // PLC, Data, IO 등 Interlock checking - // 비전 오프셋을 쓰길 원한다면, 첫 번째 Object가 Arc 혹은 Dot이어야 함. - if (_SequenceSetting.UseImageAcquire) { - foreach (ICanvasLayer layer in _ScannerCanvasUserCtrl.Model.Layers) { - List sourcelist = layer.Objects; - _UnpackDrawObject?.Clear(); - _UnpackDrawObject = new List(); - UnpackRecipes(sourcelist); - - for (int i = 0; i < _UnpackDrawObject.Count; i++) { - if (!(_UnpackDrawObject[i] is Arc || _UnpackDrawObject[i] is Dot || _UnpackDrawObject[i] is Spline)) { - Log.E(string.Format("Object of Page{0} is not Arc & Dot. If you use a Image Acquire, check Page{0} objects", layer.No, layer.No)); - return false; - } - } - } - - // 패턴 갯수 관련 인터락 추가 - int patternCount = _Patterns.Count(); - int layerCount = _ScannerCanvasUserCtrl.Model.Layers.Count(); - if (_SequenceSetting.UseSubPatternOnFailure) { - if (patternCount < layerCount * 2) { - Log.E($"Can't Use SubPattern. Because of Sizes. Pattern Count : {patternCount}; Layer Count :{layerCount}"); - return false; - } - } - else { - if (patternCount < layerCount) { - Log.E($"Can't Use Pattern. Because of Sizes. Pattern Count : {patternCount}; Layer Count :{layerCount}"); - return false; - } - } + if (_AxisX == null) + { + Log.W("[MoveStageToOrigin] AxisX2 null - 스킵"); + return SequenceAction.Ok(); } - return true; + + Log.I("[MoveStageToOrigin] Stage X → 0 이동 시작"); + + // (스캐너의 0,0 && 용접 대상의 시작 위치) >> X축을 이동 + _AxisX.SetTargetPos(0, TargetPosType.ABS); + _AxisX.SetMoveVelocityImm(AuroraACS.Speed.M); + _AxisX.AccelerationImm(AuroraACS.Speed.M); + _AxisX.DecelerationImm(AuroraACS.Speed.M); + _AxisX.JerkImm(AuroraACS.Speed.M); + _AxisX.Move(); + + // Laser FocusPosition Move + _AxisZ.SetTargetPos(0, TargetPosType.ABS); + _AxisZ.SetMoveVelocityImm(AuroraACS.Speed.M); + _AxisZ.AccelerationImm(AuroraACS.Speed.M); + _AxisZ.DecelerationImm(AuroraACS.Speed.M); + _AxisZ.JerkImm(AuroraACS.Speed.M); + _AxisZ.Move(); + + var res = context.RetryUntilSuccess( + () => _AxisX.IsReachedTargetPosition(0) && _AxisZ.IsReachedTargetPosition(0), + 30 * 1000, 20, true); + + if (res == E2.TIMEOUT) { Log.E("[MoveStageToOrigin] TIMEOUT"); return null; } + else if (res == E2.CANCELLED) { Log.E("[MoveStageToOrigin] CANCELLED"); return null; } + + Log.I("[MoveStageToOrigin] Stage X = 0 도달 완료"); + return SequenceAction.Ok(); + } - - private bool InitializeDeviceStatus(SequenceContext context) + private SequenceActionResult SetStandbyScanner(SequenceContext context, string id, SequenceActionResult param) { + // Scanner Default Setting + var mainPage = CommonHelper.GetMainPage(); + _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; + _WeldingScannerListNo = eListNo.LIST1; + _SelectedObjectList = FindObjects(); + //Vision Correction File 선택 + _Scanner.SelectCorrectionTable(2); - return true; - } - - private void TranslateImageToField(double imgPosX, double imgPosY, out double realPosX, out double realPosY) - { - var imageWidthChild = _FieldScanParams.GetimageSizeWidthChild(); - var imageHeightChild = _FieldScanParams.GetimageSizeHeightChild(); - double moveOffsetX = 0; - double moveOffsetY = 0; - var cameraROIWidth = ((imageWidthChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; - var cameraROIHeight = ((imageHeightChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; - - moveOffsetX = ((imgPosX * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0 - cameraROIWidth * 0.5; - moveOffsetY = cameraROIHeight * 0.5 - ((imgPosY * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; - - double angle = 0; - - realPosX = moveOffsetX * Math.Cos(angle) + moveOffsetY * Math.Sin(angle); - realPosY = -moveOffsetX * Math.Sin(angle) + moveOffsetY * Math.Cos(angle); - } - - private void FindObjectsCenter(out double x, out double y) - { - x = 0; y = 0; - List sourcelist = _ScannerCanvasUserCtrl.Model.Layers[_PageNo - 1].Objects; - - _UnpackDrawObject?.Clear(); - _UnpackDrawObject = new List(); - UnpackRecipes(sourcelist); - - List centers = new List(); - for (int i = 0; i < _UnpackDrawObject.Count; i++) { - if (_UnpackDrawObject[i] is Arc) { - Arc tempArc = _UnpackDrawObject[i] as Arc; - centers.Add(tempArc.Center); - } - else if (_UnpackDrawObject[i] is Dot) { - Dot tempDot = _UnpackDrawObject[i] as Dot; - centers.Add(tempDot.P1); - } - else if (_UnpackDrawObject[i] is Spline spline) { - centers.Add(spline.Center); - } - + if (!_Scanner.Config.UseMarkingOnTheFly) + { + Log.W("[EncoderReset] MOTF 비활성화 - 스킵"); + return SequenceAction.Ok(); } - x = centers.Count > 0 ? centers.Average(center => center.X) : 0; - y = centers.Count > 0 ? centers.Average(center => center.Y) : 0; + + Log.I("[EncoderReset] 시작"); + // SeqUploadWeldingList.MarkingOnTheFlyOn 패턴 + _Scanner.SetFlyX(_Scanner.Config.MarkingOnTheFlyEncoderResolutionX); + Log.I($"[EncoderReset] SetFlyX: {_Scanner.Config.MarkingOnTheFlyEncoderResolutionX}"); + + _Scanner.WaitForEncoderX(_Scanner.Config.MarkingStartEncoderPositionX); + Log.I($"[EncoderReset] WaitForEncoderX: {_Scanner.Config.MarkingStartEncoderPositionX}"); + + _Scanner.StoreEncoder(0); + _Scanner.SaveAndRestartTimer(); + + Log.I("[EncoderReset] 완료 - Stage(0) = Scanner(0) 동기화"); + return SequenceAction.Ok(); } + //SeqTeachingPosMoveStageA패턴 참고 - 기존 GUN 프로젝트 시퀸스 - private static void UnpackRecipes(List recipes) + private List FindObjects() { - // Recipe를 재귀적으로 탐색해서 List로 재구성하는 함수 - if (recipes == null) - return; - - for (int i = 0; i < recipes.Count; i++) { - if (recipes[i] is CoreUnit.Control.UserControl.Canvas.Group) { - CoreUnit.Control.UserControl.Canvas.Group subGroup = recipes[i] as CoreUnit.Control.UserControl.Canvas.Group; - List subrecipes = subGroup.SubObjects as List; - UnpackRecipes(subrecipes); - } - else { - _UnpackDrawObject.Add(recipes[i]); - } + if (_InitParam.IsUseExternalObjects) + { + return _InitParam.ExternalObjects; + } + else if (_InitParam.IsObjectSelectAll) + { + return _ScannerCanvasUserCtrl.Model.ActiveLayer.Objects; + } + else + { + return _ScannerCanvasUserCtrl.Canvas.Model.SelectedObjects; } } - private void ChangeRecipes(short pageNo) - { - _PageNo = pageNo; - } - - private bool RestoreDeviceStatus() - { - - return true; - } - - private void InitializePlcBits() - { - _PLC.WriteBit(eBitOutput.PC_WELD_READY_ACK, false); - _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false); - _PLC.WriteBit(eBitOutput.PC_WELD_COMPLETE, false); - _PLC.WriteBit(eBitOutput.PC_PAGE_CHANGE_COMPLETE, false); - _PLC.WriteBit(eBitOutput.PC_WELD_NG_JUDGE, false); - - var UploadDatas = Status.GetProcessingWeldingData().UploadProcessDatas; - foreach (var data in UploadDatas) - data.Clear(); - _PLC.UploadReportDatas(UploadDatas); - } #endregion - private void OnForceError(SequenceContext arg1, string arg2) + private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param) { - OnSeqActionStop(); + Status.SetWorkingPosition(eWorkingPosition.UPLOADING_WELD_LIST); + + // TeachingRun에는 용접 시퀀스만 정의해서 Auto Run에서도 사용하므로 Offset 넣어줘야 함 + SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() + { + NeedSetLaserTiming = _InitParam.NeedSetLaserTiming, + IncludeListStartEnd = true, + CellMeasureCenterOffsetX = _SystemParameter.CellPosMeasureCenterOffsetX + _InitParam.CellCenterOffsetX, + CellMeasureCenterOffsetY = _SystemParameter.CellPosMeasureCenterOffsetY + _InitParam.CellCenterOffsetY, + SelectedDrawObjectList = _SelectedObjectList, + WeldingScannerListNo = _WeldingScannerListNo, + }; + + Log.D(string.Format($"[ComponentTeachingRun] Set UploadWelindList Seq Param")); + return SequenceAction.Ok(seqParams); + } + + private SequenceActionResult GetUploadWeldingList_SeqResult(SequenceContext context, string id, SequenceActionResult param) + { + Log.D(string.Format($"[ComponentTeachingRun] Get UploadWelindList Seq Param")); + + var resultOutParam = param.Param as SeqUploadWeldingList_OutParam; + if (resultOutParam.Success == false) + { + Log.E(string.Format($"[ComponentTeachingRun] Failed UploadWeldingList Sequence")); + return null; + } + + return SequenceAction.Ok(); + } + + + private SequenceActionResult DoComponentWelding(SequenceContext context, string id, SequenceActionResult param) + { + Log.I("ExecuteList Start"); + Log.I($"Welding List Space : {_Scanner.GetListSpace()}"); + DateTime weldingTime = DateTime.Now; + _Scanner.ExecuteList(_WeldingScannerListNo); + + + // ── 26.04.06 NDY 추가: ACS Stage X 이동 ────────────── + // MOTF: Scanner List 실행과 동시에 Stage X 이동 시작 + // Stage X 엔코더가 트리거 → WaitForEncoderX 조건 도달 시 갈바노 마킹 + // TODO: 변수 맵 수신 후 _ACS.MOTFStart()로 교체 + // _ACS?.MOTFStart(); + // ──────────────────────────────────────────────────── + + + + + // ── 26.04.06 NDY 추가: ACS 완료 대기 ───────────────── + // TODO: 변수 맵 수신 후 활성화 + // while (!_ACS.CheckMOTFComp()) { Thread.Sleep(10); } + // ──────────────────────────────────────────────────── + + + if (_Scanner.Config.UseRecordSignal) + { + DateTime startTime = DateTime.Now; + _Scanner.StackRecord(); + _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); + } + + // excel 파일 작성 + SaveScannerRecordFileForamt(); + Log.D(string.Format($"[ComponentTeachingRun] SaveScannerRecordFileForamt Time : {_ScannerSaveLogTime.TotalMilliseconds}")); + + var PartialTactTime = DateTime.Now.Subtract(_partialWeldingStartTime); + Log.D(string.Format($"[TactTime] Complete Partial Component Weld : {PartialTactTime.TotalMilliseconds}")); + + _ScannerCanvasUserCtrl.TimeLabelUpdate(_MeasurementSpanTime.TotalMilliseconds, PartialTactTime.TotalMilliseconds); + + return SequenceAction.Ok(); + } + + private SequenceActionResult SetMotion(SequenceContext context, string id, SequenceActionResult param) + { + // 메뉴얼 화면에서 셋팅이 필요해보임 + _ACS.SetMOTFParams(0, 0, 0, 0, 0); + return SequenceAction.Ok(); + } + + private SequenceActionResult StartMotion(SequenceContext context, string id, SequenceActionResult param) + { + _ACS.MOTFStart(); + // 모션 동작시키고 바로 확인하면 그냥 빠져나올 것 같음 + var res = context.Wait(1000, 100); + if (res == E2.TIMEOUT) ; + else if (res == E2.CANCELLED) { Log.E("[MOTF] Motion CANCELLED"); return null; } + + res = context.RetryUntilSuccess(() => _ACS.CheckMOTFComp(), 1000 * 20, 100, true); + if (res == E2.TIMEOUT) { Log.E("[MOTF] Motion TIMEOUT"); return null; } + else if (res == E2.CANCELLED) { Log.E("[MOTF] Motion CANCELLED"); return null; } + + return SequenceAction.Ok(); + } + private SequenceActionResult EndWelding(SequenceContext context, string id, SequenceActionResult param) + { + _Scanner.WaitForListTaskCompleted(_SystemParameter.WeldLinesTaskTimeOut); + Log.I("ExecuteList Complete"); + + _MeasurementSpanTime = DateTime.Now.Subtract(_SequenceCompleteTime); + Log.D(string.Format($"[TactTime] Complete All Component Weld : {_MeasurementSpanTime.TotalMilliseconds}")); + + + //Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨 + _Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND); + _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); + _Scanner.JumpAbs(0, 0, eFunctionType.COMMAND); + + var mesurementTime = DateTime.Now; + + //용접 완료 후 CorrectionFile Vision으로 원복 + _Scanner.SelectCorrectionTable(1); + + _MeasurementSpanTime = DateTime.Now.Subtract(mesurementTime); + Log.D(string.Format($"[ComponentTeachingRun] Change SelectCorrectionTable Time : {_MeasurementSpanTime.TotalMilliseconds}")); + + return SequenceAction.Ok(); + } + + private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) + { + context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); + SeqTeachingRun_OutParam result = new SeqTeachingRun_OutParam() { Success = seqResult }; + + if (seqResult == false) + { + AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_TeachingRun_ResultFailed); + } + + Log.D("ComponentTeachingRun Sequence Complete"); + return SequenceAction.Ok(result); + } + + private void SaveScannerRecordFileForamt() + { + if (_Scanner.Config.UseRecordSignal) + { + DateTime startTime = DateTime.Now; + _Scanner.SaveStackRecord("Normal"); + _ScannerSaveLogTime += DateTime.Now.Subtract(startTime); + } + } + + private void OnForceError(SequenceContext context, string arg2) + { + // Scanner Log 저장 + SaveScannerRecordFileForamt(); + + //List 실행 종료 + _Scanner.StopExecution(); + + //Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨 + _Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND); + _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); + + //Scanner 원점 복귀 + // 복귀 시 Scanner Busy 상태일 수 있으므로 진행중인 작업이 끝날 때까지 대기 + Thread.Sleep(10); + _Scanner.JumpAbs(0, 0, eFunctionType.COMMAND); + Thread.Sleep(10); Log.I("SequenceAction Ok : OnForceError"); } - private void OnStopped(SequenceContext obj) + private void OnStopped(SequenceContext context) { - OnSeqActionStop(); + // Scanner Log 저장 + SaveScannerRecordFileForamt(); + + //List 실행 종료 + _Scanner.StopExecution(); + + //Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨 + _Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND); + _Scanner.WriteDA((uint)eAnalogPortOut.DA2, 0, eFunctionType.COMMAND); + + //Scanner 원점 복귀 + // 복귀 시 Scanner Busy 상태일 수 있으므로 진행중인 작업이 끝날 때까지 대기 + Thread.Sleep(10); + _Scanner.JumpAbs(0, 0, eFunctionType.COMMAND); + Thread.Sleep(10); + Log.I("SequenceAction Ok : OnStopped"); } - - private void OnSeqActionStop() - { - // 자동 운전 끝날 떄에는 꺼주기 - if (_Laser.GetLaserReady()) _Laser.LaserOff(); - - Status.SetStatus(eEqpStatus.Manual); - _PLC.WriteBit(eBitOutput.PC_AUTO_STATUS, false); - - InitializePlcBits(); - } - private void UpdateProductCount(SequenceContext context) - { - // SystemParameter를 저장하기 전에는 반드시 업데이트를 해주어야 한다. - // SystemParameter 값과 동기화 - _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); - - _TodayProduct = _SystemParameter.TodayProductCount; - _TotalProduct = _SystemParameter.TotalProductCount; - if (_TodayProduct < uint.MaxValue) { - _TodayProduct++; - } - if (_TotalProduct < uint.MaxValue) { - _TotalProduct++; - } - _SystemParameter.TodayProductCount = _TodayProduct; - _SystemParameter.TotalProductCount = _TotalProduct; - _WeldEndTime = DateTime.Now; - _SystemParameter.LastProductTime = _WeldEndTime; - - //Systemparameter Save - context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunPrismaticScanner_New"); - } - - private void UpdateProductInfoForView() - { - Status.GetProcessingWeldingData().TotalProduct = _TotalProduct; - Status.GetProcessingWeldingData().TodayProduct = _TodayProduct; - - Status.GetProcessingWeldingData().WeldingStartTime = _WeldStartTime; - Status.GetProcessingWeldingData().WeldingEndTime = _WeldEndTime; - Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = _WeldSpanTime.TotalMilliseconds.ToString(); - - Status.GetProcessingWeldingData().LotId = _LotId; - Status.GetProcessingWeldingData().CellId = _CellId; - } - - private void UpdateAutoLightValue(int value) - { - lightValues[0] = value; - lightValues[1] = value; - lightValues[2] = value; - lightValues[3] = value; - } } + // TODO: UseStream 으로 TeachingRun 을 할 필요가 있을까?? 확인 필요 public class SeqAutoRunPrismaticScanner_InitParam : InitParam { - public int VisionRecipeNo { get; set; } = 0; + public bool IsObjectSelectAll { get; set; } // All == true, Selected Object == false + + public bool UseStream { get; set; } + + public bool UseBlow { get; set; } + public int IntervalTimeBlowOn { get; set; } + public int IntervalTimeBlowOff { get; set; } + + public bool NeedSetLaserTiming { get; set; } // For SubSequence, SeqUploadWeldingList + } public class SeqAutoRunPrismaticScanner_OutParam : OutParam { } - - public class SeqVisionData_Param - { - public MIL_ID originalImageID; - public MIL_ID overlayImageID; - public bool IsSuccess; - public string VisionData_Foler; - public string CellId; - } } diff --git a/Machines/ILSOS_PrismaticScanner/Views/Main/UCMainAutoRunViewModel.cs b/Machines/ILSOS_PrismaticScanner/Views/Main/UCMainAutoRunViewModel.cs index 4e50f8a..29ff644 100644 --- a/Machines/ILSOS_PrismaticScanner/Views/Main/UCMainAutoRunViewModel.cs +++ b/Machines/ILSOS_PrismaticScanner/Views/Main/UCMainAutoRunViewModel.cs @@ -220,7 +220,7 @@ namespace ILSOS_PrismaticScanner.Views OnUpdateCurrentActivatedRecipe(null); var param = new SeqAutoRunPrismaticScanner_InitParam() { - VisionRecipeNo = 0 + //VisionRecipeNo = 0 // 해당 InitParam에는 없는 선언 }; Status.SetStatus(eEqpStatus.Auto); diff --git a/WeldingComponents/WeldingCommon/CommonEquipmentSetup.cs b/WeldingComponents/WeldingCommon/CommonEquipmentSetup.cs index 2783f57..41f8072 100644 --- a/WeldingComponents/WeldingCommon/CommonEquipmentSetup.cs +++ b/WeldingComponents/WeldingCommon/CommonEquipmentSetup.cs @@ -222,13 +222,13 @@ namespace WeldingCommon registry.Register(CommonDeviceIds.Scanner, () => new Scanner(CommonDeviceIds.Scanner, isSimul), new ScannerConfig()); - registry.Register(CommonDeviceIds.SmcChiller, () => new SmcChiller(CommonDeviceIds.SmcChiller, 0, isSimul), new SmcChiller.Config(), - device => new UCSMCChillerDevice() { DataContext = new UCSMCChillerDeviceViewModel(AuroraEnv, CommonDeviceIds.SmcChiller) }); + //registry.Register(CommonDeviceIds.SmcChiller, () => new SmcChiller(CommonDeviceIds.SmcChiller, 0, isSimul), new SmcChiller.Config(), + // device => new UCSMCChillerDevice() { DataContext = new UCSMCChillerDeviceViewModel(AuroraEnv, CommonDeviceIds.SmcChiller) }); VisionFactory.RegisterDevices(registry); - registry.Register(CommonDeviceIds.Light, () => new LightDevice(CommonDeviceIds.Light, eLight.ERI, isSimul), new LightConfig(), - device => new UCLight() { DataContext = new UCLightViewModel(AuroraEnv, CommonDeviceIds.Light, _SequenceSetting.LightValue) }); + //registry.Register(CommonDeviceIds.Light, () => new LightDevice(CommonDeviceIds.Light, eLight.ERI, isSimul), new LightConfig(), + // device => new UCLight() { DataContext = new UCLightViewModel(AuroraEnv, CommonDeviceIds.Light, _SequenceSetting.LightValue) }); // TODO: SystemParameterManager.Initialize 할 위치 찾자. 여기는 조금.... SystemParameterManager.Initialize(AuroraEnv); diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs index 71c87ee..d400780 100644 --- a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs +++ b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.Parameter.cs @@ -3,8 +3,12 @@ // 26.04.06 NDY using AuroraACS; + + + namespace WeldingCommon.Devices.ACS { + // ── 레이저 출력 타입 ────────────────────────────────────── // Gun의 MainRecipe.eOutType과 동일 // partial class 밖에 정의 → IScannerACS 인터페이스에서도 참조 가능 @@ -14,6 +18,114 @@ namespace WeldingCommon.Devices.ACS Interval, // hz } + #region 26.04.14 + //public partial class ScannerACS + //{ + // const string AlarmReset = "iAlarmreset"; + // const string HeavyAlarm = "iAlarm"; + // const string LightAlarm = "iLightAlarm"; + // const string AlarmCodes = "iPCAlarmNo"; // 10개 + // const string BStageRemarkUse = "iPCset_BLINE_WeldingRemarkUse"; + + // const string IsLaserOn = "LCI_DEVICE.LaserEnabled"; + + + // /// + // /// ////////////////////////////////////////////////////// + // /// + // /// + // 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"; + + + // 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"; + + // 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"; + + // const string rWeldingEdgePointRad1 = "rPCset_ALINE_EdgePointRad1"; + // const string rWeldingEdgePointRad2 = "rPCset_ALINE_EdgePointRad2"; + // const string rWeldingEdgePointRad3 = "rPCset_ALINE_EdgePointRad3"; + // const string rWeldingEdgePointRad4 = "rPCset_ALINE_EdgePointRad4"; + + // 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"; + + // 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"; + + // 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"; + + // 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"; + + // 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"; + + // const string iALaserShotMode = "iPCset_ALASER_SHOT_MODE"; + // const string iAStageLCType = "iPCset_ALINE_LCTYPE"; + + // const string iAllAxisHomeComplete = "iPCget_ALLAXIS_HOMECOMP"; + + // const string iXAxisNumber = "iPCget_LCI_ASMASK_X"; + // const string iYAxisNumber = "iPCget_LCI_ASMASK_Y"; + // const string iLaserUse = "iPCset_LASER_USE"; + + + // private enum eBuffer + // { + // All_Axis_Home, + // AxisX1_Home, + // AxisX2_Home, + // AxisY1_Home, + // AxisY2_Home, + // AxisZ_Home, + + // Welding_Line = 11, + // Welding_AllRound, + // Welding_OneShot + // } + + //} + #endregion + #region 26.04.14 public partial class ScannerACS { // ── 알람 ────────────────────────────────────────── @@ -131,4 +243,6 @@ namespace WeldingCommon.Devices.ACS MOTF_Start = 17, // 26.04.09 NDY xlsx Buffer Info 기준 확정 } } + + #endregion } \ No newline at end of file diff --git a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs index 0cb101b..90a18d0 100644 --- a/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs +++ b/WeldingComponents/WeldingCommon/Devices/ACS/ScannerACS.cs @@ -34,7 +34,7 @@ namespace WeldingCommon.Devices.ACS // 홈 bool AllAxisHomeStart(); bool AllAxisHomeStop(); - bool CheckAllAxisHome(); + bool CheckAllAxisHome(); // MOTF (Scanner 전용 - Gun에 없음) bool SetMOTFParams(double posX, double negX, double velocity, double acc, int interval); @@ -104,10 +104,10 @@ namespace WeldingCommon.Devices.ACS private ACSDeviceSetting _setting; - // Scanner는 Stage X (X2) 1축만 사용 + // Scanner는 Stage X (X2) 1축만 사용 | Z 축까지 사용 스캐너 높이 // Gun은 X1, X2, Y1, Y2, Z 5축 사용 private ACSMotor MotorStageX; // AxisX2 = Scanner Stage X - + private ACSMotor MotorStageZ; // 26.04.14 = AxisZ public MotionVariable _motorVariable; public bool HasHeavyAlarm { get; private set; } @@ -137,6 +137,9 @@ namespace WeldingCommon.Devices.ACS try { MotorStageX = env.DeviceManager[CommonDeviceIds.AxisX2] as ACSMotor; } catch { MotorStageX = null; } + try { MotorStageZ = env.DeviceManager[CommonDeviceIds.AxisZ] as ACSMotor; } + catch { MotorStageZ = null; } + SetMonitoringService(UpdateACSParam, 50); StartMonitoringService(); @@ -152,9 +155,16 @@ namespace WeldingCommon.Devices.ACS _motorVariable.X2InPosition = MotorStageX.IsInpos(); _motorVariable.X2AxisVelocity = MotorStageX.GetFeedbackVelocity(); _motorVariable.X2AxisAcceleration = MotorStageX.GetAcceleration(); - _motorVariable.IsHome = MotorStageX.GetServoStatus() == 1; + _motorVariable.IsHome |= MotorStageX.GetServoStatus() == 1; + } + if (MotorStageZ != null) + { + _motorVariable.ZAxisPosition = MotorStageZ.GetActualPos(); + _motorVariable.ZInPosition = MotorStageZ.IsInpos(); + _motorVariable.ZAxisVelocity = MotorStageZ.GetFeedbackVelocity(); + _motorVariable.ZAxisAcceleration = MotorStageZ.GetAcceleration(); + _motorVariable.IsHome |= MotorStageZ.GetServoStatus() == 1; } - // 알람 상태 갱신 HasHeavyAlarm = ReadVariableInt(HeavyAlarm) == 1; HasLightAlarm = ReadVariableInt(LightAlarm) == 1; diff --git a/WeldingComponents/WeldingCommon/EquipDefCommon.cs b/WeldingComponents/WeldingCommon/EquipDefCommon.cs index 1082caa..d432918 100644 --- a/WeldingComponents/WeldingCommon/EquipDefCommon.cs +++ b/WeldingComponents/WeldingCommon/EquipDefCommon.cs @@ -145,10 +145,10 @@ namespace WeldingCommon public const string ACS = "ACS"; // 26.04.06 추가 - public const string AxisX1 = "AxisX1"; + //public const string AxisX1 = "AxisX1"; public const string AxisX2 = "AxisX2"; // 26.04.06 추가 - public const string AxisY1 = "AxisY1"; - public const string AxisY2 = "AxisY2"; + //public const string AxisY1 = "AxisY1"; + //public const string AxisY2 = "AxisY2"; // Ajin Motor public const string AxisZ = "AxisZ"; diff --git a/WeldingComponents/WeldingCommon/Sequences/Calibration/SeqScannerCalibration.cs b/WeldingComponents/WeldingCommon/Sequences/Calibration/SeqScannerCalibration.cs index b794cf3..fa268fb 100644 --- a/WeldingComponents/WeldingCommon/Sequences/Calibration/SeqScannerCalibration.cs +++ b/WeldingComponents/WeldingCommon/Sequences/Calibration/SeqScannerCalibration.cs @@ -17,6 +17,7 @@ using WeldingCommon.Settings; namespace WeldingCommon.Sequences { + // 캘리브레이션 작업 시 타는 시퀸스 public class SeqScannerCalibration { static readonly Logger Log = new Logger("SeqScannerCalibration"); diff --git a/WeldingComponents/WeldingCommon/Sequences/Gun/SeqMotorInit.cs b/WeldingComponents/WeldingCommon/Sequences/Gun/SeqMotorInit.cs index 607fe92..10eed4b 100644 --- a/WeldingComponents/WeldingCommon/Sequences/Gun/SeqMotorInit.cs +++ b/WeldingComponents/WeldingCommon/Sequences/Gun/SeqMotorInit.cs @@ -64,7 +64,7 @@ namespace WeldingCommon.Sequences sb.AddAction(SEQ_ENTER, Sequence_Enter); sb.AddAction(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); sb.AddAction(SEQ_ACS_ALARM_RESET, ACSAlarmReset); - sb.AddAction(SEQ_INIT_ACS_AXIS, ACSAxisInit); + //sb.AddAction(SEQ_INIT_ACS_AXIS, ACSAxisInit); sb.AddAction(SEQ_INIT_COMPLETE, InitComplete); sb.OnStopped(OnStopped); @@ -116,26 +116,26 @@ namespace WeldingCommon.Sequences return SequenceAction.Ok(); } - private static SequenceActionResult ACSAxisInit(SequenceContext context, string id, SequenceActionResult param) - { - Log.V($"ACS Init Start"); - _motion.AllAxisHomeStart(); - Thread.Sleep(1000); + //private static SequenceActionResult ACSAxisInit(SequenceContext context, string id, SequenceActionResult param) + //{ + // Log.V($"ACS Init Start"); + // _motion.AllAxisHomeStart(); + // Thread.Sleep(1000); - var res = context.RetryUntilSuccess(() => _motion.CheckAllAxisHome(), SEQ_TIMEOUT, MOTION_INTERVAL); - if (res == E2.TIMEOUT) { - context.PutValue("AlarmCode", AlarmCode_PrismaticGun.ACS_AXIS_INITIALIZE_FAIL); // 26.04.13 잠시 주석 - context.PutValue("AlarmMessage", "ACS Axis Home Timeout"); - return null; - } else if (res == E2.CANCELLED) { - context.PutValue("AlarmCode", 0); - context.PutValue("AlarmMessage", "ACS Axis Home Cancel"); - return null; - } + // var res = context.RetryUntilSuccess(() => _motion.CheckAllAxisHome(), SEQ_TIMEOUT, MOTION_INTERVAL); + // if (res == E2.TIMEOUT) { + // context.PutValue("AlarmCode", AlarmCode_PrismaticGun.ACS_AXIS_INITIALIZE_FAIL); // 26.04.13 잠시 주석 + // context.PutValue("AlarmMessage", "ACS Axis Home Timeout"); + // return null; + // } else if (res == E2.CANCELLED) { + // context.PutValue("AlarmCode", 0); + // context.PutValue("AlarmMessage", "ACS Axis Home Cancel"); + // return null; + // } - Log.V($"ACS Init End"); - return SequenceAction.Ok(eTeachingPosition.SafetyPosition); - } + // Log.V($"ACS Init End"); + // return SequenceAction.Ok(eTeachingPosition.SafetyPosition); + //} private static SequenceActionResult InitComplete(SequenceContext context, string id, SequenceActionResult param) { diff --git a/WeldingComponents/WeldingCommon/Sequences/Gun/SubSequence/StageA/SeqTeachingPosMoveStageA.cs b/WeldingComponents/WeldingCommon/Sequences/Gun/SubSequence/StageA/SeqTeachingPosMoveStageA.cs index c19bb64..68025ce 100644 --- a/WeldingComponents/WeldingCommon/Sequences/Gun/SubSequence/StageA/SeqTeachingPosMoveStageA.cs +++ b/WeldingComponents/WeldingCommon/Sequences/Gun/SubSequence/StageA/SeqTeachingPosMoveStageA.cs @@ -80,10 +80,10 @@ namespace WeldingCommon.Sequences.SubSequence.StageA _acs = context.Devices[CommonDeviceIds.ACS] as ScannerACS; //260413 if (_AxisX is null) _AxisX = _FirstMoveAxis = context.Devices[CommonDeviceIds.AxisX2] as ACSMotor; - if (_AxisY1 is null) - _AxisY1 = _SecondMoveAxis = context.Devices[CommonDeviceIds.AxisY1] as ACSMotor; - if (_AxisY2 is null) - _AxisY2 = _SecondMoveAxis = context.Devices[CommonDeviceIds.AxisY2] as ACSMotor; + //if (_AxisY1 is null) + // _AxisY1 = _SecondMoveAxis = context.Devices[CommonDeviceIds.AxisY1] as ACSMotor; + //if (_AxisY2 is null) + // _AxisY2 = _SecondMoveAxis = context.Devices[CommonDeviceIds.AxisY2] as ACSMotor; if (_AxisZ is null) _AxisZ = context.Devices[CommonDeviceIds.AxisZ] as ACSMotor; diff --git a/WeldingComponents/WeldingCommon/Sequences/Main/SeqScoutNormal.cs b/WeldingComponents/WeldingCommon/Sequences/Main/SeqScoutNormal.cs index db26029..404706d 100644 --- a/WeldingComponents/WeldingCommon/Sequences/Main/SeqScoutNormal.cs +++ b/WeldingComponents/WeldingCommon/Sequences/Main/SeqScoutNormal.cs @@ -106,7 +106,7 @@ namespace WeldingCommon.Sequences _InitParam = param.Param as SeqScoutNormal_InitParam; _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); - + InitDev(context); if (!CheckDeviceReady(context)) { //Check Device AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_ScoutNormal_DeviceNotReady); diff --git a/WeldingComponents/WeldingCommon/Sequences/Main/SeqUploadWeldingList.cs b/WeldingComponents/WeldingCommon/Sequences/Main/SeqUploadWeldingList.cs index bf14ec1..fb1f663 100644 --- a/WeldingComponents/WeldingCommon/Sequences/Main/SeqUploadWeldingList.cs +++ b/WeldingComponents/WeldingCommon/Sequences/Main/SeqUploadWeldingList.cs @@ -159,7 +159,7 @@ namespace WeldingCommon.Sequences { //Device Init _Scanner = context.GetLaserScanner(); - _Laser = context.GetLaser(); + //_Laser = context.GetLaser(); } private bool CheckDeviceReady(SequenceContext context) @@ -479,31 +479,31 @@ namespace WeldingCommon.Sequences else _CenterRingRatio = (int)Math.Round((double)(100 * param.LaserPower1) / (double)(param.LaserPower1 + param.LaserPower2), 0); // Discrete 한 값이라서 Ring은 오차 발생 - if (_Laser.Config.TruFiberType == eTruFiberType.TruFiberS) { // TruFiberS Type은 비율 제어 - if (_CenterRingRatio == 0) { // Center가 0인경우 - //percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToPercent((double)param.LaserPower2, (uint)eAnalogPortOut.DA1); - percentLaser1 = (float)(_LaserPowerCalParam.CalibrateWattToMeasuredVoltage((double)param.LaserPower2, (uint)LaserPowerCalParam.beamMode.Center)); - percentLaser1 = percentLaser1 * 10; // 스캐너에 입렵하기 위한 연산 ( 1V : 10 ~~ 10V : 100 ) - } else { - //percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToPercent((double)param.LaserPower1 / (double)_CenterRingRatio * 100.0, (uint)eAnalogPortOut.DA1); - percentLaser1 = (float)(_LaserPowerCalParam.CalibrateWattToMeasuredVoltage((double)param.LaserPower1 / (double)_CenterRingRatio * 100.0, (uint)LaserPowerCalParam.beamMode.Center)); - percentLaser1 = percentLaser1 * 10; // 스캐너에 입렵하기 위한 연산 ( 1V : 10 ~~ 10V : 100 ) - } - percentLaser2 = 0; - Log.D(string.Format("TruFiber S Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2,percentLaser1,percentLaser2,_CenterRingRatio)); - } else if (_Laser.Config.TruFiberType == eTruFiberType.TruFiberP) { // Power제어 - percentLaser1 = 100; - percentLaser2 = 0; - Log.D(string.Format("TruFiber P Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2, percentLaser1, percentLaser2, _CenterRingRatio)); - } else if (_Laser.Config.TruFiberType == eTruFiberType.CalPercentToMeasuredVoltage) { - percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToMeasuredVoltage(param.LaserPower1, (uint)LaserPowerCalParam.beamMode.Center) * 10; - percentLaser2 = (float)_LaserPowerCalParam.CalibrateWattToMeasuredVoltage(param.LaserPower2, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - Log.D(string.Format("CalPercentToMeasuredVoltage Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2, percentLaser1, percentLaser2, _CenterRingRatio)); - } else { + //if (_Laser.Config.TruFiberType == eTruFiberType.TruFiberS) { // TruFiberS Type은 비율 제어 + // if (_CenterRingRatio == 0) { // Center가 0인경우 + // //percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToPercent((double)param.LaserPower2, (uint)eAnalogPortOut.DA1); + // percentLaser1 = (float)(_LaserPowerCalParam.CalibrateWattToMeasuredVoltage((double)param.LaserPower2, (uint)LaserPowerCalParam.beamMode.Center)); + // percentLaser1 = percentLaser1 * 10; // 스캐너에 입렵하기 위한 연산 ( 1V : 10 ~~ 10V : 100 ) + // } else { + // //percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToPercent((double)param.LaserPower1 / (double)_CenterRingRatio * 100.0, (uint)eAnalogPortOut.DA1); + // percentLaser1 = (float)(_LaserPowerCalParam.CalibrateWattToMeasuredVoltage((double)param.LaserPower1 / (double)_CenterRingRatio * 100.0, (uint)LaserPowerCalParam.beamMode.Center)); + // percentLaser1 = percentLaser1 * 10; // 스캐너에 입렵하기 위한 연산 ( 1V : 10 ~~ 10V : 100 ) + // } + // percentLaser2 = 0; + // Log.D(string.Format("TruFiber S Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2,percentLaser1,percentLaser2,_CenterRingRatio)); + //} else if (_Laser.Config.TruFiberType == eTruFiberType.TruFiberP) { // Power제어 + // percentLaser1 = 100; + // percentLaser2 = 0; + // Log.D(string.Format("TruFiber P Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2, percentLaser1, percentLaser2, _CenterRingRatio)); + //} else if (_Laser.Config.TruFiberType == eTruFiberType.CalPercentToMeasuredVoltage) { + // percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToMeasuredVoltage(param.LaserPower1, (uint)LaserPowerCalParam.beamMode.Center) * 10; + // percentLaser2 = (float)_LaserPowerCalParam.CalibrateWattToMeasuredVoltage(param.LaserPower2, (uint)LaserPowerCalParam.beamMode.Ring) * 10; + // Log.D(string.Format("CalPercentToMeasuredVoltage Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2, percentLaser1, percentLaser2, _CenterRingRatio)); + //} else { percentLaser1 = (float)_LaserPowerCalParam.CalibrateWattToPercent(param.LaserPower1, (uint)eAnalogPortOut.DA1); percentLaser2 = (float)_LaserPowerCalParam.CalibrateWattToPercent(param.LaserPower2, (uint)eAnalogPortOut.DA2); Log.D(string.Format("Normal Models:: Original Power1 : {0}; Original Power2 : {1}; Calibrated Percent1 :{2:0.000}; Calibrated Percent2 :{3:0.000}; CenterRingRatio :{4:0.000}", param.LaserPower1, param.LaserPower2, percentLaser1, percentLaser2, _CenterRingRatio)); - } + //} _Scanner.WriteDA((uint)eAnalogPortOut.DA1, percentLaser1, eFunctionType.LIST); _Scanner.WriteDA((uint)eAnalogPortOut.DA2, percentLaser2, eFunctionType.LIST); diff --git a/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibration.xaml b/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibration.xaml index 27a6b73..8dac8ea 100644 --- a/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibration.xaml +++ b/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibration.xaml @@ -89,8 +89,8 @@ - - + + diff --git a/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibrationViewModel.cs b/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibrationViewModel.cs index 48597ab..2cbd93e 100644 --- a/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibrationViewModel.cs +++ b/WeldingComponents/WeldingCommon/Views/Calibration/UCScannerCalibrationViewModel.cs @@ -29,7 +29,8 @@ using WeldingCommon.Settings; using WeldingCommon.Utils; using WeldingCommon.Process; using static CoreUnit.Control.UserControl.Canvas.WeldingParameterIDEditor; -using System.Diagnostics; //Process.Start +using System.Diagnostics; +using Aurora.Util.HislogPlus; //Process.Start namespace WeldingCommon.Views { @@ -135,7 +136,7 @@ namespace WeldingCommon.Views _Scanner = _Aurora.DeviceManager[CommonDeviceIds.Scanner] as Scanner; _Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser; - _LaserConfig = _Aurora.DeviceManager.GetDeviceConfig(_Laser.DeviceId) as LaserConfig; + //_LaserConfig = _Aurora.DeviceManager.GetDeviceConfig(_Laser.DeviceId) as LaserConfig; _ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(_Scanner.DeviceId) as ScannerConfig; //_SeqMarkGrid = _Aurora.SequenceEntry[CommonSequenceIds.SeqMarkGrid] as ISequence; @@ -210,11 +211,18 @@ namespace WeldingCommon.Views CurrentY = yPos; } - if (_Laser.GetLaserReady()) { - LaserStatus = true; - } else { - LaserStatus = false; - } + //if(_Laser != null) + //{ + // if (_Laser.GetLaserReady()) + // { + // LaserStatus = true; + // } + // else + // { + // LaserStatus = false; + // } + //} + } private void OnUpdateCorrectionTable(EventMessage obj) @@ -480,7 +488,7 @@ namespace WeldingCommon.Views _SeqScannerCalibration.Start(param, OnCompleteScannerCalibration); } - + //_SeqScannerCalibration 이 시퀸스가 시작된다. IsSequenceRunning_ScannerCalibration param의 값이 result가 성공해야 성공 private void OnCompleteScannerCalibration(SequenceActionResult res) { if (res != null) { diff --git a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCManualScannerOperationViewModel.cs b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCManualScannerOperationViewModel.cs index 27c1c23..77b4141 100644 --- a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCManualScannerOperationViewModel.cs +++ b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCManualScannerOperationViewModel.cs @@ -19,7 +19,7 @@ namespace WeldingCommon.Views { private readonly Logger Log = new Logger("UCManualScannerOperationViewModel"); - public ICommand CMD_ShowSelectFieldWindow { get; } + public ICommand CMD_ShowSelectFieldWindow { get; } // 메뉴얼의 SelectField 팝업 버튼 private readonly IAuroraEnvironment _Aurora; diff --git a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerLaserControlViewModel.cs b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerLaserControlViewModel.cs index f9f9b05..e6a9d09 100644 --- a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerLaserControlViewModel.cs +++ b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerLaserControlViewModel.cs @@ -40,7 +40,7 @@ namespace WeldingCommon.Views private readonly IAuroraEnvironment _Aurora; private readonly LaserConfig _LaserConfig; - private readonly Scanner _Scanner; + private readonly Scanner _Scanner; // 스캐너 private readonly Laser _Laser; private readonly ScannerConfig _ScannerConfig; @@ -111,9 +111,9 @@ namespace WeldingCommon.Views _Aurora = aurora; _Scanner = _Aurora.DeviceManager[scannerId] as Scanner; - _Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser; + //_Laser = _Aurora.DeviceManager[CommonDeviceIds.Laser] as Laser; - _LaserConfig = _Aurora.DeviceManager.GetDeviceConfig(_Laser.DeviceId) as AuroraLaser.LaserConfig; + //_LaserConfig = _Aurora.DeviceManager.GetDeviceConfig(_Laser.DeviceId) as AuroraLaser.LaserConfig; _ScannerConfig = _Aurora.DeviceManager.GetDeviceConfig(scannerId) as ScannerConfig; _SeqTeachingRun = _Aurora.SequenceEntry[CommonSequenceIds.SeqComponentTeachingRun]; @@ -122,9 +122,9 @@ namespace WeldingCommon.Views InitVariable(); CMD_VisibleChanged = new DelegateCommand(VisibleChanged); - CMD_LaserShotOnPercent = new DelegateCommand(PerformCmdLaserShotOnPercent); - CMD_LaserShotOnWatt = new DelegateCommand(PerformCmdLaserShotOnWatt); - CMD_LaserShotOff = new DelegateCommand(PerformCmdLaserShotOff); + CMD_LaserShotOnPercent = new DelegateCommand(PerformCmdLaserShotOnPercent); //레이저 온 퍼센트 적용 + CMD_LaserShotOnWatt = new DelegateCommand(PerformCmdLaserShotOnWatt); // 레이저 온 와트 적용 + CMD_LaserShotOff = new DelegateCommand(PerformCmdLaserShotOff); //레이저 끄기 CMD_ActivateOnTheFly = new DelegateCommand(PerformCmdActivateOnTheFly); CMD_DeactivateOnTheFly = new DelegateCommand(PerformCmdDeactivateOnTheFly); @@ -246,10 +246,10 @@ namespace WeldingCommon.Views MessageUtil.ShowWarningToast(string.Format("Laser, Scanner is busy.")); return; } - if (!_Laser.GetLaserReady()) { - MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status.")); - return; - } + //if (!_Laser.GetLaserReady()) { + // MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status.")); + // return; + //} if (_SeqTeachingRun.RunState == SequenceRunState.Running) { MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "Laser On"), Log); @@ -290,20 +290,9 @@ namespace WeldingCommon.Views float powerVolt1 = 0, powerVolt2 = 0; powerCalParam.Initialize(powerCalParam.PowerCalibrationCenterBeamCSVFile, powerCalParam.PowerCalibrationRingBeamCSVFile); - - if (_LaserConfig.TruFiberType == eTruFiberType.TruFiberS) { - powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent) * 10; - } else if(_LaserConfig.TruFiberType == eTruFiberType.TruFiberP){ - powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } else if (_Laser.Config.TruFiberType == eTruFiberType.CalPercentToMeasuredVoltage) { - powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } else { - powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } - Thread.Sleep(50); + powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; + powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; + Thread.Sleep(50); _Scanner.WriteDA((uint)eAnalogPortOut.DA1, powerVolt1, eFunctionType.COMMAND); _Scanner.WriteDA((uint)eAnalogPortOut.DA2, powerVolt2, eFunctionType.COMMAND); _Scanner.SetLaserPulseCtrl(LaserPeriod * 1000, LaserPulseWidth); @@ -320,10 +309,10 @@ namespace WeldingCommon.Views MessageUtil.ShowWarningToast(string.Format("Laser, Scanner is busy.")); return; } - if (!_Laser.GetLaserReady()) { - MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status.")); - return; - } + //if (!_Laser.GetLaserReady()) { + // MessageUtil.ShowWarningToast(string.Format("Laser, Check Laser Ready status.")); + // return; + //} if (_SeqTeachingRun.RunState == SequenceRunState.Running) { MessageUtil.ShowWarningToast(string.Format("이미 시퀀스가 Start 상태입니다.", "Laser On"), Log); @@ -365,20 +354,8 @@ namespace WeldingCommon.Views float powerVolt1 = 0, powerVolt2 = 0; powerCalParam.Initialize(powerCalParam.PowerCalibrationCenterBeamCSVFile, powerCalParam.PowerCalibrationRingBeamCSVFile); - - if (_LaserConfig.TruFiberType == eTruFiberType.TruFiberS) { - powerVolt1 = (float)powerCalParam.CalibrateWattToMeasuredVoltage(LaserPower1Watt) * 10; - } - else if (_LaserConfig.TruFiberType == eTruFiberType.TruFiberP) { - powerVolt1 = (float)powerCalParam.CalibrateWattToMeasuredVoltage(LaserPower1Watt, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibrateWattToMeasuredVoltage(LaserPower2Watt, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } else if (_Laser.Config.TruFiberType == eTruFiberType.CalPercentToMeasuredVoltage) { - powerVolt1 = (float)powerCalParam.CalibrateWattToMeasuredVoltage(LaserPower1Watt, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibrateWattToMeasuredVoltage(LaserPower2Watt, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } else { - powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; - powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; - } + powerVolt1 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower1Percent, (uint)LaserPowerCalParam.beamMode.Center) * 10; + powerVolt2 = (float)powerCalParam.CalibratePercentToMeasuredVoltage(LaserPower2Percent, (uint)LaserPowerCalParam.beamMode.Ring) * 10; Thread.Sleep(50); _Scanner.WriteDA((uint)eAnalogPortOut.DA1, powerVolt1, eFunctionType.COMMAND); _Scanner.WriteDA((uint)eAnalogPortOut.DA2, powerVolt2, eFunctionType.COMMAND); diff --git a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotion.xaml b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotion.xaml index 1ce0666..430cca8 100644 --- a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotion.xaml +++ b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotion.xaml @@ -11,7 +11,7 @@ xmlns:usercontrols="clr-namespace:AuroraUIComponent.UserControls;assembly=AuroraUIComponent" d:DataContext="{d:DesignInstance Type=local:UCScannerMotionViewModel}" mc:Ignorable="d" - d:DesignHeight="400" d:DesignWidth="600" x:Name="uc"> + d:DesignHeight="500" d:DesignWidth="600" x:Name="uc"> @@ -164,29 +164,54 @@ - - - - - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotionViewModel.cs b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotionViewModel.cs index 194c115..53891a4 100644 --- a/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotionViewModel.cs +++ b/WeldingComponents/WeldingCommon/Views/Manual/Scanner/UCScannerMotionViewModel.cs @@ -6,6 +6,7 @@ using Aurora.View; using AuroraACS; // 26.04.06 NDY 추가 using AuroraLaser; using AuroraLaserScanner; +using AuroraMotionBoard.Ajin; using HarfBuzzSharp; using Microsoft.Office.Interop.Excel; using System; @@ -83,12 +84,18 @@ namespace WeldingCommon.Views // 26.04.06 NDY Stage X 관련 필드 추가 ================== private ACSMotor _MotorX; + private ACSMotor _MotorZ; private double _StageXPos; public double StageXPos { get => _StageXPos; set => SetProperty(ref _StageXPos, value); } + private double _StageZPos; + public double StageZPos { get => _StageZPos; set => SetProperty(ref _StageZPos, value); } + private bool _IsStageXActivated; public bool IsStageXActivated { get => _IsStageXActivated; set => SetProperty(ref _IsStageXActivated, value); } + private bool _IsStageZActivated; + public bool IsStageZActivated { get => _IsStageZActivated; set => SetProperty(ref _IsStageZActivated, value); } // ======================================================== // PAM, RUW 처럼 2개 이상의 scanner 를 사용하는 경우가 있어, scannerId 를 받는 형태로 생성 @@ -103,6 +110,8 @@ namespace WeldingCommon.Views // 26.04.06 NDY Stage X 모터 연결 추가 =============== try { _MotorX = _Aurora.DeviceManager["AxisX2"] as ACSMotor; } catch { _MotorX = null; } + try { _MotorZ = _Aurora.DeviceManager["AxisZ"] as ACSMotor; } + catch { _MotorZ = null; } // ==================================================== InitVariable(); @@ -174,6 +183,16 @@ namespace WeldingCommon.Views { IsStageXActivated = false; } + + if (_MotorZ != null && _MotorZ.IsActivated) + { + StageZPos = _MotorZ.GetActualPos(); + IsStageZActivated = true; + } + else + { + IsStageZActivated = false; + } // ==================================================== } @@ -213,6 +232,8 @@ namespace WeldingCommon.Views // 26.04.06 NDY Stage X 버튼 추가 ================= case "Stage_X_Left": MoveStageX(eJogDirection.MINUS); break; case "Stage_X_Right": MoveStageX(eJogDirection.PLUS); break; + case "Stage_Z_Left": MoveStageZ(eJogDirection.MINUS); break; + case "Stage_Z_Right": MoveStageZ(eJogDirection.PLUS); break; // ================================================= } } @@ -227,8 +248,21 @@ namespace WeldingCommon.Views Log.I($"Stage X Move : {step}mm"); _MotorX.SetTargetPos(step, TargetPosType.REL); + _MotorX.SetVelocityImm(_MotorX.GetJogSpeed(AuroraACS.Speed.L) * _VelocityRate); _MotorX.Move(); } + private void MoveStageZ(eJogDirection direction) + { + if (_MotorZ == null || !_MotorZ.IsActivated) return; + + // 이미지 기준 방향 반전 적용 + double step = direction == eJogDirection.PLUS ? -StepValue : +StepValue; + Log.I($"Stage Z Move : {step}mm"); + + _MotorZ.SetTargetPos(step, TargetPosType.REL); + _MotorZ.SetVelocityImm(_MotorZ.GetJogSpeed(AuroraACS.Speed.L) * _VelocityRate); + _MotorZ.Move(); + } // ========================================================= private void MoveJogXYPos(eAxisType axisType, eJogDirection direction) diff --git a/WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml b/WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml index 09d173f..347fcba 100644 --- a/WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml +++ b/WeldingComponents/WeldingCommon/Views/Recipes/UCScannerObjectTeachingControlBox.xaml @@ -126,37 +126,40 @@ - + - - - - + + + + + + + + + + + - - - - - - + @@ -164,11 +167,11 @@ + FontWeight="Bold" Text="페이지 N개" + VerticalAlignment="Center"/> + Text="{Binding LargeMOTFPageCount, UpdateSourceTrigger=PropertyChanged}" + VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>