feat: 본 레이저 단일 발진기 전환 - IO 채널 재정의 및 enum 단일화

레이저 발진기 교체(임시 Core/Ring 2대 -> 본 레이저 Max MFMC-2000/2000M 1대)에
따른 IO 재정의. 현장 적용 후 정상 동작 확인.

- ePrismaticDIAddress / ePrismaticDOAddress 를 본 레이저 38핀 커넥터 매뉴얼 기준으로
  재정의. 상태 신호 8개 -> 4개. 도면(엑셀) 라벨 오기도 함께 정정
  (Laser_FIRE -> Laser_MAIN_PWR_STATE)
- PAIX_PTOP / SeqAutoRunPTOP 의 중복 enum 정의 제거.
  WeldingCommon 의 PAIX_PrismaticScanner 를 IO 채널 번호의 단일 소스로 통일
- 발진 게이트를 Core/Ring_Control 2발 -> Laser_REMOTE 1발로 변경
  (ExecuteWelding ON/OFF, 정지 시 해제)
- DO 8 충돌 제거: Auto 시작 시 PCLBADReadyStatus(=8) write 삭제.
  본 레이저 배선에서 DO 8 = Laser_AC_KEY 라 그대로 두면 Auto 시작이
  레이저 AC KEY 릴레이를 켠다. LBAD 는 미등록 디바이스라 무의미
- GetLaserReady() 를 Laser_READY 단독 판정으로 변경
- 가이드빔 DO 를 EX_Red_Control -> Laser_GUIDE_BEAM_CONTROL 로 전환
- IO Board 에 설정 화면(UCIOInterfaceView) 연결
- IsLaserReady 표시를 DO Laser_REMOTE 되읽기로 확정 (260826 협의, 현장 미검증)

원복: 각 파일의 "260824 이전 원본" region 을 살리고 아래 블록을 제거하면 된다.
This commit is contained in:
노도연 2026-08-26 11:45:40 +09:00
parent c054439c19
commit 5be34e612e
10 changed files with 206 additions and 67 deletions

View File

@ -1,5 +1,6 @@
using Aurora;
using AuroraIO;
using static WeldingCommon.Devices.Laser.PAIX_PrismaticScanner; // 260824 IO 채널 enum 단일화
using System;
using System.Collections.Generic;
using System.Linq;
@ -16,24 +17,28 @@ namespace ILSOS_PrismaticRD_PTOP.Device.IO
public int WriteDoBit(ePrismaticDOAddress index, bool bit) => _iOUnit.WriteDoBit((int)index, bit);
public bool ReadDiBit(ePrismaticDIAddress index) => _iOUnit.ReadDiBit((int)index);
public enum ePrismaticDIAddress
{
CoreLaser_Laser_Ready = 9,
CoreLaser_Error_State,
CoreLaser_Laser_Output_State,
CoreLaser_Control_Status,
RingLaser_Laser_Ready,
RingLaser_Error_State,
RingLaser_Laser_Output_State,
RingLaser_Control_Status = 23,
}
public enum ePrismaticDOAddress
{
CoreLaser_Control = 9,
CoreLaser_ErrorClearing,
RingLaser_Control = 13,
RingLaser_ErrorClearing,
EX_Red_Control = 17,
}
#region 260824 이전 원본 (중복 정의 — WeldingCommon 의 PAIX_PrismaticScanner 로 단일화)
// ↑ using static WeldingCommon.Devices.Laser.PAIX_PrismaticScanner 로 대체.
// 원복 시 아래 블록을 살리고 상단 using static 을 제거한다.
//public enum ePrismaticDIAddress
//{
// CoreLaser_Laser_Ready = 9,
// CoreLaser_Error_State,
// CoreLaser_Laser_Output_State,
// CoreLaser_Control_Status,
// RingLaser_Laser_Ready,
// RingLaser_Error_State,
// RingLaser_Laser_Output_State,
// RingLaser_Control_Status = 23,
//}
//public enum ePrismaticDOAddress
//{
// CoreLaser_Control = 9,
// CoreLaser_ErrorClearing,
// RingLaser_Control = 13,
// RingLaser_ErrorClearing,
// EX_Red_Control = 17,
//}
#endregion
}
}

View File

@ -150,7 +150,14 @@ namespace ILSOS_PrismaticRD_PTOP
//IODevice는 AjinIO가 아니라 IOUnit으로 받아오는것으로 수정해야 함
registry.Register(CommonDeviceIds.IODevice, () => new PAIX_PTOP(AuroraEnv, CommonDeviceIds.IODevice, isSimul), new IOUnitConfig());
#region 260824 이전 원본 (settingUIFactory 미지정 — IO 상태 확인 화면이 없었다)
//registry.Register(CommonDeviceIds.IODevice, () => new PAIX_PTOP(AuroraEnv, CommonDeviceIds.IODevice, isSimul), new IOUnitConfig());
#endregion
// 260824 IO Board 에 설정 화면(UCIOInterfaceView) 연결.
// DI/DO 32채널 실시간 표시(100ms 폴링) + DO 행 더블클릭 토글. 라벨은 DI.csv/DO.csv 의 Description.
// 본 레이저 교체 배선 실측용. 제어 로직 변경 없음 — settingUIFactory 인자만 추가했다.
registry.Register(CommonDeviceIds.IODevice, () => new PAIX_PTOP(AuroraEnv, CommonDeviceIds.IODevice, isSimul), new IOUnitConfig(),
device => new UCIOInterfaceView(AuroraEnv, CommonDeviceIds.IODevice));
registry.Register(CommonDeviceIds.Laser, () => new Laser(CommonDeviceIds.Laser, isSimul), new LaserConfig(),
device => new UCLaserDevice() { DataContext = new UCLaserDeviceViewModel(AuroraEnv, CommonDeviceIds.Laser) });

View File

@ -26,6 +26,7 @@ using ILSOS_PrismaticRD_PTOP.Settings;
using static AuroraIO.AJINEXTEK.AjinIO.IOModuleInfo;
using static ILSOS_PrismaticRD_PTOP.Device.PLCControllerPTOP;
using static WeldingCommon.Devices.PLCController;
using static WeldingCommon.Devices.Laser.PAIX_PrismaticScanner; // 260824 IO 채널 enum 단일화
using Application = System.Windows.Application;
using SystemParameter = WeldingCommon.Settings.SystemParameter;
@ -99,14 +100,18 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
private const int SCOUT_PROCEED_DELAY_MS = 100; // scout 완료 후 진행 지연(0.1초)
#endregion
public enum ePrismaticDOAddress
{
CoreLaser_Control = 9,
CoreLaser_ErrorClearing,
RingLaser_Control = 13,
RingLaser_ErrorClearing,
EX_Red_Control = 17,
}
#region 260824 이전 원본 (로컬 복사본 — WeldingCommon 의 PAIX_PrismaticScanner 로 단일화)
// ↑ 상단 using static WeldingCommon.Devices.Laser.PAIX_PrismaticScanner 로 대체.
// 원복 시 아래 블록을 살리고 그 using static 을 제거한다.
//public enum ePrismaticDOAddress
//{
// CoreLaser_Control = 9,
// CoreLaser_ErrorClearing,
// RingLaser_Control = 13,
// RingLaser_ErrorClearing,
// EX_Red_Control = 17,
//}
#endregion
static class ContextKey
{
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqAutoRunPTOP";
@ -1205,9 +1210,15 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
_PLC.WriteBit((int)eBitOutput.PC_WELD_BUSY, true);
_Scanner.SelectCorrectionTable(2);
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), true);
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), true);
Log.I($"[ExecuteWelding] Laser Gate ON (Core+Ring)");
#region 260824 이전 원본 (Core/Ring 2발)
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), true);
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), true);
//Log.I($"[ExecuteWelding] Laser Gate ON (Core+Ring)");
#endregion
// 260824 본 레이저 단일 발진기 — 제어권 요청 1발 (구 Core/Ring_Control 자리)
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.Laser_REMOTE), true);
Log.I($"[ExecuteWelding] Laser Gate ON (REMOTE)");
Thread.Sleep(laserEmissionGateDelayMs); // 260518 매뉴얼 기준 ≥10ms, 여유분 포함 =15ms 적용함.
Log.I($"[ExecuteWelding] Gate ON Delay {laserEmissionGateDelayMs}ms 완료 → ExecuteList 시작");
@ -1222,9 +1233,15 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
#region Gate OFF 위치 변경 - 용접 완료 즉시 OFF (TruPulse nano 매뉴얼 기준 ≥10ms)
// ↓ 이 두 줄 삭제
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), false);
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), false);
Log.I($"[ExecuteWelding] Laser Gate OFF (Core+Ring)");
#region 260824 이전 원본 (Core/Ring 2발)
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), false);
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), false);
//Log.I($"[ExecuteWelding] Laser Gate OFF (Core+Ring)");
#endregion
// 260824 본 레이저 단일 발진기 — 제어권 해제 1발
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.Laser_REMOTE), false);
Log.I($"[ExecuteWelding] Laser Gate OFF (REMOTE)");
#endregion
// 260626 Busy bit 위치 변경 - Laser On Display bit
@ -1563,8 +1580,13 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
*/
#endregion
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), true);
Log.I(string.Format($"[IOInterface]SET PCLBADReadyStatus true"));
#region 260824 제거 — DO 채널 8 충돌 (eADOAddress.PCLBADReadyStatus = 8 = 본 레이저 Laser_AC_KEY)
// LBAD 는 현재 미등록 디바이스라 이 비트를 쓰는 의미가 없고,
// 본 레이저 배선에서 DO 8 은 Laser_AC_KEY(레이저 AC 전원 투입) 이다.
// 그대로 두면 Auto 시작이 레이저 AC KEY 릴레이를 켠다. → 제거.
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), true);
//Log.I(string.Format($"[IOInterface]SET PCLBADReadyStatus true"));
#endregion
Log.I($"[InitializeDeviceStatus] 디바이스 초기상태 설정 완료");
return true;
@ -1670,8 +1692,13 @@ namespace ILSOS_PrismaticRD_PTOP.Sequences
// LBAD IO All BIT OFF
try
{
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), false);
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), false);
#region 260824 이전 원본 (Core/Ring 2발)
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.CoreLaser_Control), false);
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.RingLaser_Control), false);
#endregion
// 260824 본 레이저 단일 발진기 — 정지 시 제어권 해제 1발
_IO._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.Laser_REMOTE), false);
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false);
//_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false);
Log.I("[IOInterface] PC All Bit Off (Laser Control, LBAD Trigger, LBAD Ready)");

View File

@ -394,7 +394,10 @@ namespace ILSOS_PrismaticRD_TDC.Sequences
Log.D(string.Format($"[TeachingRun] Change SelectCorrectionTable Time : {_WeldingSpanTime.TotalMilliseconds}"));
//int recipeNo = _RecipeManager.ActivatedRecipe().Id;
_IOLaser._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.EX_Red_Control), true);
// 260824 EX_Red_Control → Laser_GUIDE_BEAM_CONTROL 로 명칭/채널 변경 (본 레이저)
// ※ 이 파일(SeqTestRun)은 미사용이며, _IOLaser 캐스팅이 항상 null 이라 실행되지 않는다.
// enum 심볼이 사라져 컴파일이 깨지므로 이름만 맞춰둔다.
_IOLaser._iOUnit.WriteDoBit(Convert.ToInt32(ePrismaticDOAddress.Laser_GUIDE_BEAM_CONTROL), true);
if()

View File

@ -23,24 +23,76 @@ namespace WeldingCommon.Devices.Laser
public int WriteDoBit(ePrismaticDOAddress index, bool bit) => _iOUnit.WriteDoBit((int)index, bit);
public bool ReadDiBit(ePrismaticDIAddress index) => _iOUnit.ReadDiBit((int)index);
#region 260824 이전 원본 (임시레이저 Core/Ring 2대 구성) — 원복 시 이 블록을 살리고 아래를 제거
//public enum ePrismaticDIAddress
//{
// CoreLaser_Laser_Ready = 9,
// CoreLaser_Error_State,
// CoreLaser_Laser_Output_State,
// CoreLaser_Control_Status,
// RingLaser_Laser_Ready,
// RingLaser_Error_State,
// RingLaser_Laser_Output_State,
// RingLaser_Control_Status = 23,
//}
//public enum ePrismaticDOAddress
//{
// CoreLaser_Control = 9,
// CoreLaser_ErrorClearing,
// RingLaser_Control = 13,
// RingLaser_ErrorClearing,
// EX_Red_Control = 17,
//}
#endregion
// ─────────────────────────────────────────────────────────────────────────────
// 260824 본 레이저(Max MFMC-2000/2000M) 단일 발진기 구성.
// Core/Ring 2대 → 1대 통합으로 상태 신호 8개 → 4개.
//
// ★ 이 enum 이 IO 채널 번호의 단일 소스다. PAIX_PTOP / SeqAutoRunPTOP 의 중복 정의를 제거하고
// 전부 이곳을 참조하도록 통일했다(260824). 번호 수정은 여기 한 곳만 고치면 된다.
//
// ※ 아래 값은 통신배선자료 엑셀 "Digital_IO (본 레이저)" 시트의 도면값이다.
// 임시레이저에서 도면이 실배선보다 DI 기준 +1 어긋난 전례가 있다(분석문서 §8).
// 실측 결과가 다르면 여기 숫자만 -1 하면 된다.
//
// 괄호 안은 레이저 I/O 커넥터 핀 번호 — 배선 추적용 메모이며 소프트웨어는 사용하지 않는다.
// ─────────────────────────────────────────────────────────────────────────────
// 260824 레이저 38핀 커넥터 매뉴얼 확인 후 명칭·의미 정정. 도면(엑셀) 라벨에 오기가 있었다.
public enum ePrismaticDIAddress
{
CoreLaser_Laser_Ready = 9,
CoreLaser_Error_State,
CoreLaser_Laser_Output_State,
CoreLaser_Control_Status,
RingLaser_Laser_Ready,
RingLaser_Error_State,
RingLaser_Laser_Output_State,
RingLaser_Control_Status = 23,
// (Pin21) LASER_READY — "Power Supply ON & No error" 일 때 High. 출사 가능 조건.
Laser_READY = 8,
// (Pin22) ERROR/ALARM — ★★ Active-Low ★★
// 정상 시 High(24V), 알람 발생 시 Low(0V). 판정할 때 반드시 부정(!)을 붙여야 한다.
// if (!ReadDiBit(Laser_ALARM)) → 알람 발생
Laser_ALARM,
// (Pin23) LASER_EMISSION_ON — Emission ON=High. DO Laser_REMOTE(External Start) 의 에코.
Laser_EMISSION_ON,
// (Pin24) MAIN_PWR_STATE — 레이저 전원 투입 상태(Key Switch ON=High).
// ※ 도면(엑셀)에는 "Laser_FIRE" 로 적혀 있으나 오기다. 발진 중 표시가 아니다.
// DO Laser_AC_KEY 의 에코.
Laser_MAIN_PWR_STATE,
}
public enum ePrismaticDOAddress
{
CoreLaser_Control = 9,
CoreLaser_ErrorClearing,
RingLaser_Control = 13,
RingLaser_ErrorClearing,
EX_Red_Control = 17,
// (Pin5,6 쇼트) REMOTE_AC_KEY_A/B — 외부 제어용 키스위치. 분리 시 Emission OFF.
Laser_AC_KEY = 8,
// (Pin7,8 쇼트) REMOTE_DC_PWR_SW1/SW2 — "External Start"
// ★ 이름과 달리 모드 전환이 아니라 Emission ON/OFF 를 직접 제어한다.
// 연결 시 Emission ON, 분리 시 Emission OFF. 구 Core/Ring_Control 자리.
Laser_REMOTE,
// (Pin18) EX_RED_CONTROL+ — 가이드 레이저 ON/OFF. 구 EX_Red_Control 자리(명칭 동일).
Laser_GUIDE_BEAM_CONTROL,
// (Pin20) EX_RESET+ — ★ Water Flow Alarm 리셋 전용. 다른 error/alarm 에는 무효다.
// 구 Core/Ring_ErrorClearing 의 완전한 대체품이 아니다.
Laser_ALARM_RESET,
}
}
public class LaserIOControl : Device
@ -76,12 +128,20 @@ namespace WeldingCommon.Devices.Laser
public bool GetLaserReady()
{
bool coreReady = false;
bool ringReady = false;
GetLaserDIStatus(ePrismaticDIAddress.CoreLaser_Laser_Ready, out coreReady);
GetLaserDIStatus(ePrismaticDIAddress.RingLaser_Laser_Ready, out ringReady);
#region 260824 이전 원본 (Core/Ring 2대 AND 판정)
//bool coreReady = false;
//bool ringReady = false;
//GetLaserDIStatus(ePrismaticDIAddress.CoreLaser_Laser_Ready, out coreReady);
//GetLaserDIStatus(ePrismaticDIAddress.RingLaser_Laser_Ready, out ringReady);
//
//return coreReady && ringReady;
#endregion
return coreReady && ringReady;
// 260824 본 레이저 단일 발진기 — Laser_READY 단독 판정
bool ready = false;
GetLaserDIStatus(ePrismaticDIAddress.Laser_READY, out ready);
return ready;
}
public int GetLaserDevice(ref IODevice _IOLaser)
{

View File

@ -295,8 +295,23 @@ namespace WeldingCommon.Views
return;
}
IsGuidBeam = _IODevice.ReadDO(17);
IsLaserReady = _IODevice.ReadDI(11) && _IODevice.ReadDI(15); // 변경 후 (260618: IO 결선 변경 12&24 → 11&15)
#region 260824 이전 원본 (임시레이저 채널 하드코딩)
//IsGuidBeam = _IODevice.ReadDO(17);
//IsLaserReady = _IODevice.ReadDI(11) && _IODevice.ReadDI(15); // 변경 후 (260618: IO 결선 변경 12&24 → 11&15)
#endregion
// 260824 본 레이저 단일 발진기 + enum 참조로 전환 (하드코딩 제거)
// 구조: 구 DI 11/15 = Core/Ring_Control_Status(명령 DO 9/13 의 에코).
// 본 레이저의 대응 짝은 DO Laser_REMOTE(External Start) → DI Laser_EMISSION_ON 이다.
// ★ Laser_READY(Pin21)를 쓰면 안 된다 — "Power Supply ON & No error" 라
// 전원만 들어오면 상시 High 이므로 버튼(CMD_LaserReadyCheck)에 반응하지 않고,
// :468 의 발진 차단 인터락도 무력해진다. (현장 확인 260824)
//
// 260826 협의 확정 — DI 에코(Laser_EMISSION_ON) 가 아니라 DO 명령 비트를 직접 표시한다.
// 버튼(CMD_LaserReadyCheck)이 토글하는 대상이 DO Laser_REMOTE 이므로,
// 같은 비트를 되읽어야 조작과 표시가 1:1 로 맞는다. IsGuidBeam 과 동일한 방식.
IsGuidBeam = _IODevice.ReadDO((int)ePrismaticDOAddress.Laser_GUIDE_BEAM_CONTROL);
IsLaserReady = _IODevice.ReadDO((int)ePrismaticDOAddress.Laser_REMOTE);
}
catch (Exception ex)
@ -577,13 +592,20 @@ namespace WeldingCommon.Views
private void PerformCmdLaserGuideBeam(object obj)
{
// Guide Beam DO 17 토글 — 모니터링도 같은 DO 17 을 읽어 표시
// Guide Beam DO 토글 — 모니터링(OnMonitoring)도 같은 DO 를 읽어 표시
// 260824: DO 17(EX_Red_Control) → ePrismaticDOAddress.Laser_GUIDE_BEAM_CONTROL 로 변경됨
// IO 미연결 가드는 현장PC에서 동작 안 해 주석 (개발PC에서 주석 해제)
//if (_IODevice == null || !_IODevice.IsConnected()) {
// return;
//}
bool cur = _IODevice.ReadDO(17);
_IODevice._iOUnit.WriteDoBit(17, !cur);
#region 260824 이전 원본 (임시레이저 DO 17 하드코딩)
//bool cur = _IODevice.ReadDO(17);
//_IODevice._iOUnit.WriteDoBit(17, !cur);
#endregion
// 260824 본 레이저 가이드빔 DO 로 전환 (EX_Red_Control 17 → Laser_GUIDE_BEAM_CONTROL)
bool cur = _IODevice.ReadDO((int)ePrismaticDOAddress.Laser_GUIDE_BEAM_CONTROL);
_IODevice._iOUnit.WriteDoBit((int)ePrismaticDOAddress.Laser_GUIDE_BEAM_CONTROL, !cur);
// [기존 소스 보존] Laser 디바이스 기반 Pilot On/Off 토글 (DO 3=GuideLaserEnable)
//if (!_Laser.GetPilotLaserSetBitStatus()) {
@ -596,16 +618,31 @@ namespace WeldingCommon.Views
private void PerformCmdLaserReadyCheck(object obj)
{
// 추후 Write bit 파라미터화 해야함
if(toggleIO)
#region 260824 이전 원본 (임시레이저 Core/Ring_Control 2발 하드코딩)
//if(toggleIO)
//{
// _IODevice._iOUnit.WriteDoBit(9, true);
// _IODevice._iOUnit.WriteDoBit(13, true);
// toggleIO = false;
//}
//else
//{
// _IODevice._iOUnit.WriteDoBit(9, false);
// _IODevice._iOUnit.WriteDoBit(13, false);
// toggleIO = true;
//}
#endregion
// 260824 본 레이저 단일 발진기 — 제어권(REMOTE) 1발 토글
// ※ AC_KEY(DO 8)는 전원 투입 계층이라 여기서 건드리지 않는다(반 하드와이어 여부 미확정, Q3).
if (toggleIO)
{
_IODevice._iOUnit.WriteDoBit(9, true);
_IODevice._iOUnit.WriteDoBit(13, true);
_IODevice._iOUnit.WriteDoBit((int)ePrismaticDOAddress.Laser_REMOTE, true);
toggleIO = false;
}
else
{
_IODevice._iOUnit.WriteDoBit(9, false);
_IODevice._iOUnit.WriteDoBit(13, false);
_IODevice._iOUnit.WriteDoBit((int)ePrismaticDOAddress.Laser_REMOTE, false);
toggleIO = true;
}
}