diff --git a/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs b/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
index f262031..c641820 100644
--- a/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
+++ b/AGVLogic/AGVNavigationCore/Models/VirtualAGV.cs
@@ -363,6 +363,9 @@ namespace AGVNavigationCore.Models
}
else
{
+ //움직이지 않는다면 움직이게하고, 움직인다면 마크스탑하낟.i
+
+
//도킹노드라면 markstop 을 나머지는 바로 스탑한다.
eAGVCommandReason reason = eAGVCommandReason.MarkStop;
if (_targetnode.StationType == StationType.Normal || _targetnode.StationType == StationType.Limit)
diff --git a/AGVLogic/EnigProtocol/enigprotocol/Commands.cs b/AGVLogic/EnigProtocol/enigprotocol/Commands.cs
index f443fd4..3377d38 100644
--- a/AGVLogic/EnigProtocol/enigprotocol/Commands.cs
+++ b/AGVLogic/EnigProtocol/enigprotocol/Commands.cs
@@ -38,6 +38,7 @@ namespace ENIGProtocol
Error = 1,
Arrived = 2,
ReadRFID = 3,
+ ActionComplete=4,
Status = 9,
}
@@ -56,7 +57,7 @@ namespace ENIGProtocol
// Operational Errors
CART_EXIST,
MARK_TIMEOUT,
- MARK_SENSOR_FAIL,
+ MARK_SENSOR_FAIL,
LIFT_ERROR,
AGV_SPEED_SET_FAIL,
AGV_RUN_FAIL,
@@ -69,6 +70,9 @@ namespace ENIGProtocol
CHARGE_RETRY_OVER,
MAGNET_ON_ERROR,
MAGNET_OF_ERROR,
+ BUFFER_NOT_COMPLETE,
+ MARK_STOP_FAIL,
+ LIDAR_STOP,
}
public static class AGVUtility
diff --git a/Document/통신프로토콜/.~lock.통신 프로토콜_AGV_V350_LF_25.01.10_r2.xlsx# b/Document/통신프로토콜/.~lock.통신 프로토콜_AGV_V350_LF_25.01.10_r2.xlsx#
deleted file mode 100644
index e184792..0000000
--- a/Document/통신프로토콜/.~lock.통신 프로토콜_AGV_V350_LF_25.01.10_r2.xlsx#
+++ /dev/null
@@ -1 +0,0 @@
-,BACKUPPC/1,backuppc,29.01.2026 14:26,file:///C:/Users/1/AppData/Roaming/LibreOffice/4;
\ No newline at end of file
diff --git a/HMI/Project/Device/Xbee.cs b/HMI/Project/Device/Xbee.cs
index 33e8fb9..9361ea8 100644
--- a/HMI/Project/Device/Xbee.cs
+++ b/HMI/Project/Device/Xbee.cs
@@ -82,7 +82,7 @@ namespace Project.Device
proto.OnMessage -= Proto_OnMessage;
}
-
+ public int senderrcnt = 0;
///
/// 지그비장치에 데이터를 전송합니다
///
@@ -93,10 +93,12 @@ namespace Project.Device
try
{
this.Write(data, 0, data.Length);
+ senderrcnt = 0;
return true;
}
catch (Exception ex)
{
+ senderrcnt += 1;
ErrorMessage = ex.Message;
return false;
}
@@ -119,6 +121,7 @@ namespace Project.Device
try
{
base.Open();
+ senderrcnt = 0;
return IsOpen;
}
catch (Exception ex)
@@ -150,6 +153,7 @@ namespace Project.Device
var buffer = new byte[dev.BytesToRead];
dev.Read(buffer, 0, buffer.Length);
proto.ProcessReceivedData(buffer);
+ VAR.TIME[eVarTime.LastRecv_XBE] = DateTime.Now;
}
///
@@ -168,6 +172,39 @@ namespace Project.Device
PUB.logxbee.AddE($"Send SendMoveComplete [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
}
+ StateMachine.ERunStep lastactioncmd = StateMachine.ERunStep.READY;
+ DateTime lastactioncmdtime = DateTime.Now;
+
+ ///
+ /// 특정행동이 완료되었을때 전달함
+ ///
+ ///
+ public void SendActionComplete(StateMachine.ERunStep actionCmd)
+ {
+ if (lastactioncmd == actionCmd)
+ {
+ var ts = DateTime.Now - lastactioncmdtime;
+ if(ts.TotalSeconds < 2)
+ {
+ return;
+ }
+ }
+
+ var id = PUB.setting.XBE_ID;
+ byte cmd = (byte)ENIGProtocol.AGVCommandEH.ActionComplete;
+ var packet = proto.CreatePacket(id, cmd, null);
+ if (Send(packet))
+ PUB.logxbee.AddI($"SendActionComplete [O] : {packet.Length} {packet.HexString()}");
+ else
+ PUB.logxbee.AddE($"SendActionComplete [X] : {packet.Length} {packet.HexString()} {PUB.XBE.ErrorMessage}");
+
+ //최종액션저장
+ lastactioncmd = actionCmd;
+ lastactioncmdtime = DateTime.Now;
+ }
+
+
+
///
/// 신규 RFID태그값이 읽혔다면 이명령을 통해서 전송한다
///
@@ -254,7 +291,7 @@ namespace Project.Device
value = 0; // stop
data.Add(value);
-
+
//나르미오류코드전송필요 260202
//agv\structure\errorflag.cs 파일의 public enum eflag 에 내용있음
data.AddRange(BitConverter.GetBytes(PUB.AGV.error.Value));
@@ -311,6 +348,10 @@ namespace Project.Device
// ErrorCode [New RunStepErrorCode]
value = (byte)PUB.Result.RunStepErrorCode;
+
+ //라이다로인해 멈춘경우 오류코드 추가 260204
+ if (value == 0 && PUB.AGV.system1.stop_by_front_detect)
+ value = (byte)ENIGProtocol.AGVErrorCode.LIDAR_STOP;
data.Add(value);
// LastTag
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN.cs b/HMI/Project/StateMachine/Step/_SM_RUN.cs
index 8ac2e48..80df2e6 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN.cs
@@ -104,6 +104,7 @@ namespace Project
case ERunStep.GOHOME:
if (_SM_RUN_GOTO_HOME(runStepisFirst, PUB.sm.GetRunSteptime) == true)
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.log.Add($"홈 이동이 완료되어 준비상태로 전환합니다");
PUB.sm.SetNewRunStep(ERunStep.READY);
}
@@ -156,7 +157,7 @@ namespace Project
PUB.log.Add($"정의되지 않은 스테이션 입니다({target.StationType}) ");
break;
}
-
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None;
PUB.sm.SetNewRunStep(ERunStep.READY);
}
@@ -187,6 +188,7 @@ namespace Project
}
else if (_SM_RUN_CHARGE_GO(runStepisFirst, PUB.sm.GetRunSteptime))
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.Speak(Lang.충전을시작합니다);
PUB.sm.SetNewRunStep(ERunStep.CHARGECHECK);
return;
@@ -202,6 +204,7 @@ namespace Project
else if (_SM_RUN_CHARGE_CHECK(runStepisFirst, PUB.sm.GetRunSteptime))
{
//충전상태가 활성화되었으므로 대기상태로 전환한다
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.sm.SetNewRunStep(ERunStep.READY);
PUB.log.AddAT("충전상태 확인 완료로 인해 대기 합니다");
}
@@ -218,6 +221,7 @@ namespace Project
//충전 상태가 OFF되어야 동작하게한다
if (_SM_RUN_CHARGE_GOFF(isFirst, stepTime) == true)
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
//충전상태가 활성화되었으므로 대기상태로 전환한다
PUB.sm.ClearRunStep();
@@ -233,6 +237,7 @@ namespace Project
case ERunStep.LOADER_IN: //로더도킹
if (_SM_RUN_ENTER(runStepisFirst, PUB.sm.GetRunSteptime))
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
//도킹완료상태를 업데이트한다.
@@ -248,6 +253,7 @@ namespace Project
case ERunStep.LOADER_OUT: //로더아웃
if (_SM_RUN_EXIT(runStepisFirst, PUB.sm.GetRunSteptime))
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.Speak(Lang.버퍼도킹해제완료);
//도킹완료상태를 업데이트한다.
@@ -262,6 +268,7 @@ namespace Project
case ERunStep.BUFFER_OUT: //버퍼아웃
if (_SM_RUN_BUFFER_OUT(runStepisFirst, PUB.sm.GetRunSteptime))
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.Speak(Lang.버퍼도킹해제완료);
//도킹완료상태를 업데이트한다.
@@ -277,6 +284,7 @@ namespace Project
case ERunStep.BUFFER_IN: //버퍼도킹
if (_SM_RUN_BUFFER_IN(runStepisFirst, PUB.sm.GetRunSteptime))
{
+ PUB.XBE.SendActionComplete(PUB.sm.RunStep);
PUB.Speak(Lang.버퍼도킹이완료되었습니다);
//도킹완료상태를 업데이트한다.
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
index 72701bd..d609316 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_IN.cs
@@ -79,34 +79,15 @@ namespace Project
if (PUB._virtualAGV.Turn == AGVNavigationCore.Models.AGVTurn.L90)
{
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 이미 Left Turn 완료 상태입니다. 턴 명령을 건너뜁니다.");
- PUB.sm.UpdateRunStepSeq();
}
else
{
- //하드웨어 상태 확인
- //var turnState = PUB.AGV.TurnInformation?.StateNew ?? arDev.eNarumiTurn.None;
-
- //if (turnState == arDev.eNarumiTurn.Left || turnState == arDev.eNarumiTurn.LeftIng)
- //{
- // //이미 좌회전 중이거나 완료된 하드웨어 상태
- // PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 하드웨어 좌회전 상태 확인됨({turnState}). 명령을 건너뜁니다.");
- // PUB.sm.UpdateRunStepSeq();
- //}
- //else if (turnState == arDev.eNarumiTurn.Right || turnState == arDev.eNarumiTurn.RightIng)
- //{
- // //비정상 상태 (우회전 중?)
- // SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 우회전 상태에서 좌회전을 시도할 수 없습니다.");
- //}
- //else
- //{
- //정상 (None) -> 턴 명령 실행
PUB.AGV.AGVMoveLeft180Turn();
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Left Turn");
VAR.TIME.Update(eVarTime.LastTurnCommandTime);
- PUB.sm.UpdateRunStepSeq();
- //}
+ PUB._mapCanvas.SetAlertMessage($"턴 실행");
}
- PUB._mapCanvas.SetAlertMessage($"턴 진행 중");
+ PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
@@ -155,7 +136,7 @@ namespace Project
//리프트 센서 확인
if (PUB.AGV.signal1.lift_down == false)
{
- VAR.I32[eVarInt32.RetryLift] = 0;
+ VAR.I32[eVarInt32.RetryLift] += 1;
var rlt = PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.DN);
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 리프트 하강 실행:{rlt}");
}
@@ -191,20 +172,20 @@ namespace Project
}
else if (PUB.sm.RunStepSeq == idx++)
{
- if(PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOffEnter)
+ if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOffEnter)
{
VAR.I32[eVarInt32.RetryManget] += 1;
PUB.AGV.LiftControl(arDev.Narumi.LiftCommand.ON);
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 마그넷ON");
}
-
+
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
//마그넷센서가 들어오는지 5초간 확인한다.
- if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOffEnter &&
+ if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOffEnter &&
PUB.AGV.signal1.magnet_on == false)
{
if (seqtime.TotalSeconds > 5)
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
index fae9f1c..57a3eac 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN_BUFFER_OUT.cs
@@ -41,6 +41,17 @@ namespace Project
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
+ {
+ //회전이없다면 오류처리한다.
+ if(PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.L90)
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.BUFFER_NOT_COMPLETE, $"[{funcname}-{PUB.sm.RunStepSeq}] 버퍼에서 나오려면 버퍼진입작업이 완료되어있어야 합니다");
+ return false;
+ }
+ PUB.sm.UpdateRunStepSeq();
+ return false;
+ }
+ else if (PUB.sm.RunStepSeq == idx++)
{
arDev.Narumi.LiftCommand lift = PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOnExit ? arDev.Narumi.LiftCommand.UP : arDev.Narumi.LiftCommand.DN;
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 리프트제어 {lift}");
@@ -57,7 +68,7 @@ namespace Project
{
if (seqtime.TotalSeconds > 20)
{
- if(VAR.I32[eVarInt32.RetryLift] < 3)
+ if (VAR.I32[eVarInt32.RetryLift] < 3)
{
PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] 리프트가 완료되지 않아 재시도 합니다");
PUB.sm.UpdateRunStepSeq(-1);
@@ -73,10 +84,10 @@ namespace Project
PUB.sm.UpdateRunStepSeq();
return false;
}
-
+
else if (PUB.sm.RunStepSeq == idx++)
{
- if (PUB.AGV.signal1.mark_sensor == false)
+ //if (PUB.AGV.signal1.mark_sensor == false)
{
//빈 상태로 아웃해야한다.
if (SpeedSetRetry)
@@ -112,7 +123,7 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
- if (PUB.AGV.signal1.mark_sensor == false)
+ //if (PUB.AGV.signal1.mark_sensor == false)
{
VAR.I32[eVarInt32.RetryMove] += 1;
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV 전진 구동 시작");
@@ -124,13 +135,13 @@ namespace Project
else if (PUB.sm.RunStepSeq == idx++)
{
//AGV구동을 확인하고 마크스탑을 설정한다.
- if (PUB.AGV.signal1.mark_sensor == false)
+ //if (PUB.AGV.signal1.mark_sensor == false)
{
if (PUB.AGV.system1.agv_run == false)
{
if (seqtime.TotalSeconds > 3)
{
- if(VAR.I32[eVarInt32.RetryMove] < 3)
+ if (VAR.I32[eVarInt32.RetryMove] < 3)
{
//재시도를 하게한다.
PUB.sm.UpdateRunStepSeq(-1);
@@ -141,7 +152,7 @@ namespace Project
SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL);
VAR.I32[eVarInt32.RetryMove] = 0;
}
-
+
}
return false;
}
@@ -161,14 +172,14 @@ namespace Project
}
else if (PUB.sm.RunStepSeq == idx++)
{
- if (PUB.AGV.signal1.mark_sensor == false)
+ //if (PUB.AGV.signal1.mark_sensor == false)
{
//마크스탑신호가 3초이내로 들어와야 한다
if (PUB.AGV.data.Speed != 'S')
{
if (seqtime.TotalSeconds > 3)
{
- if(VAR.I32[eVarInt32.RetryMarkStop] < 3)
+ if (VAR.I32[eVarInt32.RetryMarkStop] < 3)
{
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 재시도");
PUB.sm.UpdateRunStepSeq(-1);
@@ -184,7 +195,7 @@ namespace Project
}
PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] MarkStop 신구 확인 완료");
}
- else PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}]마크스탑이 미리 들어와있어. 이동및 스탑을 하지 않습니다");
+ //else PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}]마크스탑이 미리 들어와있어. 이동및 스탑을 하지 않습니다");
PUB.sm.UpdateRunStepSeq();
return false;
@@ -215,69 +226,45 @@ namespace Project
}
else
{
- //하드웨어 상태 확인
- //var turnState = PUB.AGV.TurnInformation?.StateOld ?? arDev.eNarumiTurn.None;
- //if (turnState == arDev.eNarumiTurn.Right)
- //{
- // SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}-{PUB.sm.RunStepSeq}] 턴 방향 불일치(Current:{turnState}). 버퍼진출시에는 LEFT-TURN 상태여야 합니다");
- // return false;
- //}
- //else
- //{
- //정상 (None) -> 턴 명령 실행
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn 명령 전송");
PUB.AGV.AGVMoveRight180Turn();
- //}
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] AGV Right Turn");
+ VAR.TIME.Update(eVarTime.LastTurnCommandTime);
+ PUB._mapCanvas.SetAlertMessage($"턴 실행");
}
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
- //이동확인
- if (PUB.AGV.system1.agv_run == false)
+ //이미 완료된 상태라면 대기 과정을 건너뛴다.
+ if (PUB._virtualAGV.Turn == AGVNavigationCore.Models.AGVTurn.R90)
{
- //최소3초기다려준다.
- if (seqtime.TotalSeconds > 3)
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 이미 턴이완료된 상태입니다");
+ }
+ else
+ {
+ //왼쪽턴이 완료되지 않은경우
+ if (PUB.AGV.TurnInformation.State != arDev.eNarumiTurn.Right)
{
- if (PUB._virtualAGV.Turn == AGVNavigationCore.Models.AGVTurn.R90)
+ //움직임 확인을 위해 3초간은 검증을 유예한다
+ if (PUB.AGV.TurnInformation.Runtime.TotalSeconds < 3) return false;
+
+ //턴 이동 상태가 확인되어야 한다.
+ var overtime = 30;
+ if (PUB.AGV.TurnInformation.Runtime.TotalSeconds > overtime)
{
- //이미 완료된 상태이므로 이동 확인 패스
- PUB.sm.UpdateRunStepSeq();
+ //30초동안 AGV까 움직이지 않았다면 오류 처리한다.
+ SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL, $"[{funcname}] {overtime}초이내 턴 감지 안됨");
return false;
}
-
- SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL);
+ else PUB._mapCanvas.SetAlertMessage($"턴 진행 중({PUB.AGV.TurnInformation.Runtime.TotalSeconds:N0}/{overtime})");
+ return false;
}
- return false;
- }
- PUB.sm.UpdateRunStepSeq();
- return false;
- }
- else if (PUB.sm.RunStepSeq == idx++)
- {
- //멈춤확인
- if (PUB.AGV.system1.agv_run == true)
- {
- if (seqtime.TotalSeconds > 25)
- {
- SetRunStepError(ENIGProtocol.AGVErrorCode.TURN_FAIL);
- }
- return false;
+ PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None; //턴완료
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] Turn(right) 완료 - 위치복귀됨");
}
- //턴 완료 상태 업데이트
- if (PUB._virtualAGV.Turn != AGVNavigationCore.Models.AGVTurn.R90)
- {
- if (PUB._virtualAGV.Turn == AGVNavigationCore.Models.AGVTurn.None)
- PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.R90; //left에서 right 턴을 했으니 none 이다
- else
- PUB._virtualAGV.Turn = AGVNavigationCore.Models.AGVTurn.None;
-
- PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] Turn State Updated to {PUB._virtualAGV.Turn}");
- }
-
- PUB.sm.UpdateRunStepSeq();
+ PUB.sm.UpdateRunStepSeq(); //이미완료된상태이므로 다음으로 진행한다.
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
diff --git a/HMI/Project/StateMachine/Step/_SM_RUN_EXIT.cs b/HMI/Project/StateMachine/Step/_SM_RUN_EXIT.cs
index 53f048b..c5ca003 100644
--- a/HMI/Project/StateMachine/Step/_SM_RUN_EXIT.cs
+++ b/HMI/Project/StateMachine/Step/_SM_RUN_EXIT.cs
@@ -14,22 +14,23 @@ namespace Project
///
/// 장비엣 빠젼나온다.
///
- public Boolean _SM_RUN_EXIT(bool isFirst, TimeSpan seqTime)
+ public Boolean _SM_RUN_EXIT(bool isFirst, TimeSpan seqtime)
{
var idx = 1;
- var funcname = PUB.sm.RunStep.ToString();
+ var funcname = $"[EXIT-{PUB.sm.RunStep}]";
//충전 상태가 OFF되어야 동작하게한다
- if (_SM_RUN_CHARGE_GOFF(isFirst, seqTime) == false) return false;
+ if (_SM_RUN_CHARGE_GOFF(isFirst, seqtime) == false) return false;
//라이더멈춤이 설정되어있다면 음성으로 알려준다
if (CheckLiderStop() == false) return false;
if (PUB.sm.RunStepSeq == idx++)
{
- PUB.log.Add("OUT작업-시작");
- PUB.Speak("작업을 시작합니다");
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] OUT작업-시작");
+ PUB.Speak("작업을 시작합니다(안전을위해 AGVSTOP신호를 전송합니다)");
PUB.AGV.AGVMoveStop(funcname);
+ VAR.I32[eVarInt32.RetryLift] = 0;
PUB.sm.UpdateRunStepSeq();
return false;
}
@@ -38,7 +39,7 @@ namespace Project
//작업형태에 따라서. 리프트를 제어한다.
var liftCmd = arDev.Narumi.LiftCommand.DN;
if (PUB.NextWorkCmd == ENIGProtocol.AGVCommandHE.PickOnExit) liftCmd = arDev.Narumi.LiftCommand.UP;
-
+ VAR.I32[eVarInt32.RetryLift] += 1;
PUB.AGV.LiftControl(liftCmd);
PUB.sm.UpdateRunStepSeq();
return false;
@@ -62,21 +63,32 @@ namespace Project
}
else
{
- var ts = VAR.TIME.RUN(eVarTime.LastTurnCommandTime);
- if (ts.TotalSeconds > 10)
+ if (seqtime.TotalSeconds > 20)
{
- SetRunStepError(ENIGProtocol.AGVErrorCode.LIFT_ERROR, $"[{funcname}] 리프트({liftCmd})이 확인되지 않습니다");
+ if (VAR.I32[eVarInt32.RetryLift] < 3)
+ {
+ PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] 리프트가 동작({liftCmd})하지 않아 재시도 합니다");
+ PUB.sm.UpdateRunStepSeq(-1);
+ }
+ else
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.LIFT_ERROR,
+ $"[{funcname}-{PUB.sm.RunStepSeq}] 리프트가 동작({liftCmd})하지 않습니다");
+ VAR.I32[eVarInt32.RetryLift] = 0;
+ }
}
+ else PUB._mapCanvas.SetAlertMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
return false;
}
-
- PUB.log.Add("리프트 동작 확인 완료");
+ VAR.I32[eVarInt32.RetryMoveset] = 0;
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 리프트 동작 확인 완료");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
{
- //빈 상태로 아웃해야한다.
+ //라이더 끈상태로 빠져나와야 한다
+ VAR.I32[eVarInt32.RetryMoveset] += 1;
var ret = PUB.AGV.AGVMoveSet(new arDev.Narumi.BunkiData
{
Bunki = arDev.Narumi.eBunki.Strate,
@@ -84,22 +96,45 @@ namespace Project
PBSSensor = 0,
Speed = arDev.Narumi.eMoveSpd.Low,
});
- //명령이 실패되었다면 재시도를 한다
if (ret != arDev.eNarumiCommandResult.Success)
- {
- if (ret >= arDev.eNarumiCommandResult.Error)
- {
- SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_SPEED_SET_FAIL);
- }
- return false;
- }
+ PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] moveset return fail:{ret}");
PUB.sm.UpdateRunStepSeq();
return false;
}
else if (PUB.sm.RunStepSeq == idx++)
+ {
+ //moveset 결과확인
+ if (PUB.AGV.data.Speed != 'L' ||
+ PUB.AGV.data.Sts != 'S' ||
+ PUB.AGV.data.Direction != 'F')
+ {
+ if (seqtime.TotalSeconds > 5)
+ {
+ if (VAR.I32[eVarInt32.RetryMoveset] < 3)
+ {
+ PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] MoveSet이 확인되지 않아 재시도 합니다");
+ PUB.sm.UpdateRunStepSeq(-1);
+ }
+ else
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_SPEED_SET_FAIL,
+ $"[{funcname}-{PUB.sm.RunStepSeq}] MoveSet 실패");
+ VAR.I32[eVarInt32.RetryMoveset] = 0;
+ }
+ }
+ else PUB._mapCanvas.SetAlertMessage($"이동설정 확인 중({seqtime.TotalSeconds:N0}/20)");
+ return false;
+ }
+ VAR.I32[eVarInt32.RetryMove] = 0;
+ PUB.sm.UpdateRunStepSeq();
+ return false;
+ }
+ else if (PUB.sm.RunStepSeq == idx++)
{
//전진이동
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 전진이동");
+ VAR.I32[eVarInt32.RetryMove] += 1;
PUB.AGV.AGVMoveRun(arDev.Narumi.eRunOpt.Forward);
PUB.sm.UpdateRunStepSeq();
return false;
@@ -109,14 +144,33 @@ namespace Project
//AGV구동을 확인하고 마크스탑을 설정한다.
if (PUB.AGV.system1.agv_run == false)
{
- if (seqTime.TotalMilliseconds > 1000)
+ if (seqtime.TotalSeconds > 3)
{
- //구동이확인되지 않으면 오류처리를 한다.
- SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL);
+ if (VAR.I32[eVarInt32.RetryMove] < 3)
+ {
+ PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] AGV전진이 확인되지 않아 재시도 합니다");
+ PUB.sm.UpdateRunStepSeq(-1);
+ }
+ else
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_RUN_FAIL,
+ $"[{funcname}-{PUB.sm.RunStepSeq}] agv 구동확인 안됨");
+ VAR.I32[eVarInt32.RetryMove] = 0;
+ }
}
+ else PUB._mapCanvas.SetAlertMessage($"AGV RUN 확인 중({seqtime.TotalSeconds:N0}/20)");
return false;
}
+
//마크스탑설정
+ VAR.I32[eVarInt32.RetryMarkStop] = 0;
+ PUB.sm.UpdateRunStepSeq();
+ return false;
+ }
+ else if (PUB.sm.RunStepSeq == idx++)
+ {
+ PUB.log.Add($"[{funcname}-{PUB.sm.RunStepSeq}] 마크스탑신호를 전달합니다");
+ VAR.I32[eVarInt32.RetryMarkStop] += 1;
PUB.AGV.AGVMoveStop(funcname, arDev.Narumi.eStopOpt.MarkStop);
PUB.sm.UpdateRunStepSeq();
return false;
@@ -126,10 +180,21 @@ namespace Project
//마크스탑신호가 3초이내로 들어와야 한다
if (PUB.AGV.data.Speed != 'S')
{
- if (seqTime.TotalMilliseconds > 3000)
+ if (seqtime.TotalSeconds > 20)
{
- SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_TIMEOUT);
+ if (VAR.I32[eVarInt32.RetryMarkStop] < 3)
+ {
+ PUB.log.AddAT($"[{funcname}-{PUB.sm.RunStepSeq}] 마크스탑이 확인되지 않아 재시도 합니다");
+ PUB.sm.UpdateRunStepSeq(-1);
+ }
+ else
+ {
+ SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_STOP_FAIL,
+ $"[{funcname}-{PUB.sm.RunStepSeq}] 마크스탑이 확인되지 않습니다");
+ VAR.I32[eVarInt32.RetryMarkStop] = 0;
+ }
}
+ else PUB._mapCanvas.SetAlertMessage($"리프트 하강 확인 중({seqtime.TotalSeconds:N0}/20)");
return false;
}
PUB.sm.UpdateRunStepSeq();
@@ -140,7 +205,7 @@ namespace Project
//AGV가 멈출때까지 기다린다.
if (PUB.AGV.system1.agv_run == true)
{
- if (seqTime.TotalSeconds > 10)
+ if (seqtime.TotalSeconds > 10)
{
SetRunStepError(ENIGProtocol.AGVErrorCode.AGV_STOP_FAIL);
}
@@ -154,7 +219,7 @@ namespace Project
//마크센서입력을 확인한다.
if (PUB.AGV.signal1.mark_sensor == false)
{
- if (seqTime.TotalSeconds > 5)
+ if (seqtime.TotalSeconds > 5)
{
SetRunStepError(ENIGProtocol.AGVErrorCode.MARK_SENSOR_FAIL);
}
diff --git a/HMI/Project/StateMachine/Step/_Util.cs b/HMI/Project/StateMachine/Step/_Util.cs
index 79add7d..18a4533 100644
--- a/HMI/Project/StateMachine/Step/_Util.cs
+++ b/HMI/Project/StateMachine/Step/_Util.cs
@@ -297,10 +297,17 @@ namespace Project
// 목적지 도착 여부 확인
if (PUB.AGV.signal1.mark_sensor == false)
{
-
- PUB.log.AddI($"목표도착되었으나 마크센서가 감지되지 않아 완료처리 하지않습니다");
- return false;
-
+ if(PUB._virtualAGV.TargetNode.StationType != StationType.Normal)
+ {
+ PUB.log.AddAT($"목표도착되었으나 마크센서가 감지되지 않아 완료처리 하지않습니다");
+ return false;
+ }
+ else
+ {
+ //일반노드가목표인경우에는 완료처리한다.
+ PUB.log.AddI($"일반노드는 마크센서가 감지되지 않아도 완료처리 합니다");
+ return true;
+ }
}
// 경로가 존재한다면...
diff --git a/HMI/Project/StateMachine/_AGV.cs b/HMI/Project/StateMachine/_AGV.cs
index acde730..dda272d 100644
--- a/HMI/Project/StateMachine/_AGV.cs
+++ b/HMI/Project/StateMachine/_AGV.cs
@@ -185,6 +185,14 @@ namespace Project
PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, CurrentNode, MotDireciton);
PUB._virtualAGV.SetPosition(CurrentNode, MotDireciton);
PUB.SaveLastPosition();
+
+ //노드가 들어왔는데. 일반 노드라면.. 턴 정보를 제거한다.
+ if (CurrentNode.StationType != StationType.Buffer && PUB._virtualAGV.Turn != AGVTurn.None)
+ {
+ PUB.log.AddAT($"현재노드위치가 버퍼가 아니라서 턴정보를 초기화합니다{PUB._virtualAGV.Turn}");
+ PUB._virtualAGV.Turn = AGVTurn.None;
+ }
+
}
//태그를 읽었다면 상태를 바로 전송한다
diff --git a/HMI/Project/StateMachine/_Loop.cs b/HMI/Project/StateMachine/_Loop.cs
index 86304d6..33443b3 100644
--- a/HMI/Project/StateMachine/_Loop.cs
+++ b/HMI/Project/StateMachine/_Loop.cs
@@ -172,8 +172,15 @@ namespace Project
if (PUB._mapCanvas != null)
{
this.Invoke(new Action(() => {
+
+
+ AutoLoadLastPosition();
+
PUB._mapCanvas.ExitSyncMode( AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run);
}));
+
+
+
}
}
diff --git a/HMI/Project/StateMachine/_SPS.cs b/HMI/Project/StateMachine/_SPS.cs
index 892b0f4..e040391 100644
--- a/HMI/Project/StateMachine/_SPS.cs
+++ b/HMI/Project/StateMachine/_SPS.cs
@@ -49,8 +49,17 @@ namespace Project
{
if (VAR.BOOL[eVarBool.DISABLE_AUTOCONN_XBEE] == false)
{
- ConnectSerialPort(PUB.XBE, PUB.setting.Port_XBE, PUB.setting.Baud_XBE,
- eVarTime.LastConn_XBE, eVarTime.LastConnTry_XBE, null);
+ if(PUB.XBE.senderrcnt>5)
+ {
+ ConnectSerialPort(PUB.XBE, PUB.setting.Port_XBE, PUB.setting.Baud_XBE,
+ eVarTime.LastConn_XBE, eVarTime.LastConnTry_XBE, eVarTime.LastRecv_XBE);
+ }
+ else
+ {
+ ConnectSerialPort(PUB.XBE, PUB.setting.Port_XBE, PUB.setting.Baud_XBE,
+ eVarTime.LastConn_XBE, eVarTime.LastConnTry_XBE, null);
+ }
+
}
}
diff --git a/HMI/Project/StateMachine/_Xbee.cs b/HMI/Project/StateMachine/_Xbee.cs
index 35f9ebe..0a1d6c0 100644
--- a/HMI/Project/StateMachine/_Xbee.cs
+++ b/HMI/Project/StateMachine/_Xbee.cs
@@ -210,8 +210,20 @@ namespace Project
return;
}
+
+
+ //노드가 들어왔는데. 일반 노드라면.. 턴 정보를 제거한다.
+ if (PUB._virtualAGV.CurrentNode != null &&
+ PUB._virtualAGV.CurrentNode.StationType != StationType.Buffer &&
+ PUB._virtualAGV.Turn != AGVTurn.None)
+ {
+ PUB.log.AddAT($"[{logPrefix}-Goto] 현재노드위치가 버퍼가 아니라서 턴정보를 초기화합니다{PUB._virtualAGV.Turn}");
+ PUB._virtualAGV.Turn = AGVTurn.None;
+ }
+
+
//s/w턴이 걸려있다면 이동 불가로한다.(버퍼 작업중이다)
- if(PUB._virtualAGV.Turn != AGVTurn.None)
+ if (PUB._virtualAGV.Turn != AGVTurn.None)
{
SetRunStepError(ENIGProtocol.AGVErrorCode.BUFFER_NOT_COMPLETE, $"[{logPrefix}-Goto] 버퍼작업이 완료되지 않았습니다");
return;
diff --git a/HMI/Project/ViewForm/fAuto.Designer.cs b/HMI/Project/ViewForm/fAuto.Designer.cs
index 4935a95..a654b74 100644
--- a/HMI/Project/ViewForm/fAuto.Designer.cs
+++ b/HMI/Project/ViewForm/fAuto.Designer.cs
@@ -32,63 +32,65 @@ namespace Project.ViewForm
///
private void InitializeComponent()
{
- components = new System.ComponentModel.Container();
- timer1 = new System.Windows.Forms.Timer(components);
- ctlAuto1 = new CtlAuto();
- panel1 = new Panel();
- SuspendLayout();
+ this.components = new System.ComponentModel.Container();
+ this.timer1 = new System.Windows.Forms.Timer(this.components);
+ this.ctlAuto1 = new Project.CtlAuto();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.SuspendLayout();
//
// timer1
//
- timer1.Interval = 200;
+ this.timer1.Interval = 200;
+ this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// ctlAuto1
//
- ctlAuto1.BackColor = Color.FromArgb(32, 32, 32);
- ctlAuto1.BorderColor = Color.Transparent;
- ctlAuto1.Font = new Font("맑은 고딕", 20F, FontStyle.Regular, GraphicsUnit.Point, 129);
- ctlAuto1.Font_BMS_Level = new Font("Bahnschrift Condensed", 250F, FontStyle.Bold, GraphicsUnit.Point, 0);
- ctlAuto1.Font_BMS_Volt = new Font("Bahnschrift Condensed", 50.25F, FontStyle.Bold);
- ctlAuto1.Font_MAIN_BMSLevel = new Font("Arial Narrow", 150F, FontStyle.Bold);
- ctlAuto1.ForeColor = Color.White;
- ctlAuto1.ItemGap = 0;
- ctlAuto1.Items = null;
- ctlAuto1.Location = new Point(835, 338);
- ctlAuto1.MinimumSize = new Size(100, 30);
- ctlAuto1.Name = "ctlAuto1";
- ctlAuto1.ProgressMax = 100F;
- ctlAuto1.ProgressVal = 50F;
- ctlAuto1.Scean = CtlAuto.eScean.Normal;
- ctlAuto1.Size = new Size(179, 241);
- ctlAuto1.StatusMessage = "상태메세지 입니다";
- ctlAuto1.StopMessage = "";
- ctlAuto1.StopTime = new DateTime(0L);
- ctlAuto1.TabIndex = 20;
- ctlAuto1.Text = "ctlAuto1";
+ this.ctlAuto1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(32)))), ((int)(((byte)(32)))));
+ this.ctlAuto1.BorderColor = System.Drawing.Color.Transparent;
+ this.ctlAuto1.Font = new System.Drawing.Font("맑은 고딕", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
+ this.ctlAuto1.Font_BMS_Level = new System.Drawing.Font("Bahnschrift Condensed", 250F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ctlAuto1.Font_BMS_Volt = new System.Drawing.Font("Bahnschrift Condensed", 50.25F, System.Drawing.FontStyle.Bold);
+ this.ctlAuto1.Font_MAIN_BMSLevel = new System.Drawing.Font("Microsoft Sans Serif", 150F, System.Drawing.FontStyle.Bold);
+ this.ctlAuto1.ForeColor = System.Drawing.Color.White;
+ this.ctlAuto1.ItemGap = 0;
+ this.ctlAuto1.Items = null;
+ this.ctlAuto1.Location = new System.Drawing.Point(835, 338);
+ this.ctlAuto1.MinimumSize = new System.Drawing.Size(100, 30);
+ this.ctlAuto1.Name = "ctlAuto1";
+ this.ctlAuto1.ProgressMax = 100F;
+ this.ctlAuto1.ProgressVal = 50F;
+ this.ctlAuto1.Scean = Project.CtlAuto.eScean.Normal;
+ this.ctlAuto1.Size = new System.Drawing.Size(179, 241);
+ this.ctlAuto1.StatusMessage = "상태메세지 입니다";
+ this.ctlAuto1.StopMessage = "";
+ this.ctlAuto1.StopTime = new System.DateTime(((long)(0)));
+ this.ctlAuto1.TabIndex = 20;
+ this.ctlAuto1.Text = "ctlAuto1";
//
// panel1
//
- panel1.Dock = DockStyle.Fill;
- panel1.Font = new Font("Tahoma", 8F, FontStyle.Bold);
- panel1.Location = new Point(0, 0);
- panel1.Name = "panel1";
- panel1.Size = new Size(1014, 579);
- panel1.TabIndex = 21;
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Bold);
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(1014, 579);
+ this.panel1.TabIndex = 21;
//
// fAuto
//
- AutoScaleMode = AutoScaleMode.None;
- BackColor = Color.FromArgb(15, 15, 15);
- ClientSize = new Size(1014, 579);
- Controls.Add(panel1);
- Controls.Add(ctlAuto1);
- DoubleBuffered = true;
- FormBorderStyle = FormBorderStyle.None;
- Name = "fAuto";
- Text = "fAuto";
- Load += fAuto_Load;
- VisibleChanged += fAuto_VisibleChanged;
- ResumeLayout(false);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(15)))), ((int)(((byte)(15)))), ((int)(((byte)(15)))));
+ this.ClientSize = new System.Drawing.Size(1014, 579);
+ this.Controls.Add(this.panel1);
+ this.Controls.Add(this.ctlAuto1);
+ this.DoubleBuffered = true;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.Name = "fAuto";
+ this.Text = "fAuto";
+ this.Load += new System.EventHandler(this.fAuto_Load_1);
+ this.VisibleChanged += new System.EventHandler(this.fAuto_VisibleChanged);
+ this.ResumeLayout(false);
+
}
#endregion
diff --git a/HMI/Project/ViewForm/fAuto.cs b/HMI/Project/ViewForm/fAuto.cs
index 6e4fb68..a4e6090 100644
--- a/HMI/Project/ViewForm/fAuto.cs
+++ b/HMI/Project/ViewForm/fAuto.cs
@@ -141,7 +141,7 @@ namespace Project.ViewForm
PUB.AGV.DataReceive += AGV_DataReceive;
- this.timer1.Start();
+
}
private void AGV_DataReceive(object sender, arDev.Narumi.DataEventArgs e)
{
@@ -194,34 +194,7 @@ namespace Project.ViewForm
private void timer1_Tick_1(object sender, EventArgs e)
{
- //if (this.Visible == false) return;
- //if (tmrun == true) return;
- //tmrun = true;
-
- //this.ctlAuto1.OnUpdateMode = true;
-
- //if (this.ctlAuto1.Scean == CtlAuto.eScean.Progress)
- //{
- // ctlAuto1.ProgressVal = PUB.Result.SMSG_ProgressValue;
- // ctlAuto1.ProgressMax = PUB.Result.SMSG_ProgressMax;
- // ctlAuto1.StatusMessage = VAR.STR?.Get(eVarString.StatusMessage) ?? string.Empty;
- //}
- //this.ctlAuto1.StopMessage = string.Empty;
-
- //if (PUB.sm.Step == StateMachine.eSMStep.RUN)
- //{
- // this.ctlAuto1.runStep = PUB.sm.RunStep;
- //}
- //else
- //{
- // this.ctlAuto1.runStep = ERunStep.READY;
- //}
- //this.ctlAuto1.OnUpdateMode = false;
- //this.ctlAuto1.Invalidate();
-
- //PUB.mapctl.PredictNextAction();
-
- //tmrun = false;
+
}
private void HandleRunModeClick(MapNode targetNode)
@@ -267,5 +240,56 @@ namespace Project.ViewForm
return;
}
}
+
+ private void timer1_Tick(object sender, EventArgs e)
+ {
+
+ if (this.Visible == false) return;
+ if (tmrun == true) return;
+ if (PUB.sm.Step < eSMStep.IDLE) return;
+ if (PUB._mapCanvas == null) return;
+ tmrun = true;
+
+
+ var errmsg = string.Empty;
+ if(PUB.AGV.IsOpen==false)
+ {
+ errmsg = "AGV컨트롤러 연결실패";
+ }
+ else if(PUB.XBE.IsOpen==false )
+ {
+ errmsg = "XBEE 연결실패";
+ }
+ else if (PUB.XBE.senderrcnt > 5)
+ {
+ errmsg = "XBEE 통신불가";
+ }
+ else if(PUB.AGV.error.Value > 0)
+ {
+ errmsg = PUB.AGV.error.ToString();
+ }
+ else if(PUB.AGV.system1.stop_by_front_detect)
+ {
+ errmsg = "전방 물체감지로 인해 정지";
+ }
+ else if (PUB.BMS.IsOpen == false)
+ {
+ errmsg = "BMS 연결실패";
+ }
+ else if(VAR.BOOL[eVarBool.FLAG_AUTORUN]==false)
+ {
+ errmsg = "자동모드가 아닙니다";
+ }
+
+ PUB._mapCanvas.SetAlertMessage(errmsg);
+
+
+ tmrun = false;
+ }
+
+ private void fAuto_Load_1(object sender, EventArgs e)
+ {
+ this.timer1.Start();
+ }
}
}
diff --git a/HMI/Project/fMain.cs b/HMI/Project/fMain.cs
index 790bcea..de8eb48 100644
--- a/HMI/Project/fMain.cs
+++ b/HMI/Project/fMain.cs
@@ -261,6 +261,57 @@ namespace Project
PUB.AddEEDB("프로그램 시작");
}
+ void AutoLoadLastPosition()
+ {
+ PUB.log.Add("autoload last position");
+ //마지막위치복원
+ // 마지막 위치 로드
+ var lastPos = PUB.LoadLastPosition();
+ if (lastPos != null)
+ {
+ var sb = new System.Text.StringBuilder();
+ var curNode = PUB.FindByNodeID(lastPos.NodeId);
+ var prevNode = PUB.FindByNodeID(lastPos.PrevNode);
+ var targNode = PUB.FindByNodeID(lastPos.TargetNode);
+ var staNode = PUB.FindByNodeID(lastPos.StartNode);
+ if (prevNode != null)
+ {
+ PUB._virtualAGV.SetPosition(prevNode, lastPos.PrevDirection);
+ PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, prevNode, lastPos.PrevDirection);
+ sb.AppendLine($"이전: {prevNode.ID2}, {lastPos.PrevDirection}");
+ }
+ if (curNode != null)
+ {
+ PUB._virtualAGV.SetPosition(curNode, lastPos.Direction);
+ PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, curNode, lastPos.Direction);
+ sb.AppendLine($"현재: {curNode.ID2}, {lastPos.Direction}");
+ }
+ if (staNode != null)
+ {
+ PUB._virtualAGV.StartNode = staNode;
+ sb.AppendLine($"시직:{staNode.ID2}");
+ }
+ if (targNode != null)
+ {
+ PUB._virtualAGV.TargetNode = targNode;
+ sb.AppendLine($"대상:{targNode.ID2}");
+ }
+
+ PUB._virtualAGV.Turn = lastPos.Turn;
+ sb.AppendLine($"S/W회전:{lastPos.Turn}");
+
+ if (lastPos.AGV_Turn != null)
+ {
+ PUB.AGV.TurnInformation = lastPos.AGV_Turn;
+ sb.AppendLine($"H/W회전:{lastPos.AGV_Turn}");
+ }
+
+ PUB.log.Add($"위치복원\n{sb}");
+ }
+ else PUB.log.AddE($"마지막위치가 없습니다");
+
+
+ }
void AutoLoadMapData()
{
//auto load
@@ -279,11 +330,16 @@ namespace Project
if (files.Any()) filePath = files[0];
}
+ if(PUB._mapCanvas == null)
+ {
+ UTIL.MsgE("Canvas null");
+ }
+
if (filePath.Exists)
{
var result = MapLoader.LoadMapFromFile(filePath.FullName);
- if (result.Success)
+ if (result != null && result.Success)
{
PUB._mapCanvas.SetMapLoadResult(result);
PUB._mapCanvas.MapFileName = filePath.FullName;
@@ -301,7 +357,7 @@ namespace Project
PUB.log.Add($"가상 AGV 생성: PointZero 위치");
}
- else if (PUB._virtualAGV != null)
+ else
{
PUB._virtualAGV.LowBatteryThreshold = PUB.setting.BatteryLimit_Low;
// 기존 AGV가 있으면 캔버스에 다시 연결
@@ -310,50 +366,6 @@ namespace Project
}
PUB.log.Add($"맵 파일 로드 완료: {filePath.Name}, 노드 수: {result.Nodes.Count}");
- //마지막위치복원
- // 마지막 위치 로드
- var lastPos = PUB.LoadLastPosition();
- if (lastPos != null)
- {
- var sb = new System.Text.StringBuilder();
- var curNode = PUB.FindByNodeID(lastPos.NodeId);
- var prevNode = PUB.FindByNodeID(lastPos.PrevNode);
- var targNode = PUB.FindByNodeID(lastPos.TargetNode);
- var staNode = PUB.FindByNodeID(lastPos.StartNode);
- if(prevNode != null)
- {
- PUB._virtualAGV.SetPosition(prevNode, lastPos.PrevDirection);
- PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, prevNode, lastPos.PrevDirection);
- sb.AppendLine($"이전: {prevNode.ID2}, {lastPos.PrevDirection}");
- }
- if (curNode != null)
- {
- PUB._virtualAGV.SetPosition(curNode, lastPos.Direction);
- PUB._mapCanvas.SetAGVPosition(PUB.setting.MCID, curNode, lastPos.Direction);
- sb.AppendLine($"현재: {curNode.ID2}, {lastPos.Direction}");
- }
- if (staNode != null)
- {
- PUB._virtualAGV.StartNode = staNode;
- sb.AppendLine($"시직:{staNode.ID2}");
- }
- if (targNode != null)
- {
- PUB._virtualAGV.TargetNode = targNode;
- sb.AppendLine($"대상:{targNode.ID2}");
- }
-
- PUB._virtualAGV.Turn = lastPos.Turn;
- sb.AppendLine($"S/W회전:{lastPos.Turn}");
-
- if(lastPos.AGV_Turn != null)
- {
- PUB.AGV.TurnInformation = lastPos.AGV_Turn;
- sb.AppendLine($"H/W회전:{lastPos.AGV_Turn}");
- }
-
- PUB.log.Add($"위치복원\n{sb}");
- }
//// 🔥 초기 위치 설정 및 확인 화면 표시
@@ -374,6 +386,8 @@ namespace Project
// }
// }
//}));
+
+ PUB._mapCanvas.SetView(287.6f, -147.6f, 1.13f);
}
else
{
diff --git a/HMI/SubProject/CommData/Enum.cs b/HMI/SubProject/CommData/Enum.cs
index 5ca8a3b..b2030cc 100644
--- a/HMI/SubProject/CommData/Enum.cs
+++ b/HMI/SubProject/CommData/Enum.cs
@@ -17,6 +17,7 @@ namespace COMM
RetryManget,
RetryLift,
RetryMove,
+ RetryMoveset,
RetryMarkStop,
}
public enum eVarUInt32