using Aurora; using Aurora.Api; using Aurora.Api.Control; using Aurora.Api.Devices; using Aurora.Api.Manager; using Aurora.Util.HislogPlus; using Aurora.View; using AuroraCellTracker; using AuroraIO; using AuroraLaser; using AuroraLaserScanner; using AuroraLBAD; using AuroraLBAD.Service; using AuroraOCT; using AuroraPLC; using CoreUnit.Control.UserControl.Canvas; using CoreUnit.Scanner.UserControl.ScannerCanvas; using DB; using DB.Recipe; using ExcelImageHelper; using Hermes; using ILSOS_KS.Device; using ILSOS_KS.Models; using ILSOS_KS.RMS; using ILSOS_KS.Views.Dialog; using ILSOS_KS.Views.PopUP; using Matrox.MatroxImagingLibrary; using MilUI; using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.PTG; using NPOI.Util; using OpenCvSharp; using OpenCvSharp.Dnn; using OpenCvSharp.Text; using OpenCvSharp.WpfExtensions; using Org.BouncyCastle.Asn1.Tsp; using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Configuration; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net.NetworkInformation; using System.Runtime.InteropServices.ComTypes; using System.Runtime.Remoting.Contexts; using System.Runtime.Remoting.Metadata.W3cXsd2001; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Xml.Linq; using VisionCommon; using WeldingCommon; using WeldingCommon.Alarm; using WeldingCommon.Data; using WeldingCommon.Devices; using WeldingCommon.Recipes; using WeldingCommon.Sequences; using WeldingCommon.Settings; using WeldingCommon.Utils; using WeldingCommon.Views; using WeldingCommon.Vision.WeldingObjectGenerator; //using System.Windows.Shapes; using WeldingCommon.Vision.WeldingObjectGenerator.GeometryLibrary; using WeldingCommon.Vision.WeldingObjectGenerator.PathEditorLibrary; using static Aurora.Api.SequenceBuilder; using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo; using static AuroraLBAD.Device.LBAD_PILOT; using static AuroraLBAD.Service.StreamLightLBAD; using static AuroraLBAD.Services.StreamLBADClient; using static ILSOS_KS.Device.IOController_KS; using static ILSOS_KS.Device.PLCControllerKS; using static WeldingCommon.Views.UCLBADDeviceViewModel; using Application = System.Windows.Application; using Line = CoreUnit.Control.UserControl.Canvas.Line; using Path = System.IO.Path; using Point = OpenCvSharp.Point; using SystemParameter = WeldingCommon.Settings.SystemParameter; namespace ILSOS_KS.Sequences { class SeqAutoRunKS { static readonly Logger Log = new Logger("SeqAutoRunKS_New"); const string SEQ_ENTER = "[SeqAutoRunKS] SEQ_ENTER"; // inputParam 으로 받자. const string SEQ_CHECK_INIT_CONDITION = "[SeqAutoRunKS] Check Init Condition"; // Check Init Condition // ADD jmj -> 메인페이지 레시피 넘버 확인하여 PLC에 전송후 메칭 확인 // Page 번호 가져오기. const string SEQ_CHECK_PAGENO = "[SeqAutoRunKS] CHECK PageNo"; const string SEQ_CHECK_LOAD_COMPLETE = "[SeqAutoRunKS] Check Load Complete"; // 양선전 사전검사 로직 추가(용접후 검사 결과를 보고 하구 나서 양산 시작) const string SEQ_KS_WAIT_VISION = "[SeqAutoRunKS] Ks Wait Vision"; const string SEQ_KS_COMPLETE_VISION = "[SeqAutoRunKS] Ks Complete Vision"; //const string SEQ_MEASURE_CELL_POSITION = "[SeqAutoRunKS] Measure CellPosition"; const string SEQ_SET_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunKS] Set Sequence Param (ScoutFlyingVision Seq)"; const string SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunKS] Process (ScoutFlyingVision Seq)"; const string SEQ_GET_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunKS] Get Sequence Result (ScoutFlyingVision Seq)"; const string SEQ_SET_SCOUT_NORMAL_VISION_SEQ = "[SeqRCCTeachingRun] Set Sequence Param (ScoutNormalVision Seq)"; const string SEQ_DO_ID_SCOUT_NORMAL_VISION_SEQ = "[SeqRCCTeachingRun] Process (ScoutNormalVision Seq)"; const string SEQ_GET_SCOUT_NORMAL_VISION_SEQ = "[SeqRCCTeachingRun] Get Sequence Result (ScoutNormalVision Seq)"; const string SEQ_SEND_EVENT_SENDER = "[SeqAutoRunKS] Event Sender"; const string SEQ_EVENT_Q_SAVE_FILE = "[SeqAutoRunKS] EventQ Save File"; const string SEQ_SAVE_SCOUT_IMAGE = "[SeqAutoRunKS] Save ScoutImage"; const string SEQ_FIND_EDGE = "[SeqAutoRunKS] Find Edge"; const string SEQ_DECISION_RCC_ALGORITHM_TYPE = "[SeqAutoRunKS] Decision RCC Algorithm Type"; const string SEQ_APPLY_OFFSET_OBJECT = "[SeqAutoRunKS] Apply Offset Object"; const string SEQ_GENERATE_WELDING_OBJECT = "[SeqAutoRunKS] Generate WeldingObject"; const string SEQ_READY_SCANNER_LIST = "[SeqAutoRunKS] Ready ScannerList"; const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunKS] Set Sequence Param (UploadWeldingList Seq)"; const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunKS] Process (UploadWeldingList Seq)"; const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunKS] Get Sequence Result (UploadWeldingList Seq)"; const string SEQ_WAIT_WELDING_START = "[SeqAutoRunKS] Wait Welding Start"; const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunKS] Set Sequence Param (ReceiveCellInfo Seq)"; const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunKS] Process (ReceiveCellInfo Seq)"; const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunKS] Get Sequence Result (ReceiveCellInfo Seq)"; const string SEQ_EXECUTE_WELDING = "[SeqAutoRunKS] Execute Welding"; const string SEQ_REQUEST_UNLOAD_CELL = "[SeqAutoRunKS] Request Unload Cell"; const string SEQ_WAIT_LBAD_JUDGE = "[SeqAutoRunKS] Wait LBAD Judge"; //const string SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunKS] Set Sequence Param (ReportCellResult Seq)"; //const string SEQ_DO_ID_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunKS] Process (ReportCellResult Seq)"; //const string SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunKS] Get Sequence Result (ReportCellResult Seq)"; const string SEQ_REPORT_CELLINFO_TO_PLC = "[SeqAutoRunKS] ReportCellInfoToPLC"; const string SEQ_CHECK_CYCLE_STOP = "[SeqAutoRunKS] Check Cycle Stop"; const string SEQ_SAVE_RESULT_DATA = "[SeqAutoRunKS] Save Result Data"; const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqAutoRunKS] Write Completion PLC Bit"; const string SEQ_COMPLETE = "[SeqAutoRunKS] SEQ_COMPLETE"; // 완료 const string SEQ_BEFORE_WELD_MOVE_OBJECT = "[SeqAutoRunKS] Before Weld Move Object"; const string SEQ_AFTER_WELD_CHECK_BEAD = "[SeqAutoRunKS] After Weld Check Bead"; const string SEQ_CHECK_RCC_MODE = "[SeqAutoRunKS] Check RCC Mode"; const string SEQ_CHECK_BEFORE_OR_AFTER = "[SeqRCCTeachingRun] Check before or after"; static class ContextKey { public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunKS"; public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunKS"; } const int PLC_TIMEOUT = 60; // sec, Timeout은 시퀀스 정지가 아니라 타임아웃 시간마다 로그만 남기도록 한다 private SeqAutoRunKS_New_InitParam _InitParam; private Scanner _Scanner; private LaserDevice _Laser; //private OCT _OCT; private PLCControllerKS _PLC; private IODevice _IO; private LBAD _LBAD; //private StreamLightLBAD _StreamLightLBAD; private SystemParameter _SystemParameter; private IRecipeManager _RecipeManager; private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언 private FovRecipe _FovRecipe; private CameraAgentBase _CameraAgent; private ICameraDisplay _CameraDisplay; private CamConfig _CamConfig; private eListNo _WeldingScannerListNo; private List _SelectedDrawObjectList; private MIL_ID _GrabImage = MIL.M_NULL; private ObjectGenerator _ObjGenerator; private Mat _ConvMatImage; private Mat _ConvMatImage_after; private Mat[] _WeldingImage = new Mat[4]; private uint _TodayProduct; private uint _TotalProduct; private uint _OCT_QA_ERROR_COUNT; private DateTime _AutoRunStartTime; private DateTime _WeldingStartTime; private TimeSpan _WeldingSpanTime; private DateTime _WeldEndTime; private TimeSpan _InterfaceSpanTime; private DateTime _InterfaceStartTime; private string _LotId = "N/A"; private string _CellId = "N/A"; private bool _IncludeListStartEnd = false; // ==> local private int _SeqRunCount; // For RCC private List _GeneratedDrawObjects; private List _RecipeDrawObjects; // ==> local private Stopwatch _StopwatchGenObj; private int _Radius_Pixel; // End For RCC private int _ModelNo; private int _PageNo = 0; private int _PageNoRcc = 0; private string _BcrID; private bool _IsRealTimeScout; private double _CellMeasureCenterOffsetX; private double _CellMeasureCenterOffsetY; public string EVENT_TRIGGER_SAVE_FILE = "EventTriggerSaveFile"; private UnitPoint _DetectedContourCenter; private Point[][] _MaxContour; private List _Polygon; private List _Paths; private List _SelectedArcs; private bool pre_welding = true; private List bead_result_info; //상위보고를 위한 비드 사이즈 저장 리스트 (OK:0, NG:1) private List[] result_info = new List[4]; // 경신 검수용 LBAD 검사 결과 OK,NG 반전 .. bool weldingResult = false; eScoutType _ScoutType; int[] LBADResultPage = new int[4]; IPopupService popup; public bool RecipeChange = false; ScannerObjectInfo arcinfo = new ScannerObjectInfo(); ScannerObjectInfo lineinfo = new ScannerObjectInfo(); ScannerObjectInfo splineinfo = new ScannerObjectInfo(); ScannerObjectInfo dotinfo = new ScannerObjectInfo(); string StepLBAD = ""; string StepWELDING = ""; short recipeRequestId = 1; bool ksExit = false; int[] ResultDataList = new int[4]; public SeqAutoRunKS() { var systemParameterks = Application.Current.AuroraEnv().SettingEntry[CommonSettingIds.SystemParameter] as SystemParameter; _ScoutType = systemParameterks.ScoutType; Application.Current.AuroraEnv().EventObservable.AsObservable("Pre_Test").Subscribe(OnPre_Test); string Path = System.IO.Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "RealTimeScout", string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}/")); AsyncLog.Init(Path); PopupService.Init(); popup = PopupService.Instance; } public SequenceBuilder Builder() { var sb = new SequenceBuilder(100000, 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_PAGENO, CheckPageNo); sb.AddDecision(SEQ_CHECK_LOAD_COMPLETE, CheckLoadComplete); sb.AddAction(SEQ_KS_WAIT_VISION, KSWaitVisionSquence); sb.AddAction(SEQ_KS_COMPLETE_VISION, KSCompleteVisionSquence); // RCC FlyingVision sb.AddAction(SEQ_SET_SCOUT_FLYING_VISION_SEQ, SetScoutFlyingVision_SeqParams); sb.AddSubsequence(SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ, SequenceManager.GetSeqBuilder_SeqScoutFlyingVision()); sb.AddAction(SEQ_GET_SCOUT_FLYING_VISION_SEQ, GetScoutFlyingVision_SeqResult); //sb.AddDecision(SEQ_GET_SCOUT_FLYING_VISION_SEQ, GetScoutFlyingVision_SeqResult); sb.AddEventSender(SEQ_SEND_EVENT_SENDER, SendEvent); sb.AddEventQ(SEQ_EVENT_Q_SAVE_FILE, 2); sb.AddAction(SEQ_SAVE_SCOUT_IMAGE, SaveScoutImageEvent); sb.AddAction(SEQ_FIND_EDGE, FindEdge); sb.AddDecision(SEQ_DECISION_RCC_ALGORITHM_TYPE, DecisionRCCAlgorithmType); sb.AddAction(SEQ_APPLY_OFFSET_OBJECT, ApplyOffsetObejct); sb.AddAction(SEQ_GENERATE_WELDING_OBJECT, GenerateWeldingObject); //Image Processing sb.AddAction(SEQ_BEFORE_WELD_MOVE_OBJECT, BeforeWeldMoveObject); sb.AddAction(SEQ_AFTER_WELD_CHECK_BEAD, AfterWeldCheckBead); sb.AddDecision(SEQ_CHECK_RCC_MODE, CheckRCCMode); sb.AddDecision(SEQ_CHECK_BEFORE_OR_AFTER, CheckBeforeOrAfter); // ALL (Normal & RCC & CellCenterOffset) sb.AddAction(SEQ_READY_SCANNER_LIST, ReadyScannerList); sb.AddAction(SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ, SetUploadWeldingList_SeqParams); sb.AddSubsequence(SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ, SequenceManager.GetSeqBuilder_SeqUploadWeldingList()); sb.AddAction(SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ, GetUploadWeldingList_SeqResult); sb.AddAction(SEQ_WAIT_WELDING_START, WaitWeldingStart); 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_EXECUTE_WELDING, ExecuteWelding); sb.AddAction(SEQ_REQUEST_UNLOAD_CELL, RequestUnloadCell); sb.AddAction(SEQ_WAIT_LBAD_JUDGE, WaitLBADJudge); sb.AddAction(SEQ_REPORT_CELLINFO_TO_PLC, ReportCellInfoToPLC); sb.AddDecision(SEQ_CHECK_CYCLE_STOP, CheckCycleStop); sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함. sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write sb.AddAction(SEQ_COMPLETE, Complete); sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_CHECK_PAGENO] > sb[SEQ_CHECK_LOAD_COMPLETE] > sb[SEQ_READY_SCANNER_LIST] > 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_WAIT_WELDING_START] > 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_EXECUTE_WELDING] > sb[SEQ_CHECK_RCC_MODE] > sb[SEQ_REQUEST_UNLOAD_CELL] > sb[SEQ_WAIT_LBAD_JUDGE] // 상위 보고 추가 해야된다. //> sb[SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ] > sb[SEQ_DO_ID_REPORT_CELL_RESULT_SEQ] > sb[SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ] > sb[SEQ_REPORT_CELLINFO_TO_PLC] > sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_COMPLETE]); // CellCenterOffset //sb.Flows(sb[SEQ_CHECK_LOAD_COMPLETE] > sb[SEQ_MEASURE_CELL_POSITION] > sb[SEQ_READY_SCANNER_LIST]); // RCC sb.Flows(sb[SEQ_CHECK_LOAD_COMPLETE] // RCC FlyingVision > sb[SEQ_SET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_GET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_CHECK_BEFORE_OR_AFTER] > sb[SEQ_BEFORE_WELD_MOVE_OBJECT] > sb[SEQ_READY_SCANNER_LIST]); sb.Flows(sb[SEQ_CHECK_RCC_MODE] // RCC FlyingVision > sb[SEQ_SET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_GET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_CHECK_BEFORE_OR_AFTER] > sb[SEQ_AFTER_WELD_CHECK_BEAD] > sb[SEQ_REQUEST_UNLOAD_CELL]); // 사전 검사 프로세스 추가 sb.Flows(sb[SEQ_CHECK_LOAD_COMPLETE] > sb[SEQ_KS_WAIT_VISION] //> sb[SEQ_SET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_GET_SCOUT_FLYING_VISION_SEQ] //> sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_CHECK_BEFORE_OR_AFTER] > sb[SEQ_AFTER_WELD_CHECK_BEAD] > sb[SEQ_KS_COMPLETE_VISION] > sb[SEQ_CHECK_PAGENO]); // Scout Image Save Event Seq sb.Flows(sb[SEQ_EVENT_Q_SAVE_FILE].On(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_SAVE_SCOUT_IMAGE] > sb.FlowFinal); //sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_LOAD_COMPLETE]); sb.Flows(sb[SEQ_CHECK_CYCLE_STOP] > sb[SEQ_CHECK_PAGENO]); sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final); sb.OnStopped(OnStopped); sb.OnForceError(OnForceError); sb.Draw("SeqAutoRunKS_New.pdf"); //popup.Generation(); return sb; } #region 양선전 사전검사 로직 추가(용접후 검사 결과를 보고 하구 나서 양산 시작) private void OnPre_Test(EventMessage message) { Log.I("OnPre_Test"); } private SequenceActionResult KSWaitVisionSquence(SequenceContext context, string id, SequenceActionResult param) { _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY True")); Thread.Sleep(200); _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_WELD_REQEUST).data) { Log.I(string.Format($"[PLCInterface]GET PLC_WELD_REQEUST True")); _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_REQEUST_ACK True")); break; } _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_WELD_REQEUST"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } Thread.Sleep(200); _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_REQEUST_ACK False")); _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY False")); return SequenceAction.Ok(); } private SequenceActionResult KSCompleteVisionSquence(SequenceContext context, string id, SequenceActionResult param) { _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_COMPLETE True")); Thread.Sleep(200); _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_WELD_COMPLETE_ACK).data) { Log.I(string.Format($"[PLCInterface]GET PLC_WELD_COMPLETE_ACK True")); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_COMPLETE False")); break; } _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_WELD_COMPLETE_ACK"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } while (!context.Stopped) { // 다음 페이지용 PLC 읽기 _PageNo = GetPagePlc(); SetPagePlc(_PageNo); // 다음 시퀀스 대기.. Thread.Sleep(100); if (_PLC.ReadBit((int)eBitInput.PLC_WELD_REQEUST).data) { Log.I(string.Format($"[IOInterface]Get PLC_WELD_REQEUST True")); bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); Log.I(string.Format("[PLCInterface]Pgae Reset")); break; } else { if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) { Log.I(string.Format($"[IOInterface]Get PLC_RESULT_REQUEST True")); bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); Log.I(string.Format("[PLCInterface]Pgae Reset")); break; } Thread.Sleep(100); } } return SequenceAction.Ok(); } #endregion #region 경신 용접 RCC 추가 private string CheckRCCMode(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); if (_SystemParameter.SequenceType == eSequenceType.Normal) { return SEQ_REQUEST_UNLOAD_CELL; } else { return SEQ_SET_SCOUT_FLYING_VISION_SEQ; } } private SequenceActionResult BeforeWeldMoveObject(SequenceContext context, string id, SequenceActionResult param) { MIL_ID ScannerFieldImage = Status.GetProcessingWeldingData().ScannerFiledImage; //RCC Error로 인해 시퀀스를 종료하고 있는데, NG배출해야 될지 확인 필요 _StopwatchGenObj = Stopwatch.StartNew(); double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; _ObjGenerator = new ObjectGenerator(dPixelResolution); int arc_cnt = 6 * (_PageNoRcc / 2); _ObjGenerator.ConvertMILToMat(ScannerFieldImage, out _ConvMatImage); //_ConvMatImage = Cv2.ImRead("D:\\RCC\\6_KS\\2025_7_3\\before1.PNG"); //string baseDir = @"D:\ImagesTT"; ////// 원본 이미지 저장 //string origFileName = $"Before{_PageNoRcc}_{DateTime.Now:HHmmss}.png"; //string origPath = Path.Combine(baseDir, origFileName); //Cv2.ImWrite(origPath, _ConvMatImage); // 4 Page 시퀀스 사용으로 spiral 페이지 사용시 RCC 사용안함 if (_PageNoRcc % 2 == 1) return SequenceAction.Ok(); _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; UnitPoint offset = new UnitPoint(0, 0); for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects.Count; i += 2) { int[] threshold_array = new int[] { _SystemParameter.CVThresholdCircle1, _SystemParameter.CVThresholdCircle2, _SystemParameter.CVThresholdCircle3, _SystemParameter.CVThresholdCircle4, _SystemParameter.CVThresholdCircle5, _SystemParameter.CVThresholdCircle6 }; //if (_ScannerCanvasUserCtrl.Model.Layers[0].Objects.Count < 13) return; //if (!(_ScannerCanvasUserCtrl.Model.Layers[0].Objects[12] is Spline)) return; //if (((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[12]).Center.Y < 0) // threshold_array = new int[] { _SystemParameter.CVThresholdCircle2_1, _SystemParameter.CVThresholdCircle2_2, _SystemParameter.CVThresholdCircle2_3, _SystemParameter.CVThresholdCircle2_4, _SystemParameter.CVThresholdCircle2_5, _SystemParameter.CVThresholdCircle2_6 }; FovInfo _FovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault(); PatternAgentBase _PatternAgent = PatternAgentManager.GetAgent(_FovInfo); var item = _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i]; _ObjGenerator = new ObjectGenerator(dPixelResolution); if (item is Arc) { arc_cnt += 1; var procPatternInfo = VisionRecipeManager.GetProcPatternInfo(_FovInfo, $"Arc{(_PageNoRcc / 2) + 1}_{arc_cnt - 6 * (_PageNoRcc/2)}", (eProcPatternId)arc_cnt - 1); var patternInfo = _PatternAgent.GetPatternInfo(_FovInfo, procPatternInfo.PatternId); //Log.I($"Finding pattern info procid : Arc{(_PageNoRcc / 2) + 1}_{arc_cnt - 6 * (_PageNoRcc / 2)}, patternid : {(eProcPatternId)arc_cnt - 1}, {patternInfo}"); UnitPoint center = ((Arc)item).Center; double my_radius = ((Arc)item).Radius; //int roi_height = _PatternAgent.GetFindROI(patternInfo).Height; //int roi_width = _PatternAgent.GetFindROI(patternInfo).Width; int roi_height = 736; int roi_width = 1472; OpenCvSharp.Rect my_ROI = new OpenCvSharp.Rect((int)(center.X / dPixelResolution + _ConvMatImage.Width / 2 - roi_width / 2), (int)(_ConvMatImage.Height / 2 - center.Y / dPixelResolution - roi_height / 2), roi_width, roi_height); Mat roi_img = new Mat(_ConvMatImage, my_ROI); Cv2.CvtColor(roi_img, roi_img, ColorConversionCodes.GRAY2BGR); Cv2.CvtColor(roi_img, roi_img, ColorConversionCodes.BGR2GRAY); //MIL.MbufAllocColor(MilEnvironment.Instance.GetSystem(_cameraAgent._CamConfig.CamConnConfig.BoardSlotPos), 3, loadImg.Width, loadImg.Height, 8 + MIL.M_UNSIGNED, MIL.M_IMAGE + MIL.M_DISP + MIL.M_PROC, ref mil_roi_img); MIL_ID mil_roi_img = _ObjGenerator.ConvertMatToMilID(roi_img); //MIL.MbufLoad($"D:/test_{arc_cnt}.png", mil_roi_img); //Mat roi_img_img; //_ObjGenerator.ConvertMILToMat(mil_roi_img, out roi_img_img); //Cv2.ImWrite($"D:/test_convert_{arc_cnt}.png", roi_img_img); Point2d found_center_pixel, found_center_pixel_mm; var cameraDisplay = CameraDisplayManager.GetDisplay(_FovInfo, eDisplayType.Pattern) as CameraDisplay; PatternResult _PatternResult = _PatternAgent.Find(patternInfo, mil_roi_img, _CameraDisplay); MIL.MbufFree(mil_roi_img); if (_PatternResult.Status == eFoundStatus.FoundOK) { Log.W("Pattern is found."); var resultsList = _PatternResult.Results.ToList(); found_center_pixel = new Point2d(resultsList[0].ImagePosition.X + my_ROI.X, resultsList[0].ImagePosition.Y + my_ROI.Y); found_center_pixel_mm = new Point2d((found_center_pixel.X - _ConvMatImage.Width / 2) * dPixelResolution, (_ConvMatImage.Height / 2 - found_center_pixel.Y) * dPixelResolution); if ( _SystemParameter.OffsetInterlock>0 && Math.Abs(found_center_pixel_mm.X - center.X)< _SystemParameter.OffsetInterlock && Math.Abs(found_center_pixel_mm.Y - center.Y) < _SystemParameter.OffsetInterlock) offset = new UnitPoint(found_center_pixel_mm.X - center.X, found_center_pixel_mm.Y - center.Y); else if (_SystemParameter.OffsetInterlock == 0 && Math.Abs(found_center_pixel_mm.X - center.X) < 1 && Math.Abs(found_center_pixel_mm.Y - center.Y) < 1) offset = new UnitPoint(found_center_pixel_mm.X - center.X, found_center_pixel_mm.Y - center.Y); else Log.W($"Offset is too large (x : {found_center_pixel_mm.X - center.X} y : {found_center_pixel_mm.Y - center.Y})"); } else { Log.W("Pattern is not found."); } //var ROI_X = (center.X - my_radius * 2) / dPixelResolution + _ConvMatImage.Width / 2; //var ROI_Y = -(center.Y + my_radius * 2) / dPixelResolution + _ConvMatImage.Height / 2; //var ROI_size = my_radius * 4 / dPixelResolution; //Point2f circle = _ObjGenerator.find_circle_center(_ConvMatImage, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, (int)ROI_size, (int)ROI_size), threshold_array[circle_cnt], _SystemParameter.CVRadiusMargin, my_radius / dPixelResolution); //circle_cnt += 1; //circle = new Point2f((float)(circle.X + ROI_X), (float)(circle.Y + ROI_Y)); ////Point2f circle = _ObjectGenerator.find_circle_center(_DetectImageMat, new OpenCvSharp.Rect(3325, 4250, 500, 500), threshold, my_radius, my_radius / dPixelResolution); ////Cv2.Circle(_DetectImageMat, new Point(circle.X, circle.Y), (int)(my_radius / dPixelResolution), Scalar.Red, 8); //circle = new Point2f((float)((circle.X - _ConvMatImage.Width / 2) * dPixelResolution), (float)((-circle.Y + _ConvMatImage.Height / 2) * dPixelResolution)); Log.I($"Offset : {offset.X},{offset.Y}"); IDrawObject objclone = item.Clone(); objclone.Move(offset); //_ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i] = objclone; _SelectedDrawObjectList[i] = objclone; //IDrawObject objclone_line = _ScannerCanvasUserCtrl.Model.Layers[0].Objects[i + 1].Clone(); IDrawObject objclone_line = _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i + 1].Clone(); objclone_line.Move(offset);/// //_ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i + 1] = objclone_line; _SelectedDrawObjectList[i + 1] = objclone_line; } else if (item is Line) { //var line_length = Math.Abs(((Line)item).PF1.Y - ((Line)item).PF2.Y); //if (line_length < 2) continue; //int ROI_size = (int)(line_length * 1.5 / dPixelResolution); //int ROI_X = (int)(((Line)item).PF1.X / dPixelResolution + _ConvMatImage.Width / 2) - ROI_size / 2; //int ROI_Y = (int)(-Math.Max(((Line)item).PF1.Y, ((Line)item).PF2.Y) / dPixelResolution + _ConvMatImage.Height / 2) - ROI_size / 4; //RotatedRect r = _ObjGenerator.find_line_center(_ConvMatImage, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, (int)ROI_size, (int)ROI_size), // _SystemParameter.CVThresholdLine1, _SystemParameter.CVThresholdLine2); //Point[] intVertices = new Point[4]; //for (int j = 0; j < 4; j++) //{ // intVertices[j] = new Point(r.Points()[j].X + ROI_X, r.Points()[j].Y + ROI_Y); //} //UnitPoint LineCenter = new UnitPoint((r.Center.X + ROI_X - _ConvMatImage.Width / 2) * dPixelResolution, (-r.Center.Y - ROI_Y + _ConvMatImage.Height / 2) * dPixelResolution); //UnitPoint offset = new UnitPoint(LineCenter.X - (((Line)item).PF1.X + ((Line)item).PF2.X) / 2, LineCenter.Y - (((Line)item).PF1.Y + ((Line)item).PF2.Y) / 2); //IDrawObject objclone = item.Clone(); //float angle = Math.Min(r.Angle, 90 - r.Angle); //objclone.Rotate(angle, LineCenter); //objclone.Move(offset); //_ScannerCanvasUserCtrl.Model.Layers[0].Objects[i] = objclone; } } return SequenceAction.Ok(); } //private SequenceActionResult AfterWeldCheckBead(SequenceContext context, string id, SequenceActionResult param) //{ // //if (_SystemParameter.SequenceType == eSequenceType.Normal) return SequenceAction.Ok(); // MIL_ID ScannerFieldImage = Status.GetProcessingWeldingData().ScannerFiledImage; // //RCC Error로 인해 시퀀스를 종료하고 있는데, NG배출해야 될지 확인 필요 // if (_ConvMatImage.Type() == MatType.CV_8UC1) // Cv2.CvtColor(_ConvMatImage, _ConvMatImage, ColorConversionCodes.GRAY2BGR); // _StopwatchGenObj = Stopwatch.StartNew(); // _ObjGenerator.ConvertMILToMat(ScannerFieldImage, out _ConvMatImage_after); // if (_ConvMatImage_after.Type() == MatType.CV_8UC1) // Cv2.CvtColor(_ConvMatImage_after, _ConvMatImage_after, ColorConversionCodes.GRAY2BGR); // _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); // double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; // _ObjGenerator = new ObjectGenerator(dPixelResolution); // var mainPage = WeldingRecipeManager.GetWeldingPage(); // _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; // bead_result_info = new List(); // //for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects.Count; i++) // for (int i = 0; i < _SelectedDrawObjectList.Count; i++) // { // //var item = _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i]; // var item = _SelectedDrawObjectList[i]; // double my_radius = 0; // int ROI_X = 0; // int ROI_Y = 0; // int ROI_W = 0; // int ROI_H = 0; // double bead_size1 = 0; // double bead_size2 = 0; // int search_size = 0; // UnitPoint center = new UnitPoint(0, 0); // OpenCvSharp.Point p1 = new OpenCvSharp.Point(); // OpenCvSharp.Point p2 = new OpenCvSharp.Point(); // Point[][] contour; // int type = -1; // if (item is Arc) // { // bead_result_info.Add(_SystemParameter.ArcBeadSizeMin); // bead_result_info.Add(_SystemParameter.ArcBeadSizeMax); // center = ((Arc)item).Center; // my_radius = ((Arc)item).Radius; // type = 0; // //ROI_W = (int)(my_radius * 2 / dPixelResolution); // ROI_W = 779; // ROI_H = 779; // ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; // ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_H / 2; // //if (center.Y > 0 && center.X > 15) ROI_Y -= 20; //우측 상단 비드 missalign이 있어 ROI영역 조절하도록 하드코딩 // search_size = (int)(ROI_W / 10); // //double size_margin = 10000; // int[] bead_size_info = new int[3]; // Point[] start_bead_point_info = new Point[3]; // Point[] end_bead_point_info = new Point[3]; // (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjGenerator.check_bead_size(_ConvMatImage_after, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, search_size); // //(bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, _SystemParameter.CVSearchSize); // //Cv2.Line(_ConvMatImage_after, p1, p2, Scalar.LimeGreen, 10); // //Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + 10), new Point(p1.X, p1.Y - 10), Scalar.LimeGreen, 10); // //Cv2.Line(_ConvMatImage_after, new Point(p2.X, p2.Y + 10), new Point(p2.X, p2.Y - 10), Scalar.LimeGreen, 10); // //Cv2.PutText(_ConvMatImage_after, $"{Math.Round(bead_size1 * dPixelResolution, 3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); // int min_bead_size = int.MaxValue; // int average_bead_size = 0; // for (int li = 0; li < bead_size_info.Length; li++) // { // p1 = start_bead_point_info[li]; // p2 = end_bead_point_info[li]; // Cv2.Line(_ConvMatImage_after, p1, p2, Scalar.LimeGreen, 12); // if (Math.Abs(p1.X - p2.X) > Math.Abs(p1.Y - p2.Y)) // { // Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + 12), new Point(p1.X, p1.Y - 12), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p2.X, p2.Y + 12), new Point(p2.X, p2.Y - 12), Scalar.LimeGreen, 12); // } // else // { // Cv2.Line(_ConvMatImage_after, new Point(p1.X + 12, p1.Y), new Point(p1.X - 12, p1.Y), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p2.X + 12, p2.Y), new Point(p2.X - 12, p2.Y), Scalar.LimeGreen, 12); // } // // Cv2.PutText(_DetectImageMat, $"{Math.Round(bead_size_info[li] * dPixelResolution, 3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); // average_bead_size += bead_size_info[li]; // if (min_bead_size > bead_size_info[li]) min_bead_size = bead_size_info[li]; // } // Cv2.PutText(_ConvMatImage_after, $"MIN : {Math.Round(min_bead_size * dPixelResolution, 3)}", new Point(ROI_X - 600, ROI_Y + 800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); // Cv2.PutText(_ConvMatImage_after, $"AVG : {Math.Round(average_bead_size * dPixelResolution / bead_size_info.Length, 3)}", new Point(ROI_X - 600, ROI_Y + 1000), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); // bead_size1 = average_bead_size / bead_size_info.Length * dPixelResolution; // //bead_size1 = bead_size1 * dPixelResolution; // Log.I($"arc length : {bead_size1}"); // bead_result_info.Add(bead_size1); // if (bead_size1 <= _SystemParameter.ArcBeadSizeMax && bead_size1 >= _SystemParameter.ArcBeadSizeMin) // { // bead_result_info.Add(1); // OK -> 1 // } // else // { // bead_result_info.Add(2); // NG -> 2 // } // } // else if (item is Spline) // { // //bead_result_info.Add(_SystemParameter.SpiralBeadWidthMin); // //bead_result_info.Add(_SystemParameter.SpiralBeadWidthMax); // //bead_result_info.Add(_SystemParameter.SpiralBeadHeightMin); // //bead_result_info.Add(_SystemParameter.SpiralBeadHeightMax); // center = ((Spline)item).Center; // my_radius = ((Spline)item).Radius; // type = 1; // /* // ROI_W = (int)(my_radius * 4 / dPixelResolution); // ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; // ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_W / 2; // (bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, 0); // */ // ROI_W = 492; // ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; // ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_W / 2; // //double size_margin = 10000; // double[] spline_y = new double[3]; // //spline_y[0] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[0]).Center.Y; // spline_y[0] = ((Spline)_SelectedDrawObjectList[0]).Center.Y; // //spline_y[1] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[1]).Center.Y; // spline_y[1] = ((Spline)_SelectedDrawObjectList[1]).Center.Y; // //spline_y[2] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[2]).Center.Y; // spline_y[2] = ((Spline)_SelectedDrawObjectList[2]).Center.Y; // Array.Sort(spline_y); // //int spline_empty_spot_y = (int)(_ConvMatImage.Height / 2 - (spline_y[0] - ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[0]).Radius * 1.5) / dPixelResolution); // int spline_empty_spot_y = (int)(_ConvMatImage.Height / 2 - (spline_y[0] - ((Spline)_SelectedDrawObjectList[0]).Radius * 1.5) / dPixelResolution); // //(bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); // int[] bead_size_info = new int[3]; // Point[] start_bead_point_info = new Point[3]; // Point[] end_bead_point_info = new Point[3]; // (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjGenerator.check_bead_size(_ConvMatImage_after, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); // bead_size1 = bead_size_info[0]; // bead_size2 = bead_size_info[1]; // p1 = start_bead_point_info[0]; // Cv2.Line(_ConvMatImage_after, new Point(p1.X - bead_size1 / 2, p1.Y), new Point(p1.X + bead_size1 / 2, p1.Y), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + bead_size2 / 2), new Point(p1.X, p1.Y - bead_size2 / 2), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p1.X - bead_size1 / 2, p1.Y + 12), new Point(p1.X - bead_size1 / 2, p1.Y - 12), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p1.X + bead_size1 / 2, p1.Y + 12), new Point(p1.X + bead_size1 / 2, p1.Y - 12), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p1.X - 10, p1.Y - bead_size2 / 2), new Point(p1.X + 10 / 2, p1.Y - bead_size2 / 2), Scalar.LimeGreen, 12); // Cv2.Line(_ConvMatImage_after, new Point(p1.X - 10, p1.Y + bead_size2 / 2), new Point(p1.X + 10 / 2, p1.Y + bead_size2 / 2), Scalar.LimeGreen, 12); // Cv2.PutText(_ConvMatImage_after, $"W : {Math.Round(bead_size1 * dPixelResolution, 3)} ", new Point(p1.X + bead_size1 / 2, p1.Y), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); // //Cv2.PutText(_ConvMatImage_after, $"H : {Math.Round(bead_size2 * dPixelResolution, 3)} mm", new Point(p1.X + bead_size1 / 2, p1.Y + bead_size2 / 2 + 50), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); // Cv2.PutText(_ConvMatImage_after, $"H: {Math.Round(bead_size2 * dPixelResolution, 3)} ", new Point(p1.X + bead_size1 / 2, p1.Y + 200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); // bead_size1 = bead_size1 * dPixelResolution; // bead_size2 = bead_size2 * dPixelResolution; // Log.I($"spiral length : {bead_size1}, {bead_size2}"); // ScannerParam _SplineParam = ScannerCanvasUserCtrl.ScannerParams[((Spline)item).ScannerParamNo]; // Log.I($"ScannerParam ->{_SplineParam.LaserPower1}, {_SplineParam.LaserPower2}"); // bead_result_info.Add(_SystemParameter.SpiralBeadWidthMin); // bead_result_info.Add(_SystemParameter.SpiralBeadWidthMax); // bead_result_info.Add(bead_size1); // bead_result_info.Add(_SystemParameter.SpiralBeadHeightMin); // bead_result_info.Add(_SystemParameter.SpiralBeadHeightMax); // bead_result_info.Add(bead_size2); // if (bead_size1 <= _SystemParameter.SpiralBeadWidthMax && bead_size1 >= _SystemParameter.SpiralBeadWidthMin // && bead_size2 <= _SystemParameter.SpiralBeadHeightMax && bead_size2 >= _SystemParameter.SpiralBeadHeightMin) // { // bead_result_info.Add(1); // OK -> 1 // } // else // { // bead_result_info.Add(2); // NG -> 2 // } // } // } // return SequenceAction.Ok(); //} private SequenceActionResult AfterWeldCheckBead(SequenceContext context, string id, SequenceActionResult param) { //if (_SystemParameter.SequenceType == eSequenceType.Normal) return SequenceAction.Ok(); MIL_ID ScannerFieldImage = Status.GetProcessingWeldingData().ScannerFiledImage; //RCC Error로 인해 시퀀스를 종료하고 있는데, NG배출해야 될지 확인 필요 if (_ConvMatImage.Type() == MatType.CV_8UC1) Cv2.CvtColor(_ConvMatImage, _ConvMatImage, ColorConversionCodes.GRAY2BGR); _StopwatchGenObj = Stopwatch.StartNew(); _ObjGenerator.ConvertMILToMat(ScannerFieldImage, out _ConvMatImage_after); if (_ConvMatImage_after.Type() == MatType.CV_8UC1) Cv2.CvtColor(_ConvMatImage_after, _ConvMatImage_after, ColorConversionCodes.GRAY2BGR); _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; _ObjGenerator = new ObjectGenerator(dPixelResolution); var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; bead_result_info = new List(); //for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects.Count; i++) for (int i = 0; i < _SelectedDrawObjectList.Count; i++) { //var item = _ScannerCanvasUserCtrl.Model.Layers[_PageNoRcc].Objects[i]; var item = _SelectedDrawObjectList[i]; double my_radius = 0; int ROI_X = 0; int ROI_Y = 0; int ROI_W = 0; int ROI_H = 0; double bead_size1 = 0; double bead_size2 = 0; int search_size = 0; UnitPoint center = new UnitPoint(0, 0); OpenCvSharp.Point p1 = new OpenCvSharp.Point(); OpenCvSharp.Point p2 = new OpenCvSharp.Point(); Point[][] contour; int type = -1; if (item is Arc) { bead_result_info.Add(_SystemParameter.ArcBeadSizeMin); bead_result_info.Add(_SystemParameter.ArcBeadSizeMax); center = ((Arc)item).Center; my_radius = ((Arc)item).Radius; type = 0; //ROI_W = (int)(my_radius * 2 / dPixelResolution); ROI_W = 779; ROI_H = 779; ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_H / 2; //if (center.Y > 0 && center.X > 15) ROI_Y -= 20; //우측 상단 비드 missalign이 있어 ROI영역 조절하도록 하드코딩 search_size = (int)(ROI_W / 10); //double size_margin = 10000; int[] bead_size_info = new int[3]; Point[] start_bead_point_info = new Point[3]; Point[] end_bead_point_info = new Point[3]; (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjGenerator.check_bead_size(_ConvMatImage_after, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, search_size); //(bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_H), type, _SystemParameter.CVSearchSize); //Cv2.Line(_ConvMatImage_after, p1, p2, Scalar.LimeGreen, 10); //Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + 10), new Point(p1.X, p1.Y - 10), Scalar.LimeGreen, 10); //Cv2.Line(_ConvMatImage_after, new Point(p2.X, p2.Y + 10), new Point(p2.X, p2.Y - 10), Scalar.LimeGreen, 10); //Cv2.PutText(_ConvMatImage_after, $"{Math.Round(bead_size1 * dPixelResolution, 3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); int min_bead_size = int.MaxValue; int max_bead_size = int.MinValue; int average_bead_size = 0; for (int li = 0; li < bead_size_info.Length; li++) { p1 = start_bead_point_info[li]; p2 = end_bead_point_info[li]; Cv2.Line(_ConvMatImage_after, p1, p2, Scalar.LimeGreen, 12); if (Math.Abs(p1.X - p2.X) > Math.Abs(p1.Y - p2.Y)) { Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + 12), new Point(p1.X, p1.Y - 12), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p2.X, p2.Y + 12), new Point(p2.X, p2.Y - 12), Scalar.LimeGreen, 12); } else { Cv2.Line(_ConvMatImage_after, new Point(p1.X + 12, p1.Y), new Point(p1.X - 12, p1.Y), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p2.X + 12, p2.Y), new Point(p2.X - 12, p2.Y), Scalar.LimeGreen, 12); } // Cv2.PutText(_DetectImageMat, $"{Math.Round(bead_size_info[li] * dPixelResolution, 3)} mm", new Point(p1.X + 10, p1.Y + 220), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); average_bead_size += bead_size_info[li]; if (min_bead_size > bead_size_info[li]) min_bead_size = bead_size_info[li]; if (max_bead_size < bead_size_info[li]) max_bead_size = bead_size_info[li]; bead_result_info.Add(Math.Round(bead_size_info[li] * dPixelResolution, 3)); Log.I($"Bead Size : {Math.Round(bead_size_info[li] * dPixelResolution, 3)}"); } //Cv2.PutText(_ConvMatImage_after, $"MIN : {Math.Round(min_bead_size * dPixelResolution, 3)}", new Point(ROI_X - 600, ROI_Y + 800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); //Cv2.PutText(_ConvMatImage_after, $"AVG : {Math.Round(average_bead_size * dPixelResolution / bead_size_info.Length, 3)}", new Point(ROI_X - 600, ROI_Y + 1000), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); if (_ConvMatImage_after.Height / 2 > ROI_Y) { Cv2.PutText(_ConvMatImage_after, $"1 : {Math.Round(bead_size_info[0] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"2 : {Math.Round(bead_size_info[1] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1400), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"3 : {Math.Round(bead_size_info[2] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1600), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"4 : {Math.Round(bead_size_info[3] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y + 1800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Log.I($"1:{bead_size_info[0]}, 2:{bead_size_info[1]}, 3:{bead_size_info[2]}, 4:{bead_size_info[3]}"); } else { Cv2.PutText(_ConvMatImage_after, $"1 : {Math.Round(bead_size_info[0] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"2 : {Math.Round(bead_size_info[1] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 400), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"3 : {Math.Round(bead_size_info[2] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 600), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"4 : {Math.Round(bead_size_info[3] * dPixelResolution, 3)}", new Point(ROI_X - 200, ROI_Y - 800), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); Log.I($"1:{bead_size_info[0]}, 2:{bead_size_info[1]}, 3:{bead_size_info[2]}, 4:{bead_size_info[3]}"); } bead_size1 = average_bead_size / bead_size_info.Length * dPixelResolution; var edit_bead_size_min = Math.Round(min_bead_size * dPixelResolution, 3); var edit_bead_size_max = Math.Round(max_bead_size * dPixelResolution, 3); //bead_size1 = bead_size1 * dPixelResolution; Log.I($"arc length : {bead_size1}"); // 260113 Bead Avr, Min, Max -> Bead1,2,3,4 //bead_result_info.Add(bead_size1); // 251223 Bead Size Min / Max 값을 변경함 //bead_result_info.Add(min_bead_size); //bead_result_info.Add(max_bead_size); //bead_result_info.Add(edit_bead_size_min); //bead_result_info.Add(edit_bead_size_max); Log.D($"Bead Size [min({edit_bead_size_min}) / max({edit_bead_size_max})]"); // 260113 조건 수정 // 네 개 항목이 모두 OK range 안에 들어올 때만 OK로 판단하도록 하는건 지난번 말씀드린 것 처럼 한줄만 수정하면 적용 가능합니다. //if (bead_size1 <= _SystemParameter.ArcBeadSizeMax && bead_size1 >= _SystemParameter.ArcBeadSizeMin) if (edit_bead_size_max <= _SystemParameter.ArcBeadSizeMax && edit_bead_size_min >= _SystemParameter.ArcBeadSizeMin) { bead_result_info.Add(1); // OK -> 1 } else { bead_result_info.Add(2); // NG -> 2 } } else if (item is Spline) { //bead_result_info.Add(_SystemParameter.SpiralBeadWidthMin); //bead_result_info.Add(_SystemParameter.SpiralBeadWidthMax); //bead_result_info.Add(_SystemParameter.SpiralBeadHeightMin); //bead_result_info.Add(_SystemParameter.SpiralBeadHeightMax); center = ((Spline)item).Center; my_radius = ((Spline)item).Radius; type = 1; /* ROI_W = (int)(my_radius * 4 / dPixelResolution); ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_W / 2; (bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, 0); */ ROI_W = 492; ROI_X = (int)(center.X / dPixelResolution) + _ConvMatImage.Width / 2 - ROI_W / 2; ROI_Y = -(int)(center.Y / dPixelResolution) + _ConvMatImage.Height / 2 - ROI_W / 2; //double size_margin = 10000; double[] spline_y = new double[3]; //spline_y[0] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[0]).Center.Y; spline_y[0] = ((Spline)_SelectedDrawObjectList[0]).Center.Y; //spline_y[1] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[1]).Center.Y; spline_y[1] = ((Spline)_SelectedDrawObjectList[1]).Center.Y; //spline_y[2] = ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[2]).Center.Y; spline_y[2] = ((Spline)_SelectedDrawObjectList[2]).Center.Y; Array.Sort(spline_y); //int spline_empty_spot_y = (int)(_ConvMatImage.Height / 2 - (spline_y[0] - ((Spline)_ScannerCanvasUserCtrl.Model.Layers[0].Objects[0]).Radius * 1.5) / dPixelResolution); int spline_empty_spot_y = (int)(_ConvMatImage.Height / 2 - (spline_y[0] - ((Spline)_SelectedDrawObjectList[0]).Radius * 1.5) / dPixelResolution); //(bead_size1, bead_size2, p1, p2, contour) = _ObjGenerator.check_bead_size(_ConvMatImage, _ConvMatImage, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); int[] bead_size_info = new int[3]; Point[] start_bead_point_info = new Point[3]; Point[] end_bead_point_info = new Point[3]; (bead_size_info, start_bead_point_info, end_bead_point_info, contour) = _ObjGenerator.check_bead_size(_ConvMatImage_after, _ConvMatImage_after, new OpenCvSharp.Rect((int)ROI_X, (int)ROI_Y, ROI_W, ROI_W), type, spline_empty_spot_y); bead_size1 = bead_size_info[0]; bead_size2 = bead_size_info[1]; p1 = start_bead_point_info[0]; Cv2.Line(_ConvMatImage_after, new Point(p1.X - bead_size1 / 2, p1.Y), new Point(p1.X + bead_size1 / 2, p1.Y), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p1.X, p1.Y + bead_size2 / 2), new Point(p1.X, p1.Y - bead_size2 / 2), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p1.X - bead_size1 / 2, p1.Y + 12), new Point(p1.X - bead_size1 / 2, p1.Y - 12), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p1.X + bead_size1 / 2, p1.Y + 12), new Point(p1.X + bead_size1 / 2, p1.Y - 12), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p1.X - 10, p1.Y - bead_size2 / 2), new Point(p1.X + 10 / 2, p1.Y - bead_size2 / 2), Scalar.LimeGreen, 12); Cv2.Line(_ConvMatImage_after, new Point(p1.X - 10, p1.Y + bead_size2 / 2), new Point(p1.X + 10 / 2, p1.Y + bead_size2 / 2), Scalar.LimeGreen, 12); Cv2.PutText(_ConvMatImage_after, $"W : {Math.Round(bead_size1 * dPixelResolution, 3)} ", new Point(p1.X + bead_size1 / 2, p1.Y), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); //Cv2.PutText(_ConvMatImage_after, $"H : {Math.Round(bead_size2 * dPixelResolution, 3)} mm", new Point(p1.X + bead_size1 / 2, p1.Y + bead_size2 / 2 + 50), HersheyFonts.HersheyComplexSmall, 10, Scalar.LimeGreen, 25); Cv2.PutText(_ConvMatImage_after, $"H: {Math.Round(bead_size2 * dPixelResolution, 3)} ", new Point(p1.X + bead_size1 / 2, p1.Y + 200), HersheyFonts.HersheyComplexSmall, 11, Scalar.LimeGreen, 25); bead_size1 = bead_size1 * dPixelResolution; bead_size2 = bead_size2 * dPixelResolution; Log.I($"spiral length : {bead_size1}, {bead_size2}"); ScannerParam _SplineParam = ScannerCanvasUserCtrl.ScannerParams[((Spline)item).ScannerParamNo]; Log.I($"ScannerParam ->{_SplineParam.LaserPower1}, {_SplineParam.LaserPower2}"); bead_result_info.Add(_SystemParameter.SpiralBeadMin); bead_result_info.Add(_SystemParameter.SpiralBeadMax); bead_result_info.Add(bead_size1); bead_result_info.Add(_SystemParameter.SpiralBeadMin); bead_result_info.Add(_SystemParameter.SpiralBeadMax); bead_result_info.Add(bead_size2); if (bead_size1 <= _SystemParameter.SpiralBeadMax && bead_size1 >= _SystemParameter.SpiralBeadMin && bead_size2 <= _SystemParameter.SpiralBeadMax && bead_size2 >= _SystemParameter.SpiralBeadMin) { bead_result_info.Add(1); // OK -> 1 } else { bead_result_info.Add(2); // NG -> 2 } } } return SequenceAction.Ok(); } #endregion #region TT public List Init_ArcInfo() { List info = new List(); Random rnd = new Random(); int sets = 6; // 6개 세트 for (int i = 0; i < sets; i++) { // LowerLimit, UpperLimit, Result (-3 ~ 3) info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // -3 ~ 3, 소수점 3자리 info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // OK_NG (1 또는 2) info.Add(rnd.Next(1, 3)); // 1 또는 2 } return info; } public List Init_SpiralInfo() { List info = new List(); Random rnd = new Random(); int sets = 3; // Spiral 3세트 for (int i = 1; i <= sets; i++) { // Horizontal info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // LowerLimit info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // UpperLimit info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // Result // Vertical info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // LowerLimit info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // UpperLimit info.Add(Math.Round(rnd.NextDouble() * 6 - 3, 3)); // Result // Width OK/NG (1 또는 2) info.Add(rnd.Next(1, 3)); } return info; } private void SaveExcelFileRing(Mat img, string ExcelFile, int Count, List data) { List RingLable = new List(); for (int i = 1; i <= 6; i++) { RingLable.Add($"Ring #{i} _ BeadWidthLowerLimit"); RingLable.Add($"Ring #{i} _ BeadWidthUpperLimit"); RingLable.Add($"Ring #{i} _ BeadWidthResult"); RingLable.Add($"Ring #{i} _ BeadWidthOK_NG"); } List RingData = new List(); for (int i = 0; i < data.Count; i++) { RingData.Add(ToIntThousand(data[i]).ToString()); } var inserter = new ExcelImageInserter(ExcelFile); var entry = new ExcelEntry { Name = string.Format("그림{0}", Count), Image = img, ParametersSets = new List> { RingLable, RingData }, Content = "추가 내용" }; inserter.AddEntry(entry, string.Format("MySheet{0}", Count), widthCm: 8, heightCm: 8); inserter.Save(); string fileName = Path.GetFileName(ExcelFile); string directory = Path.GetDirectoryName(ExcelFile); AsyncLog.I($"{Count} SaveExcelFile.... {directory}{fileName}"); } private void SaveExcelFileSpiral(Mat img, string ExcelFile, int Count, List data) { List SpiralLable = new List(); for (int i = 1; i <= 3; i++) { SpiralLable.Add($"Spiral #{i} _ HorizontalLowerLimit"); SpiralLable.Add($"Spiral #{i} _ HorizontalUpperLimit"); SpiralLable.Add($"Spiral #{i} _ HorizontalResult"); SpiralLable.Add($"Spiral #{i} _ VerticalLowerLimit"); SpiralLable.Add($"Spiral #{i} _ VerticalUpperLimit"); SpiralLable.Add($"Spiral #{i} _ VerticalResult"); SpiralLable.Add($"Spiral #{i} _ WidthOK_NG"); } List SpiralData = new List(); for (int i = 0; i < data.Count; i++) { SpiralData.Add(ToIntThousand(data[i]).ToString()); } var inserter = new ExcelImageInserter(ExcelFile); var entry = new ExcelEntry { Name = string.Format("그림{0}", Count), Image = img, ParametersSets = new List> { SpiralLable, SpiralData }, Content = "추가 내용" }; inserter.AddEntry(entry, string.Format("MySheet{0}", Count), widthCm: 8, heightCm: 8); inserter.Save(); string fileName = Path.GetFileName(ExcelFile); string directory = Path.GetDirectoryName(ExcelFile); AsyncLog.I($"{Count} SaveExcelFile.... {directory}{fileName}"); } #endregion Mat matLeftTop; Mat matRightTop; Mat matLeftBottom; Mat matRightBottom; OpenCvSharp.Rect rectT; private void TestopupWin(SequenceContext context) { // OpenCV Version 4.9.0 //D:\ILSOSConfig\_vision\Def string Png1 = string.Format("D:\\ILSOSConfig\\_vision\\Def\\1.png"); string Png2 = string.Format("D:\\ILSOSConfig\\_vision\\Def\\2.png"); string Png3 = string.Format("D:\\ILSOSConfig\\_vision\\Def\\3.png"); string Png4 = string.Format("D:\\ILSOSConfig\\_vision\\Def\\4.png"); matLeftTop = Cv2.ImRead(Png1); matRightTop = Cv2.ImRead(Png2); matLeftBottom = Cv2.ImRead(Png3); matRightBottom = Cv2.ImRead(Png4); // Width 10368, Height 9856 // 1153 896 6918 8056 rectT = new OpenCvSharp.Rect(1153, 896, 6918, 8056); popup.Show(); popup.UpdateImages1(matLeftTop, rectT); popup.UpdateImages2(matRightTop, rectT); popup.UpdateImages3(matLeftBottom, rectT); popup.UpdateImages4(matRightBottom, rectT); List infoArc = Init_ArcInfo(); List infoSpiral = Init_SpiralInfo(); popup.SetParameters1(infoArc); // 24 popup.SetParameters2(infoSpiral); // 21 popup.SetParameters3(infoArc); popup.SetParameters4(infoSpiral); popup.SetStepLBAD("OK"); popup.SetStepWELDING("OK"); _AutoRunStartTime = DateTime.Now; string ExcelFile = System.IO.Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "RealTimeScout", string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}/out/{_AutoRunStartTime.ToString("HHmmss")}.xlsx")); SaveExcelFileRing(matLeftTop, ExcelFile, 1, infoArc); // 24 SaveExcelFileSpiral(matRightTop, ExcelFile, 2, infoSpiral); // 21 SaveExcelFileRing(matLeftBottom, ExcelFile, 3, infoArc); SaveExcelFileSpiral(matRightBottom, ExcelFile, 4, infoSpiral); result_info[0] = infoArc; result_info[1] = infoSpiral; result_info[2] = infoArc; result_info[3] = infoSpiral; // 레시피 값 가져오기 : 9 + 2 -> 총 11개 //List recipe = Get_Recipe_Info(); // Recipe : 9 //WeldingInfoSendPLC(recipe, "OK", "OK"); //KS_WeldingInfo weldingInfo = new KS_WeldingInfo(); //List Info = weldingInfo.MakeData(infoArc, infoSpiral, infoArc, infoSpiral, recipe, "OK", "OK"); while (!context.Stopped) { Thread.Sleep(100); } } private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param) { var activatedRecipeId = Application.Current.AuroraEnv().RecipeManager.ActivatedRecipe().Id; var recipeName = WeldingRecipeManager.SearchRecipeItem(activatedRecipeId); Status.GetProcessingWeldingData().ActRecipe = recipeName; //Status.GetProcessingWeldingData().PageNO = _PageNoRcc.ToString(); //Status.GetProcessingWeldingData().BcrID = "PRD-9X7K2M5Q8T1Z4L6R3W0VYCNJHBDGFZ"; //TestopupWin(context); //while (true) { }; Log.I("SeqAutoRunKS_New Start"); Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION); _InitParam = param.Param as SeqAutoRunKS_New_InitParam; _RecipeManager = Application.Current.AuroraEnv().RecipeManager; _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); InitDev(context); if (!CheckDeviceReady(context)) { //Check Device AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_DeviceNotReady); Log.E("The devices are not active."); return null; } if (InitSequenceVariable(context) == false) { AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_InitVariableError); return null; } return SequenceAction.Ok(); } private bool InitSequenceVariable(SequenceContext context) { _AutoRunStartTime = DateTime.Now; _SeqRunCount = 0; _TodayProduct = _SystemParameter.TodayProductCount; _TotalProduct = _SystemParameter.TotalProductCount; //_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; if (_SystemParameter.SequenceType == eSequenceType.Normal) { _IsRealTimeScout = false; } else if (_SystemParameter.SequenceType == eSequenceType.RCC) { double dPixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0; //ConvEdgeObjectViewModel에서도 생성되지만.. Seq에서 재생성하고 쓰고 버리자 _ObjGenerator = new ObjectGenerator(dPixelResolution); if (_SystemParameter.OffsetType == eOffsetType.manual) _ObjGenerator.SetOffsetType("Manual"); else { _ObjGenerator.SetOffsetType("CSV"); _ObjGenerator.SetOffsetTable(_SystemParameter.OffsetCSVFile, _SystemParameter.LensMagnification, _SystemParameter.CameraPixelSize); } _ObjGenerator.SetInterlockProperties(_SystemParameter.DrawObjectDistanceRange, _SystemParameter.DrawObjectArcLengthMax, _SystemParameter.DrawObjectLengthSumDiffRange, _SystemParameter.DrawObjectCenterXYDiffRange, _SystemParameter.MaxMinDiffHigh, _SystemParameter.MaxMinDiffLow, _SystemParameter.CheckCenterDiff, _SystemParameter.DistortionCenterDiff, _SystemParameter.AutoMissAlignHigh, _SystemParameter.AutoMissAlignLow); //if (!_ObjGenerator.GetArcInfoFromRecipe(_RecipeDrawObjects, out _SelectedArcs)) { // Log.E(string.Format("Recipe Infomation Register Error")); // return false; //} _IsRealTimeScout = true; } else if (_SystemParameter.SequenceType == eSequenceType.CellCenterOffset) { // VisionDevice 추가 // InitializeCameraDevice _FovRecipe = VisionRecipeManager.GetFovRecipe(_InitParam.ScoutSeqParams.FovInfo); _CameraAgent = CameraAgentManager.GetCameraAgent(_InitParam.ScoutSeqParams.FovInfo); _CameraDisplay = CameraDisplayManager.GetDisplay(_InitParam.ScoutSeqParams.FovInfo, _InitParam.ScoutSeqParams.DisplayType); // InitGrabImageBuffer 함수 try { IpAdapter.Instance.IpEnvironment.FreeImage(_GrabImage); _GrabImage = (MIL_ID)_CameraAgent.CloneImageBuffer(); } catch (Exception e) { Log.E(e.Message); } _IsRealTimeScout = false; } else { Log.E("Invalid SequenceType."); return false; } var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObjects = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; _WeldingScannerListNo = eListNo.LIST1; _CellMeasureCenterOffsetX = 0.0; _CellMeasureCenterOffsetY = 0.0; var currentModelName = context.Recipes.ActivatedModelName(); var modelItem = context.GetModel(currentModelName, CommonModelIds.EquipmentSpecificModel); _ModelNo = modelItem.Model_No; return true; } private void InitDev(SequenceContext context) { //Device Init _Scanner = context.GetLaserScanner(); _Laser = context.GetLaser(); //_StreamLightLBAD._Client = context.GetStreamLightClient(); _PLC = context.Devices[DeviceIds.PLCDevice] as PLCControllerKS; _IO = context.GetIOUnit(); _LBAD = context.GetLBAD(); } private bool CheckDeviceReady(SequenceContext context) { List deviceListToCheck = new List() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.PLCDevice, CommonDeviceIds.IODevice, CommonDeviceIds.LBAD }; bool isAllDeviceActivated = true; foreach (string item in deviceListToCheck) { if (!context.Devices[item].IsActivated) { isAllDeviceActivated = isAllDeviceActivated && false; } } return isAllDeviceActivated; } private bool CheckCondition(SequenceContext context) { if (CheckCondition_Interlock()) { if (InitializeDeviceStatus(context)) { return true; } } return false; } private bool CheckCondition_Interlock() { // PLC, Data, IO 등 Interlock checking return true; } private bool InitializeDeviceStatus(SequenceContext context) { // PLC Interface AutoStatus Start InitAutoRunBit(); // Laser Initialize _Laser.PilotLaserOff(); _Laser.LaserOn(); Thread.Sleep(100); if (!_Laser.GetLaserReady()) { Log.E("ERROR Initialize Laser"); return false; } // Scanner Initialize // Scanner 없음. // OCT Initialize // TODO: EnterSequenceModeOCT 와 함께 Initialize 하는 것을 재구현 필요함. 초반에 한번만 check 하고 돌아 갈수 있도록 // PLC Initialize if (_PLC.ReadBit((int)eBitInput.PLC_AUTO_STATUS).data == false) { Log.E(string.Format("ERROR Initialize PLC, Bit Off PLC_AUTO_STATUS")); return false; } // LBAD Initialize // LBAD 는 server 이기 때문에, 만약 끊어졌으면 다시 접속이 필요함 if (!_LBAD.GetConnected()) { _LBAD.DisConnect(); Thread.Sleep(500); int ret = _LBAD.Open(_LBAD.Config); if (ret == -1) { Log.E($"LBAD Open Error : {ret}"); return false; } } _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), true); Log.I(string.Format($"[IOInterface]SET PCLBADReadyStatus true")); if (_SystemParameter.SequenceType == eSequenceType.Normal) { _Scanner.SelectCorrectionTable(2); Log.I(string.Format("Normal, Select Laser Correction File")); } else if (_SystemParameter.SequenceType == eSequenceType.RCC) { _Scanner.SelectCorrectionTable(1); Log.I(string.Format("RCC, Select Vision Correction File")); } else if (_SystemParameter.SequenceType == eSequenceType.CellCenterOffset) { _Scanner.SelectCorrectionTable(1); Log.I(string.Format("CellCenterOffset, Select Vision Correction File")); } else { Log.I(string.Format("Invalid SequenceType.")); } return true; } private void InitAutoRunBit() { Log.I(string.Format($"[PLCInterface] Start AutoRun PLC Bit Initialize")); _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_REQEUST_ACK False")); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_COMPLETE False")); _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY False")); _PLC.WriteBit((int)eBitOutput.PC_AUTO_STATUS, true); Log.I(string.Format($"[PLCInterface]SET PC_AUTO_STATUS True")); // Page Rrset bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); Log.I(string.Format("[PLCInterface]Pgae Reset")); _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, false); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_NG False")); _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_OK, false); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_OK False")); _PLC.WriteBit((int)eBitOutput.PC_RECIPE_PARAM_UPLOAD_COMPLETE, false); Log.I(string.Format($"[PLCInterface]SET PC_RECIPE_PARAM_UPLOAD_COMPLETE false")); UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG); Log.I(string.Format($"[IOInterface] Start AutoRun IO Bit Initialize")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false); Log.I(string.Format($"[IOInterface]SET PCLBADReadyStatus False")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false); Log.I(string.Format($"[IOInterface]SET PCLBADWeldingTrigger False")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); Log.I(string.Format($"[IOInterface]SET PCLBADWeldingStop False")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false); Log.I(string.Format($"[IOInterface]SET PCLBADJudgementCompleteAck False")); Log.I(string.Format($"[IOInterface] Complete AutoRun IO Bit Initialize")); } private string CheckBeforeOrAfter(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { _SystemParameter = context.GetSetting(CommonSettingIds.SystemParameter); var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam; //return SequenceAction.Ok(); if (pre_welding) { pre_welding = !pre_welding; return SEQ_BEFORE_WELD_MOVE_OBJECT; } else { pre_welding = !pre_welding; return SEQ_AFTER_WELD_CHECK_BEAD; } } private string CheckInitCondition(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { 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); Log.D("ReceiveCellInfo Sequence CheckInitCondition"); //return SEQ_CHECK_LOAD_COMPLETE; return SEQ_CHECK_PAGENO; } //private string GetPLC_WordDataToString(short[] rawData) //{ // byte[] bytes = new byte[rawData.Length * 2]; // for (int i = 0; i < rawData.Length; i++) // { // bytes[i * 2] = (byte)(rawData[i] & 0xFF); // 하위 바이트 // bytes[i * 2 + 1] = (byte)((rawData[i] >> 8) & 0xFF); // 상위 바이트 // } // string result = Encoding.ASCII.GetString(bytes); // return result; //} private short[] SetPLC_StringDataToWord(string dataString) { List shorts = new List(); for (int i = 0; i < dataString.Length; i += 2) { byte first = (byte)dataString[i]; byte second = (i + 1 < dataString.Length) ? (byte)dataString[i + 1] : (byte)0; // 반전하여 저장: second first short combined = (short)((second << 8) | first); shorts.Add(combined); } return shorts.ToArray(); } public static short[] IntArrayToShortArray(int[] intArray) { // short 범위 -> -32768 ~ 32767 short[] shortArray = new short[intArray.Length * 2]; for (int i = 0; i < intArray.Length; i++) { shortArray[i * 2] = (short)((intArray[i] >> 16) & 0xFFFF); // 상위 16비트 shortArray[i * 2 + 1] = (short)(intArray[i] & 0xFFFF); // 하위 16비트 } return shortArray; } public static int[] ShortArrayToIntArray(short[] shortArray) { if (shortArray.Length % 2 != 0) throw new ArgumentException("short 배열 길이는 반드시 짝수여야 합니다."); int[] intArray = new int[shortArray.Length / 2]; for (int i = 0; i < intArray.Length; i++) { int high = (ushort)shortArray[i * 2]; // 부호 없는 16비트로 캐스팅 int low = (ushort)shortArray[i * 2 + 1]; intArray[i] = (high << 16) | low; } return intArray; } public void SetBCRID(string id) { //string TestString = "ABCDEFG"; //short[] data = SetPLC_StringDataToWord(TestString); //string hexString1 = string.Join(" ", Array.ConvertAll(data, s => s.ToString("X4"))); ////short[] WordData = new short[] { 0x00A0, 0x00B0 }; //_PLC.WriteWordBlock((int)eWordOutput.PC_RECIPE_NO, 2, data); //var Red = _PLC.ReadWordBlock((int)eWordOutput.PC_RECIPE_NO, 2).data; //Log.I(string.Format($"[PLCInterface]SET PLC_BCR_ID {0}", _BcrID)); } //public string GetBCRID() //{ // string id = ""; // var bcrid = _PLC.ReadWordBlock((int)eWordInput.PLC_BCR_ID, 16).data; // string hexString = string.Join(" ", Array.ConvertAll(bcrid, s => s.ToString("X4"))); // // 4241 4443 4645 4847 4A49 4C4B 4E4D 504F 5251 5453 3130 3332 3534 3736 3938 0000 // id = GetPLC_WordDataToString(bcrid); // Log.I(string.Format($"[PLCInterface]GET PLC_BCR_ID {0}", id)); // return id; //} public void SetPagePlc(int num) { bool[] Page = new bool[4]; switch (num) { case 0: { Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); } break; case 1: { Page = new bool[4] { true, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); } break; case 2: { Page = new bool[4] { false, true, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); } break; case 3: { Page = new bool[4] { false, false, true, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); } break; case 4: { Page = new bool[4] { false, false, false, true }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); } break; } } public int GetPagePlc() { int num = 0; bool[] page = _PLC.ReadBitBlock((int)eBitInput.PLC_SET_WELD_PAGE_1, 4).data; if (page[0]) num = 1; if (page[1]) num = 2; if (page[2]) num = 3; if (page[3]) num = 4; return num; } // Add jmj -> private SequenceActionResult CheckPageNo(SequenceContext context, string id, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL); #region ex //UpdatePLCMemoryArea_test(); //int nRecipeNo = _RecipeManager.ActivatedRecipe().Id; //int recipeRequestId = 18; //if (nRecipeNo != recipeRequestId) //{ // var recipeName = WeldingRecipeManager.SearchRecipeItem(recipeRequestId); // if (recipeName != string.Empty) // { // Application.Current.AuroraEnv().EventPublisher.Publish(new EventMessage(SequenceIds.SeqAutoRunKS_New, "Autorun_Recipe_Change", (recipeRequestId, recipeName))); // Thread.Sleep(500); // } // nRecipeNo = _RecipeManager.ActivatedRecipe().Id; //} #endregion // Cell 이 Load 완료되어서 Scout 가 가능한 상태인지 확인 #region Whie -> PLC_JIG_LOAD_COMPLETE _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_JIG_LOAD_COMPLETE).data) { Log.I(string.Format("Cell Loading is completed.")); break; } _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_JIG_LOAD_COMPLETE"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } #endregion _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_OK, false); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_OK False")); _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, false); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_NG False")); _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { #region PLC 에서 PAGE 정보 가져오기 ( BIT 영역 ) _PageNo = GetPagePlc(); #endregion if (_PageNo != 0) break; _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_PAGENO"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } if (_PageNo != 0) { if (ksExit) { UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG); popup.Hide(); } _BcrID = _PLC.GetBcrCode();// GetBCRID(); Log.I($"Bcr Id : {_BcrID}"); Status.GetProcessingWeldingData().BcrID = _BcrID; // RCC 들어가기전에 1로 바꿔있어야된다... _Scanner.SelectCorrectionTable(1); var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObjects = _ScannerCanvasUserCtrl.Model.Layers[_PageNo - 1].Objects; List tempobject = new List(); int startindex = 0; int nCount = _RecipeDrawObjects.Count; for (int i = startindex; i < _RecipeDrawObjects.Count; i++) { if (i >= startindex + nCount) break; tempobject.Add(_RecipeDrawObjects[i]); } _SelectedDrawObjectList = tempobject; _WeldingScannerListNo = eListNo.LIST1; SetPagePlc(_PageNo); _PageNoRcc = _PageNo - 1; var activatedRecipeId = Application.Current.AuroraEnv().RecipeManager.ActivatedRecipe().Id; var recipeName = WeldingRecipeManager.SearchRecipeItem(activatedRecipeId); Status.GetProcessingWeldingData().ActRecipe = recipeName; Status.GetProcessingWeldingData().PageNO = (_PageNoRcc + 1).ToString(); //Status.GetProcessingWeldingData().BcrID = "PRD-9X7K2M5Q8T1Z4L6R3W0VYCNJHBDGFZ"; Status.GetProcessingWeldingData().BcrID = _BcrID; } return SequenceAction.Ok(); } // 지그 상태 확인 private string CheckLoadComplete(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL); TimeSpan spanTime; DateTime startTime = DateTime.Now; if (RecipeChange) { return SEQ_KS_WAIT_VISION; } else { if (_SystemParameter.SequenceType == eSequenceType.Normal) { // CorrectionTable ==> 2 return SEQ_READY_SCANNER_LIST; } else { _CamConfig = Application.Current.AuroraEnv().DeviceManager.GetDeviceConfig(eCamId.CAM1.ToString()) as CamConfig; // RCC, CellCenterOffset // RCC의 경우 LoadCompleteCheck 전 Scout 첫번째 위치로 스캐너 이동 해놓는게 시간을 벌듯.. // CellCenterOffset은 중심위치에서 그랩하니깐 해당 기능 필요없을 것이라 우선 여기서 if문 처리하자 // 즉 정리하면, RCC 만 이동하고, CellCenterOffset은 이동 하지 않음. if (_SystemParameter.SequenceType == eSequenceType.RCC) { int scoutNo = 0; if (_CamConfig.ChildImage.ChildBufRowCols[scoutNo].Enabled) { double XPos = _CamConfig.ChildImage.ChildBufRowCols[scoutNo].MotorPos.X + _CamConfig.ChildImage.ChildBufRowCols[scoutNo].MotorPosOffset.X; //카메라 위치에 대한 보정값 입력 double YPos = _CamConfig.ChildImage.ChildBufRowCols[scoutNo].MotorPos.Y + _CamConfig.ChildImage.ChildBufRowCols[scoutNo].MotorPosOffset.Y; //카메라 위치에 대한 보정값 입력 Log.I(string.Format($"Move No.{scoutNo + 1} Field Scan Pos(X,Y:{XPos},{YPos})")); //1.스캐너 필드 위치 이동(Jump) _Scanner.JumpAbs(XPos, YPos, eFunctionType.COMMAND); } return SEQ_SET_SCOUT_FLYING_VISION_SEQ; } return SEQ_READY_SCANNER_LIST; } } } 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(); } public MIL_ID DoGrab() { var image = (object)_GrabImage; _CameraAgent.GrabSync(_CameraDisplay, ref image); _GrabImage = (MIL_ID)image; return _GrabImage; } // RCC FlyingVision #region RCC FlyingVision private SequenceActionResult SetScoutFlyingVision_SeqParams(SequenceContext context, string id, SequenceActionResult param) { Log.I($"AutoRun Seq Run Count : {_SeqRunCount}"); var scoutSeqParams = new ScoutSeqParams(VisionRecipeManager.GetFovInfos()[0], eDisplayType.Machine_B); SeqScoutFlyingVision_InitParam seqParams = new SeqScoutFlyingVision_InitParam() { IsRealTimeScout = _IsRealTimeScout, ScoutSeqParams = scoutSeqParams, SequenceAutoRunCount = _SeqRunCount, WeldingScannerListNo = eListNo.LIST2, }; return SequenceAction.Ok(seqParams); } //private string GetScoutFlyingVision_SeqResult(SequenceContext context, string id, ICollection branches, SequenceActionResult param) //{ // var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam; // if (pre_welding) // { // pre_welding = !pre_welding; // return SEQ_BEFORE_WELD_MOVE_OBJECT; // } // else // { // pre_welding = !pre_welding; // return SEQ_AFTER_WELD_CHECK_BEAD; // } // if (resultOutParam.Success == false) // { // return null; // } //} private SequenceActionResult GetScoutFlyingVision_SeqResult(SequenceContext context, string id, SequenceActionResult param) { var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam; return SequenceAction.Ok(); //if (pre_welding) //{ // pre_welding = !pre_welding; // return SEQ_BEFORE_WELD_MOVE_OBJECT; //} //else //{ // pre_welding = !pre_welding; // return SEQ_AFTER_WELD_CHECK_BEAD; //} if (resultOutParam.Success == false) { return null; } } #endregion // RCC Normal Vision #region RCC Normal Vision private SequenceActionResult SetScoutNORMALVision_SeqParams(SequenceContext context, string id, SequenceActionResult param) { Log.I($"AutoRun Seq Run Count : {_SeqRunCount}"); var scoutSeqParams = new ScoutSeqParams(VisionRecipeManager.GetFovInfos()[0], eDisplayType.Machine_B); SeqScoutFlyingVision_InitParam seqParams = new SeqScoutFlyingVision_InitParam() { IsRealTimeScout = _IsRealTimeScout, ScoutSeqParams = scoutSeqParams, SequenceAutoRunCount = _SeqRunCount, WeldingScannerListNo = eListNo.LIST2, }; return SequenceAction.Ok(seqParams); } private SequenceActionResult GetScoutNORMALVision_SeqResult(SequenceContext context, string id, SequenceActionResult param) { var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam; if (resultOutParam.Success == false) { return null; } return SequenceAction.Ok(); } #endregion // For RCC Only private SequenceActionResult SaveScoutImageEvent(SequenceContext context, string id, SequenceActionResult param) { MIL_ID ScannerFieldImage = Status.GetProcessingWeldingData().ScannerFiledImage; if (ScannerFieldImage != null) { SaveScoutImage(ScannerFieldImage); } else { Log.E("ScannerFieldImage is Null"); } return SequenceAction.Ok(); } private object SendEvent(SequenceContext context, string id, SequenceActionResult param) { //Event로 넘겨줄 Param은 따로 없다. return null; } private SequenceActionResult FindEdge(SequenceContext context, string id, SequenceActionResult param) { MIL_ID ScannerFieldImage = Status.GetProcessingWeldingData().ScannerFiledImage; //RCC Error로 인해 시퀀스를 종료하고 있는데, NG배출해야 될지 확인 필요 _StopwatchGenObj = Stopwatch.StartNew(); #region Find Edge _ObjGenerator.ConvertMILToMat(ScannerFieldImage, out _ConvMatImage); if (_ConvMatImage == null) { Log.E(string.Format("[GenerateWeldingObject] Scout Image is empty. Check Camera or Cell.")); return null; } var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvMatImage); if (_ObjGenerator.FindEdge(_ConvMatImage, _Radius_Pixel, _SystemParameter.Margin, _SystemParameter.PointNum, _SystemParameter.CVThreshold, centerX, centerY, _SystemParameter.DetectPointPercent, _SystemParameter.CVJigSize, out Point[][] maxContour, out _DetectedContourCenter) == false) { Log.E(string.Format("[GenerateWeldingObject] Edge Detection Interlock.")); return null; } if (maxContour[0].Count() < 1 || maxContour == null) { Log.E(string.Format("[GenerateWeldingObject] MaxContour is Null. Check Scout Image.")); return null; } context.PutValue("MAX_CONTOUR_FIND_EDGE", maxContour); _StopwatchGenObj.Stop(); Log.I(string.Format($"[GenerateWeldingObject] Find Edge Complete Time : {_StopwatchGenObj.ElapsedMilliseconds} msec")); #endregion return SequenceAction.Ok(); } private (int centerX, int centerY) FindCenterReicpeSingleArc(Mat image) { int centerX = 0, centerY = 0; foreach (var item in _RecipeDrawObjects) { if (item is Arc) { Arc arc = (Arc)item; centerX = (int)(arc.Center.X * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Width / 2); centerY = (int)(-arc.Center.Y * 1000.0 / _SystemParameter.CameraPixelSize * _SystemParameter.LensMagnification + image.Height / 2); break; } } return (centerX, centerY); } private string DecisionRCCAlgorithmType(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { // FindEdge의 maxContour를 param으로 받아오기 Point[][] maxContour = context.GetValue("MAX_CONTOUR_FIND_EDGE"); // CheckEdge의 Return 결과를 param 으로 받아와서 현재 노드에서 4가지 경우로 분류하자 var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvMatImage); int[] shrinkList = new int[] { _SystemParameter.CVShrinkPixel, _SystemParameter.CVShrinkPixel2, _SystemParameter.CVShrinkPixel3, _SystemParameter.CVShrinkPixel4 }; int resultCheckEdge = _ObjGenerator.CheckEdge(maxContour, shrinkList, _ConvMatImage.Height, _ConvMatImage.Width, centerX, centerY, _SystemParameter.EnableAutoMissAlign, out _MaxContour); if (resultCheckEdge == 3) { Log.E("Error Check Edge. Check EdgeDetect Center or Over LocalMaxMinDiff Upper"); return null; } if (_SystemParameter.RCCAlgorithmType == eRCCAlgorithmType.OnlyGenObject) { return SEQ_GENERATE_WELDING_OBJECT; } else if (_SystemParameter.RCCAlgorithmType == eRCCAlgorithmType.OnlyOffsetObject) { return SEQ_APPLY_OFFSET_OBJECT; } else { if (resultCheckEdge == 0) { return SEQ_READY_SCANNER_LIST; } else if (resultCheckEdge == 1) { return SEQ_APPLY_OFFSET_OBJECT; } else if (resultCheckEdge == 2) { return SEQ_GENERATE_WELDING_OBJECT; } else { Log.E("Error Check Edge. Check EdgeDetect Center or Over LocalMaxMinDiff Upper"); return null; } } } private SequenceActionResult ApplyOffsetObejct(SequenceContext context, string id, SequenceActionResult param) { var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvMatImage); // Recipe 객체는 그대로 사용하고 CetnerOffset 값을 SeqUploadWeldingList에서 사용할 수 있도록 넣어준다 double centerOffsetX = _DetectedContourCenter.X - centerX; double centerOffsetY = _DetectedContourCenter.Y - centerY; _CellMeasureCenterOffsetX = centerOffsetX; _CellMeasureCenterOffsetY = centerOffsetY; Log.I(string.Format($"Object CenterOffsetX : {centerOffsetX}, CenterOffsetY : {centerOffsetY}")); return SequenceAction.Ok(); } private SequenceActionResult GenerateWeldingObject(SequenceContext context, string id, SequenceActionResult param) { #region Generate Object _StopwatchGenObj.Restart(); _ObjGenerator.SetPolygonFromList(_MaxContour, out _Polygon); if (_SystemParameter.ObjectGenType == eObjectGenType.FitArcsAndLines) { _ObjGenerator.CalculateAutoPath(_ConvMatImage, _SelectedArcs[0], _Polygon, _SystemParameter.dMergeDist, _SystemParameter.nMaxArcRadius, _SystemParameter.nLineTolerance, _SystemParameter.nArcTolerance, _DetectedContourCenter, out _Paths); } else { _ObjGenerator.CalculateAutoPathAngle(_ConvMatImage, _SelectedArcs[0], _Polygon, _SystemParameter.dMergeDist, _SystemParameter.ObjectNumber, _DetectedContourCenter, out _Paths); } //Generate 한 object 를 SelectedDrawObjects 에 넣어두고 쓴다. _ObjGenerator.ConvertPathItemToDrawingObjects(_Paths, _SystemParameter.fLineDefualtWidth, _ConvMatImage, _SelectedArcs[0], out _GeneratedDrawObjects); //objGenerator.SaveDrawingObjectsToCSV(GeneratedDrawObjects, "SeqAutoRunKS_RCC_before"); if (_ObjGenerator.CheckInterlockDrawingObjectPosition(_GeneratedDrawObjects, _DetectedContourCenter, _SelectedArcs[0]) == false) { Log.E(string.Format("[GenerateWeldingObject]Interlock DrawingObject.")); return null; } List tempobject = new List(); int startindex = 0; int nCount = _RecipeDrawObjects.Count; for (int i = startindex; i < _RecipeDrawObjects.Count; i++) { if (i >= startindex + nCount) break; tempobject.Add(_RecipeDrawObjects[i]); } _SelectedDrawObjectList = tempobject; //현재 Recipe의 Arc객체를 RCC로 생성된 객체로 대체하면서 Group화 해준다 _ObjGenerator.ReplaceRCCObject(eArcCount.FirstArc, _SelectedDrawObjectList, _GeneratedDrawObjects, _DetectedContourCenter); _ObjGenerator.SaveDrawingObjectsToCSV(_GeneratedDrawObjects, "SeqAutoRunKS_RCC"); _StopwatchGenObj.Stop(); Log.I(string.Format($"[GenerateWeldingObject] Generate Object Complete Time : {_StopwatchGenObj.ElapsedMilliseconds} msec")); #endregion return SequenceAction.Ok(); } private SequenceActionResult ReadyScannerList(SequenceContext context, string id, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.UPLOADING_WELD_LIST); return SequenceAction.Ok(); } private SequenceActionResult SetUploadWeldingList_SeqParams(SequenceContext context, string id, SequenceActionResult param) { Log.I("SeqDryRun SetUploadWeldingList_SeqParams"); SeqUploadWeldingList_InitParam seqParams = new SeqUploadWeldingList_InitParam() { NeedSetLaserTiming = false, IncludeListStartEnd = true, CellMeasureCenterOffsetX = _CellMeasureCenterOffsetX, CellMeasureCenterOffsetY = _CellMeasureCenterOffsetY, SelectedDrawObjectList = _SelectedDrawObjectList, WeldingScannerListNo = _WeldingScannerListNo, }; return SequenceAction.Ok(seqParams); } private SequenceActionResult GetUploadWeldingList_SeqResult(SequenceContext context, string id, SequenceActionResult param) { var resultOutParam = param.Param as SeqUploadWeldingList_OutParam; if (resultOutParam.Success == false) { AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_UploadWeldingList_ResultFailed); return null; } return SequenceAction.Ok(); } private SequenceActionResult WaitWeldingStart(SequenceContext context, string id, SequenceActionResult param) { _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY True")); Thread.Sleep(500); #region PLC_WELD_REQEUST 채크로직 _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_WELD_REQEUST).data) { Log.I(string.Format($"[PLCInterface]GET PLC_WELD_REQEUST True")); _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_REQEUST_ACK True")); break; } _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_WELD_REQEUST"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } #endregion return SequenceAction.Ok(); } private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD); // Laser Correction 파일로 변경, 레이저를 사용해야 하므로 2 _Scanner.SelectCorrectionTable(2); _CellId = Status.GetProcessingWeldingData().BcrID; _LotId = Status.GetProcessingWeldingData().WorkLotId; int recipeNo = _RecipeManager.ActivatedRecipe().Id; _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), true); //int sendresult = _LBAD.SendCellData(_LotId, _CellId, recipeNo, _ModelNo); if (_BcrID.Contains("")) { DateTime T1 = DateTime.Now; string s1 = T1.ToString("yyyyMMdd"); string s2 = _LotId; string s3 = recipeNo.ToString(); string s4 = _ModelNo.ToString(); string LBADSendBcrId = _BcrID; if (LBADSendBcrId == "" || LBADSendBcrId.Equals(null)) LBADSendBcrId = T1.ToString("HHmmss"); // 바코드가 안 읽히면 임의 값 보내기 int sendresult = _LBAD.SendCellData("LBM" + s1, LBADSendBcrId, recipeNo, _ModelNo); Log.I(string.Format($"SendCellData result :{sendresult}")); } else { DateTime T1 = DateTime.Now; string s1 = T1.ToString("yyyyMMdd"); string LBADSendBcrId = _BcrID; if (LBADSendBcrId == "" || LBADSendBcrId.Equals(null)) LBADSendBcrId = T1.ToString("HHmmss"); // PLC 에 바코드 값이 있으면 int sendresult = _LBAD.SendCellData("LBM" + s1, LBADSendBcrId, recipeNo, _ModelNo); Log.I(string.Format($"SendCellData result :{sendresult}")); } _WeldingStartTime = DateTime.Now; Status.GetProcessingWeldingData().WeldStartTime = _WeldingStartTime.ToString("yyyyMMddHHmmss"); recipeRequestId = (short)_PLC.ReadDWord((int)eWordOutput.PC_RECIPE_NO, isInput:false).data; Log.I(string.Format($"PLC recipe NO {recipeRequestId}")); if (recipeRequestId == 21) { Log.I(string.Format($"TEST!! Welding : ExecuteList_{_WeldingScannerListNo}")); } else { _Scanner.ExecuteList(_WeldingScannerListNo); Log.I(string.Format($"START Welding : ExecuteList_{_WeldingScannerListNo}")); } //WaitForListTaskCompleted 함수에서 List 완료 여부를 Check함, List실행이 끝나면 while문을 빠져나옴 _Scanner.WaitForListTaskCompleted(_SystemParameter.WeldLinesTaskTimeOut, context); _WeldEndTime = DateTime.Now; _WeldingSpanTime = DateTime.Now.Subtract(_WeldingStartTime); Log.I(string.Format($"Welding Complete Time : {_WeldingSpanTime.TotalMilliseconds} msec")); Status.GetProcessingWeldingData().WeldTime = _WeldingSpanTime.TotalSeconds.ToString(); double dExecuteListTime = _Scanner.GetTime(); Log.I(string.Format($"ExecuteList Time : {dExecuteListTime * 1000} msec")); _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_REQEUST_ACK False")); _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY False")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false); Log.I(string.Format($"[IOInterface]SET PCWeldingTrigger false")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), true); Log.I(string.Format($"[IOInterface]{_PageNo} setp --> SET PCWeldingStop true")); return SequenceAction.Ok(); } private SequenceActionResult RequestUnloadCell(SequenceContext context, string id, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL); // PC → PLC , Unload Cell Request _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, true); Log.I(string.Format($"[PLCInterface]SET PC_WELD_COMPLETE True")); _InterfaceStartTime = DateTime.Now; while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_WELD_COMPLETE_ACK).data) { Log.I(string.Format($"[PLCInterface]GET PLC_WELD_COMPLETE_ACK True")); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false); Log.I(string.Format($"[PLCInterface]SET PC_WELD_COMPLETE False")); break; } _InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime); if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) { Log.E("TIMEOUT_PLC_WELD_COMPLETE_ACK"); _InterfaceStartTime = DateTime.Now; } Thread.Sleep(10); } UpdateProductCount(context); UpdateProductInfoForView(); return SequenceAction.Ok(); } private SequenceActionResult WaitLBADJudge(SequenceContext context, string id, SequenceActionResult param) { // 1. LBAD 결과 수신, 확인 & 처리 //LBAD 결과 받아오는 부분 우선 여기서 추가하여 테스트하고 Sub 시퀀스로 빼자 if (_LBAD.IsSimul) { _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); Log.I(string.Format($"[IOInterface]SET PCLBADWeldingStop false, LBAD is Simul")); } else { } return SequenceAction.Ok(); } /// /// 소수점 3제자리 까지 int 반환 /// /// /// 소수점 3제자리까지만 int 변환 public static int ToIntThousand(double value) { decimal decValue = (decimal)value; //return (int)Math.Round(decValue * 100m, MidpointRounding.AwayFromZero); return (int)Math.Round(decValue * 100m); } public static short[] IntArrayToCatShortArray(int[] intArray) { short[] shortArray = new short[intArray.Length]; for (int i = 0; i < intArray.Length; i++) { shortArray[i] = (short)intArray[i]; } return shortArray; } private SequenceActionResult ReportCellInfoToPLC(SequenceContext context, string id, SequenceActionResult param) { return SequenceAction.Ok(); } private void UpdatePLCMemoryAreaCls(int startAddress, int endAddress) { int start = 0; int entcount = (endAddress - startAddress) + 1; for (int i = 0; i < entcount; i++) { start = startAddress + i; _PLC.WriteWord(start, 0); Log.I(string.Format("[PLCInterface]SET {0:X4} -> {1:X4}", 0x2500 + start, 0)); //Log.I(string.Format("[PLCInterface]SET {0:X4} -> {1:X4}", startAddress + i, 0)); Thread.Sleep(2); } } private void UpdatePLCMemoryArea(int startAddress, List result_info) { //Log.I($"[INFO] UpdatePLCMemoryArea : {string.Join(", ", result_info)} \n Count : {result_info.Count}"); Log.I(string.Format("[PLCInterface]Start Plc Write ...... Map W{0:X4}", 0x2500 + startAddress)); List resultList = new List(); foreach (double info in result_info) { resultList.Add(ToIntThousand(info)); } short[] resultShort = IntArrayToCatShortArray(resultList.ToArray()); //Log.I($"[PLCInterface]SET resultShort: " + string.Join(", ", resultShort)); int start = 0; for (int i = 0; i < resultShort.Length; i++) { start = startAddress + i; _PLC.WriteWord(start, resultShort[i]); Log.I(string.Format("[PLCInterface]SET {0:X4} -> {1:X4} : {2}", 0x2500 + start, resultShort[i], resultShort[i])); Thread.Sleep(2); } Log.I(string.Format("[PLCInterface]End Plc Write ...... Map W{0:X4} / Lenght {1}", 0x2500 + start, resultShort.Length)); } private void UpdatePLCMemoryAreaRecipe(int startAddress, List result_info) { //Log.I($"[INFO] UpdatePLCMemoryArea : {string.Join(", ", result_info)} \n Count : {result_info.Count}"); short[] info = result_info.ToArray(); Log.I(string.Format("[PLCInterface]Start Plc Write ...... Map {0:X4}", 0x2500 + startAddress)); int start = 0; for (int i = 0; i < info.Length; i++) { start = startAddress + i; _PLC.WriteWord(start, info[i]); Log.I(string.Format("[PLCInterface]SET {0:X4} -> {1:X4} : {2}", 0x2500 + start, info[i], info[i])); Thread.Sleep(2); } Log.I(string.Format("[PLCInterface]End Plc Write ...... Map {0:X4} / Lenght {1}", 0x2500 + start, info.Length)); } public List Get_Recipe_Info() { var mainPage = WeldingRecipeManager.GetWeldingPage(); _ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching; _RecipeDrawObjects = _ScannerCanvasUserCtrl.Model.Layers[0].Objects; var activatedRecipeId = Application.Current.AuroraEnv().RecipeManager.ActivatedRecipe().Id; var scannerObjects = new List(); for (int i = 0; i < _ScannerCanvasUserCtrl.Model.Layers.Length; i++) { foreach (var item in _ScannerCanvasUserCtrl.Model.Layers[i].Objects) { ScannerParam param = null; if (item is Arc arc) { param = ScannerCanvasUserCtrl.ScannerParams[arc.ScannerParamNo]; if (param != null) arcinfo = (new ScannerObjectInfo { Object = arc, LaserPower1 = param.LaserPower1, LaserPower2 = param.LaserPower2, JumpSpeed = param.JumpSpeed, MarkSpeed = param.MarkSpeed }); } else if (item is Line line) { param = ScannerCanvasUserCtrl.ScannerParams[line.ScannerParamNo]; if (param != null) lineinfo = new ScannerObjectInfo { Object = line, LaserPower1 = param.LaserPower1, LaserPower2 = param.LaserPower2, JumpSpeed = param.JumpSpeed, MarkSpeed = param.MarkSpeed }; } else if (item is Spline spline) { param = ScannerCanvasUserCtrl.ScannerParams[spline.ScannerParamNo]; if (param != null) splineinfo = new ScannerObjectInfo { Object = spline, LaserPower1 = param.LaserPower1, LaserPower2 = param.LaserPower2, JumpSpeed = param.JumpSpeed, MarkSpeed = param.MarkSpeed }; } else if (item is Dot dot) { param = ScannerCanvasUserCtrl.ScannerParams[dot.ScannerParamNo]; if (param != null) dotinfo = new ScannerObjectInfo { Object = dot, LaserPower1 = param.LaserPower1, LaserPower2 = param.LaserPower2, JumpSpeed = param.JumpSpeed, MarkSpeed = param.MarkSpeed }; } } } List Recipe = new List(); Recipe.Add((short)lineinfo.LaserPower1); Recipe.Add((short)lineinfo.LaserPower2); Recipe.Add((short)lineinfo.MarkSpeed); Recipe.Add((short)arcinfo.LaserPower1); Recipe.Add((short)arcinfo.LaserPower2); Recipe.Add((short)arcinfo.MarkSpeed); Recipe.Add((short)splineinfo.LaserPower1); Recipe.Add((short)splineinfo.LaserPower2); Recipe.Add((short)splineinfo.MarkSpeed); return Recipe; } //private void WeldingInfoSendPLC(List recipe, string LBAD, string WELDING) //{ // // PLC 영역쓰기 : 0 // if (result_info[0].Count == 24) // { // UpdatePLCMemoryArea((int)eWordOutput.STEP1_Arc1_LowerLimit, result_info[0]); // Ring : 24 // } // else // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[0])} \n Count : {result_info[0].Count}"); // } // // PLC 영역쓰기 : 1 // if (result_info[1].Count == 21) // { // UpdatePLCMemoryArea((int)eWordOutput.STEP2_Spiral1_HorizontalLowerLimit, result_info[1]); // Spiral : 21 // } // else // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[1])} \n Count : {result_info[1].Count}"); // } // // PLC 영역쓰기 : 2 // if (result_info[2].Count == 24) // { // UpdatePLCMemoryArea((int)eWordOutput.STEP3_Arc1_LowerLimit, result_info[2]); // Ring : 24 // } // else // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[2])} \n Count : {result_info[2].Count}"); // } // // PLC 영역쓰기 : 3 // if (result_info[3].Count == 21) // { // UpdatePLCMemoryArea((int)eWordOutput.STEP4_Spiral1_HorizontalLowerLimit, result_info[3]); // Spiral : 21 // } // else // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[3])} \n Count : {result_info[3].Count}"); // } // UpdatePLCMemoryAreaRecipe((int)eWordOutput.Line_LaserPower1, recipe); // // LBAD 검사 결과 확인 // if (string.Equals(LBAD, "OK")) // { // _PLC.WriteWord((int)eWordOutput.LBADOK_NG, 100); // } // else // { // _PLC.WriteWord((int)eWordOutput.LBADOK_NG, 200); // } // // 용접후 검사 결과 확인 // if (string.Equals(WELDING, "OK")) // { // _PLC.WriteWord((int)eWordOutput.WeldingOK_NG, 100); // } // else // { // _PLC.WriteWord((int)eWordOutput.WeldingOK_NG, 200); // } //} private void WeldingInfoSendPLC(List recipe, string LBAD, string WELDING) { // PLC 영역쓰기 : 0 if (result_info[0].Count == 42) { UpdatePLCMemoryArea((int)eWordOutput.STEP1_Arc1_LowerLimit, result_info[0]); // Ring : 24 -> 36 -> 42 } else { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[0])} \n Count : {result_info[0].Count}"); } // PLC 영역쓰기 : 1 if (result_info[1].Count == 21) { UpdatePLCMemoryArea((int)eWordOutput.STEP2_Spiral1_HorizontalLowerLimit, result_info[1]); // Spiral : 21 } else { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[1])} \n Count : {result_info[1].Count}"); } // PLC 영역쓰기 : 2 if (result_info[2].Count == 42) { UpdatePLCMemoryArea((int)eWordOutput.STEP3_Arc1_LowerLimit, result_info[2]); // Ring : 24 -> 36 -> 42 } else { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[2])} \n Count : {result_info[2].Count}"); } // PLC 영역쓰기 : 3 if (result_info[3].Count == 21) { UpdatePLCMemoryArea((int)eWordOutput.STEP4_Spiral1_HorizontalLowerLimit, result_info[3]); // Spiral : 21 } else { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", result_info[3])} \n Count : {result_info[3].Count}"); } UpdatePLCMemoryAreaRecipe((int)eWordOutput.Line_LaserPower1, recipe); Log.I($"Channel 0: {ResultDataList[0]}, Channel 1: {ResultDataList[1]}, Channel 2: {ResultDataList[2]}, Channel 3: {ResultDataList[3]}"); _PLC.WriteDWord((int)eWordOutput.LBAD_Total_Power_Average_H, ResultDataList[0]); _PLC.WriteDWord((int)eWordOutput.LBAD_Total_Power_Max_H, ResultDataList[1]); _PLC.WriteDWord((int)eWordOutput.LBAD_Total_Power_Min_H, ResultDataList[2]); // LBAD 검사 결과 확인 if (string.Equals(LBAD, "OK")) { _PLC.WriteWord((int)eWordOutput.LBADOK_NG, 100); } else { _PLC.WriteWord((int)eWordOutput.LBADOK_NG, 200); } // 용접후 검사 결과 확인 if (string.Equals(WELDING, "OK")) { _PLC.WriteWord((int)eWordOutput.WeldingOK_NG, 100); } else { _PLC.WriteWord((int)eWordOutput.WeldingOK_NG, 200); } } private void SaveExcelFile(Mat img, string ExcelFile) { //string ImgFile = string.Format("D:\\ILSOSConfig\\_vision\\Def\\1.png"); //Mat img = Cv2.ImRead(ImgFile); //string ExcelFile = string.Format("D:\\ILSOSConfig\\_vision\\Def\\Test.xlsx"); var inserter = new ExcelImageInserter(ExcelFile); var entry = new ExcelEntry { Name = "그림1", Image = img, ParametersSets = new List> { new List { "파라A", "파라B" }, // 1행 new List { "뉴욕A", "뉴욕B" } // 2행 }, Content = "추가 내용" }; inserter.AddEntry(entry, "MySheet", widthCm: 8, heightCm: 8); inserter.Save(); } public bool StepWELDING_Get() { bool WELDING = false; List _weding = new List(); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring1_BeadWidthOK_NG]); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring2_BeadWidthOK_NG]); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring3_BeadWidthOK_NG]); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring4_BeadWidthOK_NG]); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring5_BeadWidthOK_NG]); _weding.Add((int)result_info[0][(int)EWeldingStepRing.Ring6_BeadWidthOK_NG]); _weding.Add((int)result_info[1][(int)EWeldingStepSpiral.Spiral1_BeadWidthOK_NG]); _weding.Add((int)result_info[1][(int)EWeldingStepSpiral.Spiral2_BeadWidthOK_NG]); _weding.Add((int)result_info[1][(int)EWeldingStepSpiral.Spiral3_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring1_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring2_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring3_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring4_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring5_BeadWidthOK_NG]); _weding.Add((int)result_info[2][(int)EWeldingStepRing.Ring6_BeadWidthOK_NG]); _weding.Add((int)result_info[3][(int)EWeldingStepSpiral.Spiral1_BeadWidthOK_NG]); _weding.Add((int)result_info[3][(int)EWeldingStepSpiral.Spiral2_BeadWidthOK_NG]); _weding.Add((int)result_info[3][(int)EWeldingStepSpiral.Spiral3_BeadWidthOK_NG]); for (int i = 0; i < _weding.Count; i++) { // NG 일경우 if (_weding[i] == 2) { return false; } } return true; } private void SaveFile(string Dir, List res, string num) { string fullPath = Path.Combine(Dir, $"{DateTime.Now.ToString("HHmmss")}_{num}.txt"); string fileName = System.IO.Path.GetFileName(fullPath); string directory = Path.GetDirectoryName(fullPath); // 디렉토리 존재 여부 확인 후 없으면 생성 if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } // using으로 StreamWriter 사용 using (StreamWriter writer = new StreamWriter(fullPath)) { writer.WriteLine(string.Join(", ",res)); } Log.I(string.Format($"{num} -> {fileName}")); } private void SaveWImage(string Dir, Mat img, string num) { string fullPath = Path.Combine(Dir, $"{ DateTime.Now.ToString("HHmmss")}_{ num}.PNG"); string fileName = System.IO.Path.GetFileName(fullPath); string dirPath = Path.GetDirectoryName(fullPath); if (!string.IsNullOrEmpty(dirPath)) { Directory.CreateDirectory(dirPath); } Cv2.ImWrite(fullPath, img); Log.I(string.Format($"{num} -> {fileName}")); } //private string CheckCycleStop(SequenceContext context, string id, ICollection branches, SequenceActionResult param) //{ // Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE); // string strLBADJudge = Status.GetProcessingWeldingData().LBAD_Judge; // Int16 judgeFlag = 0; // string judgeResult = ""; // DateTime timeoutTime = new DateTime(); // bool WeldingEnd = false; // int count = 0; // _WeldingImage[_PageNoRcc] = new Mat(); // _WeldingImage[_PageNoRcc] = _ConvMatImage_after; // result_info[_PageNoRcc] = new List(); // result_info[_PageNoRcc] = bead_result_info; // switch (_PageNoRcc) // { // case 0: if (bead_result_info.Count != 24) // 변경 -> 36 // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); // } // break; // case 1: if (bead_result_info.Count != 21) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; // case 2: if (bead_result_info.Count != 24) // 변경 -> 36 // { // Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); // } // break; // case 3: if (bead_result_info.Count != 21) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; // } // Log.I($"[INFO] bead_result_info: {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); // while (!context.Stopped) // { // // 다음 페이지용 PLC 읽기 // _PageNo = GetPagePlc(); // //Log.I(string.Format($"[PLCInterface]GET PLC_SET_WELD_PAGE {0}", _PageNo)); // // PLC 에 페이지 써줘야 넘어간다. // SetPagePlc(_PageNo); // // 다음 시퀀스 대기.. // Thread.Sleep(100); // if (_PLC.ReadBit((int)eBitInput.PLC_WELD_REQEUST).data) // { // Log.I(string.Format($"[IOInterface]Get PLC_WELD_REQEUST True")); // _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); // Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false")); // bool[] Page = new bool[4]; // Page = new bool[4] { false, false, false, false }; // _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); // recipeRequestId = (short)_PLC.ReadDWord((int)eWordOutput.PC_RECIPE_NO, isInput: false).data; // Log.I(string.Format($"PLC recipe NO {recipeRequestId}")); // if(recipeRequestId == 21) // { // if (_PageNoRcc == 3) // { // WeldingEnd = true; // StepLBAD = "OK"; // break; // } // else // { // Log.I(string.Format($"STEP{_PageNoRcc} / Again : CheckCycleStop -> SEQ_CHECK_PAGENO")); // ksExit = false; // WeldingEnd = false; // return SEQ_CHECK_PAGENO; // } // } // else // { // Log.I(string.Format($"STEP{_PageNoRcc} / Again : CheckCycleStop -> SEQ_CHECK_PAGENO")); // ksExit = false; // WeldingEnd = false; // return SEQ_CHECK_PAGENO; // } // } // else // { // if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) // { // Log.I(string.Format($"[IOInterface]Get PLC_RESULT_REQUEST True")); // WeldingEnd = true; // _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); // Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false")); // DateTime startTime = DateTime.Now; // TimeSpan timeoutDuration = TimeSpan.FromSeconds(5); // while (!context.Stopped) // { // if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADJudgementComplete))) // { // Log.I(string.Format($"[IOInterface]SET LBADJudgementComplete true")); // int result = _LBAD.GetResult(out judgeFlag); // List ResultList; // int result1 = _LBAD.GetResultDataList(out ResultList); // if (result == E1.OK) // { // switch (judgeFlag) // { // case 0: // judgeResult = "OK"; // break; // case 1: // judgeResult = "WARNING"; // break; // case 2: // judgeResult = "NA"; // break; // case 3: // judgeResult = "NG"; // break; // case 4: // judgeResult = "ERROR"; // break; // default: // judgeResult = "NG"; // break; // } // } // else // { // // TODO: LBAD 가 not Activated 인 상황이다. error 로 보내야 할꺼 같음. // judgeFlag = 3; // judgeResult = "NG"; // } // // 경신 페이지 추가하여 검사 내용 추가 // //LBADResultPage[_PageNo - 1] = judgeFlag; // Log.I(string.Format($"LBAD Judge Flag [kS] : {judgeFlag} PageResult : {judgeResult}")); // _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), true); // Status.GetProcessingWeldingData().LBAD_Judge = (judgeFlag + 1).ToString(); // Log.I(string.Format($"[IOInterface]SET PCJudgementCompleteAck true")); // break; // } // Log.I(string.Format($"---> LBAD Sleep..... {count}")); // DateTime tto = startTime + timeoutDuration; // if (count >= 300) // { // count = 0; // Log.I(string.Format($"---> LBAD Sleep..... {count} Break !!!!")); // judgeFlag = 3; // judgeResult = "NG"; // break; // } // count++; // Thread.Sleep(100); // } // _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false); // Log.I(string.Format($"[IOInterface]SET PCJudgementCompleteAck false")); // //return SEQ_CHECK_PAGENO; // } // Thread.Sleep(100); // } // if (WeldingEnd) { break; } // } // // if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) // while (!context.Stopped) // { // if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) // { // try // { // popup.Hide(); // Thread.Sleep(100); // } // catch (Exception e) // { // Log.I(string.Format($"Popup Hide ERR !!!!")); // } // // 검사 결화 화면 띠운다.. // popup.Show(); // popup.UpdateImages1(_WeldingImage[0], new OpenCvSharp.Rect(1153, 1296, 7000, 8156)); // // popup.UpdateImages2(_WeldingImage[1], new OpenCvSharp.Rect(1153, 1296, 7000, 8156)); // 6918 // popup.UpdateImages3(_WeldingImage[2], new OpenCvSharp.Rect(1153, 1296, 7000, 8156)); // 6918 // popup.UpdateImages4(_WeldingImage[3], new OpenCvSharp.Rect(1153, 1296, 7000, 8156)); // 6918 // if (result_info[0].Count == 24) popup.SetParameters1(result_info[0]); // if (result_info[1].Count == 21) popup.SetParameters2(result_info[1]); // if (result_info[2].Count == 24) popup.SetParameters3(result_info[2]); // if (result_info[3].Count == 21) popup.SetParameters4(result_info[3]); // switch (judgeFlag) // { // case 0: // popup.SetStepLBAD("OK"); // StepLBAD = "OK"; // break; // case 3: // popup.SetStepLBAD("NG"); // StepLBAD = "NG"; // break; // default: // popup.SetStepLBAD("NG"); // StepLBAD = "NG"; // break; // } // if (StepWELDING_Get()) // { // popup.SetStepWELDING("OK"); // StepWELDING = "OK"; // } // else // { // popup.SetStepWELDING("NG"); // StepWELDING = "NG"; // } // // 레시피 값 가져오기 : 9 + 2 -> 총 11개 // List recipe = Get_Recipe_Info(); // Recipe : 9 // WeldingInfoSendPLC(recipe, StepLBAD, StepWELDING); // if (strLBADJudge == "4" || StepWELDING.Contains("NG")) // { // _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, true); // Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_NG True, LBAD Result : {strLBADJudge}")); // } // else if (strLBADJudge != "4") // { // _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_OK, true); // Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_OK True, LBAD Result : {strLBADJudge}")); // } // bool[] Page = new bool[4]; // Page = new bool[4] { false, false, false, false }; // _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); // string Dir = System.IO.Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "QualityResults", // string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}")); // SaveWImage(Dir, _WeldingImage[0], "Step1"); // SaveWImage(Dir, _WeldingImage[1], "Step2"); // SaveWImage(Dir, _WeldingImage[2], "Step3"); // SaveWImage(Dir, _WeldingImage[3], "Step4"); // KS_WeldingInfo weldingInfo = new KS_WeldingInfo(); // List Info = weldingInfo.MakeData(result_info[0], result_info[1], result_info[2], result_info[3], recipe, "OK", "OK"); // SaveFile(Dir, Info, "result"); // //KS_WeldingInfo weldingInfo = weldingInfo.MakeData() // Log.I(string.Format($"STEP{_PageNoRcc} / End : CheckCycleStop -> SEQ_CHECK_PAGENO")); // ksExit = true; // WeldingEnd = false; // return SEQ_CHECK_PAGENO; // } // Log.I("---> PLC_RESULT_REQUEST W"); // Thread.Sleep(100); // } // return SEQ_CHECK_PAGENO; //} private string CheckCycleStop(SequenceContext context, string id, ICollection branches, SequenceActionResult param) { Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE); string strLBADJudge = Status.GetProcessingWeldingData().LBAD_Judge; Int16 judgeFlag = 0; string judgeResult = ""; DateTime timeoutTime = new DateTime(); bool WeldingEnd = false; int count = 0; _WeldingImage[_PageNoRcc] = new Mat(); _WeldingImage[_PageNoRcc] = _ConvMatImage_after; result_info[_PageNoRcc] = new List(); result_info[_PageNoRcc] = bead_result_info; switch (_PageNoRcc) { case 0: if (bead_result_info.Count != 42) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; case 1: if (bead_result_info.Count != 21) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; case 2: if (bead_result_info.Count != 42) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; case 3: if (bead_result_info.Count != 21) { Log.I($"[INFO] WeldingInfoSendPLC: Err -> {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); } break; } Log.I($"[INFO] bead_result_info: {string.Join(", ", bead_result_info)} \n Count : {bead_result_info.Count}"); while (!context.Stopped) { // 다음 페이지용 PLC 읽기 _PageNo = GetPagePlc(); //Log.I(string.Format($"[PLCInterface]GET PLC_SET_WELD_PAGE {0}", _PageNo)); // PLC 에 페이지 써줘야 넘어간다. SetPagePlc(_PageNo); // 다음 시퀀스 대기.. Thread.Sleep(100); if (_PLC.ReadBit((int)eBitInput.PLC_WELD_REQEUST).data) { Log.I(string.Format($"[IOInterface]Get PLC_WELD_REQEUST True")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false")); bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); recipeRequestId = (short)_PLC.ReadDWord((int)eWordOutput.PC_RECIPE_NO, isInput: false).data; Log.I(string.Format($"PLC recipe NO {recipeRequestId}")); if (recipeRequestId == 21) { if (_PageNoRcc == 3) { WeldingEnd = true; StepLBAD = "OK"; break; } else { Log.I(string.Format($"STEP{_PageNoRcc} / Again : CheckCycleStop -> SEQ_CHECK_PAGENO")); ksExit = false; WeldingEnd = false; return SEQ_CHECK_PAGENO; } } else { Log.I(string.Format($"STEP{_PageNoRcc} / Again : CheckCycleStop -> SEQ_CHECK_PAGENO")); ksExit = false; WeldingEnd = false; return SEQ_CHECK_PAGENO; } } else { if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) { Log.I(string.Format($"[IOInterface]Get PLC_RESULT_REQUEST True")); WeldingEnd = true; _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false")); DateTime startTime = DateTime.Now; TimeSpan timeoutDuration = TimeSpan.FromSeconds(5); while (!context.Stopped) { if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADJudgementComplete))) { Log.I(string.Format($"[IOInterface]SET LBADJudgementComplete true")); //int result = _LBAD.GetResult(out judgeFlag); //Thread.Sleep(500); List ResultList = new List(); int result = _LBAD.GetResultDataList(out ResultList); Thread.Sleep(20); if (result == E1.OK) { Log.I($"before Clear >> Result Item Count[{ResultList.Count}]"); stReceiveData tt = ResultList.Last(); // fixed double 배열에 접근하기 위해 unsafe 블록 사용 unsafe { int val1 = (int)tt.arrAverage[0]; // input power int val2 = (int)tt.arrMax[0]; int val3 = (int)tt.arrMin[0]; ResultDataList[0] = (int)tt.arrAverage[0]; // input power ResultDataList[1] = (int)tt.arrMax[0]; ResultDataList[2] = (int)tt.arrMin[0]; //ResultDataList[0] = (int)tt.arrAverage[0]; // 첫 번째 채널 //ResultDataList[1] = (int)tt.arrAverage[1]; // 두 번째 채널 //ResultDataList[2] = (int)tt.arrAverage[2]; // 세 번째 채널 //ResultDataList[3] = (int)tt.arrAverage[3]; // 네 번째 채널 // 필요한 값을 사용하세요 Log.I($"Channel 0: {ResultDataList[0]}, Channel 1: {ResultDataList[1]}, Channel 2: {ResultDataList[2]}, Channel 3: {ResultDataList[3]}"); } judgeFlag = tt.nResultFlag; Log.I(string.Format($"[LBAD] stReceiveData[0] {tt.nResultFlag} ")); switch (judgeFlag) { case 0: judgeResult = "OK"; break; case 1: judgeResult = "WARNING"; break; case 2: judgeResult = "NA"; break; case 3: judgeResult = "NG"; break; case 4: judgeResult = "ERROR"; break; default: judgeResult = "NG"; break; } } else { // TODO: LBAD 가 not Activated 인 상황이다. error 로 보내야 할꺼 같음. judgeFlag = 3; judgeResult = "NG"; } _LBAD.ClearResultDataList(); Log.I($"after Clear >> Result Item Count[{ResultList.Count}]"); // 경신 페이지 추가하여 검사 내용 추가 //LBADResultPage[_PageNo - 1] = judgeFlag; Log.I(string.Format($"LBAD Judge Flag [kS] : {judgeFlag} PageResult : {judgeResult}")); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), true); Status.GetProcessingWeldingData().LBAD_Judge = (judgeFlag + 1).ToString(); Log.I(string.Format($"[IOInterface]SET PCJudgementCompleteAck true")); break; } Log.I(string.Format($"---> LBAD Sleep..... {count}")); DateTime tto = startTime + timeoutDuration; if (count >= 300) { count = 0; Log.I(string.Format($"---> LBAD Sleep..... {count} Break !!!!")); judgeFlag = 3; judgeResult = "NG"; break; } count++; Thread.Sleep(100); } _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false); Log.I(string.Format($"[IOInterface]SET PCJudgementCompleteAck false")); //return SEQ_CHECK_PAGENO; } Thread.Sleep(100); } if (WeldingEnd) { break; } } // if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) while (!context.Stopped) { if (_PLC.ReadBit((int)eBitInput.PLC_RESULT_REQUEST).data) { try { popup.Hide(); Thread.Sleep(100); } catch (Exception e) { Log.I(string.Format($"Popup Hide ERR !!!!")); } // 검사 결과 화면 표시 popup.Show(); popup.UpdateImages1(_WeldingImage[0], new OpenCvSharp.Rect(1153, 896, 7000, 8156)); // popup.UpdateImages2(_WeldingImage[1], new OpenCvSharp.Rect(1153, 896, 7000, 8156)); // 6918 popup.UpdateImages3(_WeldingImage[2], new OpenCvSharp.Rect(1153, 896, 7000, 8156)); // 6918 popup.UpdateImages4(_WeldingImage[3], new OpenCvSharp.Rect(1153, 896, 7000, 8156)); // 6918 if (result_info[0].Count == 42) popup.SetParameters1(result_info[0]); else { Log.I(string.Format($"Popup SetParameters1 ERR !!!!")); } if (result_info[1].Count == 21) popup.SetParameters2(result_info[1]); else { Log.I(string.Format($"Popup SetParameters2 ERR !!!!")); } if (result_info[2].Count == 42) popup.SetParameters3(result_info[2]); else { Log.I(string.Format($"Popup SetParameters3 ERR !!!!")); } if (result_info[3].Count == 21) popup.SetParameters4(result_info[3]); else { Log.I(string.Format($"Popup SetParameters4 ERR !!!!")); } switch (judgeFlag) { case 0: popup.SetStepLBAD("OK"); StepLBAD = "OK"; break; case 3: popup.SetStepLBAD("NG"); StepLBAD = "NG"; break; default: popup.SetStepLBAD("NG"); StepLBAD = "NG"; break; } if (StepWELDING_Get()) { popup.SetStepWELDING("OK"); StepWELDING = "OK"; } else { popup.SetStepWELDING("NG"); StepWELDING = "NG"; } // 레시피 값 가져오기 : 9 + 2 -> 총 11개 List recipe = Get_Recipe_Info(); // Recipe : 9 WeldingInfoSendPLC(recipe, StepLBAD, StepWELDING); if (Status.GetProcessingWeldingData().LBAD_Judge == "4" || StepWELDING.Contains("NG")) { _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, true); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_NG True, LBAD Result : {Status.GetProcessingWeldingData().LBAD_Judge}")); } else if (Status.GetProcessingWeldingData().LBAD_Judge != "4" || recipeRequestId == 21) { _PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_OK, true); Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_OK True, LBAD Result : {Status.GetProcessingWeldingData().LBAD_Judge}")); } bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); string Dir = System.IO.Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "QualityResults", string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}")); SaveWImage(Dir, _WeldingImage[0], "Step1"); SaveWImage(Dir, _WeldingImage[1], "Step2"); SaveWImage(Dir, _WeldingImage[2], "Step3"); SaveWImage(Dir, _WeldingImage[3], "Step4"); KS_WeldingInfo weldingInfo = new KS_WeldingInfo(); List Info = weldingInfo.MakeData(result_info[0], result_info[1], result_info[2], result_info[3], recipe, "OK", "OK"); SaveFile(Dir, Info, "result"); //KS_WeldingInfo weldingInfo = weldingInfo.MakeData() Log.I(string.Format($"STEP{_PageNoRcc} / End : CheckCycleStop -> SEQ_CHECK_PAGENO")); ksExit = true; WeldingEnd = false; return SEQ_CHECK_PAGENO; } Log.I("---> PLC_RESULT_REQUEST W"); Thread.Sleep(100); } return SEQ_CHECK_PAGENO; } private void UpdateProductCount(SequenceContext context) { string currentDate = DateTime.Now.ToString("yyyy-MM-dd"); if (_SystemParameter.CurrentDate != currentDate) { _TodayProduct = 0; _SystemParameter.CurrentDate = currentDate; } else { _TodayProduct = _SystemParameter.TodayProductCount; } if (_TodayProduct < uint.MaxValue) { _TodayProduct++; } if (_TotalProduct < uint.MaxValue) { _TotalProduct++; } _SystemParameter.TodayProductCount = _TodayProduct; _SystemParameter.TotalProductCount = _TotalProduct; //Systemparameter Save context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunKS_New"); } private void UpdateProductInfoForView() { Status.GetProcessingWeldingData().TotalProduct = _TotalProduct; Status.GetProcessingWeldingData().TodayProduct = _TodayProduct; Status.GetProcessingWeldingData().AutoRunStartTime = _AutoRunStartTime; Status.GetProcessingWeldingData().WeldingStartTime = _WeldingStartTime; Status.GetProcessingWeldingData().WeldingEndTime = _WeldEndTime; int totalSeconds = (int)_WeldingSpanTime.TotalSeconds; string temp = totalSeconds.ToString(); //Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = _WeldingSpanTime.TotalMilliseconds.ToString(); Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = totalSeconds.ToString() + " Sec"; Status.GetProcessingWeldingData().LotId = _LotId; DateTime T1 = DateTime.Now; string LBADSendBcrId = _BcrID; if (LBADSendBcrId == "" || LBADSendBcrId.Equals(null)) LBADSendBcrId = T1.ToString("HHmmss"); Status.GetProcessingWeldingData().CellId = LBADSendBcrId; } // TODO: ImageUtil 에 있는 함수를 사용하도록 수정 필요 private void SaveScoutImage(MIL_ID imageID) { // 테스트를 위해서 저장한다. 테스트 끝나고 삭제할것 Log.I(string.Format($"Start to store completed field scan image")); string fieldScanImageFile = ""; //4.스캐너 필드 이미지 파일 저장 fieldScanImageFile = System.IO.Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "RealTimeScout", string.Format($"{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}/{DateTime.Now.ToString("HHmmss")}.PNG")); //5.압축하여 저장 //CompressSaveImage(imageID, fieldScanImageFile, MIL.M_JPEG_LOSSY, 10); SaveImage(imageID, fieldScanImageFile, MIL.M_PNG); } private bool SaveImage(MIL_ID image, string filePath, MIL_INT format) { string directoryName = Path.GetDirectoryName(filePath); if (Directory.Exists(directoryName) == false) { Directory.CreateDirectory(directoryName); } MIL.MbufExport(filePath, format, image); return true; } private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param) { context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true); return SequenceAction.Ok(); } private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param) { // 완료 비트 write 하는 Node 추가 필요. format 유지, ReceiveCellInfo 없음 Log.D("AutoRun Sequence WriteCompletionPLCBit"); return SequenceAction.Ok(); } private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param) { RestoreDeviceStatus(); Log.I("AutoRun Complete"); context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult); SeqAutoRunKS_New_OutParam result = new SeqAutoRunKS_New_OutParam() { Success = seqResult }; if (seqResult == false) { AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_ResultFailed); } Log.D("AutoRun Sequence Complete"); Status.SetWorkingPosition(eWorkingPosition.DONE); return SequenceAction.Ok(result); } private bool RestoreDeviceStatus() { //PLC All BIT OFF _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false); _PLC.WriteBit((int)eBitOutput.PC_AUTO_STATUS, false); _PLC.WriteBit((int)eBitOutput.PC_RECIPE_PARAM_UPLOAD_COMPLETE, false); Log.I(string.Format("[PLCInterface]PC All Bit Off")); bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); Log.I(string.Format("[PLCInterface]Pgae Reset")); UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG); //LBAD IO All BIT OFF _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false); Log.I(string.Format("[IOInterface]PC All Bit Off")); _LBAD.SetReadybyAuto(false); #region _StreamLightLBAD //LBAD Ready Off ////_LBAD.SetReadybyAuto(false); //if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false) { // Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null")); //} #endregion //Laser Off _Laser.LaserOff(); //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.JumpAbs(0, 0, eFunctionType.COMMAND); //Vision Correctiong 파일 변경 _Scanner.SelectCorrectionTable(1); //Recipe를 기존에 Manual에서 작업하던 화면으로 rollback WeldingRecipeManager.RollbackRecipe(); ksExit = false; Status.GetProcessingWeldingData().ActRecipe = ""; Status.GetProcessingWeldingData().PageNO = ""; Status.GetProcessingWeldingData().BcrID = ""; return true; } private void OnForceError(SequenceContext arg1, string arg2) { OnSeqActionStop(); Log.I("SequenceAction Ok : OnForceError"); } private void OnStopped(SequenceContext obj) { OnSeqActionStop(); Log.I("SequenceAction Ok : OnStopped"); } private void OnSeqActionStop() { //PLC All BIT OFF _PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false); _PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false); _PLC.WriteBit((int)eBitOutput.PC_AUTO_STATUS, false); _PLC.WriteBit((int)eBitOutput.PC_RECIPE_PARAM_UPLOAD_COMPLETE, false); Log.I(string.Format("[PLCInterface]PC All Bit Off")); bool[] Page = new bool[4]; Page = new bool[4] { false, false, false, false }; _PLC.WriteBitBlock((int)eBitOutput.PC_WELD_PAGE_CHANGE_COMPLETE_1, 4, Page); Log.I(string.Format("[PLCInterface]Pgae Reset")); UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG); //LBAD IO All BIT OFF _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false); _IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false); Log.I(string.Format("[IOInterface]PC All Bit Off")); _LBAD.SetReadybyAuto(false); #region _StreamLightLBAD //LBAD Ready Off ////_LBAD.SetReadybyAuto(false); //if (_StreamLightLBAD.SendReadyStatus(eRequestData.Ready_Off) == false) //{ // Log.I(string.Format($"[LBAD Interface]CheckReadyStatus null")); //} #endregion //Laser Off _Laser.LaserOff(); //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.JumpAbs(0, 0, eFunctionType.COMMAND); //Vision Correctiong 파일 변경 _Scanner.SelectCorrectionTable(1); //Recipe를 기존에 Manual에서 작업하던 화면으로 rollback WeldingRecipeManager.RollbackRecipe(); ksExit = false; Status.GetProcessingWeldingData().ActRecipe = ""; Status.GetProcessingWeldingData().PageNO = ""; Status.GetProcessingWeldingData().BcrID = ""; } } // For CSV 저장용 public class CenterPositionData : NotifyPropertyChangedBase { private double _CenterX; public double CenterX { get => _CenterX; set => SetProperty(ref _CenterX, value); } private double _CenterY; public double CenterY { get => _CenterY; set => SetProperty(ref _CenterY, value); } } public class SeqAutoRunKS_New_InitParam : InitParam { public ScoutSeqParams ScoutSeqParams { get; set; } } public class SeqAutoRunKS_New_OutParam : OutParam { } public class ScannerObjectInfo { public object Object { get; set; } // Arc, Line, Spline, Dot public uint LaserPower1 { get; set; } public uint LaserPower2 { get; set; } public double JumpSpeed { get; set; } public double MarkSpeed { get; set; } } }