1464 lines
68 KiB
C#
1464 lines
68 KiB
C#
using Aurora.Api;
|
|
using AuroraCellTracker;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using WeldingCommon.Sequences;
|
|
using WeldingCommon;
|
|
using AuroraLaserScanner;
|
|
using WeldingCommon.Settings;
|
|
using WeldingCommon.Utils;
|
|
using AuroraLaser;
|
|
using AuroraOCT;
|
|
using AuroraPLC;
|
|
using AuroraIO;
|
|
using VisionCommon;
|
|
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
|
using Aurora.Api.Manager;
|
|
using AuroraLBAD;
|
|
using CoreUnit.Control.UserControl.Canvas;
|
|
using Matrox.MatroxImagingLibrary;
|
|
using WeldingCommon.Vision.WeldingObjectGenerator;
|
|
using OpenCvSharp;
|
|
using System.Diagnostics;
|
|
using ILSOS_SMW.Models;
|
|
using Aurora;
|
|
using DB.Recipe;
|
|
using System.Runtime.Remoting.Contexts;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using OpenCvSharp.Dnn;
|
|
using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
|
|
using DB;
|
|
using System.Configuration;
|
|
using System.Runtime.InteropServices.ComTypes;
|
|
using System.Windows.Media.Imaging;
|
|
using OpenCvSharp.WpfExtensions;
|
|
using System.Windows;
|
|
using Aurora.View;
|
|
using System.Drawing;
|
|
using System.Collections.ObjectModel;
|
|
using WeldingCommon.Views;
|
|
using WeldingCommon.Data;
|
|
using Hermes;
|
|
using ILSOS_SMW.RMS;
|
|
using System.CodeDom.Compiler;
|
|
using static Aurora.Api.SequenceBuilder;
|
|
using WeldingCommon.Devices;
|
|
using static ILSOS_SMW.Device.PLCControllerSMW;
|
|
using System.Windows.Forms.VisualStyles;
|
|
using WeldingCommon.Alarm;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.Remoting.Metadata.W3cXsd2001;
|
|
using SystemParameter = WeldingCommon.Settings.SystemParameter;
|
|
using Application = System.Windows.Application;
|
|
using Point = OpenCvSharp.Point;
|
|
using System.Windows.Shapes;
|
|
using WeldingCommon.Vision.WeldingObjectGenerator.GeometryLibrary;
|
|
using WeldingCommon.Vision.WeldingObjectGenerator.PathEditorLibrary;
|
|
using Path = System.IO.Path;
|
|
using static ILSOS_SMW.Device.IOController_SMW;
|
|
using WeldingCommon.Recipes;
|
|
|
|
namespace ILSOS_SMW.Sequences
|
|
{
|
|
class SeqAutoRunSMW_New
|
|
{
|
|
static readonly Logger Log = new Logger("SeqAutoRunSMW_New");
|
|
|
|
const string SEQ_ENTER = "[SeqAutoRunSMW] SEQ_ENTER"; // inputParam 으로 받자.
|
|
const string SEQ_CHECK_INIT_CONDITION = "[SeqAutoRunSMW] Check Init Condition"; // Check Init Condition
|
|
|
|
const string SEQ_CHECK_LOAD_COMPLETE = "[SeqAutoRunSMW] Check Load Complete";
|
|
|
|
const string SEQ_MEASURE_CELL_POSITION = "[SeqAutoRunSMW] Measure CellPosition";
|
|
|
|
const string SEQ_SET_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunSMW] Set Sequence Param (ScoutFlyingVision Seq)";
|
|
const string SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunSMW] Process (ScoutFlyingVision Seq)";
|
|
const string SEQ_GET_SCOUT_FLYING_VISION_SEQ = "[SeqAutoRunSMW] Get Sequence Result (ScoutFlyingVision Seq)";
|
|
|
|
const string SEQ_SEND_EVENT_SENDER = "[SeqAutoRunSMW] Event Sender";
|
|
const string SEQ_EVENT_Q_SAVE_FILE = "[SeqAutoRunSMW] EventQ Save File";
|
|
const string SEQ_SAVE_SCOUT_IMAGE = "[SeqAutoRunSMW] Save ScoutImage";
|
|
|
|
const string SEQ_FIND_EDGE = "[SeqAutoRunSMW] Find Edge";
|
|
const string SEQ_DECISION_RCC_ALGORITHM_TYPE = "[SeqAutoRunSMW] Decision RCC Algorithm Type";
|
|
const string SEQ_APPLY_OFFSET_OBJECT = "[SeqAutoRunSMW] Apply Offset Object";
|
|
const string SEQ_GENERATE_WELDING_OBJECT = "[SeqAutoRunSMW] Generate WeldingObject";
|
|
|
|
const string SEQ_READY_SCANNER_LIST = "[SeqAutoRunSMW] Ready ScannerList";
|
|
const string SEQ_SET_PARAMS_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunSMW] Set Sequence Param (UploadWeldingList Seq)";
|
|
const string SEQ_DO_ID_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunSMW] Process (UploadWeldingList Seq)";
|
|
const string SEQ_GET_RESULT_UPLOAD_WELDING_LIST_SEQ = "[SeqAutoRunSMW] Get Sequence Result (UploadWeldingList Seq)";
|
|
|
|
const string SEQ_WAIT_WELDING_START = "[SeqAutoRunSMW] Wait Welding Start";
|
|
|
|
const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunSMW] Set Sequence Param (ReceiveCellInfo Seq)";
|
|
const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunSMW] Process (ReceiveCellInfo Seq)";
|
|
const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "[SeqAutoRunSMW] Get Sequence Result (ReceiveCellInfo Seq)";
|
|
|
|
const string SEQ_EXECUTE_WELDING = "[SeqAutoRunSMW] Execute Welding";
|
|
const string SEQ_REQUEST_UNLOAD_CELL = "[SeqAutoRunSMW] Request Unload Cell";
|
|
const string SEQ_WAIT_LBAD_JUDGE = "[SeqAutoRunSMW] Wait LBAD Judge";
|
|
|
|
const string SEQ_SET_PARAMS_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunSMW] Set Sequence Param (ReportCellResult Seq)";
|
|
const string SEQ_DO_ID_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunSMW] Process (ReportCellResult Seq)";
|
|
const string SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ = "[SeqAutoRunSMW] Get Sequence Result (ReportCellResult Seq)";
|
|
|
|
const string SEQ_REPORT_CELLINFO_TO_PLC = "[SeqAutoRunSMW] ReportCellInfoToPLC";
|
|
const string SEQ_CHECK_CYCLE_STOP = "[SeqAutoRunSMW] Check Cycle Stop";
|
|
|
|
const string SEQ_SAVE_RESULT_DATA = "[SeqAutoRunSMW] Save Result Data";
|
|
|
|
const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqAutoRunSMW] Write Completion PLC Bit";
|
|
const string SEQ_COMPLETE = "[SeqAutoRunSMW] SEQ_COMPLETE"; // 완료
|
|
|
|
static class ContextKey
|
|
{
|
|
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunSMW";
|
|
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunSMW";
|
|
}
|
|
|
|
const int PLC_TIMEOUT = 60; // sec, Timeout은 시퀀스 정지가 아니라 타임아웃 시간마다 로그만 남기도록 한다
|
|
|
|
private SeqAutoRunSMW_New_InitParam _InitParam;
|
|
|
|
private Scanner _Scanner;
|
|
private LaserDevice _Laser;
|
|
private OCT _OCT;
|
|
private PLCController _PLC;
|
|
private IODevice _IO;
|
|
private LBAD _LBAD;
|
|
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<IDrawObject> _SelectedDrawObjectList;
|
|
|
|
private MIL_ID _GrabImage = MIL.M_NULL;
|
|
private ObjectGenerator _ObjGenerator;
|
|
private Mat _ConvMatImage;
|
|
|
|
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<IDrawObject> _GeneratedDrawObjects;
|
|
private List<IDrawObject> _RecipeDrawObjects; // ==> local
|
|
|
|
private Stopwatch _StopwatchGenObj;
|
|
|
|
private int _Radius_Pixel;
|
|
// End For RCC
|
|
|
|
private int _ModelNo;
|
|
|
|
private bool _IsRealTimeScout;
|
|
private double _CellMeasureCenterOffsetX;
|
|
private double _CellMeasureCenterOffsetY;
|
|
|
|
public string EVENT_TRIGGER_SAVE_FILE = "EventTriggerSaveFile";
|
|
private UnitPoint _DetectedContourCenter;
|
|
private Point[][] _MaxContour;
|
|
private List<TPoint> _Polygon;
|
|
private List<PathItem> _Paths;
|
|
private List<Arc> _SelectedArcs;
|
|
|
|
public SequenceBuilder Builder()
|
|
{
|
|
var sb = new SequenceBuilder(5000, true);
|
|
////var sb = new SequenceBuilder(1000, false); // With log
|
|
|
|
sb.AddAction(SEQ_ENTER, Sequence_Enter);
|
|
sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기
|
|
|
|
sb.AddDecision(SEQ_CHECK_LOAD_COMPLETE, CheckLoadComplete);
|
|
|
|
// CellCenterOffset
|
|
sb.AddAction(SEQ_MEASURE_CELL_POSITION, MeasureCellPosition);
|
|
|
|
// RCC
|
|
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.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);
|
|
|
|
// 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_SET_PARAMS_REPORT_CELL_RESULT_SEQ, SetReportCellResult_SeqParams);
|
|
sb.AddSubsequence(SEQ_DO_ID_REPORT_CELL_RESULT_SEQ, SequenceManager.GetSeqBuilder_SeqReportCellResult());
|
|
sb.AddAction(SEQ_GET_RESULT_REPORT_CELL_RESULT_SEQ, GetReportCellResult_SeqResult);
|
|
|
|
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_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_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]
|
|
> 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_FIND_EDGE] > sb[SEQ_DECISION_RCC_ALGORITHM_TYPE]
|
|
> sb[SEQ_GENERATE_WELDING_OBJECT] > sb[SEQ_READY_SCANNER_LIST])
|
|
.Flows(sb[SEQ_DECISION_RCC_ALGORITHM_TYPE] > sb[SEQ_APPLY_OFFSET_OBJECT] > sb[SEQ_READY_SCANNER_LIST])
|
|
.Flows(sb[SEQ_DECISION_RCC_ALGORITHM_TYPE] > sb[SEQ_READY_SCANNER_LIST]);
|
|
// 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_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
|
|
|
|
|
sb.OnStopped(OnStopped);
|
|
sb.OnForceError(OnForceError);
|
|
|
|
|
|
sb.Draw("SeqAutoRunSMW_New.pdf");
|
|
|
|
return sb;
|
|
}
|
|
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("SeqAutoRunSMW_New Start");
|
|
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION);
|
|
|
|
_InitParam = param.Param as SeqAutoRunSMW_New_InitParam;
|
|
_RecipeManager = Application.Current.AuroraEnv().RecipeManager;
|
|
_SystemParameter = context.GetSetting<SystemParameter>(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<EquipmentSpecificModel_SMW>(currentModelName, CommonModelIds.EquipmentSpecificModel);
|
|
_ModelNo = modelItem.Model_No;
|
|
|
|
return true;
|
|
}
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
//Device Init
|
|
_Scanner = context.GetLaserScanner();
|
|
_Laser = context.GetLaser();
|
|
_OCT = context.GetOCT();
|
|
_PLC = context.GetPLC();
|
|
_IO = context.GetIOUnit();
|
|
_LBAD = context.GetLBAD();
|
|
}
|
|
|
|
private bool CheckDeviceReady(SequenceContext context)
|
|
{
|
|
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.OCT,
|
|
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 하고 돌아 갈수 있도록
|
|
_OCT_QA_ERROR_COUNT = 0;
|
|
_OCT.OCT_QA_Error = false;
|
|
int octStatus = _OCT.GetStatus();
|
|
if ((octStatus == 1 || octStatus == 2) == false) {
|
|
int ret = _OCT.GetRemoteControl();
|
|
if (ret == -1) {
|
|
Log.E("ERROR Initialize OCT");
|
|
return false;
|
|
} else if (ret == 0) {
|
|
ret = _OCT.EnterRemoteMode(20000);
|
|
Log.I("OCT Enter Remote Mode");
|
|
}
|
|
} else {
|
|
Log.I("OCT Already Remote Mode");
|
|
}
|
|
|
|
// 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"));
|
|
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
while (!context.Stopped) {
|
|
if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADReadyStatus))) {
|
|
// TODO: AlarmMonitor 들어 오면서 추가된 부분으로, Sequence 가 돌고 있을 때, Device 상태 체크를 하는 Alarm 을 안띄우도록 하는 로직 임.
|
|
// TODO: 수정 필요함.
|
|
_LBAD.SetReadybyAuto(true);
|
|
Log.I(string.Format($"[IOInterface]SET DI_LBADReadyStatus True"));
|
|
break;
|
|
}
|
|
|
|
// LBAD 가 Ready 되지 않으면 지속적으로 log 발생하는 요구 사항. 종료조건은 없음
|
|
// false 가 없음.
|
|
if (sw.ElapsedMilliseconds > PLC_TIMEOUT * 1000) {
|
|
Log.E("TIMEOUT_DI_LBAD_READY_STATUS");
|
|
sw.Restart();
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
|
|
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"));
|
|
|
|
_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_LDD_RESULT_NG, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_RESULT_NG False"));
|
|
_PLC.WriteBit((int)eBitOutput.PC_LDD_DATA_RECEIVE_TIME_OUT, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_DATA_RECEIVE_TIME_OUT 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_LDD_RESULT_OK, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_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"));
|
|
Log.I(string.Format($"[PLCInterface] Complete AutoRun PLC Bit Initialize"));
|
|
|
|
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 CheckInitCondition(SequenceContext context, string id, ICollection<string> 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;
|
|
}
|
|
|
|
// 지그 상태 확인
|
|
private string CheckLoadComplete(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL);
|
|
|
|
TimeSpan spanTime;
|
|
DateTime startTime = DateTime.Now;
|
|
|
|
if (!StartInterfaceOCT(context)) {
|
|
Log.E(string.Format($"AutoRun Sequence Stopped because of OCT SequenceMode Fail"));
|
|
return null;
|
|
}
|
|
|
|
if (_SystemParameter.SequenceType == eSequenceType.Normal) {
|
|
// CorrectionTable ==> 2
|
|
return SEQ_READY_SCANNER_LIST;
|
|
} else {
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
// Cell 이 Load 완료되어서 Scout 가 가능한 상태인지 확인
|
|
_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);
|
|
}
|
|
|
|
if (_SystemParameter.SequenceType == eSequenceType.RCC) {
|
|
return SEQ_SET_SCOUT_FLYING_VISION_SEQ;
|
|
} else {
|
|
return SEQ_MEASURE_CELL_POSITION;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
|
|
// For Only CellCenterOffset
|
|
private SequenceActionResult MeasureCellPosition(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// Lid Holl 측정하려면 Camera ROI 센터에 Lid가 보여야 함
|
|
// Manual로 센터값을 찾은 뒤 SystemParameter로 넣어주면 Scanner가 최초 시작 시 해당 위치로 이동함
|
|
double ScannerPosX = _SystemParameter.CellPosMeasureCenterOffsetX;
|
|
double ScannerPosY = _SystemParameter.CellPosMeasureCenterOffsetY;
|
|
Log.I(string.Format($"ScannerPosX : {ScannerPosX},ScannerPosY : {ScannerPosY} "));
|
|
|
|
if (Math.Abs(ScannerPosX) > 10.0 || Math.Abs(ScannerPosY) > 10.0) {
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
} else {
|
|
_Scanner.JumpAbs(ScannerPosX, ScannerPosY, eFunctionType.COMMAND);
|
|
}
|
|
|
|
// Vision Grab
|
|
Log.I(string.Format($"Start Grab Image"));
|
|
_GrabImage = DoGrab();
|
|
|
|
// Vision 인식
|
|
//WPF Bitmapsource로 변환
|
|
int width = (int)MIL.MbufInquire(_GrabImage, MIL.M_SIZE_X, MIL.M_NULL);
|
|
int height = (int)MIL.MbufInquire(_GrabImage, MIL.M_SIZE_Y, MIL.M_NULL);
|
|
//int stride = width; // Assuming 8-bit grayscale image
|
|
int stride = width * 3; // Assuming 24-bit BRG image
|
|
byte[] imageData = new byte[width * height * 3];
|
|
MIL.MbufGetColor(_GrabImage, MIL.M_PACKED + MIL.M_BGR24, MIL.M_ALL_BANDS, imageData);
|
|
|
|
//32-bit 3ch bgr
|
|
BitmapSource bitmapSource = BitmapSource.Create(
|
|
width, height, 96, 96, System.Windows.Media.PixelFormats.Bgr24, null, imageData, stride);
|
|
|
|
//Convert bitmapsource to Mat
|
|
Mat ConvImg;
|
|
|
|
ConvImg = bitmapSource.ToMat();
|
|
OpenCvSharp.Point[][] minContour;
|
|
//SystemParameter 추가 필요
|
|
double CVThreshold = _SystemParameter.CVThreshold;
|
|
minContour = ImageUtil.FindMinContourForCenter(ConvImg, CVThreshold);
|
|
|
|
OpenCvSharp.Rect minRect = Cv2.BoundingRect(minContour[0]);
|
|
double centerX = minRect.X + (minRect.Width / 2);
|
|
double centerY = minRect.Y + (minRect.Height / 2);
|
|
|
|
double mCenterX = (((centerX - ConvImg.Width / 2) * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
double mCenterY = (((ConvImg.Height / 2 - centerY) * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
mCenterX += ScannerPosX;
|
|
mCenterY += ScannerPosY;
|
|
// Logging
|
|
ImageUtil.SaveCenterImage(ConvImg);
|
|
|
|
string savepath = Path.Combine(ConfigurationManager.AppSettings.Get("DATA_PATH"), "_vision", "EdgeContour", "Auto",
|
|
string.Format($"CenterDetect_{DateTime.Now.Year}_{DateTime.Now.Month}_{DateTime.Now.Day}.csv"));
|
|
|
|
List<CenterPositionData> centerPositionDataList = new List<CenterPositionData>();
|
|
var centerPosition = new CenterPositionData();
|
|
centerPosition.CenterX = mCenterX;
|
|
centerPosition.CenterY = mCenterY;
|
|
|
|
centerPositionDataList.Add(centerPosition);
|
|
bool result = CSV_Manager.GetInstance().Save_ListToCsv(savepath, centerPositionDataList, true);
|
|
//SaveCenterToCsv(mCenterX, mCenterY
|
|
|
|
_CellMeasureCenterOffsetX = mCenterX;
|
|
_CellMeasureCenterOffsetY = mCenterY;
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
public MIL_ID DoGrab()
|
|
{
|
|
var image = (object)_GrabImage;
|
|
_CameraAgent.GrabSync(_CameraDisplay, ref image);
|
|
_GrabImage = (MIL_ID)image;
|
|
|
|
return _GrabImage;
|
|
}
|
|
|
|
// For Only RCC
|
|
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 SequenceActionResult GetScoutFlyingVision_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
// 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<string> branches, SequenceActionResult param)
|
|
{
|
|
// FindEdge의 maxContour를 param으로 받아오기
|
|
Point[][] maxContour = context.GetValue<Point[][]>("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)
|
|
{
|
|
// Recipe Arc Center점을 기준(DOE)으로 새로 찾은 Center만 더해서 용접해야 함
|
|
_CellMeasureCenterOffsetX = _DetectedContourCenter.X;
|
|
_CellMeasureCenterOffsetY = _DetectedContourCenter.Y;
|
|
Log.I(string.Format($"Object CenterOffsetX : {_DetectedContourCenter.X.ToString("F3")}, CenterOffsetY : {_DetectedContourCenter.Y.ToString("F3")}"));
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
private SequenceActionResult GenerateWeldingObject(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
#region Generate Object
|
|
_StopwatchGenObj.Restart();
|
|
// Reicpe Arc의 Center만큼 객체 생성후 옮겨서 용접해야 함. 즉, Recipe Arc Center가 DOE가 되어있어야 함
|
|
var (centerX, centerY) = FindCenterReicpeSingleArc(_ConvMatImage);
|
|
_CellMeasureCenterOffsetX = centerX;
|
|
_CellMeasureCenterOffsetY = centerY;
|
|
|
|
_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, "SeqAutoRunSMW_RCC_before");
|
|
if (_ObjGenerator.CheckInterlockDrawingObjectPosition(_GeneratedDrawObjects, _DetectedContourCenter, _SelectedArcs[0]) == false) {
|
|
Log.E(string.Format("[GenerateWeldingObject]Interlock DrawingObject."));
|
|
return null;
|
|
}
|
|
List<IDrawObject> tempobject = new List<IDrawObject>();
|
|
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, "SeqAutoRunSMW_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)
|
|
{
|
|
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)
|
|
{
|
|
//if (!StartInterfaceOCT(context)) {
|
|
// Log.E(string.Format($"AutoRun Sequence Stopped because of OCT SequenceMode Fail"));
|
|
// return null;
|
|
//}
|
|
|
|
_PLC.WriteBit((int)eBitOutput.PC_WELD_READY, true);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY True"));
|
|
|
|
_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);
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool StartInterfaceOCT(SequenceContext context)
|
|
{
|
|
_InterfaceStartTime = DateTime.Now;
|
|
if (!EnterSequenceModeOCT()) {
|
|
while (!context.Stopped) {
|
|
if (EnterSequenceModeOCT())
|
|
break;
|
|
_InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime);
|
|
|
|
if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) {
|
|
Log.E("Fail to Enter OCT SequenceMode");
|
|
_InterfaceStartTime = DateTime.Now;
|
|
return false;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
}
|
|
//Trigger 상태 체크 추가 필요
|
|
_InterfaceStartTime = DateTime.Now;
|
|
while (!context.Stopped) {
|
|
if (_OCT.GetStatus() == 2) {
|
|
Log.I("OCT Status Completed in Waiting For Trigger");
|
|
break;
|
|
}
|
|
|
|
_InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime);
|
|
if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) {
|
|
Log.E("Time Out Waiting for Trigger of OCT Status");
|
|
return false;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD);
|
|
|
|
// Laser Correction 파일로 변경, 레이저를 사용해야 하므로 2
|
|
_Scanner.SelectCorrectionTable(2);
|
|
_CellId = Status.GetProcessingWeldingData().WorkCellId;
|
|
_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);
|
|
Log.I(string.Format($"SendCellData result :{sendresult}"));
|
|
|
|
_OCT.AddWorkPieceID(_CellId);
|
|
|
|
_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"));
|
|
|
|
_WeldingStartTime = DateTime.Now;
|
|
Status.GetProcessingWeldingData().WeldStartTime = _WeldingStartTime.ToString("yyyyMMddHHmmss");
|
|
|
|
_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"));
|
|
|
|
_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]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();
|
|
|
|
_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_LDD_RESULT_NG, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_RESULT_NG False"));
|
|
_PLC.WriteBit((int)eBitOutput.PC_LDD_DATA_RECEIVE_TIME_OUT, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_DATA_RECEIVE_TIME_OUT 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_LDD_RESULT_OK, false);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_RESULT_OK False"));
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult WaitLBADJudge(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Int16 judgeFlag = 0;
|
|
string judgeResult = "";
|
|
|
|
// 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 {
|
|
_InterfaceStartTime = DateTime.Now;
|
|
while (!context.Stopped) {
|
|
if (_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADJudgementComplete))) {
|
|
Log.I(string.Format($"[IOInterface]SET LBADJudgementComplete true"));
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
|
Log.I(string.Format($"[IOInterface]SET PCWeldingStop false"));
|
|
|
|
int result = _LBAD.GetResult(out judgeFlag);
|
|
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";
|
|
}
|
|
|
|
Log.I(string.Format($"LBAD Judge Flag : {judgeFlag} Result : {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;
|
|
}
|
|
_InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime);
|
|
if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) {
|
|
Log.E("TIMEOUT_DI_LBADJudgementComplete_TRUE");
|
|
_InterfaceStartTime = DateTime.Now;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
|
|
// 2. LBAD 처리를 IO 에서 확인
|
|
_InterfaceStartTime = DateTime.Now;
|
|
while (!context.Stopped) {
|
|
if (!_IO._iOUnit.ReadDiBit(Convert.ToInt32(eADIAddress.LBADJudgementComplete))) {
|
|
Log.I(string.Format($"[IOInterface]GET LBADJudgementComplete false"));
|
|
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false);
|
|
Log.I(string.Format($"[IOInterface]SET PCJudgementCompleteAck false"));
|
|
|
|
break;
|
|
}
|
|
_InterfaceSpanTime = DateTime.Now.Subtract(_InterfaceStartTime);
|
|
if (_InterfaceSpanTime.TotalMilliseconds > (PLC_TIMEOUT * 1000)) {
|
|
Log.E("TIMEOUT_DI_LBADJudgementComplete_FALSE");
|
|
_InterfaceStartTime = DateTime.Now;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SetReportCellResult_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
|
|
|
SeqReportCellResult_InitParam seqParams = new SeqReportCellResult_InitParam() {
|
|
EDC_Interface = new EDC(),
|
|
};
|
|
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
|
|
private SequenceActionResult GetReportCellResult_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqReportCellResult_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult ReportCellInfoToPLC(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
string strLBADJudge = Status.GetProcessingWeldingData().LBAD_Judge;
|
|
string strLDDJudge = Status.GetProcessingWeldingData().LDD_Judge;
|
|
|
|
if (strLDDJudge == "1") {
|
|
_OCT_QA_ERROR_COUNT = 0;
|
|
_OCT.OCT_QA_Error = false;
|
|
_PLC.WriteBit((int)eBitOutput.PC_LDD_RESULT_OK, true);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_RESULT_NG True, LDD Result : {strLDDJudge}"));
|
|
} else {
|
|
if (strLDDJudge == "4" || strLDDJudge == "") {
|
|
_OCT_QA_ERROR_COUNT++;
|
|
Log.I(string.Format($"OCT QA Data Error Count : {_OCT_QA_ERROR_COUNT}"));
|
|
_PLC.WriteBit((int)eBitOutput.PC_LDD_DATA_RECEIVE_TIME_OUT, true);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_DATA_RECEIVE_TIME_OUT True, LDD Result : {strLDDJudge}"));
|
|
} else {
|
|
_OCT_QA_ERROR_COUNT = 0;
|
|
_OCT.OCT_QA_Error = false;
|
|
_PLC.WriteBit((int)eBitOutput.PC_LDD_RESULT_NG, true);
|
|
Log.I(string.Format($"[PLCInterface]SET PC_LDD_RESULT_NG True, LDD Result : {strLDDJudge}"));
|
|
}
|
|
|
|
if (_SystemParameter.OCT_QA_Error_Count <= _OCT_QA_ERROR_COUNT) {
|
|
_OCT.OCT_QA_Error = true;
|
|
_OCT_QA_ERROR_COUNT = 0;
|
|
}
|
|
}
|
|
|
|
if (strLBADJudge == "4") {
|
|
_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}"));
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private static string CheckCycleStop(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CYCLE);
|
|
|
|
// TODO: 확인 필요, CybleStop 에 대한 내용, cycle stop 여부 가져오기
|
|
//bCycleStop = GetCycleStopRequest();
|
|
|
|
// TODO: 한번만 돌도록 설정함, PLC 로 받으면 좋음.
|
|
//Jin : cycleStop 명령을 용접 프로그램에서 할 경우가 현재는 없음..
|
|
// CheckCycleStop 노드와 Complete 노드 사이 다른 노드가 필요하다면 해당 노드를 CheckCycleStop 노드 위로 올리자
|
|
bool cycleStop = false;
|
|
if (cycleStop) {
|
|
return SEQ_SAVE_RESULT_DATA;
|
|
} else {
|
|
return SEQ_CHECK_LOAD_COMPLETE;
|
|
}
|
|
}
|
|
|
|
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, "SeqAutoRunSMW_New");
|
|
}
|
|
|
|
private void UpdateProductInfoForView()
|
|
{
|
|
Status.GetProcessingWeldingData().TotalProduct = _TotalProduct;
|
|
Status.GetProcessingWeldingData().TodayProduct = _TodayProduct;
|
|
|
|
Status.GetProcessingWeldingData().AutoRunStartTime = _AutoRunStartTime;
|
|
|
|
Status.GetProcessingWeldingData().WeldingStartTime = _WeldingStartTime;
|
|
Status.GetProcessingWeldingData().WeldingEndTime = _WeldEndTime;
|
|
Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = _WeldingSpanTime.TotalMilliseconds.ToString();
|
|
|
|
Status.GetProcessingWeldingData().LotId = _LotId;
|
|
Status.GetProcessingWeldingData().CellId = _CellId;
|
|
}
|
|
|
|
// TODO: EnterSequenceModeOCT 와 함께 Initialize 하는 것을 재구현 필요함. 초반에 한번만 check 하고 돌아 갈수 있도록
|
|
private bool EnterSequenceModeOCT()
|
|
{
|
|
//initOCT 부분에서 EnterRemoteMode 명령 후 실제 Remote seq Mode 진입시까지 약 10~20초 가량 소모됨
|
|
// GetStatus 의 return이 2일경우 이미 Trigger 상태이므로 추가 명령은 필요 없음
|
|
// GetStatus 의 return이 1일경우 Remote mode로 전환만 된 상태이므로 Trigger 명령을 해줘야 함
|
|
// 둘다 아닌 경우 remote 모드가 아닌것으로 간주, GetRemoteControl() 명령으로 확인
|
|
if (_OCT == null) {
|
|
return false;
|
|
}
|
|
if (_OCT.IsSimul) {
|
|
return true;
|
|
}
|
|
|
|
int nStatus = _OCT.GetStatus(); //nStatus = 1 Ready for Command , nStatus = 2 Waiting For Tirgger
|
|
if (nStatus != 2) {
|
|
int nRet = _OCT.GetRemoteControl(); // nRet = 0 OFF ,nRet = 1 Remote job , nRet = 2 remote sequence
|
|
if (nRet == -1 || nRet == 0) {
|
|
//Log.E("ERROR OCT");
|
|
return false;
|
|
} else {
|
|
_OCT.SetProgram(1);
|
|
Log.I("OCT Trigger On");
|
|
|
|
Thread.Sleep(500);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// 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);
|
|
SeqAutoRunSMW_New_OutParam result = new SeqAutoRunSMW_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"));
|
|
|
|
//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);
|
|
|
|
//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();
|
|
|
|
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"));
|
|
|
|
//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);
|
|
|
|
//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();
|
|
}
|
|
|
|
}
|
|
// 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 SeqAutoRunSMW_New_InitParam : InitParam
|
|
{
|
|
public ScoutSeqParams ScoutSeqParams { get; set; }
|
|
|
|
}
|
|
|
|
public class SeqAutoRunSMW_New_OutParam : OutParam
|
|
{
|
|
|
|
}
|
|
} |