From 6024f372d3d92118e17c250548155e15956cfe50 Mon Sep 17 00:00:00 2001 From: backuppc Date: Thu, 11 Dec 2025 08:22:52 +0900 Subject: [PATCH] =?UTF-8?q?buffer=20in/out=20=EC=8B=9C=ED=80=80=EC=8A=A4?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cs_HMI/AGVCSharp.sln | 15 + .../AGVNavigationCore/Models/VirtualAGV.cs | 20 ++ Cs_HMI/Project/AGV4.csproj | 10 +- Cs_HMI/Project/CSetting.cs | 5 + Cs_HMI/Project/Class/Lang.cs | 7 +- Cs_HMI/Project/Device/Xbee.cs | 4 + Cs_HMI/Project/PUB.cs | 2 +- Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs | 172 +++++++---- .../StateMachine/Step/_SM_RUN_BUFFER_IN.cs | 263 +++++++++++++++++ .../StateMachine/Step/_SM_RUN_BUFFER_OUT.cs | 135 +++++++++ .../StateMachine/Step/_SM_RUN_GODOWN.cs | 223 --------------- .../Project/StateMachine/Step/_SM_RUN_GOTO.cs | 2 + .../Project/StateMachine/Step/_SM_RUN_GOUP.cs | 269 ------------------ .../StateMachine/Step/_SM_RUN_READY.cs | 68 ----- Cs_HMI/Project/StateMachine/_TMDisplay.cs | 4 +- Cs_HMI/Project/StateMachine/_Xbee.cs | 61 ++-- Cs_HMI/Project/fMain.cs | 169 ++--------- Cs_HMI/StateMachine/EnumStruct.cs | 8 +- Cs_HMI/StateMachine/StateMachine.cs | 2 + Cs_HMI/SubProject/AGV/Command.cs | 14 +- Cs_HMI/SubProject/CommData/Enum.cs | 20 +- Cs_HMI/SubProject/CommUtil | 2 +- Cs_HMI/SubProject/EnigProtocol | 2 +- 23 files changed, 671 insertions(+), 806 deletions(-) create mode 100644 Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs create mode 100644 Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs delete mode 100644 Cs_HMI/Project/StateMachine/Step/_SM_RUN_GODOWN.cs delete mode 100644 Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOUP.cs diff --git a/Cs_HMI/AGVCSharp.sln b/Cs_HMI/AGVCSharp.sln index c754bb6..28df278 100644 --- a/Cs_HMI/AGVCSharp.sln +++ b/Cs_HMI/AGVCSharp.sln @@ -38,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AGVSimulator", "AGVLogic\AG EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "arCommUtil", "SubProject\commutil\arCommUtil.csproj", "{14E8C9A5-013E-49BA-B435-FFFFFF7DD623}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Supertonic.Netfx48", "SubProject\SuperTonic\Supertonic.Netfx48.csproj", "{19675E19-EB91-493E-88C3-32B3C094B749}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -180,6 +182,18 @@ Global {14E8C9A5-013E-49BA-B435-FFFFFF7DD623}.Release|x64.Build.0 = Release|Any CPU {14E8C9A5-013E-49BA-B435-FFFFFF7DD623}.Release|x86.ActiveCfg = Release|x86 {14E8C9A5-013E-49BA-B435-FFFFFF7DD623}.Release|x86.Build.0 = Release|x86 + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|x64.ActiveCfg = Debug|x64 + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|x64.Build.0 = Debug|x64 + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|x86.ActiveCfg = Debug|Win32 + {19675E19-EB91-493E-88C3-32B3C094B749}.Debug|x86.Build.0 = Debug|Win32 + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|Any CPU.Build.0 = Release|Any CPU + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|x64.ActiveCfg = Release|x64 + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|x64.Build.0 = Release|x64 + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|x86.ActiveCfg = Release|Win32 + {19675E19-EB91-493E-88C3-32B3C094B749}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -193,6 +207,7 @@ Global {A1B2C3D4-E5F6-7890-ABCD-EF1234567890} = {E5C75D32-5AD6-44DD-8F27-E32023206EBB} {B2C3D4E5-0000-0000-0000-000000000000} = {E5C75D32-5AD6-44DD-8F27-E32023206EBB} {14E8C9A5-013E-49BA-B435-FFFFFF7DD623} = {C423C39A-44E7-4F09-B2F7-7943975FF948} + {19675E19-EB91-493E-88C3-32B3C094B749} = {C423C39A-44E7-4F09-B2F7-7943975FF948} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B5B1FD72-356F-4840-83E8-B070AC21C8D9} diff --git a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs index 209bce3..998fd64 100644 --- a/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs +++ b/Cs_HMI/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs @@ -43,6 +43,8 @@ namespace AGVNavigationCore.Models /// public event EventHandler ErrorOccurred; + + #endregion #region Fields @@ -83,6 +85,8 @@ namespace AGVNavigationCore.Models #region Properties + public bool Turn180 { get; set; } = false; + /// /// 대상 이동시 모터 방향 /// @@ -647,6 +651,19 @@ namespace AGVNavigationCore.Models #endregion + + + /// + /// 노드 ID를 RFID 값으로 변환 (NodeResolver 사용) + /// + public string GetRfidByNodeId(List _mapNodes, string nodeId) + { + var node = _mapNodes?.FirstOrDefault(n => n.NodeId == nodeId); + return node?.HasRfid() == true ? node.RfidId : nodeId; + } + + + #region Private Methods /// @@ -799,6 +816,9 @@ namespace AGVNavigationCore.Models BatteryLevel = Math.Max(0, BatteryLevel); } + public MapNode StartNode { get; set; } = null; + public MapNode TargetNode { get; set; } = null; + private void ProcessNextNode() { if (_remainingNodes == null || _currentNodeIndex >= _remainingNodes.Count - 1) diff --git a/Cs_HMI/Project/AGV4.csproj b/Cs_HMI/Project/AGV4.csproj index af3f021..a8464ec 100644 --- a/Cs_HMI/Project/AGV4.csproj +++ b/Cs_HMI/Project/AGV4.csproj @@ -195,12 +195,6 @@ fCounter.cs - - Form - - - fQuestionBox.cs - Form @@ -311,10 +305,10 @@ Form - + Form - + Form diff --git a/Cs_HMI/Project/CSetting.cs b/Cs_HMI/Project/CSetting.cs index ec3bb6b..9b103c9 100644 --- a/Cs_HMI/Project/CSetting.cs +++ b/Cs_HMI/Project/CSetting.cs @@ -333,6 +333,11 @@ namespace Project public Single interval_xbe { get; set; } [Browsable(false)] public int interval_bms { get; set; } + + /// + /// 스피커출력 간격 + /// + [DisplayName("Speak Term")] public int doorSoundTerm { get; set; } [Browsable(false)] diff --git a/Cs_HMI/Project/Class/Lang.cs b/Cs_HMI/Project/Class/Lang.cs index f3d609a..addf803 100644 --- a/Cs_HMI/Project/Class/Lang.cs +++ b/Cs_HMI/Project/Class/Lang.cs @@ -51,8 +51,7 @@ namespace Project public static string AGV연결실패 { get { return string.Format("AGV {0}", 연결실패); } } public static string 예측값이계산되지않아이동을중단합니다 = "이동 예측이 동작하지 않습니다. 개발부서에 문의 하세요"; public static string 목적지이동이완료되었습니다 = "목적지 이동 이 완료 되었습니다"; - public static string 홈검색을시작합니다 = "홈검색을시작합니다"; - + public static string FindCurrentPisition = "현재 위치를 검색 합니다"; public static string 상차 = "상차"; public static string 하차 = "하차"; @@ -70,8 +69,8 @@ namespace Project public static string 커버를올립니다 = "커버를 올립니다"; public static string 홈위치로이동합니다 = "홈 위치로 이동 합니다"; - public static string 하차작업이완료되었습니다 = "하차 작업이 완료 되었습니다"; - public static string 상차작업이완료되었습니다 = "상차 작업이 완료 되었습니다"; + public static string 버퍼도킹이완료되었습니다 = "버퍼 도킹이 완료 되었습니다"; + public static string 버퍼도킹해제완료 = "버퍼 도킹이 해제 되었습니다"; public static string 커버업대기상태가아닙니다 = "커버 업 대기 상태가 아닙니다"; public static string QC이동버튼은상하차에서만사용가능합니다 = "QC이동 버튼은 상,하차 에서만 사용 가능합니다"; public static string QA이동버튼은상하차에서만사용가능합니다 = "QA이동 버튼은 상,하차 에서만 사용 가능합니다"; diff --git a/Cs_HMI/Project/Device/Xbee.cs b/Cs_HMI/Project/Device/Xbee.cs index 7f0982f..2310498 100644 --- a/Cs_HMI/Project/Device/Xbee.cs +++ b/Cs_HMI/Project/Device/Xbee.cs @@ -154,6 +154,10 @@ namespace Project.Device Send(packet); } + public bool BufferInReady { get; set; } + public bool BufferInComplete { get; set; } + public bool BufferOutComplete { get; set; } + public bool BufferReadyError { get; set; } /// diff --git a/Cs_HMI/Project/PUB.cs b/Cs_HMI/Project/PUB.cs index d2be189..7853486 100644 --- a/Cs_HMI/Project/PUB.cs +++ b/Cs_HMI/Project/PUB.cs @@ -118,7 +118,7 @@ namespace Project if (VAR.BOOL[eVarBool.FLAG_AUTORUN] && VAR.BOOL[eVarBool.FLAG_CHARGEONM] == false && PUB.BMS.Current_Level > PUB.setting.ChargeEmergencyLevel && - PUB.sm.RunStep != StateMachine.ERunStep.GOUP && + PUB.sm.RunStep != StateMachine.ERunStep.BUFFER_OUT && VAR.BOOL[eVarBool.WAIT_COVER_DOWN] == false && VAR.BOOL[eVarBool.WAIT_COVER_UP] == false) { diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs index 7a258c8..f87616d 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN.cs @@ -92,11 +92,110 @@ namespace Project return; } + //선로이탈감지 + if (PUB.AGV.error.runerror_by_no_magent_line == true) + { + var tsSpeak = DateTime.Now - LastSpeakTime; + if (tsSpeak.TotalSeconds >= PUB.setting.doorSoundTerm) + { + PUB.Speak(Lang.선로를이탈했습니다); + LastSpeakTime = DateTime.Now; + } + return; + } + + //현재위치를 모르는 상태라면 이동하여 현재 위치를 찾는다 + if (PUB._virtualAGV.CurrentNodeId.isEmpty())// .cur. . CurrentPos == ePosition.NONE) + { + //이동중이지 않거나 홈이동상태가 아니라면? + if (PUB.AGV.system1.agv_run == false || PUB.sm.RunStep != ERunStep.GOHOME) + { + //현재위치를 검색해야함 + PUB.sm.ClearRunStep(); + PUB.sm.SetNewRunStep(ERunStep.GOHOME); + PUB.AddEEDB($"READY상태에서 현재위치를 몰라 홈으로 이동 백업스텝:{PUB.sm.RunStep}"); + PUB.sm.BackupRunStep.Push(PUB.sm.RunStep); //현재 상태를 백업 + return; + } + VAR.STR[eVarString.ChargeCheckMsg] = "현재 위치 모름"; + } + //나머지 상황체크 switch (PUB.sm.RunStep) { + case ERunStep.GOHOME: + if (runStepisFirst) + { + PUB.Speak(Lang.FindCurrentPisition); + } + else if (_SM_RUN_GOHOME(runStepisFirst, PUB.sm.GetRunSteptime)) + { + //230601 + PUB.Speak(Lang.홈이동완료대기상태로전환합니다); + VAR.TIME.Update(eVarTime.ChargeTry); + + ERunStep NextStep = ERunStep.READY; + if (PUB.sm.BackupRunStep.Count > 0) + NextStep = PUB.sm.BackupRunStep.Pop(); + + PUB.log.Add($"현재위치 검색완료로 {NextStep} 으로 RUNSTEP값을 변경 합니다"); + PUB.sm.SetNewRunStep(NextStep); //대기상태로 전환한다 + return; + } + break; + case ERunStep.GOTO: //목적지까지 이동하는 경우 - _SM_RUN_GOTO(runStepisFirst, PUB.sm.GetRunSteptime); + if (_SM_RUN_GOTO(runStepisFirst, PUB.sm.GetRunSteptime) == true) + { + //목적지가 BUFFER라면 버퍼투입대기위치까지 완료했다는 시그널을 보낸다. + var target = PUB._virtualAGV.TargetNode; + PUB.log.Add($"목적지({target.RfidId}) 도착완료 타입:{target.Type}, 출발지:{PUB._virtualAGV.StartNode.RfidId}"); + if (target.Type == AGVNavigationCore.Models.NodeType.Buffer) + { + + //현재위치가 마지막경로의 NODEID와 일치해야한다 + var lastPath = PUB._virtualAGV.CurrentPath.DetailedPath.LastOrDefault(); + if(lastPath.NodeId.Equals(PUB._virtualAGV.CurrentNodeId)) + { + //버퍼진입전 노드에 도착완료했따 + PUB.XBE.BufferInReady = true; + PUB.XBE.BufferReadyError = false; + } + else + { + //마지막위치가 아닌 다른 위치에 있으니 버퍼 작업을 할 수없다 + PUB.log.AddAT("목적지 버퍼이동완료 했지만 마지막 노드가 아닙니다"); + PUB.XBE.BufferInReady = false; + PUB.XBE.BufferReadyError = true; + } + PUB.XBE.BufferInComplete = false; + PUB.XBE.BufferOutComplete = false; + } + + else if(target.Type == AGVNavigationCore.Models.NodeType.Charging) + { + + } + else if (target.Type == AGVNavigationCore.Models.NodeType.Loader) + { + + } + else if (target.Type == AGVNavigationCore.Models.NodeType.Clearner) + { + + } + else if (target.Type == AGVNavigationCore.Models.NodeType.UnLoader) + { + + } + else + { + //목적지다 다른 형태이다 + + } + PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None; + PUB.sm.SetNewRunStep(ERunStep.READY); + } break; case ERunStep.MARKSTROPB: //후진방향으로 마크스탑 @@ -177,76 +276,37 @@ namespace Project } } break; - case ERunStep.GOUP: //상차이동 - if (_SM_RUN_GOUP(runStepisFirst, PUB.sm.GetRunSteptime)) + case ERunStep.BUFFER_OUT: //버퍼아웃 + if (_SM_RUN_BUFFER_OUT(runStepisFirst, PUB.sm.GetRunSteptime)) { - PUB.Speak(Lang.상차작업이완료되었습니다); + PUB.Speak(Lang.버퍼도킹해제완료); - //230601 - // if (PUB.Result != null && PUB.sm != null) - // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); + //도킹완료상태를 업데이트한다. + PUB.XBE.BufferInComplete = false; + PUB.XBE.BufferOutComplete = true; - //QA를 제외한 경우에는 기본 QC로 이동한다 - if (PUB.Result.NextPos == ePosition.QA) - PUB.Result.TargetPos = ePosition.QA; - else - PUB.Result.TargetPos = ePosition.QC; - - - PUB.sm.SetNewRunStep(ERunStep.GODOWN); //하차작업으로 전환 + //대기상태로 전환 + PUB.sm.SetNewRunStep(ERunStep.READY); return; } break; - case ERunStep.GODOWN: //하차이동 - if (_SM_RUN_GODOWN(runStepisFirst, PUB.sm.GetRunSteptime)) + case ERunStep.BUFFER_IN: //버퍼도킹 + if (_SM_RUN_BUFFER_IN(runStepisFirst, PUB.sm.GetRunSteptime)) { - PUB.Speak(Lang.하차작업이완료되었습니다); - VAR.TIME.Update(eVarTime.ChargeTry); - PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);// (Device.PLC.ZMotDirection.Down); //하차작업이 완료되면 커버를 내려서 바로 작업할 수 있게 한다. + PUB.Speak(Lang.버퍼도킹이완료되었습니다); - //230601 - //if (PUB.Result != null && PUB.sm != null) - // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); + //도킹완료상태를 업데이트한다. + PUB.XBE.BufferInComplete = true; - //하차가 완료되면 충전대기시간을 30초 남겨두고 없데이트한다 - //충전이 필요할 경우 바로 될수있도록 220118 - VAR.TIME[eVarTime.ChargeTry] = DateTime.Now.AddSeconds(-1 * PUB.setting.ChargeRetryTerm + 30); - - if (PUB.Result.CurrentPos == ePosition.QC) - { - PUB.Speak(Lang.대기상태로전환합니다); - PUB.sm.SetNewRunStep(ERunStep.READY); - } - else - { - //홈 이동 명령처리 - PUB.sm.ClearRunStep(); - PUB.Result.TargetPos = ePosition.QC; - PUB.sm.SetNewRunStep(ERunStep.GOHOME); - PUB.Speak(Lang.홈위치로이동합니다); - } + //버퍼아웃으로 자동 진행 합니다 + PUB.sm.ClearRunStep(); + PUB.sm.SetNewRunStep(ERunStep.BUFFER_OUT); return; } break; - case ERunStep.GOHOME: - if (runStepisFirst) - { - PUB.Speak(Lang.홈검색을시작합니다); - } - else if (_SM_RUN_GOHOME(runStepisFirst, PUB.sm.GetRunSteptime)) - { - //230601 - // if (PUB.Result != null && PUB.sm != null) - // EEMStatus.AddEEDBSQL(PUB.sm.Step, PUB.sm.RunStep.ToString(), PUB.Result.TargetPos.ToString()); - PUB.Speak(Lang.홈이동완료대기상태로전환합니다); - VAR.TIME.Update(eVarTime.ChargeTry); - PUB.sm.SetNewRunStep(ERunStep.READY); //대기상태로 전환한다 - return; - } - break; } diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs new file mode 100644 index 0000000..5d3f44b --- /dev/null +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs @@ -0,0 +1,263 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using Project.StateMachine; +using COMM; +using AR; + +namespace Project +{ + public partial class fMain + { + /// + /// 버퍼도킹 + /// + /// + /// + /// + public Boolean _SM_RUN_BUFFER_IN(bool isFirst, TimeSpan stepTime) + { + var funcname = "_SM_RUN_BUFFER_IN"; + var idx = 1; + + if (runStepisFirst) + { + //PUB.flag.set(EFlag.FLAG_NEXTSTOP_ALIGN, false); + VAR.BOOL[eVarBool.FLAG_NEXTSTOP_ALIGN] = false;// + //VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = false;//); + } + + //HW 연결오류 + if (PUB.AGV.IsOpen == false) + { + PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR); + return false; + } + + + //충전 상태가 OFF되어야 동작하게한다 + if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) + return false; + + //라이더멈춤이 설정되어있다면 음성으로 알려준다 200409 + if (PUB.AGV.system1.stop_by_front_detect == true) + { + var tsSpeak = DateTime.Now - LastSpeakTime; + if (tsSpeak.TotalSeconds >= PUB.setting.doorSoundTerm) + { + PUB.Speak(Lang.전방에물체가감지되었습니다); + LastSpeakTime = DateTime.Now; + } + return false; + } + + //현재 위치가 결정되어있는지 체크한다 + if (_SM_RUN_POSCHK(isFirst, stepTime) == false) + return false; + + /* + * 버퍼IN시퀀스 + * 1. 회전이 진행되지 않았다면 회전을 진행한다. + * 2. LIFT DOWN + * 3. 후진-저속-마크다운 실행 + */ + + + if (PUB.sm.RunStepSeq == idx++) + { + PUB.log.Add("버퍼도킹시작"); + PUB.Speak(Lang.하차작업을시작합니다); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //모션 전후진 제어 + if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90) + { + //동작중이면 동작을 멈춘다 + if (PUB.AGV.system1.agv_run == true) + { + var ts = VAR.TIME.RUN(eVarTime.LastStopCommandTime); + if (ts.TotalSeconds > 3) + { + PUB.AGV.AGVMoveStop(funcname); + VAR.TIME.Update(eVarTime.LastStopCommandTime); + } + } + else PUB.sm.UpdateRunStepSeq(); //agv가 멈춰있으므로 턴을 진행해야 한다 + } + else PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다. + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90) + { + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.AGV.AGVMoveLeft180Turn(); + PUB.log.Add("AGV Left Turn"); + PUB.sm.UpdateRunStepSeq(); + } + else PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다. + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90) + { + //5초이내에 턴이동 상태가 확인되어야 한다. + if (PUB.AGV.system1.agv_run == false) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 5) + { + //5초동안 AGV까 움직이지 않았다면 오류 처리한다. + PUB.AGV.AGVMoveStop("5초이내 턴 감지 안됨"); + PUB.log.AddE("5초이내 턴 감지 안됨"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + return false; + } + } + PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다. + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //턴이완료되었느닞 확인한다. + if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90) + { + //10초 이상 가동하고 있다면 문제이다 + if (PUB.AGV.system1.agv_run == true) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 15) + { + PUB.AGV.AGVMoveStop("15초이내 턴 이 완료되지 않음"); + PUB.log.AddE("5초이내 턴 완료 확인 안됨"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + return false; + } + else PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.L90; + } + PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다. + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //리프트를 내린다. + PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN); + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //리프트다운센서를 확인한다. + var liftdown = true; + if (liftdown == false) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 10) + { + PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.STP); + PUB.log.AddE("리프트 하강이 확인되지 않습니다(10초)"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + } + PUB.log.Add("리프트 하강 완료"); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //마크스탑셋팅 + PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop); + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //저속이동 + var moveset = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData + { + Bunki = arDev.Narumi.eBunki.Strate, + Direction = arDev.Narumi.eMoveDir.Backward, + PBSSensor = 0, + Speed = arDev.Narumi.eMoveSpd.Low, + }); + if (moveset == false) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 10) + { + PUB.AGV.AGVMoveStop(funcname); + PUB.log.AddE("AGV속도설정이 완료되지 않았습니다"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + } + PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Backward); + PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop); + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //마크스탑신호가 3초이내로 들어와야 한다 + if (PUB.AGV.signal.mark_sensor == false) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 3) + { + PUB.AGV.AGVMoveStop(funcname); + PUB.log.AddE("MARK STOP신호가 확인되지 않습니다"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + } + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //AGV가 멈출때까지 기다린다. + if (PUB.AGV.system1.agv_run == true) + { + var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime); + if (ts.TotalSeconds > 10) + { + PUB.AGV.AGVMoveStop(funcname); + PUB.log.AddE("AGV가 멈추지 않아 강제종료 합니다"); + PUB.sm.SetNewRunStep(ERunStep.ERROR); + return false; + } + return false; + } + VAR.TIME.Update(eVarTime.LastTurnCommandTime); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //완료되었다. (ACS에 보내야함) + PUB.log.Add("버퍼투입완료"); + PUB.sm.UpdateRunStepSeq(); + return false; + } + + PUB.AddEEDB($"버퍼투입완료({PUB.Result.TargetPos})"); + return true; + } + } +} diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs new file mode 100644 index 0000000..3ff6561 --- /dev/null +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using Project.StateMachine; +using COMM; +using AR; + +namespace Project +{ + public partial class fMain + { + + public Boolean _SM_RUN_BUFFER_OUT(bool isFirst, TimeSpan stepTime) + { + if (runStepisFirst) + { + + } + + //HW 연결오류 + if (PUB.AGV.IsOpen == false) + { + PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR); + return false; + } + + //충전 상태가 OFF되어야 동작하게한다 + if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) + return false; + + //라이더멈춤이 설정되어있다면 음성으로 알려준다 200409 + if (PUB.AGV.system1.stop_by_front_detect == true) + { + var tsSpeak = DateTime.Now - LastSpeakTime; + if (tsSpeak.TotalSeconds >= PUB.setting.doorSoundTerm) + { + PUB.Speak(Lang.전방에물체가감지되었습니다); + LastSpeakTime = DateTime.Now; + } + return false; + } + + //현재 위치가 결정되어있는지 체크한다 + if (_SM_RUN_POSCHK(isFirst, stepTime) == false) + return false; + + var idx = 1; + if (PUB.sm.RunStepSeq == idx++) + { + //빈 상태로 아웃해야한다. + PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData + { + Bunki = arDev.Narumi.eBunki.Strate, + Direction = arDev.Narumi.eMoveDir.Forward, + PBSSensor = 0, + Speed = arDev.Narumi.eMoveSpd.Low, + }); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //전진이동 + PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //마크스탑 + PUB.AGV.AGVMoveStop("buffer out", arDev.Narumi.eStopOpt.MarkStop); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //이동확인 + if (PUB.AGV.system1.agv_run == false) + { + return false; + } + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //멈춤확인 + if (PUB.AGV.system1.agv_run == true) + { + return false; + } + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //우측으로 180도 턴 + PUB.AGV.AGVMoveRight180Turn(); + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //이동확인 + if (PUB.AGV.system1.agv_run == false) + { + return false; + } + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + //멈춤확인 + if (PUB.AGV.system1.agv_run == true) + { + return false; + } + PUB.sm.UpdateRunStepSeq(); + return false; + } + else if (PUB.sm.RunStepSeq == idx++) + { + PUB.log.Add("BufferOut Complete"); + PUB.sm.UpdateRunStepSeq(); + return false; + } + + PUB.AddEEDB($"bufferout 완료({PUB.Result.TargetPos})"); + return true; + } + } +} diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GODOWN.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GODOWN.cs deleted file mode 100644 index e1b0d65..0000000 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GODOWN.cs +++ /dev/null @@ -1,223 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using Project.StateMachine; -using COMM; -using AR; - -namespace Project -{ - public partial class fMain - { - public Boolean _SM_RUN_GODOWN(bool isFirst, TimeSpan stepTime) - { - if (runStepisFirst) - { - //PUB.flag.set(EFlag.FLAG_NEXTSTOP_ALIGN, false); - VAR.BOOL[eVarBool.FLAG_NEXTSTOP_ALIGN] = false;// - //VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = false;//); - } - - //HW 연결오류 - if (PUB.AGV.IsOpen == false) - { - PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR); - return false; - } - - - //충전 상태가 OFF되어야 동작하게한다 - if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) - return false; - - //라이더멈춤이 설정되어있다면 음성으로 알려준다 200409 - if (PUB.AGV.system1.stop_by_front_detect == true) - { - var tsSpeak = DateTime.Now - LastSpeakTime; - if (tsSpeak.TotalSeconds >= PUB.setting.doorSoundTerm) - { - PUB.Speak(Lang.전방에물체가감지되었습니다); - LastSpeakTime = DateTime.Now; - } - return false; - } - - - //현재 위치가 결정되어있는지 체크한다 - if (_SM_RUN_POSCHK(isFirst, stepTime) == false) - return false; - - if (PUB.sm.RunStepSeq == 1) - { - //하차는 무조건 대상이 QC가 된다 - if (PUB.Result.TargetPos == ePosition.NONE) - PUB.Result.TargetPos = ePosition.QC; - - //if (PUB.Result.TargetPos == ePosition.QA && - // PUB.Result.CurrentPos == ePosition.QC && - // (PUB.PLC.IsLimitDn())) - //{ - // PUB.Speak("안전 커버를 올리고 다시 시도하세요", true); - // PUB.sm.ClearRunStep(); - // PUB.sm.SetNewRunStep(ERunStep.READY); - //} - PUB.AddEEDB($"하차작업시작({PUB.Result.TargetPos})"); - PUB.Speak(Lang.하차작업을시작합니다); - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == 2) - { - //모션 전후진 제어 - if (UpdateMotionPositionForMark("GODOWN")) - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == 3) - { - //위치 확정이 완료될때까지 대기 - if (PUB.Result.CurrentPos == PUB.Result.TargetPos) - { - //PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GODOWN:위치확정"); - PUB.AGV.AGVMoveStop("sm_run_godown"); - PUB.sm.UpdateRunStepSeq(); - } - else if (PUB.AGV.system1.agv_run == false) - { - //움직이지않으면 방향을 다시 조정한다 - PUB.sm.SetStepSeq(2); - } - - return false; - } - else if (PUB.sm.RunStepSeq == 4) - { - //대상까지 모두 완료되었다.(완전히 정차할때까지 기다린다) - if (PUB.AGV.system1.agv_run == false) - { - PUB.log.Add("이동 정지 확인"); - PUB.sm.UpdateRunStepSeq(); - } - - return false; - } - else if (PUB.sm.RunStepSeq == 5) - { - //하차수량증가 - if (PUB.Result.TargetPos == ePosition.QA) - PUB.counter.CountQA += 1; - else - PUB.counter.CountQC += 1; - PUB.counter.Save(); - - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == 6) - { - //커버를 자동으로 내려준다 - CoverControlTime = DateTime.Now; - UpdateProgressStatus(stepTime.TotalSeconds, 5, Lang.안전커버를내립니다); - VAR.BOOL[eVarBool.WAIT_COVER_DOWN] = true; - PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);// - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == 7) - { - //커버 내림이 완료될때까지 기다린다 - //if (PUB.PLC.IsLimitDn() == true) - //{ - // VAR.BOOL[eVarBool.WAIT_COVER_DOWN] = false; - // PUB.sm.UpdateRunStepSeq(); - //} - //else - { - //경과시간이 10초가 지나면 5초마다 음성을 출력한다 - var tsCover = DateTime.Now - CoverControlTime; - if (tsCover.TotalSeconds >= 7) - { - PUB.Speak(Lang.안전커버를내려주세요); - CoverControlTime = DateTime.Now; - } - } - - return false; - } - else if (PUB.sm.RunStepSeq == 8) - { - //IO업데이트 간격 전송 - UpdateProgressStatus(stepTime.TotalSeconds, 5, Lang.안전커버를올려주세요); - //PUB.Speak(Lang.안전커버를올리면하차가완료됩니다); - VAR.BOOL[eVarBool.WAIT_COVER_UP] = true; - CoverControlTime = DateTime.Now; - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == 9) - { - //커버 올림이 완료될때까지 기다린다 - if (VAR.BOOL[eVarBool.FLAG_LIMITHIGH] == true) - { - VAR.BOOL[eVarBool.WAIT_COVER_UP] = false; - VAR.BOOL[eVarBool.ITEMON] = false; - PUB.sm.UpdateRunStepSeq(); - } - else - { - //경과시간이 10초가 지나면 5초마다 음성을 출력한다 - var tsCover = DateTime.Now - CoverControlTime; - if (tsCover.TotalSeconds >= PUB.setting.doorSoundTerm) - { - PUB.Speak(Lang.안전커버를올려주세요); - CoverControlTime = DateTime.Now; - - ////한쪽이 올라가 있는 상태에.. - //if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU) == true) - //{ - // //모터는 올리는 방향일때에... - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_LDIR) == true) - // { - // //모터가 멈춰있을때에.. - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_LRUN) == false) - // { - // //자동으로 올려준다 (센서가 간혹 인식이 안되어서 .대기하는 경우가 잇음) - - // //왼쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU) == false) - // PUB.PLC.ZMot_Left(arDev.FakePLC.ZMotDirection.Up); - // } - // } - //} - //if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU) == true) - //{ - // //모터는 올리는 방향일때에... - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_RDIR) == true) - // { - // //모터가 멈춰있을때에.. - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_RRUN) == false) - // { - // //자동으로 올려준다 (센서가 간혹 인식이 안되어서 .대기하는 경우가 잇음) - - // //왼쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU) == false) - // PUB.PLC.ZMot_Right(arDev.FakePLC.ZMotDirection.Up); - // } - // } - //} - - - } - } - - return false; - } - - PUB.AddEEDB($"하차작업완료({PUB.Result.TargetPos})"); - EEMStatus.AddStatusCount(1, PUB.Result.TargetPos.ToString()); //230620 - return true; - } - } -} diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs index 423d9af..bc763dd 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOTO.cs @@ -29,6 +29,8 @@ namespace Project VAR.TIME.Update(eVarTime.CheckGotoTargetSet); } + //PUB._virtualAGV. + //목적지가 설정되었는지 체크한다. //Z if (PUB.mapctl.Manager.agv.TargetRFID.IsEmpty) // { diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOUP.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOUP.cs deleted file mode 100644 index ca0d7c6..0000000 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_GOUP.cs +++ /dev/null @@ -1,269 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Text; -using Project.StateMachine; -using COMM; -using AR; - -namespace Project -{ - public partial class fMain - { - - public Boolean _SM_RUN_GOUP(bool isFirst, TimeSpan stepTime) - { - if (runStepisFirst) - { - // VAR.BOOL[eVarBool.FLAG_NEXTSTOP_MARK] = false;//); - VAR.BOOL[eVarBool.FLAG_NEXTSTOP_ALIGN] = false; - } - - //HW 연결오류 - if (PUB.AGV.IsOpen == false) - { - PUB.Result.SetResultMessage(eResult.Hardware, eECode.AGVCONN, eNextStep.ERROR); - return false; - } - - //충전 상태가 OFF되어야 동작하게한다 - if (_SM_RUN_CHGOFF(isFirst, stepTime) == false) - return false; - - //라이더멈춤이 설정되어있다면 음성으로 알려준다 200409 - if (PUB.AGV.system1.stop_by_front_detect == true) - { - var tsSpeak = DateTime.Now - LastSpeakTime; - if (tsSpeak.TotalSeconds >= PUB.setting.doorSoundTerm) - { - PUB.Speak(Lang.전방에물체가감지되었습니다); - LastSpeakTime = DateTime.Now; - } - return false; - } - - //현재 위치가 결정되어있는지 체크한다 - if (_SM_RUN_POSCHK(isFirst, stepTime) == false) - return false; - - var idx = 1; - if (PUB.sm.RunStepSeq == idx++) - { - //상차 가능 조건 확인 - if (PUB.Result.TargetPos == ePosition.NONE) - { - PUB.Result.SetResultMessage(eResult.Hardware, eECode.NOTALLOWUP, eNextStep.ERROR); - } - else - { - PUB.AddEEDB($"상차작업시작({PUB.Result.TargetPos})"); - PUB.Speak(Lang.상차작업을시작합니다); - PUB.sm.UpdateRunStepSeq(); - } - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - //모션 전후진 제어 - if (UpdateMotionPositionForMark("GOUP")) - PUB.sm.UpdateRunStepSeq(); - - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - //장비멈춤확인 - if (PUB.AGV.system1.agv_run == true) - { - var ts = DateTime.Now - LastCommandTime; - if (ts.TotalMilliseconds > 2000) - { - PUB.AGV.AGVMoveStop("SM_RUN_GOUP");// PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GOUP:위치확정"); - LastCommandTime = DateTime.Now; - } - } - else - { - //움직이지 않고 있다면 다시 이동을 시켜준다. - PUB.log.Add("이동 정지 확인"); - PUB.sm.UpdateRunStepSeq(); - } - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - if (PUB.AGV.system1.agv_run == true) - { - var ts = DateTime.Now - LastCommandTime; - if (ts.TotalMilliseconds > 2000) - { - PUB.AGV.AGVMoveStop("SM_RUN_GOUP");// PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GOUP:위치확정"); - LastCommandTime = DateTime.Now; - } - } - - //커버를 자동으로 내려준다 - CoverControlTime = DateTime.Now; - UpdateProgressStatus(stepTime.TotalSeconds, 5, Lang.안전커버를내립니다); - PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN); - VAR.BOOL[eVarBool.WAIT_COVER_DOWN] = true; - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - if (PUB.AGV.system1.agv_run == true) - { - var ts = DateTime.Now - LastCommandTime; - if (ts.TotalMilliseconds > 2000) - { - PUB.AGV.AGVMoveStop("SM_RUN_GOUP");// PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GOUP:위치확정"); - LastCommandTime = DateTime.Now; - } - } - - - //커버 내림이 완료될때까지 기다린다 - if (true) - { - VAR.BOOL[eVarBool.WAIT_COVER_DOWN] = false; - PUB.Result.NextPos = ePosition.NONE; - PUB.sm.UpdateRunStepSeq(); - } - else - { - - - //경과시간이 10초가 지나면 5초마다 음성을 출력한다 - var tsCover = DateTime.Now - CoverControlTime; - if (tsCover.TotalSeconds >= 7) - { - PUB.Speak(Lang.안전커버를내려주세요); - CoverControlTime = DateTime.Now; - } - } - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - if (PUB.AGV.system1.agv_run == true) - { - var ts = DateTime.Now - LastCommandTime; - if (ts.TotalMilliseconds > 2000) - { - PUB.AGV.AGVMoveStop("SM_RUN_GOUP");// PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GOUP:위치확정"); - LastCommandTime = DateTime.Now; - } - return false; - } - - - //상차는 여기서 수량확인한다 - if (PUB.Result.TargetPos == ePosition.F1) - PUB.counter.CountUp1 += 1; - else if (PUB.Result.TargetPos == ePosition.F2) - PUB.counter.CountUp2 += 1; - else if (PUB.Result.TargetPos == ePosition.F3) - PUB.counter.CountUp3 += 1; - else if (PUB.Result.TargetPos == ePosition.F4) - PUB.counter.CountUp4 += 1; - //else if (PUB.Result.TargetPos == ePosition.QA) - // PUB.counter.CountQA += 1; - PUB.counter.Save(); - PUB.sm.UpdateRunStepSeq(); - return false; - } - else if (PUB.sm.RunStepSeq == idx++) - { - - //IO업데이트 간격 전송 - UpdateProgressStatus(stepTime.TotalSeconds, 5, Lang.안전커버를올려주세요); - PUB.Speak(Lang.안전커버를올리면상차가완료됩니다); - PUB.sm.UpdateRunStepSeq(); - VAR.BOOL[eVarBool.WAIT_COVER_UP] = true; - PUB.Result.NextPos = ePosition.NONE; - CoverControlTime = DateTime.Now; - return false; - } - - else if (PUB.sm.RunStepSeq == idx++) - { - if (PUB.AGV.system1.agv_run == true) - { - var ts = DateTime.Now - LastCommandTime; - if (ts.TotalMilliseconds > 2000) - { - PUB.AGV.AGVMoveStop("SM_RUN_GOUP");// PUB.PLC.Move(Device.PLC.Rundirection.Stop, "GOUP:위치확정"); - LastCommandTime = DateTime.Now; - } - } - - - //커버 올림이 완료될때까지 기다린다 - if (VAR.BOOL[eVarBool.FLAG_LIMITHIGH] == true) - { - VAR.BOOL[eVarBool.WAIT_COVER_UP] = false; - VAR.BOOL[eVarBool.ITEMON] = true; - PUB.sm.UpdateRunStepSeq(); - } - else - { - //경과시간이 10초가 지나면 5초마다 음성을 출력한다 - var tsCover = DateTime.Now - CoverControlTime; - if (tsCover.TotalSeconds >= PUB.setting.doorSoundTerm) - { - PUB.Speak(Lang.안전커버를올려주세요); - CoverControlTime = DateTime.Now; - - ////한쪽이 올라가 있는 상태에.. - //if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU) == true) - //{ - // //모터는 올리는 방향일때에... - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_LDIR) == true) - // { - // //모터가 멈춰있을때에.. - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_LRUN) == false) - // { - // //자동으로 올려준다 (센서가 간혹 인식이 안되어서 .대기하는 경우가 잇음) - - // //왼쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU) == false) - // PUB.PLC.ZMot_Left(arDev.FakePLC.ZMotDirection.Up); - - // //오른쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU) == false) - // PUB.PLC.ZMot_Right(arDev.FakePLC.ZMotDirection.Up); - // } - // } - //} - //if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU) == true) - //{ - // //모터는 올리는 방향일때에... - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_RDIR) == true) - // { - // //모터가 멈춰있을때에.. - // if (PUB.PLC.GetValueO(arDev.FakePLC.DOName.PINO_GUIDEMOTOR_RRUN) == false) - // { - // //자동으로 올려준다 (센서가 간혹 인식이 안되어서 .대기하는 경우가 잇음) - - // //왼쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU) == false) - // PUB.PLC.ZMot_Left(arDev.FakePLC.ZMotDirection.Up); - - // //오른쪽이 올라가 있지 않은 경우 - // if (PUB.PLC.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU) == false) - // PUB.PLC.ZMot_Right(arDev.FakePLC.ZMotDirection.Up); - // } - // } - //} - } - } - return false; - } - - PUB.AddEEDB($"상차작업완료({PUB.Result.TargetPos})"); - return true; - } - } -} diff --git a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs index 01719e4..0a0fca1 100644 --- a/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs +++ b/Cs_HMI/Project/StateMachine/Step/_SM_RUN_READY.cs @@ -58,74 +58,6 @@ namespace Project VAR.STR[eVarString.ChargeCheckMsg] = "수동 충전"; } - //현재위치를 모르는 상태라면 이동하여 현재 위치를 찾는다 - else if (PUB.Result.CurrentPos == ePosition.NONE) - { - if (PUB.AGV.system1.agv_run == false && - PUB.AGV.error.Emergency == false && - PUB.AGV.error.runerror_by_no_magent_line == false) - { - //현재위치를 검색해야함 - PUB.sm.ClearRunStep(); - PUB.sm.SetNewRunStep(ERunStep.GOHOME); - PUB.sm.SetNewStep(eSMStep.RUN); - PUB.AddEEDB($"READY상태에서 현재위치를 몰라 홈으로 이동"); - } - VAR.STR[eVarString.ChargeCheckMsg] = "현재 위치 모름"; - } - //else if (PUB.setting.Enable_AutoCharge == true ) - //{ - // if(bAutoChageOn) - // { - // VAR.BOOL[eVarBool.CHARGE_READY] = true; - // if (PUB.BMS.Current_Level < PUB.setting.ChargeStartLevel) - // { - // //레벨에 의한 자동 충전간격은 - // var ts = VAR.TIME.RUN(eVarTime.ChargeTry); - // if (ts.TotalSeconds >= PUB.setting.ChargeRetryTerm) - // { - // VAR.I32[eVarInt32.ChargeWaitSec] = 0; - // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - // PUB.log.Add($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); - // PUB.sm.ClearRunStep(); - // PUB.sm.SetNewRunStep(ERunStep.GOCHARGE); - // PUB.sm.SetNewStep(eSMStep.RUN); - // PUB.AddEEDB($"자동충전레벨시작 {PUB.BMS.Current_Level}/{PUB.setting.ChargeStartLevel}"); - // } - // else - // { - // VAR.I32[eVarInt32.ChargeWaitSec] = (int)(PUB.setting.ChargeRetryTerm - ts.TotalSeconds); - // VAR.BOOL[eVarBool.CHARGE_WAIT] = true; - // } - // VAR.STR[eVarString.ChargeCheckMsg] = "배터리 충전 레벨 필요"; - // } - // else - // { - // //아직 레벨이 높다 - // VAR.BOOL[eVarBool.CHARGE_READY] = false; - // VAR.I32[eVarInt32.ChargeWaitSec] = 0; - // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - // VAR.STR[eVarString.ChargeCheckMsg] = "배터리 레벨상 충전 불필요"; - // } - // } - // else - // { - // VAR.BOOL[eVarBool.CHARGE_READY] = false; - // VAR.I32[eVarInt32.ChargeWaitSec] = 0; - // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - // VAR.STR[eVarString.ChargeCheckMsg] = "충전 불가 조건"; - // //충전조건이 맞지 않는다 - // } - //} - //else - //{ - // VAR.BOOL[eVarBool.CHARGE_READY] = false; - // VAR.I32[eVarInt32.ChargeWaitSec] = 0; - // VAR.BOOL[eVarBool.CHARGE_WAIT] = false; - // //자동충전이 해제된 상태이므로 처리하지 않는다 - // VAR.STR[eVarString.ChargeCheckMsg] = "자동 충전 해제 됨"; - //} - //대기모드에서는 움직이지 않게 한다 if(PUB.AGV.system1.agv_run) { diff --git a/Cs_HMI/Project/StateMachine/_TMDisplay.cs b/Cs_HMI/Project/StateMachine/_TMDisplay.cs index 9a7dfec..390e52b 100644 --- a/Cs_HMI/Project/StateMachine/_TMDisplay.cs +++ b/Cs_HMI/Project/StateMachine/_TMDisplay.cs @@ -697,7 +697,7 @@ namespace Project } else { - if (PUB.sm.RunStep == ERunStep.GODOWN) + if (PUB.sm.RunStep == ERunStep.BUFFER_IN) { if (PUB.sm.RunStepSeq == 1) { @@ -705,7 +705,7 @@ namespace Project } else UpdateStatusMessage(String.Format("하차 이동 중 ({0})", PUB.Result.TargetPos), Color.Lime, Color.Black); } - else if (PUB.sm.RunStep == ERunStep.GOUP) + else if (PUB.sm.RunStep == ERunStep.BUFFER_OUT) { if (PUB.sm.RunStepSeq == 1) { diff --git a/Cs_HMI/Project/StateMachine/_Xbee.cs b/Cs_HMI/Project/StateMachine/_Xbee.cs index d16eab4..c4d75bc 100644 --- a/Cs_HMI/Project/StateMachine/_Xbee.cs +++ b/Cs_HMI/Project/StateMachine/_Xbee.cs @@ -53,7 +53,8 @@ namespace Project PUB.log.AddE($"[{logPrefix}-SetCurrent] 노드정보를 찾을 수 없습니다 RFID:{currTag}"); PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, $"{currTag}"); return; - }else + } + else { PUB.log.AddI($"XBEE:현재위치설정:[{node.RfidId}]{node.NodeId}"); } @@ -69,6 +70,17 @@ namespace Project { var currTag = System.Text.Encoding.Default.GetString(data, 1, data.Length - 1); var targetNode = PUB._mapNodes.FirstOrDefault(t => t.RfidId == currTag); + + + //자동상태가아니라면 처리하지 않는다. + if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) + { + PUB.log.AddE($"[{logPrefix}-Goto] 자동실행상태가 아닙니다"); + PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.ManualMode, $"{currTag}"); + } + + //목적지 + PUB._virtualAGV.TargetNode = targetNode; if (targetNode == null) { PUB.log.AddE($"[{logPrefix}-Goto] 노드정보를 찾을 수 없습니다 RFID:{currTag}"); @@ -76,24 +88,37 @@ namespace Project return; } + ///출발지 var startNode = PUB._mapNodes.FirstOrDefault(t => t.RfidId == PUB._virtualAGV.CurrentNodeId); + PUB._virtualAGV.StartNode = startNode; if (startNode == null) { - PUB.log.AddE($"[{logPrefix}-Goto] 노드정보를 찾을 수 없습니다 RFID:{PUB._virtualAGV.CurrentNodeId}"); - PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.EmptyNode, $"{PUB._virtualAGV.CurrentNodeId}"); - return; + PUB.log.AddE($"[{logPrefix}-Goto] 시작노드가 없습니다(현재위치 없음) NodeID:{PUB._virtualAGV.CurrentNodeId}"); } - var rltGoto = CalcPath(startNode, targetNode); - if (rltGoto.result == false) + if (startNode != null) { - PUB.log.AddE($"[{logPrefix}-Goto] {rltGoto.message}"); - PUB.XBE.SendError(ENIGProtocol.AGVErrorCode.Goto, rltGoto.message); - return; + //시작위치가 존재한다면 경로를 예측한다. + var rltGoto = CalcPath(startNode, targetNode); + if (rltGoto.result == null) + { + PUB.log.AddE($"[{logPrefix}-Goto] 경로예측실패 {rltGoto.message}"); + } + else + { + //경로예측을 화면에 표시해준다. + PUB._virtualAGV.SetPath(rltGoto.result); + var pathWithRfid = rltGoto.result.GetSimplePath().Select(nodeId => PUB._virtualAGV.GetRfidByNodeId(PUB._mapNodes, nodeId)).ToList(); + PUB.log.Add($"경로예측결과:{pathWithRfid}"); + } } + //대상이동으로 처리한다. + PUB.sm.SetNewRunStep(StateMachine.ERunStep.GOTO); + //Move to PUB.log.Add($"[{logPrefix}-Goto] {startNode.RfidId} -> {targetNode.RfidId}"); + } else PUB.log.AddE($"[{logPrefix}-Goto] TagString Lenght Errorr:{data.Length}"); break; @@ -164,7 +189,7 @@ namespace Project arDev.Narumi.LiftCommand LCmd = arDev.Narumi.LiftCommand.STP; if (LiftCommand == 1) LCmd = arDev.Narumi.LiftCommand.UP; else if (LiftCommand == 2) LCmd = arDev.Narumi.LiftCommand.DN; - + PUB.log.Add($"[{logPrefix}-LiftControl] {LCmd}"); PUB.AGV.LiftControl(LCmd); //리프트제어 break; @@ -173,13 +198,13 @@ namespace Project var chargeAction = data[1] == 1; //0= off, 1=on //충전시퀀스가 진행되지 않았다면 진행한다 - if(PUB.sm.RunStep == StateMachine.ERunStep.GOCHARGE && PUB.sm.RunStepNew != StateMachine.ERunStep.GOCHARGE) + if (PUB.sm.RunStep == StateMachine.ERunStep.GOCHARGE && PUB.sm.RunStepNew != StateMachine.ERunStep.GOCHARGE) { PUB.sm.SetNewRunStep(StateMachine.ERunStep.GOCHARGE); PUB.log.AddI($"충전을 시작합니다"); } break; - + } } } @@ -191,12 +216,12 @@ namespace Project } AGVNavigationCore.PathFinding.Planning.AGVPathfinder _advancedPathfinder = null; - (bool result, string message) CalcPath(MapNode startNode, MapNode targetNode) + (AGVNavigationCore.PathFinding.Core.AGVPathResult result, string message) CalcPath(MapNode startNode, MapNode targetNode) { var _mapNodes = PUB._mapNodes; // 시작 RFID가 없으면 AGV 현재 위치로 설정 if (startNode == null || targetNode == null) - return (false, "시작 RFID와 목표 RFID를 선택해주세요."); + return (null, "시작 RFID와 목표 RFID를 선택해주세요."); //경로계산기확인 if (_advancedPathfinder == null) @@ -216,6 +241,7 @@ namespace Project var _simulatorCanvas = PUB._mapCanvas; _simulatorCanvas.FitToNodes(); + string Message = string.Empty; if (advancedResult.Success) { // 도킹 검증이 없는 경우 추가 검증 수행 @@ -234,14 +260,17 @@ namespace Project // 고급 경로 디버깅 정보 표시 //UpdateAdvancedPathDebugInfo(advancedResult); - return (true, string.Empty); + } else { // 경로 실패시 디버깅 정보 초기화 //_pathDebugLabel.Text = $"경로: 실패 - {advancedResult.ErrorMessage}"; - return (false, $"경로를 찾을 수 없습니다:\n{advancedResult.ErrorMessage}"); + advancedResult = null; + Message = $"경로를 찾을 수 없습니다:\n{advancedResult.ErrorMessage}"; } + + return (advancedResult, Message); } diff --git a/Cs_HMI/Project/fMain.cs b/Cs_HMI/Project/fMain.cs index 282a972..c407029 100644 --- a/Cs_HMI/Project/fMain.cs +++ b/Cs_HMI/Project/fMain.cs @@ -244,17 +244,17 @@ namespace Project PUB.sm.SetMsgOptOff(); //모든 메세지출력을 해제한다. (이벤트는 동작함) PUB.log.Add("State Machine Start"); - + try { PUB.sm = new StateMachine.StateMachine(); PUB.log.Add("StateMachine", $"객체 생성 완료 - Type: {PUB.sm.GetType().FullName}"); - + // StateMachine 객체의 속성 확인 var smType = PUB.sm.GetType(); var properties = smType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); PUB.log.Add("StateMachine", $"Public Properties: {properties.Length}개"); - + var methods = smType.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly); PUB.log.Add("StateMachine", $"Public Methods: {methods.Length}개"); } @@ -264,22 +264,22 @@ namespace Project PUB.log.AddE($"StackTrace: {ex.StackTrace}"); throw; } - + PUB.sm.StepChanged += sm_StepChanged; PUB.log.Add("StateMachine", "StepChanged 이벤트 등록 완료"); - + PUB.sm.Message += sm_Message; PUB.log.Add("StateMachine", "Message 이벤트 등록 완료"); - + PUB.sm.Running += sm_Running; PUB.log.Add("StateMachine", "Running 이벤트 등록 완료"); - + PUB.sm.SPS += sm_SPS; PUB.log.Add("StateMachine", "SPS 이벤트 등록 완료"); - + PUB.sm.Start(); PUB.log.Add("StateMachine", $"Start() 호출 완료 - IsThreadRun:{PUB.sm.IsThreadRun}"); - + // 스레드 시작 대기 (최대 3초) for (int i = 0; i < 30; i++) { @@ -290,15 +290,15 @@ namespace Project break; } } - + if (!PUB.sm.IsThreadRun) { - PUB.log.AddE( "경고: 3초 대기 후에도 스레드가 시작되지 않음!"); + PUB.log.AddE("경고: 3초 대기 후에도 스레드가 시작되지 않음!"); System.Windows.Forms.MessageBox.Show( "상태머신 스레드가 시작되지 않았습니다.\n" + "로그 파일을 확인하세요.", - "오류", - System.Windows.Forms.MessageBoxButtons.OK, + "오류", + System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } @@ -417,12 +417,12 @@ namespace Project void func_sw_start(bool Prompt = false) { - if(PUB.sm.Step == eSMStep.SYNC) + if (PUB.sm.Step < eSMStep.IDLE) { UTIL.MsgE("초기화 중에는 사용할 수 없습니다\n초기화가 완료 된 후 시도하세요"); return; } - if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false) //자동상태가 아니라면 + if (VAR.BOOL[eVarBool.FLAG_AUTORUN] == false || PUB.sm.Step != eSMStep.RUN) //자동상태가 아니라면 { PUB.AGV.AGVErrorReset(); if (Prompt) @@ -507,136 +507,8 @@ namespace Project PUB.log.Add("사용자 임의 위치 클릭 : " + e.Item.Title); switch (e.Item.Position) { - case ePosition.QA: - //아이템을 가지고 있었으니 하차를 해야한다 - if (VAR.BOOL[eVarBool.ITEMON]) - { - dlg.setMessage("작업 실행\n" + - "(QA) 위치로 하차를 진행 할까요?\n" + - "대상위치 : QA\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - //아이템이 있으면 하차이고 없으면 상차이다 - PUB.sm.ClearRunStep(); - PUB.Result.TargetPos = ePosition.QA; - PUB.sm.SetNewRunStep(ERunStep.GODOWN); - PUB.sm.SetNewStep(eSMStep.RUN); - } - } - else - { - dlg.setMessage("작업 실행\n" + - "(QA) 위치로 이동을 실행 할까요?\n" + - "대상위치 : QA\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - - //아이템이 있으면 하차이고 없으면 상차이다 - PUB.sm.ClearRunStep(); - PUB.Result.TargetPos = ePosition.QA; - PUB.sm.SetNewRunStep(ERunStep.GOHOME); - PUB.sm.SetNewStep(eSMStep.RUN); - } - } - - break; - case ePosition.QC: - - //아이템을 가지고 있었으니 하차를 해야한다 - if (VAR.BOOL[eVarBool.ITEMON]) - { - dlg.setMessage("작업 실행\n" + - "홈(QC) 위치로 하차를 진행 할까요?\n" + - "대상위치 : QC\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - //아이템이 있으면 하차이고 없으면 상차이다 - PUB.sm.ClearRunStep(); - PUB.Result.TargetPos = ePosition.QC; - PUB.sm.SetNewRunStep(ERunStep.GODOWN); - PUB.sm.SetNewStep(eSMStep.RUN); - } - } - else - { - dlg.setMessage("작업 실행\n" + - "홈(QC) 위치로 이동을 실행 할까요?\n" + - "대상위치 : QC\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - - if (dlg.ShowDialog() == DialogResult.Yes) - { - - //아이템이 있으면 하차이고 없으면 상차이다 - PUB.sm.ClearRunStep(); - PUB.Result.TargetPos = ePosition.QC; - PUB.sm.SetNewRunStep(ERunStep.GOHOME); - PUB.sm.SetNewStep(eSMStep.RUN); - } - } - - break; - case ePosition.F1: //FVI영역은 모두 상차이동 - dlg.setMessage("작업 실행\n" + - "(상차) 작업을 실행 할까요?\n" + - "대상위치 : FVI-1\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - PUB.Result.TargetPos = ePosition.F1; - PUB.sm.SetNewRunStep(ERunStep.GOUP); - PUB.sm.SetNewStep(eSMStep.RUN); - } - - break; - case ePosition.F2: - dlg.setMessage("작업 실행\n" + - "(상차) 작업을 실행 할까요?\n" + - "대상위치 : FVI-2\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - - PUB.Result.TargetPos = ePosition.F2; - PUB.sm.SetNewRunStep(ERunStep.GOUP); - PUB.sm.SetNewStep(eSMStep.RUN); - } - - break; - case ePosition.F3: - dlg.setMessage("작업 실행\n" + - "(상차) 작업을 실행 할까요?\n" + - "대상위치 : FVI-3\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - - PUB.Result.TargetPos = ePosition.F3; - PUB.sm.SetNewRunStep(ERunStep.GOUP); - PUB.sm.SetNewStep(eSMStep.RUN); - //VAR.BOOL[eVarBool.FLAG_AUTORUN] = true; - } - - break; - case ePosition.F4: - dlg.setMessage("작업 실행\n" + - "(상차) 작업을 실행 할까요?\n" + - "대상위치 : FVI-4\n" + - "현재위치 : " + PUB.Result.CurrentPos.ToString()); - if (dlg.ShowDialog() == DialogResult.Yes) - { - - PUB.Result.TargetPos = ePosition.F4; - PUB.sm.SetNewRunStep(ERunStep.GOUP); - PUB.sm.SetNewStep(eSMStep.RUN); - } - - break; } if (dlg != null) dlg.Dispose(); @@ -705,7 +577,6 @@ namespace Project } VAR.BOOL[eVarBool.FLAG_SETUP] = false;// VAR.BOOL[eVarBool.FLAG_SETUP] = false;//VAR.BOOL[eVarBool.FLAG_SETUP] = false; - if (popmsg) PUB.popup.Visible = true; } @@ -969,7 +840,7 @@ namespace Project private void loadToolStripMenuItem_Click(object sender, EventArgs e) { //load - + var od = new OpenFileDialog { Filter = "AGV Map Files (*.agvmap)|*.agvmap|All Files (*.*)|*.*", @@ -1086,11 +957,11 @@ namespace Project sb.AppendLine($"Current Step: {PUB.sm.Step}"); sb.AppendLine($"Current RunStep: {PUB.sm.RunStep}"); sb.AppendLine(); - + var process = System.Diagnostics.Process.GetCurrentProcess(); sb.AppendLine($"총 스레드 수: {process.Threads.Count}"); sb.AppendLine(); - + foreach (System.Diagnostics.ProcessThread thread in process.Threads) { sb.AppendLine($"Thread {thread.Id}:"); @@ -1102,11 +973,11 @@ namespace Project } sb.AppendLine(); } - + var dump = sb.ToString(); PUB.log.Add("THREAD_DUMP", dump); Console.WriteLine(dump); - + MessageBox.Show( $"스레드 덤프 완료\n로그 파일에 저장되었습니다.\n\n" + //$"마지막 sm_Running: {(DateTime.Now - lastSmRunningTime).TotalSeconds:F1}초 전\n" + diff --git a/Cs_HMI/StateMachine/EnumStruct.cs b/Cs_HMI/StateMachine/EnumStruct.cs index d5a31c1..475b635 100644 --- a/Cs_HMI/StateMachine/EnumStruct.cs +++ b/Cs_HMI/StateMachine/EnumStruct.cs @@ -75,13 +75,13 @@ namespace Project.StateMachine /// /// 상차이동 /// - GOUP, + BUFFER_OUT, /// /// 하차이동 /// - GODOWN, + BUFFER_IN, @@ -100,6 +100,10 @@ namespace Project.StateMachine /// MARKSTROPB, + /// + /// 에러발생 + /// + ERROR, } diff --git a/Cs_HMI/StateMachine/StateMachine.cs b/Cs_HMI/StateMachine/StateMachine.cs index 42ce385..60bbfe2 100644 --- a/Cs_HMI/StateMachine/StateMachine.cs +++ b/Cs_HMI/StateMachine/StateMachine.cs @@ -283,6 +283,8 @@ namespace Project.StateMachine private int _runStepSeq = 0; public int RunStepSeq { get { return _runStepSeq; } } + public Stack BackupRunStep = new Stack(); + private DateTime runStepStartTime = DateTime.Parse("1982-11-23"); private ERunStep _runstepn = ERunStep.READY; private ERunStep _runstepo = ERunStep.READY; diff --git a/Cs_HMI/SubProject/AGV/Command.cs b/Cs_HMI/SubProject/AGV/Command.cs index 6ebec1d..51cef83 100644 --- a/Cs_HMI/SubProject/AGV/Command.cs +++ b/Cs_HMI/SubProject/AGV/Command.cs @@ -143,7 +143,7 @@ namespace arDev $"SSK{interval:0000}", $"SCK{value:0000}" }; - return AddCommand(cmds); + return AddCommand( cmds); } public bool AGVSetTagReinputTime(int value) @@ -164,19 +164,29 @@ namespace arDev $"{cmd}I{cmd2}{I:0000}", $"{cmd}D{cmd2}{D:0000}", }; - return AddCommand(cmds); + return AddCommand( cmds); } + /// + /// 전송을시도한 시간 + /// + //public Dictionary LastCommandTime { get; set; } + /// + /// 전송에 성공한 명령시간 + /// + //public Dictionary LastCommandOKTime { get; set; } protected bool AddCommand(params string[] cmds) { bool ret = true; ACKData = string.Empty; //회신값 제거 + //LastCommandTime.Add(cmd, DateTime.Now); foreach (var cmdline in cmds) { var fullcmd = MakeCheckSum(cmdline); //commandQueue.Enqueue(fullcmd); if (WriteData(fullcmd) == false) ret = false; + //else LastCommandOKTime.Add(cmd, DateTime.Now); System.Threading.Thread.Sleep(1); } return ret; diff --git a/Cs_HMI/SubProject/CommData/Enum.cs b/Cs_HMI/SubProject/CommData/Enum.cs index c469415..f95025f 100644 --- a/Cs_HMI/SubProject/CommData/Enum.cs +++ b/Cs_HMI/SubProject/CommData/Enum.cs @@ -194,8 +194,20 @@ namespace COMM CheckGotoTargetSet, SendGotoCommand, + + /// + /// 마지막으로 멈춤 명령을 전송한 시간 + /// + LastStopCommandTime, + + /// + /// 마지막으로 멈춤(마크스탑) 명령을 전송한 시간 + /// + LastMarkStopCommandTime, + + /// + /// 마지막으로 턴 명령을 전송한 시간 + /// + LastTurnCommandTime, } - - - -} +} \ No newline at end of file diff --git a/Cs_HMI/SubProject/CommUtil b/Cs_HMI/SubProject/CommUtil index 632b087..ed05439 160000 --- a/Cs_HMI/SubProject/CommUtil +++ b/Cs_HMI/SubProject/CommUtil @@ -1 +1 @@ -Subproject commit 632b087c5be6b94ee953a374a25992aa54d56c7c +Subproject commit ed05439991fdddba2d7123b7a89a89245bcd044c diff --git a/Cs_HMI/SubProject/EnigProtocol b/Cs_HMI/SubProject/EnigProtocol index 8877cb1..82bca1c 160000 --- a/Cs_HMI/SubProject/EnigProtocol +++ b/Cs_HMI/SubProject/EnigProtocol @@ -1 +1 @@ -Subproject commit 8877cb1a9dbf97228ebb3fd57ca0004fef77fe24 +Subproject commit 82bca1c90b35c1268e3f85edc41aa115d94866fe