351 lines
13 KiB
C#
351 lines
13 KiB
C#
using Aurora.Api;
|
|
using AuroraLaser.Coherent;
|
|
using AuroraLaserScanner;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Settings;
|
|
|
|
namespace WeldingCommon.Sequences
|
|
{
|
|
public class SeqMarkGrid
|
|
{
|
|
static readonly Logger Log = new Logger("SeqMarkGrid");
|
|
|
|
const string SEQ_ENTER = "[SeqMarkGrid] SEQ_ENTER"; // inputParam 으로 받자.
|
|
const string SEQ_CHECK_INIT_CONDITION = "[SeqMarkGrid] Check Init Condition"; // Check Init Condition
|
|
|
|
const string SEQ_DOWNLOAD_MARKING_GRID_LIST = "[SeqMarkGrid] Download Marking GridList";
|
|
const string SEQ_EXCUTE_SCANNER = "[SeqMarkGrid] Excute Scanner";
|
|
const string SEQ_WAIT_SCANNER_TASK_COMPLETE = "[SeqMarkGrid] Wait Scanner Task Complete";
|
|
|
|
const string SEQ_SAVE_RESULT_DATA = "[SeqMarkGrid] Save Result Data";
|
|
|
|
const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqMarkGrid] Write Completion PLC Bit";
|
|
const string SEQ_COMPLETE = "[SeqMarkGrid] SEQ_COMPLETE"; // 완료
|
|
|
|
static class ContextKey
|
|
{
|
|
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqMarkGrid";
|
|
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqMarkGrid";
|
|
}
|
|
|
|
|
|
private SeqMarkGrid_InitParam _InitParam;
|
|
|
|
private Scanner _Scanner;
|
|
private SystemParameter _SystemParameter;
|
|
|
|
private eListNo _MarkingGridScannerListNo;
|
|
private double _JumpSpeed;
|
|
|
|
private List<PointF> _MarkingPositionList_MM; // MM 은 밀리미터 단위 인듯
|
|
|
|
//private DateTime _WeldingStartTime;
|
|
|
|
public SequenceBuilder Builder()
|
|
{
|
|
var sb = new SequenceBuilder(1000, true);
|
|
////var sb = new SequenceBuilder(1000, false); // With log
|
|
|
|
sb.AddAction(SEQ_ENTER, Sequence_Enter);
|
|
sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기
|
|
|
|
sb.AddAction(SEQ_DOWNLOAD_MARKING_GRID_LIST, DownloadMarkingGridList); //분기
|
|
sb.AddAction(SEQ_EXCUTE_SCANNER, ExcuteScanner);
|
|
sb.AddAction(SEQ_WAIT_SCANNER_TASK_COMPLETE, WaitScannerTaskComplete);
|
|
|
|
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_DOWNLOAD_MARKING_GRID_LIST] > sb[SEQ_EXCUTE_SCANNER] > sb[SEQ_WAIT_SCANNER_TASK_COMPLETE]
|
|
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_COMPLETE]);
|
|
|
|
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
|
|
|
|
|
sb.OnStopped(OnStopped);
|
|
sb.OnForceError(OnForceError);
|
|
|
|
|
|
//sb.Draw("SeqMarkGrid.pdf");
|
|
|
|
return sb;
|
|
}
|
|
|
|
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("SeqMarkGrid Start");
|
|
|
|
_InitParam = param.Param as SeqMarkGrid_InitParam;
|
|
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
|
|
|
InitDev(context);
|
|
if (!CheckDeviceReady(context)) { //Check Device
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_MarkGrid_DeviceNotReady);
|
|
Log.E("The devices are not active.");
|
|
return null;
|
|
}
|
|
|
|
if (InitSequenceVariable(context) == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_MarkGrid_InitVariableError);
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool InitSequenceVariable(SequenceContext context)
|
|
{
|
|
// MarkGrid 는 Scanner의 List2 를 사용한다.
|
|
_MarkingGridScannerListNo = eListNo.LIST2;
|
|
_JumpSpeed = _Scanner.Config.JumpSpeed;
|
|
|
|
// Initialize MasterPos
|
|
_MarkingPositionList_MM = new List<PointF>();
|
|
|
|
float posX = 0;
|
|
float posY = 0;
|
|
|
|
for (int column = 0; column < _InitParam.ColumnCount; column++) {
|
|
posX = _InitParam.UnitLength * ((column % _InitParam.ColumnCount) - (_InitParam.ColumnCount - 1) / 2f);
|
|
|
|
for (int row = 0; row < _InitParam.RowCount; row++) {
|
|
posY = _InitParam.UnitLength * ((row % _InitParam.RowCount) - (_InitParam.RowCount - 1) / 2f);
|
|
|
|
_MarkingPositionList_MM.Add(new PointF(posX, posY));
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
//Device Init
|
|
_Scanner = context.GetLaserScanner();
|
|
}
|
|
|
|
private bool CheckDeviceReady(SequenceContext context)
|
|
{
|
|
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner };
|
|
bool isAllDeviceActivated = true;
|
|
foreach (string item in deviceListToCheck) {
|
|
if (!context.Devices[item].IsActivated) {
|
|
isAllDeviceActivated = isAllDeviceActivated && false;
|
|
}
|
|
}
|
|
|
|
return isAllDeviceActivated;
|
|
}
|
|
|
|
private bool CheckCondition()
|
|
{
|
|
if (CheckCondition_Interlock()) {
|
|
if (InitializeDeviceStatus()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool CheckCondition_Interlock()
|
|
{
|
|
// PLC, Data, IO 등 Interlock checking
|
|
return true;
|
|
}
|
|
|
|
private bool InitializeDeviceStatus()
|
|
{
|
|
// Device 의 status 를 맞추자. MarkGrid 는 Scanner 를 설정 한다. 초기 설정 해야 하는 값으로
|
|
|
|
//LaserCorrectionTable 사용 (1 소스 Initialize() 함수에 있던 내용)
|
|
_Scanner.SelectCorrectionTable(2);
|
|
|
|
// 1.스캐너 리스트 동작구성
|
|
_Scanner.SetStartList(_MarkingGridScannerListNo);
|
|
|
|
//P5동 2층 데모기 테스트 temp
|
|
_Scanner.SetLaserTiming(1, 10000 * 1000, 10000 * 1000);
|
|
|
|
_Scanner.SetLaesrDelay(0, 0);
|
|
|
|
//3.DA(레이저 파워값) 설정
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, (float)_InitParam.MarkPower, eFunctionType.LIST);
|
|
|
|
////4.점프 및 마크 속도 설정
|
|
_Scanner.SetJumpSpeed(_JumpSpeed);
|
|
_Scanner.SetMarkSpeed(_InitParam.MarkSpeed);
|
|
|
|
return true;
|
|
}
|
|
|
|
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (!CheckCondition()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_MarkGrid_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("DoCrossLaserShot Sequence CheckInitCondition");
|
|
return SEQ_DOWNLOAD_MARKING_GRID_LIST;
|
|
}
|
|
|
|
private SequenceActionResult DownloadMarkingGridList(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("Start List up Marking Grid.");
|
|
|
|
for (int i = 0; i < _MarkingPositionList_MM.Count; i++) {
|
|
//십자마킹 가로
|
|
_Scanner.JumpAbs(_MarkingPositionList_MM[i].X - _InitParam.MarkLength * 0.5, _MarkingPositionList_MM[i].Y, eFunctionType.LIST);
|
|
_Scanner.MarkAbs(_MarkingPositionList_MM[i].X + _InitParam.MarkLength * 0.5, _MarkingPositionList_MM[i].Y);
|
|
|
|
//십자마킹 세로
|
|
_Scanner.JumpAbs(_MarkingPositionList_MM[i].X, _MarkingPositionList_MM[i].Y - _InitParam.MarkLength * 0.5, eFunctionType.LIST);
|
|
_Scanner.MarkAbs(_MarkingPositionList_MM[i].X, _MarkingPositionList_MM[i].Y + _InitParam.MarkLength * 0.5);
|
|
}
|
|
|
|
_Scanner.SetEndList();
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult ExcuteScanner(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("Marking Start");
|
|
//_WeldingStartTime = DateTime.Now;
|
|
_Scanner.ExecuteList(_MarkingGridScannerListNo);
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult WaitScannerTaskComplete(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.FuncI(MethodBase.GetCurrentMethod().Name);
|
|
|
|
var res = context.RetryUntilSuccess(CheckScannerTaskComplete, _SystemParameter.WeldLinesTaskTimeOut * 1000);
|
|
if (res == E2.TIMEOUT) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_MarkGrid_TimeOverExcuteList);
|
|
// Scanner complete 되는 것이 timeout 까지 종료되지 않으면, excute time over 로 sequence 종료
|
|
Log.FuncE("Time Over excuteList");
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool CheckScannerTaskComplete()
|
|
{
|
|
if (_Scanner.GetBusyStatus()) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 결과 Data 를 업데이트 함. format 유지, MarkGrid 없음
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 완료 비트 write 하는 Node 추가 필요. format 유지, MarkGrid 없음
|
|
|
|
Log.D("MarkGrid Sequence WriteCompletionPLCBit");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
RestoreDeviceStatus();
|
|
Log.I("MarkGrid Complete");
|
|
|
|
context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult);
|
|
SeqMarkGrid_OutParam result = new SeqMarkGrid_OutParam() { Success = seqResult };
|
|
|
|
if (seqResult == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_MarkGrid_ResultFailed);
|
|
}
|
|
|
|
Log.D("MarkGrid Sequence Complete");
|
|
return SequenceAction.Ok(result);
|
|
}
|
|
|
|
private bool RestoreDeviceStatus()
|
|
{
|
|
//vision correctiontable로 원복
|
|
_Scanner.SelectCorrectionTable(1);
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
return true;
|
|
}
|
|
|
|
private void OnForceError(SequenceContext arg1, string arg2)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.E("MarkGrid Sequence is stopped");
|
|
}
|
|
|
|
private void OnStopped(SequenceContext obj)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.E("MarkGrid Sequence is stopped");
|
|
}
|
|
|
|
}
|
|
|
|
public class SeqMarkGrid_InitParam : InitParam
|
|
{
|
|
//public bool IsLaserCalibration { get; set; }
|
|
public int ColumnCount { get; set; }
|
|
public int RowCount { get; set; }
|
|
public float UnitLength { get; set; } // 단위 mm
|
|
public double MarkPower { get; set; } // 단위 %
|
|
public double MarkSpeed { get; set; } // 단위 mm/s
|
|
public double MarkLength { get; set; } // 단위 mm
|
|
|
|
}
|
|
|
|
public class SeqMarkGrid_OutParam : OutParam
|
|
{
|
|
// 레이저 쏘기만 하기 때문에 필요 없음.
|
|
}
|
|
}
|