1385 lines
63 KiB
C#
1385 lines
63 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.Devices;
|
|
using Aurora.Api.Manager;
|
|
using Aurora.View;
|
|
using AuroraCellTracker;
|
|
using AuroraIO;
|
|
using AuroraLaser;
|
|
using AuroraLaser.Trumpf;
|
|
using AuroraLaserScanner;
|
|
using AuroraLBAD;
|
|
using AuroraLight;
|
|
using AuroraOCT;
|
|
using AuroraPLC;
|
|
using CoreUnit.Control.UserControl.Canvas;
|
|
using CoreUnit.Scanner.UserControl.ScannerCanvas;
|
|
using DB;
|
|
using DB.Recipe;
|
|
using Hermes;
|
|
using Hermes.Functional.Option;
|
|
using ILSOS_PrismaticScanner.Device;
|
|
using ILSOS_PrismaticScanner.Models;
|
|
using Matrox.MatroxImagingLibrary;
|
|
using MilCommon;
|
|
using MilUI;
|
|
using OpenCvSharp;
|
|
using OpenCvSharp.Dnn;
|
|
using OpenCvSharp.WpfExtensions;
|
|
using System;
|
|
using System.CodeDom.Compiler;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Configuration;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.IO.Pipes;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices.ComTypes;
|
|
using System.Runtime.Remoting.Contexts;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Forms.VisualStyles;
|
|
using System.Windows.Media.Imaging;
|
|
using VisionCommon;
|
|
using WeldingCommon;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Data;
|
|
using WeldingCommon.Devices;
|
|
using WeldingCommon.Models;
|
|
using WeldingCommon.Sequences;
|
|
using WeldingCommon.Sequences.Main;
|
|
using WeldingCommon.Settings;
|
|
using WeldingCommon.Utils;
|
|
using WeldingCommon.Views;
|
|
using WeldingCommon.Vision.WeldingObjectGenerator;
|
|
using static Aurora.Api.SequenceBuilder;
|
|
using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
|
|
using static AuroraIO.Vendor.PAIX.PAIXIO;
|
|
using static ILSOS_PrismaticScanner.Device.PLCControllerPrismaticScanner;
|
|
using static WeldingCommon.Devices.PLCController;
|
|
using static WeldingCommon.Sequences.Main.SeqExecutePlcBitInterface_InitParam;
|
|
|
|
namespace ILSOS_PrismaticScanner.Sequences
|
|
{
|
|
/// <summary>
|
|
/// 각형 스캐너 타입 자동 운전을 위한 시퀸스
|
|
/// </summary>
|
|
class SeqAutoRunPrismaticScanner
|
|
{
|
|
static readonly Logger Log = new Logger("SeqAutoRunPrismaticScanner");
|
|
|
|
#region 시퀸스 변수명
|
|
const string SEQ_ENTER = "SEQ_ENTER"; // inputParam 으로 받자.
|
|
const string SEQ_CHECK_INIT_CONDITION = "Check Init Condition"; // Check Init Condition
|
|
|
|
const string SEQ_FORK_CHECK_SEQ_SETTING = "Fork Check Seq Setting";
|
|
|
|
const string SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ = "Set Sequence Param (ExecutePlcPageChangeOrWeldRequestInterface Seq)";
|
|
const string SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST = "Process (Wait Page Change Request Or Weld Request)";
|
|
const string SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ = "Get Sequence Result (ExecutePlcPageChangeOrWeldRequestInterface Seq)";
|
|
|
|
const string SEQ_CHECK_CELL_INFO_RECEIVE = "Check Cell Info Receive"; // 셀 정보 수신 확인
|
|
const string SEQ_CHECK_WELDDING_RETRY = "Check Welding Retry";
|
|
const string SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ = "Get Sequence Result (ReceiveCellInfo Seq)";
|
|
const string SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ = "Process (ReceiveCellInfo Seq)";
|
|
const string SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ = "Set Sequence Param (ReceiveCellInfo Seq)";
|
|
const string SEQ_JOIN_CELL_INFO_RECEIVE = "Complete Check Cell Info Receive";
|
|
|
|
const string SEQ_CHECK_VISION_COMPENSION_USE = "Check Vision Compensation Use"; // 비전 보상 사용 확인
|
|
const string SEQ_DO_VISION_JOB = "Do Vision Job"; // 비전 작업 진행
|
|
const string SEQ_JOIN_VISION_COMPENSION = "Complete Vision Compensation";
|
|
const string SEQ_CHECK_SAVE_WELD_IMAGE = "Check Save Weld Image";
|
|
const string SEQ_SAVE_WELD_IMAGE = "Save Weld Image"; // 용접 후 이미지 저장
|
|
|
|
const string SEQ_JOIN_CHECK_SEQ_SETTING = "Join Check Seq Setting";
|
|
|
|
const string SEQ_SEND_EVENT_SENDER = "Event Sender"; // Image Q 저장
|
|
const string SEQ_SEND_EVENT_SENDER2 = "Event Sender2"; // Image Q 저장
|
|
|
|
const string SEQ_EVENT_Q_SAVE_FILE = "EventQ Save File";
|
|
const string SEQ_SAVE_IMAGES = "Save Images";
|
|
|
|
const string SEQ_CHECK_VISION_COMPLETE = "Check Vision Complete";
|
|
const string SEQ_NG_RESULT_PROCESS = "Ng Result Process";
|
|
|
|
const string SEQ_GENERATE_WELDING_OBJECT = "Generate Welding Object"; // 용접 객체 생성
|
|
const string SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ = "Set Params Component Teachingrun Seq"; // 용접 리스트 업로드 파라미터 설정
|
|
const string SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ = "Process (Component Teachingrun Seq)"; // 용접 리스트 업로드 시퀀스 처리
|
|
const string SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ = "Get Result Component Teachingrun Seq"; // 용접 리스트 업로드 결과 가져오기
|
|
|
|
const string SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Get Sequence Result (PLC Weld Complete Interface Seq)";
|
|
const string SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Process (PLC Weld Complete Interface Seq)";
|
|
const string SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ = "Set Sequence Param (PLC Weld Complete Interface Seq)";
|
|
|
|
const string SEQ_SAVE_RESULT_DATA = "Save Result Data"; // 결과 데이터 저장
|
|
const string SEQ_COMPLETE = "SEQ_COMPLETE"; // 완료
|
|
#endregion
|
|
|
|
static class ContextKey
|
|
{
|
|
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunPrismaticScanner";
|
|
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqAutoRunPrismaticScanner";
|
|
}
|
|
|
|
#region 변수 정의
|
|
// 디바이스 정의
|
|
private Scanner _Scanner;
|
|
#warning to KSJ > _Laser 참조되는거 다 IOLaser로 변경해야함, 필요 없으면 지워도 무방
|
|
private Laser _Laser;
|
|
private PLCControllerPrismaticScanner _PLC;
|
|
private IODevice _IO;
|
|
private LightDevice _Light;
|
|
|
|
// 비전 정의
|
|
private CameraAgentBase _CameraAgent;
|
|
private ICameraDisplay _CameraDisplay;
|
|
private PatternAgentBase _PatternAgent;
|
|
private List<PatternInfo> _Patterns;
|
|
private PatternInfo _PatternInfo;
|
|
private PatternResult _PatternResult;
|
|
private FieldScanParams _FieldScanParams;
|
|
private object _GrabImage;
|
|
private MIL_ID _GrabImageMilId;
|
|
private int _RetryCount = 0;
|
|
private double _OffsetXfromModelFinder = 0;
|
|
private double _OffsetYfromModelFinder = 0;
|
|
// 시스템 및 용접 파라미터 정의
|
|
private SystemParameter _SystemParameter;
|
|
private static SequenceSetting _SequenceSetting;
|
|
private ScannerCanvasUserCtrl _ScannerCanvasUserCtrl; //스캐너 동작관련 객체 선언
|
|
private List<IDrawObject> _SelectedDrawObjectList;
|
|
private static List<IDrawObject> _UnpackDrawObject;
|
|
|
|
private SeqAutoRunPrismaticScanner_InitParam _InitParam;
|
|
|
|
// 생산 데이터 정의
|
|
private uint _TodayProduct;
|
|
private uint _TotalProduct;
|
|
|
|
private DateTime _AutoRunStartTime;
|
|
private DateTime _WeldStartTime;
|
|
private DateTime _WeldEndTime;
|
|
private TimeSpan _WeldSpanTime;
|
|
private TimeSpan _InterfaceSpanTime;
|
|
private DateTime _InterfaceStartTime;
|
|
|
|
private string _LotId = "N/A";
|
|
private string _CellId = "N/A";
|
|
const int timeoutSeconds = 10;
|
|
|
|
private bool _FirstUpdateStep = true;
|
|
private bool _IsWeldingRetry = false;
|
|
private int _CurrentWeldingStep = 0;
|
|
private int _TotalWeldingStep = 0;
|
|
private int _PreviousTotalWeldingStep = 0;
|
|
private int _PageNo = 1;
|
|
private MIL_ID _ResultImageMilId;
|
|
private bool _SuccessVisionResult = false;
|
|
const int PLC_TIMEOUT = 60; // sec, Timeout은 시퀀스 정지가 아니라 타임아웃 시간마다 로그만 남기도록 한다
|
|
|
|
public string EVENT_TRIGGER_SAVE_FILE = "EventTriggerSaveFile";
|
|
|
|
// 공정 시간 측정
|
|
private static DateTime _WeldReqTime;
|
|
private static DateTime _WeldComTime;
|
|
|
|
private List<int> lightValues = new List<int> { 255, 255, 255, 255 };
|
|
|
|
private (double X, double Y) TargetObjectCenterPosition = (X: 0.0, Y: 0.0);
|
|
#endregion
|
|
|
|
public SequenceBuilder Builder()
|
|
{
|
|
var sb = new SequenceBuilder(1000, true);
|
|
////var sb = new SequenceBuilder(1000, false); // With log
|
|
|
|
sb.AddAction(SEQ_ENTER, Sequence_Enter);
|
|
sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기
|
|
|
|
///// PLC_USE_PAGE_CHANGE_INTERFACE
|
|
sb.AddAction(SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ, SetPlcPageChangeOrWeldRequest_SeqParams);
|
|
sb.AddSubsequence(SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST, SequenceManager.GetSeqBuilder_SeqWaitWeldOrChangePage());
|
|
sb.AddAction(SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ, GetPlcPageChangeOrWeldRequest_SeqParams);
|
|
|
|
///// Fork
|
|
sb.AddFork(SEQ_FORK_CHECK_SEQ_SETTING);
|
|
|
|
///// Check & Cell Load
|
|
sb.AddDecision(SEQ_CHECK_CELL_INFO_RECEIVE, CheckCellInfoReceive);
|
|
sb.AddDecision(SEQ_CHECK_WELDDING_RETRY, CheckWeldingRetry);
|
|
sb.AddAction(SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ, SetReceiveCellInfo_SeqParams);
|
|
sb.AddSubsequence(SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ, SequenceManager.GetSeqBuilder_SeqReceiveCellInfo());
|
|
sb.AddAction(SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ, GetReceiveCellInfo_SeqResult);
|
|
sb.AddAction(SEQ_JOIN_CELL_INFO_RECEIVE, JoinCellInfoReceive);
|
|
|
|
///// Check & Use Model Finder
|
|
sb.AddDecision(SEQ_CHECK_VISION_COMPENSION_USE, CheckVisionCompensationUse);
|
|
sb.AddAction(SEQ_DO_VISION_JOB, DoVisionJob);
|
|
sb.AddAction(SEQ_JOIN_VISION_COMPENSION, JoinVisionCompensation);
|
|
sb.AddDecision(SEQ_CHECK_SAVE_WELD_IMAGE, CheckSaveWeldImage);
|
|
sb.AddAction(SEQ_SAVE_WELD_IMAGE, SaveWeldImage);
|
|
|
|
///// Event Q
|
|
sb.AddEventSender(SEQ_SEND_EVENT_SENDER, SendEvent);
|
|
sb.AddEventSender(SEQ_SEND_EVENT_SENDER2, SendEvent);
|
|
sb.AddEventQ(SEQ_EVENT_Q_SAVE_FILE, 2);
|
|
sb.AddAction(SEQ_SAVE_IMAGES, SaveImagesEvent);
|
|
|
|
///// Join
|
|
sb.AddJoin(SEQ_JOIN_CHECK_SEQ_SETTING);
|
|
sb.AddDecision(SEQ_CHECK_VISION_COMPLETE, CheckVisionComplete);
|
|
sb.AddAction(SEQ_NG_RESULT_PROCESS, NgResultProcess);
|
|
|
|
///// Weld Start / Complete
|
|
sb.AddAction(SEQ_GENERATE_WELDING_OBJECT, GenerateWeldingObject);
|
|
sb.AddAction(SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ, SetComponentTeachingrun_SeqParams);
|
|
sb.AddSubsequence(SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ, SequenceManager.GetSeqBuilder_SeqComponentTeachingRun());
|
|
sb.AddAction(SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ, GetComponentTeachingrun_SeqResult);
|
|
|
|
///// Check Welding Retry Request;
|
|
sb.AddAction(SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ, SetPlcWeldCompleteInterface_SeqParams);
|
|
sb.AddSubsequence(SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ, SequenceManager.GetSeqBuilder_SeqExecutePlcBitInterface());
|
|
sb.AddAction(SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ, GetPlcWeldCompleteInterface_SeqParams);
|
|
|
|
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
|
sb.AddAction(SEQ_COMPLETE, Complete);
|
|
|
|
// [Action] 초기 세팅
|
|
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION]
|
|
// [Decision] PLC에서 페이지 변경 및 용접 요청 들어온 경우
|
|
> sb[SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ] > sb[SEQ_WAIT_CHANGE_PAGE_OR_WELD_REQUEST] > sb[SEQ_GET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ]
|
|
//// Fork1
|
|
// [Decision] 셀 ID를 받을 수 있는 설정인 경우
|
|
> sb[SEQ_FORK_CHECK_SEQ_SETTING]);
|
|
|
|
sb.Flows(sb[SEQ_FORK_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_CELL_INFO_RECEIVE] > sb[SEQ_CHECK_WELDDING_RETRY] > sb[SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_DO_ID_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_GET_PARAMS_RECEIVE_CELL_INFO_SEQ] > sb[SEQ_JOIN_CELL_INFO_RECEIVE]
|
|
//// Join
|
|
> sb[SEQ_JOIN_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_VISION_COMPLETE]);
|
|
// 비전 실패
|
|
sb.Flows(sb[SEQ_CHECK_VISION_COMPLETE] > sb[SEQ_NG_RESULT_PROCESS] > sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ]);
|
|
// 비전 성공
|
|
sb.Flows(sb[SEQ_CHECK_VISION_COMPLETE] > sb[SEQ_GENERATE_WELDING_OBJECT]
|
|
//// [Action] 용접 시작
|
|
> sb[SEQ_SET_PARAMS_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_DO_ID_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_GET_RESULT_COMPONENT_TEACHINGRUN_SEQ] > sb[SEQ_CHECK_SAVE_WELD_IMAGE] > sb[SEQ_SAVE_WELD_IMAGE] > sb[SEQ_SEND_EVENT_SENDER2].Send(EVENT_TRIGGER_SAVE_FILE)
|
|
//// [Decision] 용접 완료 혹은 재시작 (GET_PARAMS 에서 진행)
|
|
> sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ] > sb[SEQ_DO_PLC_WELD_COMPLETE_INTERFACE_SEQ] > sb[SEQ_GET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ]
|
|
// [Action] 결과값 입력
|
|
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ]);
|
|
|
|
///// Fork2 & Join
|
|
// [Decision] 비전 보상이 필요한 경우
|
|
// [Decision] OFFSET 입력 혹은 재시도 결정
|
|
sb.Flows(sb[SEQ_FORK_CHECK_SEQ_SETTING] > sb[SEQ_CHECK_VISION_COMPENSION_USE] > sb[SEQ_DO_VISION_JOB] > sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_JOIN_VISION_COMPENSION] > sb[SEQ_JOIN_CHECK_SEQ_SETTING]);
|
|
// Scout Image Save Event Seq
|
|
sb.Flows(sb[SEQ_EVENT_Q_SAVE_FILE].On(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_SAVE_IMAGES] > sb.FlowFinal);
|
|
|
|
// SEQ_CHECK_INIT_CONDITION
|
|
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
|
// SEQ_CHECK_CELL_INFO_RECEIVE
|
|
sb.Flows(sb[SEQ_CHECK_CELL_INFO_RECEIVE] > sb[SEQ_JOIN_CELL_INFO_RECEIVE]);
|
|
sb.Flows(sb[SEQ_CHECK_WELDDING_RETRY] > sb[SEQ_JOIN_CELL_INFO_RECEIVE]);
|
|
|
|
// SEQ_CHECK_VISION_COMPENSION_USE
|
|
sb.Flows(sb[SEQ_CHECK_VISION_COMPENSION_USE] > sb[SEQ_JOIN_VISION_COMPENSION]);
|
|
sb.Flows(sb[SEQ_CHECK_SAVE_WELD_IMAGE] > sb[SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ]);
|
|
|
|
sb.OnForceError(OnForceError);
|
|
sb.OnStopped(OnStopped);
|
|
|
|
//sb.Draw("SeqAutoRunPrismaticScanner.pdf");
|
|
|
|
return sb;
|
|
}
|
|
|
|
private string CheckWeldingRetry(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_IsWeldingRetry) return SEQ_JOIN_CELL_INFO_RECEIVE;
|
|
else return SEQ_SET_PARAMS_RECEIVE_CELL_INFO_SEQ;
|
|
}
|
|
|
|
#region 시퀸스 함수
|
|
|
|
#region 1. 디바이스 및 변수 상태 확인
|
|
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("SeqAutoRunPrismaticScanner Start");
|
|
|
|
_InitParam = param.Param as SeqAutoRunPrismaticScanner_InitParam;
|
|
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
|
_SequenceSetting = context.GetSetting<SequenceSetting>(CommonSettingIds.Sequence);
|
|
|
|
InitDev(context);
|
|
if (!CheckDeviceReady(context)) {
|
|
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;
|
|
}
|
|
|
|
// Setting 값
|
|
_PageNo = _SequenceSetting.LastPageNo;
|
|
Log.I($"Previous Page No is {_PageNo}");
|
|
Log.I($"Sequence Setting Info is 1) ImageAcquire : {_SequenceSetting.UseImageAcquire}, 2) UseCellOffset : {_SequenceSetting.UseCellOffset}.");
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.CHECKING_CONDITION);
|
|
|
|
if (!CheckCondition(context)) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_CheckInitCondition);
|
|
Log.E("Condition is not in state to start sequence.");
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false);
|
|
return SEQ_COMPLETE;
|
|
}
|
|
|
|
var startTime = DateTime.Now;
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime);
|
|
|
|
// 자동 운전 시, 비전 보상 유무에 따른 조명 값 변경
|
|
if (_SequenceSetting.UseCellOffset) UpdateAutoLightValue(_SequenceSetting.CompensationLightValue);
|
|
else UpdateAutoLightValue(_SequenceSetting.LightValue);
|
|
|
|
// Light ALL ON
|
|
if (!_Light.CheckLightOnAndValue(lightValues[0])) {
|
|
_Light.SetLightValue(lightValues);
|
|
Log.I($"Light All On !");
|
|
}
|
|
|
|
// 레이저 레디 상태가 아니면, 레디 시켜야 함.
|
|
if (!_Laser.GetLaserReady()) {
|
|
_Laser.LaserOn();
|
|
Log.I($"Start Laser ON in CheckInitCondition");
|
|
}
|
|
|
|
// 너무 빨리 되어서 문제인 것인가 ?
|
|
var res = context.RetryUntilSuccess(_Laser.GetLaserReady, timeoutSeconds * 1000, 10);
|
|
if (res == E2.TIMEOUT) {
|
|
Log.E("Laser Ready Fail When Autorun");
|
|
return null;
|
|
}
|
|
|
|
InitializePlcBits();
|
|
|
|
// CheckInitCondition 완료된다면..
|
|
_PLC.WriteBit(eBitOutput.PC_AUTO_STATUS, true);
|
|
_PLC.WriteWord(eWordOutput.PC_PAGE_NO, (short)_PageNo);
|
|
|
|
Log.I("Complete CheckInitCondition.");
|
|
|
|
return SEQ_SET_PARAMS_PLC_PAGE_CHANGE_OR_WELD_REQ_INTERFACE_SEQ;
|
|
}
|
|
#endregion
|
|
|
|
#region 2. Page 변경 시퀸스 ~ 3. Weld Req 시퀸스
|
|
private SequenceActionResult SetPlcPageChangeOrWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I(string.Format("PLC Interface(PageChange, WeldReq) Start; (REQ,ACK); ({0},{1});({2},{3})",
|
|
(int)eBitInput.PLC_PAGE_CHANGE_REQ, (int)eBitOutput.PC_PAGE_CHANGE_COMPLETE, (int)eBitInput.PLC_WELD_READY_REQ, (int)eBitOutput.PC_WELD_READY_ACK));
|
|
|
|
Status.SetWorkingPosition(eWorkingPosition.LOADING_CELL);
|
|
|
|
// PLC 인터페이스 전까지 테스트
|
|
SeqWaitWeldOrChangePage_InitParam seqParams = new SeqWaitWeldOrChangePage_InitParam() {
|
|
CurrentPageNo = (short)_PageNo,
|
|
NeedPageNo = _SequenceSetting.UsePageChangeMode,
|
|
TimeoutSec = 10,
|
|
Models = _ScannerCanvasUserCtrl.Model
|
|
};
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
|
|
private SequenceActionResult GetPlcPageChangeOrWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// PageChangeOrWeldRequest 탈출 조건은 Weld Request가 동작했을 때임
|
|
// 해당 단계까지 왔다면 용접 요청까지 받은 상태
|
|
var resultOutParam = param.Param as SeqWaitWeldOrChangePage_OutParam;
|
|
_WeldReqTime = resultOutParam._WeldReqTime;
|
|
if (resultOutParam.Success == false) {
|
|
Log.E("Failed Page Change & Weld Request Interface");
|
|
return null;
|
|
}
|
|
|
|
Log.I($"Complete Page Change & Weld Request Interface");
|
|
|
|
// 처음 인터페이스할 때, Word Data 받아옴.
|
|
_PreviousTotalWeldingStep = _TotalWeldingStep;
|
|
_PageNo = resultOutParam.PLCPageNo;
|
|
// Total은 항상 같으므로 상관 없을 듯.
|
|
_TotalWeldingStep = Convert.ToInt16(_PLC.ReadWord(eWordInput.PLC_STEP_NO).data);
|
|
|
|
_SequenceSetting.LastPageNo = _PageNo;
|
|
context.Settings.Save(CommonSettingIds.Sequence, _SequenceSetting, "SeqAutoRunPrismaticScanner_New");
|
|
|
|
// 용접 전에 NG 및 FDC 정보를 초기화한다.
|
|
Status.GetProcessingWeldingData().IsVisionNG = false;
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_NG_JUDGE, false);
|
|
//var UploadDatas = Status.GetProcessingWeldingData().UploadProcessDatas;
|
|
//foreach (var data in UploadDatas)
|
|
// data.Clear();
|
|
//_PLC.UploadReportDatas(UploadDatas);
|
|
|
|
// PLC에게 값을 써주어야 함.
|
|
//_PLC.WriteWord((int)eWordOutput.PC_PAGE_NO, (short)_PageNo, PLCBase.ePLCDevice.D);
|
|
|
|
Log.I(string.Format("Read Words; Page No: {0}; Step No: {1}", _PageNo, _TotalWeldingStep));
|
|
|
|
if (_PageNo > _ScannerCanvasUserCtrl.Model.Layers.Count() && _PageNo > 0) {
|
|
Log.E(string.Format("Page No isn't proper. ;Page No : {0}; Layers Count: {1}", _PageNo, _ScannerCanvasUserCtrl.Model.Layers.Count()));
|
|
return null;
|
|
}
|
|
|
|
Status.GetProcessingWeldingData().CellId = _PLC.CellId();
|
|
Status.GetProcessingWeldingData().LotId = _PLC.LotId();
|
|
|
|
if (_FirstUpdateStep) {
|
|
_FirstUpdateStep = false;
|
|
return SequenceAction.Ok();
|
|
}
|
|
if (_PreviousTotalWeldingStep != _TotalWeldingStep) {
|
|
Log.E(string.Format("SeqCheckWeldingComplete Error;Changed Step No; Prev: {0}; Current: {1}", _PreviousTotalWeldingStep, _TotalWeldingStep));
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
#region 3. 용접 요청 인터페이스 (PLC <-> PC)
|
|
private SequenceActionResult SetPlcWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I(string.Format("Test1; REQ: {0}; ACK: {1}", (int)eBitInput.PLC_WELD_READY_REQ, (int)eBitOutput.PC_WELD_READY_ACK));
|
|
|
|
// PLC 인터페이스 전까지 테스트
|
|
SeqExecutePlcBitInterface_InitParam seqParams = new SeqExecutePlcBitInterface_InitParam() {
|
|
GetAddress = eCommonBitInput.PLC_WELD_READY_REQ,
|
|
SetAddress = eCommonBitOutput.PC_WELD_READY_ACK,
|
|
TimeoutSec = 60,
|
|
FirstTimeoutSec = 6 * 60 * 60, // 2시간동안 대기,
|
|
IsSetMode = false
|
|
};
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
|
|
private SequenceActionResult GetPlcWeldRequest_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// PLC 인터페이스 전까지 테스트
|
|
var resultOutParam = param.Param as SeqExecutePlcBitInterface_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
#region 4.1. 셀 데이터 받기
|
|
private string CheckCellInfoReceive(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_SequenceSetting.UseCellReport) {
|
|
Log.I(string.Format("Check Cell Info Receive"));
|
|
return SEQ_CHECK_WELDDING_RETRY;
|
|
}
|
|
else {
|
|
Log.I(string.Format("Pass Cell Info Receive"));
|
|
return SEQ_JOIN_CELL_INFO_RECEIVE;
|
|
}
|
|
}
|
|
|
|
private SequenceActionResult SetReceiveCellInfo_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
SeqReceiveCellInfo_InitParam seqParams = new SeqReceiveCellInfo_InitParam() {
|
|
};
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
|
|
private SequenceActionResult GetReceiveCellInfo_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqReceiveCellInfo_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult JoinCellInfoReceive(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
#region 4.2. 비전 보상 진행
|
|
private string CheckVisionCompensationUse(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_SequenceSetting.UseImageAcquire) {
|
|
Log.I(string.Format("Use Image Acquire"));
|
|
|
|
// 비전 보상 유무에 따른 조명 값 변경
|
|
if (_SequenceSetting.UseCellOffset) UpdateAutoLightValue(_SequenceSetting.CompensationLightValue);
|
|
else UpdateAutoLightValue(_SequenceSetting.LightValue);
|
|
|
|
if (!_Light.CheckLightOnAndValue(lightValues[0])) {
|
|
_Light.SetLightValue(lightValues);
|
|
Log.I($"Light All On !");
|
|
}
|
|
|
|
return SEQ_DO_VISION_JOB;
|
|
}
|
|
else {
|
|
// Welding Object로 넘겨주기 전에는 Offset 값을 써주어야 됨 !!
|
|
_RetryCount = 0;
|
|
_OffsetXfromModelFinder = 0;
|
|
_OffsetYfromModelFinder = 0;
|
|
Log.I(string.Format("Unuse Image Acquire"));
|
|
return SEQ_JOIN_VISION_COMPENSION;
|
|
}
|
|
}
|
|
private static SeqVisionData_Param visionParam;
|
|
private SequenceActionResult DoVisionJob(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 1. Pattern은 0번부터 시작이며, Page 숫자 OR 그 이상으로 Pattern이 있어야 함.
|
|
_PatternInfo = _Patterns[_PageNo - 1];
|
|
|
|
// 2.1. 스캐너 이동을 객체 기반의 중앙 기반 이동
|
|
FindObjectsCenter(out TargetObjectCenterPosition.X, out TargetObjectCenterPosition.Y);
|
|
Log.I(string.Format($"Move Scanner - ScannerPosX : {TargetObjectCenterPosition.X},ScannerPosY : {TargetObjectCenterPosition.Y} "));
|
|
_Scanner.JumpAbs(TargetObjectCenterPosition.X, TargetObjectCenterPosition.Y);
|
|
|
|
// 2.2. 이동까지 기다려주어야 함.
|
|
//250701 Vision Image 흔들림으로 인해 20ms로 변경
|
|
Thread.Sleep(20);
|
|
|
|
// 3.1. CameraDisplay의 Overlay된 것들 모두 클리어해줌.
|
|
_CameraDisplay.ClearMeasureGraphics();
|
|
_CameraDisplay.ClearFindGraphics();
|
|
_CameraDisplay.ClearTrainGraphics();
|
|
|
|
// 3.2. StopLive GrabSync를 통해서 이미지를 취득함.
|
|
object image = null;
|
|
_CameraAgent.StopLive();
|
|
_CameraAgent.GrabSync(_CameraDisplay, ref image);
|
|
|
|
// 4. 패턴 찾기 및 Score 기반으로 용접 여부 판단 변수 업데이트
|
|
bool isHigherLimitScore = false;
|
|
|
|
// 첫 번째 Offset 값을 사용하고 싶을 경우 UseExistOffset 활용할 것. 그러나 활용도는 매우 낮을 듯 함. 250701 기준 EL도 사용하지 않음.
|
|
if (_SequenceSetting.UseExistOffset && _PageNo != 1) {
|
|
Log.I(string.Format($"UseExistOffset : X(mm) : {_OffsetXfromModelFinder}, Y(mm) : {_OffsetYfromModelFinder}"));
|
|
if (_PatternResult != null && _PatternResult.Status == eFoundStatus.FoundOK)
|
|
isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.FirstLimitScore, _PatternInfo.PatternType);
|
|
}
|
|
else {
|
|
_PatternResult = _PatternAgent.Find(_PatternInfo, image, _CameraDisplay);
|
|
Log.I(string.Format($"First Model Find : {_PatternResult.Status.ToString()}"));
|
|
|
|
// 첫 번째 실패하면, 한 번 더 찾을 수 있는 로직 구성. (UseSubPatternOnFailure 사용)
|
|
if (_PatternResult.Status != eFoundStatus.FoundOK && _SequenceSetting.UseSubPatternOnFailure) {
|
|
_PatternInfo = _Patterns[_PageNo - 1 + _TotalWeldingStep];
|
|
_PatternResult = _PatternAgent.Find(_PatternInfo, image, _CameraDisplay);
|
|
Log.I(string.Format($"Second Model Find : {_PatternResult.Status.ToString()}"));
|
|
|
|
if (_PatternResult.Status == eFoundStatus.FoundOK)
|
|
isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.SecondLimitScore, _PatternInfo.PatternType);
|
|
}
|
|
else {
|
|
if (_PatternResult.Status == eFoundStatus.FoundOK)
|
|
isHigherLimitScore = IsHigherLimitScore(_SequenceSetting.FirstLimitScore, _PatternInfo.PatternType);
|
|
}
|
|
}
|
|
|
|
// 4.1. 패턴 Found 여부 업데이트
|
|
if (_PatternResult != null && _PatternResult.Status == eFoundStatus.FoundOK)
|
|
Status.GetProcessingWeldingData().IsVisionNG = false;
|
|
else
|
|
Status.GetProcessingWeldingData().IsVisionNG = true;
|
|
|
|
// 5. 이미지 저장 관련 EventQueue 사용을 위한 Parameter 생성
|
|
MIL_ID temp1;
|
|
MIL_ID temp2;
|
|
|
|
// 5.1. 만약, Draw 중 문제 생길 경우 Log Error 발생하도록 수정
|
|
try {
|
|
if (!Status.GetProcessingWeldingData().IsVisionNG)
|
|
_PatternAgent.Draw(_PatternInfo, _PatternResult, _CameraDisplay);
|
|
|
|
temp1 = MilEnvironment.CloneImage((MIL_ID)image);
|
|
temp2 = MilEnvironment.GetOverlayImage((IMilCameraDisplay)_CameraDisplay);
|
|
Log.I($"Vision Draw Successed.");
|
|
}
|
|
catch (Exception ex) {
|
|
temp1 = MIL.M_NULL;
|
|
temp2 = MIL.M_NULL;
|
|
Log.E($"Vision Draw Error Occured !!!!!!;{ex.Message}");
|
|
}
|
|
|
|
// 6. Offset 값 추출 및 인터락 체크
|
|
if (!Status.GetProcessingWeldingData().IsVisionNG) {
|
|
// 6.1. 보상 필요할 경우 Offset 값 구하기
|
|
if (_SequenceSetting.UseCellOffset) {
|
|
double offsetX = 0;
|
|
double offsetY = 0;
|
|
|
|
#region 기존 Offset 값 추출 코드. 뒤 코드 가독성이 좋아보여서 수정하였음. 문제 시 해당 코드 사용
|
|
//foreach (BaseResult baseResult in _PatternResult.Results) {
|
|
// if (_PatternInfo.PatternType == ePatternType.ImageModelFinder || _PatternInfo.PatternType == ePatternType.ShapeModelFinder) {
|
|
// var result = baseResult as ModelFinderResult;
|
|
// offsetX = result.ImagePosition.X;
|
|
// offsetY = result.ImagePosition.Y;
|
|
// } else if (_PatternInfo.PatternType == ePatternType.PatternMatching) {
|
|
// var result = baseResult as PatternMatchingResult;
|
|
// offsetX = result.ImagePosition.X;
|
|
// offsetY = result.ImagePosition.Y;
|
|
// } else {
|
|
// Log.E("Pattern Type is not proper !!! ");
|
|
// return null;
|
|
// }
|
|
// break;
|
|
//}
|
|
#endregion
|
|
|
|
// 6.1.1. 첫 번째 결과를 보상 값으로 활용함. 해당 구문 활용하여 추후 Score가 제일 높은 것을 고를 수도 있을 듯 함.
|
|
BaseResult baseResult = _PatternResult.Results.FirstOrDefault();
|
|
|
|
if (baseResult != null) {
|
|
switch (_PatternInfo.PatternType) {
|
|
case ePatternType.ImageModelFinder:
|
|
case ePatternType.ShapeModelFinder:
|
|
offsetX = (baseResult as ModelFinderResult).ImagePosition.X;
|
|
offsetY = (baseResult as ModelFinderResult).ImagePosition.Y;
|
|
break;
|
|
case ePatternType.PatternMatching:
|
|
offsetX = (baseResult as PatternMatchingResult).ImagePosition.X;
|
|
offsetY = (baseResult as PatternMatchingResult).ImagePosition.Y;
|
|
break;
|
|
default:
|
|
Log.E("Pattern Type is not proper !!! ");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
TranslateImageToField(offsetX, offsetY, out double _PatternOffsetX, out double _PatternOffsetY);
|
|
|
|
// 6.1.2. Offset 값의 Distance 및 Score 따른 보상 진행 여부 결정
|
|
double distance = Math.Sqrt(_PatternOffsetX * _PatternOffsetX + _PatternOffsetY * _PatternOffsetY);
|
|
// 260317 현장 작업으로 주석함
|
|
if (distance < _SequenceSetting.CellOffsetLimit /*|| isHigherLimitScore*/) {
|
|
_OffsetXfromModelFinder = _PatternOffsetX;
|
|
_OffsetYfromModelFinder = _PatternOffsetY;
|
|
_SuccessVisionResult = true;
|
|
Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; Can Compensate ; - PatternOffsetX(mm) : {_PatternOffsetX}, PatternOffsetY(mm) : {_PatternOffsetY}, Distance(mm) : {distance}, Vision Offset OK"));
|
|
}
|
|
else {
|
|
_OffsetXfromModelFinder = 0;
|
|
_OffsetYfromModelFinder = 0;
|
|
_SuccessVisionResult = false;
|
|
Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; Can't Compensate ; - PatternOffsetX(mm) : {_PatternOffsetX}, PatternOffsetY(mm) : {_PatternOffsetY}, Distance(mm) : {distance}, Vision Offset Fail"));
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
_OffsetXfromModelFinder = 0;
|
|
_OffsetYfromModelFinder = 0;
|
|
Log.I(string.Format($"UseCellOffset Mode : {_SequenceSetting.UseCellOffset}; OR Not Found ;"));
|
|
}
|
|
|
|
|
|
visionParam = new SeqVisionData_Param {
|
|
originalImageID = temp1,
|
|
overlayImageID = temp2,
|
|
IsSuccess = !Status.GetProcessingWeldingData().IsVisionNG,
|
|
VisionData_Foler = _SequenceSetting.VisionFolderName,
|
|
CellId = Status.GetProcessingWeldingData().CellId,
|
|
};
|
|
|
|
// 7. 필요시 해당 구문 테스트 필요
|
|
//_CameraAgent.StartLive(_CameraDisplay);
|
|
|
|
return SequenceAction.Ok(visionParam);
|
|
}
|
|
private bool IsHigherLimitScore(double limitScore, ePatternType patternType)
|
|
{
|
|
double Score = -1;
|
|
|
|
#region 기존 코드. 이 후 코드가 가독성이 좋아보여서 수정. 필요 시, 사용할 것.
|
|
//foreach (BaseResult baseResult in _PatternResult.Results) {
|
|
// if (_PatternInfo.PatternType == ePatternType.ImageModelFinder || _PatternInfo.PatternType == ePatternType.ShapeModelFinder) {
|
|
// var result = baseResult as ModelFinderResult;
|
|
// Score = result.Score;
|
|
// } else if (_PatternInfo.PatternType == ePatternType.PatternMatching) {
|
|
// var result = baseResult as PatternMatchingResult;
|
|
// Score = result.Score;
|
|
// }
|
|
// break;
|
|
//}
|
|
#endregion
|
|
|
|
Score = GetPatternScore(patternType);
|
|
Log.I(string.Format($"Extract Score : {Score}; Limit Score : {limitScore}"));
|
|
|
|
if (Score.Equals(double.NaN)) {
|
|
Log.I(string.Format($"Fail Extract Score : Pattern Find Logic Mismatch"));
|
|
return false;
|
|
}
|
|
|
|
return Score > limitScore ? true : false;
|
|
}
|
|
private double GetPatternScore(ePatternType patternType)
|
|
{
|
|
BaseResult baseResult = _PatternResult?.Results?.FirstOrDefault();
|
|
|
|
if (baseResult != null) {
|
|
switch (patternType) {
|
|
case ePatternType.ImageModelFinder:
|
|
case ePatternType.ShapeModelFinder:
|
|
return (baseResult as ModelFinderResult).Score;
|
|
case ePatternType.PatternMatching:
|
|
return (baseResult as PatternMatchingResult).Score;
|
|
default:
|
|
Log.E("Pattern Type is not proper !!! ");
|
|
return double.NaN;
|
|
}
|
|
}
|
|
return double.NaN;
|
|
}
|
|
private SequenceActionResult SaveImagesEvent(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (visionParam is SeqVisionData_Param result && result != null) {
|
|
var currentDate = DateTime.Now;
|
|
string SequenceSettingFilePath = result.VisionData_Foler;
|
|
|
|
var FinalFilePath = Path.Combine(SequenceSettingFilePath, currentDate.ToString("yyyy"), currentDate.ToString("MM"), currentDate.ToString("dd"));
|
|
if (!Directory.Exists(FinalFilePath)) {
|
|
Directory.CreateDirectory(FinalFilePath);
|
|
}
|
|
|
|
string SuccessStatus = result.IsSuccess ? "OK" : "NG";
|
|
string CurrentTimeStamp = DateTime.Now.ToString("HHmmss");
|
|
string rawFileName = $"{FinalFilePath}\\Raw\\Page{_PageNo.ToString()}\\{SuccessStatus}\\{CurrentTimeStamp}_{result.CellId}.png";
|
|
string resultFileName = $"{FinalFilePath}\\Result\\Page{_PageNo.ToString()}\\{SuccessStatus}\\{CurrentTimeStamp}_{result.CellId}.png";
|
|
|
|
if (result.originalImageID != MIL.M_NULL) {
|
|
ImageUtil.SaveFieldScanImageJPG(result.originalImageID, rawFileName, 10);
|
|
MilEnvironment.FreeImage(result.originalImageID);
|
|
result.originalImageID = MIL.M_NULL;
|
|
Log.D($"Update Q Raw Image Complete;{rawFileName}");
|
|
}
|
|
else {
|
|
Log.E($"Update Q Raw Image Failed;{rawFileName};rawImage Is Null..");
|
|
}
|
|
if (result.overlayImageID != MIL.M_NULL) {
|
|
ImageUtil.SaveFieldScanImageJPG(result.overlayImageID, resultFileName, 10);
|
|
MilEnvironment.FreeImage(result.overlayImageID);
|
|
result.overlayImageID = MIL.M_NULL;
|
|
Log.D($"Update Q Overlay Image Complete;{resultFileName}");
|
|
}
|
|
else {
|
|
Log.E($"Update Q Overlay Image Failed;{resultFileName};resultImage Is Null");
|
|
}
|
|
}
|
|
else
|
|
Log.E("SeqVisionData_Param is null >> Image Save Fail");
|
|
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
private string CheckSaveWeldImage(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_SequenceSetting.UseWeldResultImage) {
|
|
return SEQ_SAVE_WELD_IMAGE;
|
|
}
|
|
else {
|
|
return SEQ_SET_PARAMS_PLC_WELD_COMPLETE_INTERFACE_SEQ;
|
|
}
|
|
}
|
|
|
|
private SequenceActionResult SaveWeldImage(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// WeldResult이미지는 EventQ 저장 버그가 발생하였는데 원인 파악중.
|
|
double ScannerPosX = 0, ScannerPosY = 0;
|
|
|
|
// 용접 이후에 용접 전에 찍은 이미지와 동일한 위치로 용접을 진행해야 함
|
|
// 객체 기반의 중앙 기반
|
|
FindObjectsCenter(out ScannerPosX, out ScannerPosY);
|
|
Log.I(string.Format($"Move Scanner - ScannerPosX : {ScannerPosX},ScannerPosY : {ScannerPosY} "));
|
|
_Scanner.JumpAbs(ScannerPosX, ScannerPosY);
|
|
|
|
// 이동까지 기다려주어야 함.
|
|
Thread.Sleep(20); // EL Welder에서 10ms로 설정 시 이동중에 이미지가 촬영되어 대기시간 증가
|
|
|
|
_CameraDisplay.ClearMeasureGraphics();
|
|
_CameraDisplay.ClearFindGraphics();
|
|
_CameraDisplay.ClearTrainGraphics();
|
|
|
|
object image = null;
|
|
_CameraAgent.StopLive();
|
|
_CameraAgent.GrabSync(_CameraDisplay, ref image);
|
|
|
|
if (_PatternResult?.Status == eFoundStatus.FoundOK) {
|
|
_PatternAgent.Draw(_PatternInfo, _PatternResult, _CameraDisplay);
|
|
}
|
|
|
|
MIL_ID temp1;
|
|
MIL_ID temp2;
|
|
try {
|
|
// 성공하든 아니든 이미지를 남겨보자.
|
|
temp1 = MilEnvironment.CloneImage((MIL_ID)image);
|
|
temp2 = MilEnvironment.GetOverlayImage((IMilCameraDisplay)_CameraDisplay);
|
|
}
|
|
catch (Exception ex) {
|
|
temp1 = MIL.M_NULL;
|
|
temp2 = MIL.M_NULL;
|
|
Log.FuncE($"Vision Draw Error Occured !!!!!!;{ex.Message}");
|
|
}
|
|
|
|
visionParam = new SeqVisionData_Param {
|
|
originalImageID = temp1,
|
|
overlayImageID = temp2,
|
|
IsSuccess = !Status.GetProcessingWeldingData().IsVisionNG,
|
|
VisionData_Foler = _SequenceSetting.WeldResultFolderName,
|
|
CellId = Status.GetProcessingWeldingData().CellId,
|
|
};
|
|
return SequenceAction.Ok(visionParam);
|
|
|
|
}
|
|
|
|
private object SendEvent(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var seqParam = param.Param as SeqVisionData_Param;
|
|
return SequenceAction.Ok(seqParam);
|
|
}
|
|
private SequenceActionResult JoinVisionCompensation(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
return SequenceAction.Ok();
|
|
}
|
|
#endregion
|
|
|
|
private string CheckVisionComplete(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_SequenceSetting.UseImageAcquire) {
|
|
try {
|
|
int delayTimeMsec = _SequenceSetting.ImageAcquireDelayTime;
|
|
Log.I($"Welding Before Delay : {delayTimeMsec}msec");
|
|
Thread.Sleep(delayTimeMsec);
|
|
} catch (Exception) {
|
|
}
|
|
}
|
|
|
|
var visionComplete = !Status.GetProcessingWeldingData().IsVisionNG && _SuccessVisionResult && _SequenceSetting.UseCellOffset;
|
|
var WeldingSkip = !visionComplete && _SequenceSetting.UseNgCellSkip;
|
|
if (WeldingSkip) {
|
|
Log.I($"Vision Compension Complete[{!Status.GetProcessingWeldingData().IsVisionNG}] / Vision Result[{_SuccessVisionResult}] / UseCellOffset[{_SequenceSetting.UseCellOffset}]");
|
|
return SEQ_NG_RESULT_PROCESS;
|
|
}
|
|
|
|
// 성공했거나, Vision Offset을 사용 안하면 다음 스텝으로
|
|
return SEQ_GENERATE_WELDING_OBJECT;
|
|
}
|
|
|
|
private SequenceActionResult NgResultProcess(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 이미 NG 처리는 했고, PLC에서 로직상 BUSY는 토글되야 한다고 해서 넣어줌
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_NG_JUDGE, Status.GetProcessingWeldingData().IsVisionNG || !_SuccessVisionResult);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_BUSY, true);
|
|
Thread.Sleep(100);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
#region 5. 용접 진행
|
|
private SequenceActionResult GenerateWeldingObject(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
_SelectedDrawObjectList = _ScannerCanvasUserCtrl.Model.Layers[_PageNo - 1].Objects;
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SetComponentTeachingrun_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_BUSY, true);
|
|
|
|
Log.I(string.Format("Weld Busy On ! Set ComponentTeachingrun Start."));
|
|
|
|
_WeldStartTime = DateTime.Now;
|
|
Status.GetProcessingWeldingData().WeldingStartTime = _WeldStartTime;
|
|
|
|
var currentModelInfo = EquipmentSpecificModelUtil.GetCurrentRecipeEquipmentSpecificModel();
|
|
if (currentModelInfo.equipmentSpecificModel == null) {
|
|
MessageUtil.ShowWarningToast(string.Format("선택된 model 이 없습니다.", "Laser On"));
|
|
return null;
|
|
}
|
|
|
|
var intervalTimeBlowOn = 0;
|
|
var intervalTimeBlowOff = 0;
|
|
|
|
if (currentModelInfo.equipmentSpecificModel.UseBlow) {
|
|
intervalTimeBlowOn = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOn;
|
|
intervalTimeBlowOff = currentModelInfo.equipmentSpecificModel.IntervalTimeBlowOff;
|
|
}
|
|
|
|
Log.I(string.Format("Set ComponentTeachingrun Immediately!"));
|
|
|
|
// Object를 만들어
|
|
SeqTeachingRun_InitParam seqParam = new SeqTeachingRun_InitParam() {
|
|
IsUseExternalObjects = true,
|
|
ExternalObjects = _SelectedDrawObjectList,
|
|
|
|
//UseStream = _EquipmentInfo.UseStream,
|
|
UseStream = currentModelInfo.equipmentSpecificModel.UseStream,
|
|
|
|
UseBlow = currentModelInfo.equipmentSpecificModel.UseBlow,
|
|
IntervalTimeBlowOn = intervalTimeBlowOn,
|
|
IntervalTimeBlowOff = intervalTimeBlowOff,
|
|
|
|
NeedSetLaserTiming = true,
|
|
CellCenterOffsetX = _OffsetXfromModelFinder,
|
|
CellCenterOffsetY = _OffsetYfromModelFinder
|
|
};
|
|
|
|
Log.I(string.Format("Set ComponentTeachingrun Complete!"));
|
|
|
|
return SequenceAction.Ok(seqParam);
|
|
}
|
|
|
|
private SequenceActionResult GetComponentTeachingrun_SeqResult(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqTeachingRun_OutParam;
|
|
Log.I(string.Format("Get ComponentTeachingrun Complete!"));
|
|
|
|
if (resultOutParam.Success == false) {
|
|
Log.I(string.Format("SeqComponentTeachingrun Complete Error;Success Failed."));
|
|
return null;
|
|
}
|
|
else Log.I(string.Format("SeqComponentTeachingrun Complete Success;Welding Complete!"));
|
|
|
|
int bitRet = _PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false);
|
|
Log.I("Weld Busy OFF!");
|
|
|
|
_WeldEndTime = DateTime.Now;
|
|
_WeldSpanTime = _WeldEndTime.Subtract(_WeldStartTime);
|
|
|
|
Log.I($"[TactTime] Page({_PageNo}) Total Welding Time : {_WeldSpanTime.TotalMilliseconds}msec");
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult GetPlcWeldCompleteInterface_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
var resultOutParam = param.Param as SeqExecutePlcBitInterface_OutParam;
|
|
if (resultOutParam.Success == false) {
|
|
Log.I(string.Format("SeqCheckWeldingComplete Error;Success Failed."));
|
|
return null;
|
|
}
|
|
else Log.I(string.Format("SeqCheckWeldingComplete Success;Welding Complete!"));
|
|
|
|
_WeldComTime = DateTime.Now;
|
|
Log.I($"***** 공정 시간 WeldPage No : {_PageNo} WeldRequest ~ WeldComplete : {_WeldComTime.Subtract(_WeldReqTime).TotalMilliseconds}ms");
|
|
_CurrentWeldingStep++;
|
|
|
|
if (_CurrentWeldingStep >= _TotalWeldingStep) {
|
|
Log.I(string.Format("Need to Update the Cell Info;{0}/{1}", _CurrentWeldingStep, _TotalWeldingStep));
|
|
_IsWeldingRetry = false;
|
|
_CurrentWeldingStep = 0;
|
|
Status.SetWorkingPosition(eWorkingPosition.UNLOADING_CELL);
|
|
UpdateProductCount(context);
|
|
UpdateProductInfoForView();
|
|
}
|
|
else {
|
|
Log.I(string.Format("Update Welding Step;{0}/{1}", _CurrentWeldingStep, _TotalWeldingStep));
|
|
_IsWeldingRetry = true;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SetPlcWeldCompleteInterface_SeqParams(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_SequenceSetting.UseImageAcquire) {
|
|
try {
|
|
int delayTimeMsec = _SequenceSetting.ImageAcquireDelayTime;
|
|
Log.I($"Welding After Delay : {delayTimeMsec}msec");
|
|
Thread.Sleep(delayTimeMsec);
|
|
} catch (Exception) {
|
|
}
|
|
}
|
|
|
|
Log.I(string.Format("SeqCheckWeldingComplete Set Parameters"));
|
|
|
|
SeqExecutePlcBitInterface_InitParam seqParams = new SeqExecutePlcBitInterface_InitParam() {
|
|
GetAddress = (eCommonBitInput)eBitInput.PLC_WELD_COMPLETE_ACK,
|
|
SetAddress = (eCommonBitOutput)eBitOutput.PC_WELD_COMPLETE,
|
|
TimeoutSec = 60,
|
|
FirstTimeoutSec = 60,
|
|
IsSetMode = true
|
|
};
|
|
return SequenceAction.Ok(seqParams);
|
|
}
|
|
#endregion
|
|
|
|
#region 6. 데이터 쓰기 및 종료
|
|
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Status.SetWorkingPosition(eWorkingPosition.REPORTING_RESULT);
|
|
|
|
DataTable table = new DataTable("CellHistory");
|
|
table.Columns.Add("time", typeof(string));
|
|
table.Columns.Add("Cell Id", typeof(string));
|
|
table.Columns.Add("Pre Compensation X", typeof(double));
|
|
table.Columns.Add("Pre Compensation Y", typeof(double));
|
|
table.Columns.Add("Post Compensation X", typeof(double));
|
|
table.Columns.Add("Post Compensation Y", typeof(double));
|
|
table.Columns.Add("(Pre - Post) X", typeof(double));
|
|
table.Columns.Add("(Pre - Post) Y", typeof(double));
|
|
table.Columns.Add("(Pre - Post) RMS", typeof(double));
|
|
table.Columns.Add("Score", typeof(double));
|
|
|
|
var SystemSetting = context.Settings[CommonSettingIds.SystemParameter] as SystemParameter;
|
|
|
|
var DrawingObjectCenterX = TargetObjectCenterPosition.X;
|
|
var DrawingObjectCenterY = TargetObjectCenterPosition.Y;
|
|
|
|
var FindObjectCenterX = _OffsetXfromModelFinder;
|
|
var FindObjectCenterY = _OffsetYfromModelFinder;
|
|
|
|
var CompensionGapX = DrawingObjectCenterX - FindObjectCenterX;
|
|
var CompensionGapY = DrawingObjectCenterY - FindObjectCenterY;
|
|
|
|
table.Rows.Add(DateTime.Now.ToString("HH:mm:ss"),
|
|
Status.GetProcessingWeldingData().CellId,
|
|
DrawingObjectCenterX, DrawingObjectCenterY,
|
|
FindObjectCenterX, FindObjectCenterY,
|
|
CompensionGapX, CompensionGapY,
|
|
Math.Sqrt(CompensionGapX * CompensionGapX + CompensionGapY * CompensionGapY),
|
|
GetPatternScore(_PatternInfo.PatternType));
|
|
|
|
string today = DateTime.Now.ToString("yyyyMMdd", CultureInfo.InvariantCulture);
|
|
string safeName = $"CellInfo_{today}.csv";
|
|
|
|
CSV_Manager.GetInstance().Save_DataTableToCsv(SystemSetting.CellHistoryFolderPath, safeName, table);
|
|
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
RestoreDeviceStatus();
|
|
|
|
context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult);
|
|
SeqAutoRunPrismaticScanner_OutParam result = new SeqAutoRunPrismaticScanner_OutParam() { Success = seqResult };
|
|
|
|
if (seqResult == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_AutoRun_ResultFailed);
|
|
}
|
|
Status.SetWorkingPosition(eWorkingPosition.DONE);
|
|
|
|
return SequenceAction.Ok(result);
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region 구동 함수
|
|
|
|
private bool InitSequenceVariable(SequenceContext context)
|
|
{
|
|
// TODO: [장비구현필요] Initialize Variable 추가
|
|
FovInfo _fovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault();
|
|
_PatternAgent = FovPatternAgentManager.GetAgent(_fovInfo.ToSubSysInfo());
|
|
_Patterns = _PatternAgent.GetMainPatterns(_fovInfo);
|
|
_PatternInfo = _Patterns[_InitParam.VisionRecipeNo];
|
|
_CameraDisplay = CameraDisplayManager.GetDisplay(_fovInfo, eDisplayType.Machine_A);
|
|
_CameraAgent = CameraAgentManager.GetCameraAgent(_fovInfo);
|
|
_FieldScanParams = FieldScanParams.GetInstance();
|
|
_RetryCount = 0;
|
|
|
|
var mainPage = CommonHelper.GetMainPage();
|
|
_ScannerCanvasUserCtrl = mainPage.ScannerCanvasCtrlTeaching;
|
|
// PLC에게 받는 PageNo는 1부터 시작 !
|
|
_PageNo = 1;
|
|
_CurrentWeldingStep = 0;
|
|
_PreviousTotalWeldingStep = 0;
|
|
_TotalWeldingStep = 0;
|
|
_OffsetXfromModelFinder = 0;
|
|
_OffsetYfromModelFinder = 0;
|
|
|
|
_IsWeldingRetry = false;
|
|
_FirstUpdateStep = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
//Device Init
|
|
_Scanner = context.GetLaserScanner();
|
|
_Laser = context.GetLaser();
|
|
_PLC = context.GetPLC() as PLCControllerPrismaticScanner;
|
|
_Light = context.GetLight();
|
|
}
|
|
|
|
private bool CheckDeviceReady(SequenceContext context)
|
|
{
|
|
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner, CommonDeviceIds.Laser, CommonDeviceIds.PLCDevice };
|
|
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
|
|
// 비전 오프셋을 쓰길 원한다면, 첫 번째 Object가 Arc 혹은 Dot이어야 함.
|
|
if (_SequenceSetting.UseImageAcquire) {
|
|
foreach (ICanvasLayer layer in _ScannerCanvasUserCtrl.Model.Layers) {
|
|
List<IDrawObject> sourcelist = layer.Objects;
|
|
_UnpackDrawObject?.Clear();
|
|
_UnpackDrawObject = new List<IDrawObject>();
|
|
UnpackRecipes(sourcelist);
|
|
|
|
for (int i = 0; i < _UnpackDrawObject.Count; i++) {
|
|
if (!(_UnpackDrawObject[i] is Arc || _UnpackDrawObject[i] is Dot || _UnpackDrawObject[i] is Spline)) {
|
|
Log.E(string.Format("Object of Page{0} is not Arc & Dot. If you use a Image Acquire, check Page{0} objects", layer.No, layer.No));
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 패턴 갯수 관련 인터락 추가
|
|
int patternCount = _Patterns.Count();
|
|
int layerCount = _ScannerCanvasUserCtrl.Model.Layers.Count();
|
|
if (_SequenceSetting.UseSubPatternOnFailure) {
|
|
if (patternCount < layerCount * 2) {
|
|
Log.E($"Can't Use SubPattern. Because of Sizes. Pattern Count : {patternCount}; Layer Count :{layerCount}");
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
if (patternCount < layerCount) {
|
|
Log.E($"Can't Use Pattern. Because of Sizes. Pattern Count : {patternCount}; Layer Count :{layerCount}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool InitializeDeviceStatus(SequenceContext context)
|
|
{
|
|
|
|
return true;
|
|
}
|
|
|
|
private void TranslateImageToField(double imgPosX, double imgPosY, out double realPosX, out double realPosY)
|
|
{
|
|
var imageWidthChild = _FieldScanParams.GetimageSizeWidthChild();
|
|
var imageHeightChild = _FieldScanParams.GetimageSizeHeightChild();
|
|
double moveOffsetX = 0;
|
|
double moveOffsetY = 0;
|
|
var cameraROIWidth = ((imageWidthChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
var cameraROIHeight = ((imageHeightChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
|
|
moveOffsetX = ((imgPosX * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0 - cameraROIWidth * 0.5;
|
|
moveOffsetY = cameraROIHeight * 0.5 - ((imgPosY * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
|
|
double angle = 0;
|
|
|
|
realPosX = moveOffsetX * Math.Cos(angle) + moveOffsetY * Math.Sin(angle);
|
|
realPosY = -moveOffsetX * Math.Sin(angle) + moveOffsetY * Math.Cos(angle);
|
|
}
|
|
|
|
private void FindObjectsCenter(out double x, out double y)
|
|
{
|
|
x = 0; y = 0;
|
|
List<IDrawObject> sourcelist = _ScannerCanvasUserCtrl.Model.Layers[_PageNo - 1].Objects;
|
|
|
|
_UnpackDrawObject?.Clear();
|
|
_UnpackDrawObject = new List<IDrawObject>();
|
|
UnpackRecipes(sourcelist);
|
|
|
|
List<UnitPoint> centers = new List<UnitPoint>();
|
|
for (int i = 0; i < _UnpackDrawObject.Count; i++) {
|
|
if (_UnpackDrawObject[i] is Arc) {
|
|
Arc tempArc = _UnpackDrawObject[i] as Arc;
|
|
centers.Add(tempArc.Center);
|
|
}
|
|
else if (_UnpackDrawObject[i] is Dot) {
|
|
Dot tempDot = _UnpackDrawObject[i] as Dot;
|
|
centers.Add(tempDot.P1);
|
|
}
|
|
else if (_UnpackDrawObject[i] is Spline spline) {
|
|
centers.Add(spline.Center);
|
|
}
|
|
|
|
}
|
|
x = centers.Count > 0 ? centers.Average(center => center.X) : 0;
|
|
y = centers.Count > 0 ? centers.Average(center => center.Y) : 0;
|
|
}
|
|
|
|
private static void UnpackRecipes(List<IDrawObject> recipes)
|
|
{
|
|
// Recipe를 재귀적으로 탐색해서 List로 재구성하는 함수
|
|
if (recipes == null)
|
|
return;
|
|
|
|
for (int i = 0; i < recipes.Count; i++) {
|
|
if (recipes[i] is CoreUnit.Control.UserControl.Canvas.Group) {
|
|
CoreUnit.Control.UserControl.Canvas.Group subGroup = recipes[i] as CoreUnit.Control.UserControl.Canvas.Group;
|
|
List<IDrawObject> subrecipes = subGroup.SubObjects as List<IDrawObject>;
|
|
UnpackRecipes(subrecipes);
|
|
}
|
|
else {
|
|
_UnpackDrawObject.Add(recipes[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ChangeRecipes(short pageNo)
|
|
{
|
|
_PageNo = pageNo;
|
|
}
|
|
|
|
private bool RestoreDeviceStatus()
|
|
{
|
|
|
|
return true;
|
|
}
|
|
|
|
private void InitializePlcBits()
|
|
{
|
|
// 초기화
|
|
_PLC.WriteBit(eBitOutput.PC_PAGE_CHANGE_COMPLETE, false);
|
|
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_READY_ACK, false);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_BUSY, false);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_COMPLETE, false);
|
|
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_P_READY_REQ, false);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_P_BUSY, false);
|
|
_PLC.WriteBit(eBitOutput.PC_WELD_P_COMP_ACK, false);
|
|
|
|
//var UploadDatas = Status.GetProcessingWeldingData().UploadProcessDatas;
|
|
//foreach (var data in UploadDatas)
|
|
// data.Clear();
|
|
//_PLC.UploadReportDatas(UploadDatas);
|
|
}
|
|
#endregion
|
|
|
|
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()
|
|
{
|
|
// 자동 운전 끝날 떄에는 꺼주기
|
|
if (_Laser.GetLaserReady()) _Laser.LaserOff();
|
|
|
|
Status.SetStatus(eEqpStatus.Manual);
|
|
_PLC.WriteBit(eBitOutput.PC_AUTO_STATUS, false);
|
|
|
|
InitializePlcBits();
|
|
}
|
|
private void UpdateProductCount(SequenceContext context)
|
|
{
|
|
// SystemParameter를 저장하기 전에는 반드시 업데이트를 해주어야 한다.
|
|
// SystemParameter 값과 동기화
|
|
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
|
|
|
_TodayProduct = _SystemParameter.TodayProductCount;
|
|
_TotalProduct = _SystemParameter.TotalProductCount;
|
|
if (_TodayProduct < uint.MaxValue) {
|
|
_TodayProduct++;
|
|
}
|
|
if (_TotalProduct < uint.MaxValue) {
|
|
_TotalProduct++;
|
|
}
|
|
_SystemParameter.TodayProductCount = _TodayProduct;
|
|
_SystemParameter.TotalProductCount = _TotalProduct;
|
|
_WeldEndTime = DateTime.Now;
|
|
_SystemParameter.LastProductTime = _WeldEndTime;
|
|
|
|
//Systemparameter Save
|
|
context.Settings.Save(CommonSettingIds.SystemParameter, _SystemParameter, "SeqAutoRunPrismaticScanner_New");
|
|
}
|
|
|
|
private void UpdateProductInfoForView()
|
|
{
|
|
Status.GetProcessingWeldingData().TotalProduct = _TotalProduct;
|
|
Status.GetProcessingWeldingData().TodayProduct = _TodayProduct;
|
|
|
|
Status.GetProcessingWeldingData().WeldingStartTime = _WeldStartTime;
|
|
Status.GetProcessingWeldingData().WeldingEndTime = _WeldEndTime;
|
|
Status.GetProcessingWeldingData().WeldingSpanTimeMilliseconds = _WeldSpanTime.TotalMilliseconds.ToString();
|
|
|
|
Status.GetProcessingWeldingData().LotId = _LotId;
|
|
Status.GetProcessingWeldingData().CellId = _CellId;
|
|
}
|
|
|
|
private void UpdateAutoLightValue(int value)
|
|
{
|
|
lightValues[0] = value;
|
|
lightValues[1] = value;
|
|
lightValues[2] = value;
|
|
lightValues[3] = value;
|
|
}
|
|
}
|
|
|
|
public class SeqAutoRunPrismaticScanner_InitParam : InitParam
|
|
{
|
|
public int VisionRecipeNo { get; set; } = 0;
|
|
}
|
|
|
|
public class SeqAutoRunPrismaticScanner_OutParam : OutParam
|
|
{
|
|
|
|
}
|
|
|
|
public class SeqVisionData_Param
|
|
{
|
|
public MIL_ID originalImageID;
|
|
public MIL_ID overlayImageID;
|
|
public bool IsSuccess;
|
|
public string VisionData_Foler;
|
|
public string CellId;
|
|
}
|
|
}
|