# Performance Inspect & Laser Marking System - 개발자 메뉴얼 본 문서는 **양산형 테스트 기기 모니터링 시스템**의 유지보수, 릴리즈, 시스템 통합 및 디버깅을 위한 개발자용 상세 기술 사양서입니다. 시스템 설계 정보, 하드웨어 연동 규격, 그리고 제어 시퀀스를 포함하고 있습니다. --- ## 1. 시스템 아키텍처 및 요구사항 ### 1.1 기술 스택 - **프레임워크**: .NET Framework 4.7.2 (WPF) - **UI 패턴**: MVVM (MainWindow, SettingsWindow, StartupLoginWindow 등) - **데이터베이스**: Microsoft SQL Server 2012 이상 (ADO.NET 연동) - **장비 연동**: - LMC1 레이저 각인 컨트롤러 (C++ Wrapped DLL `MarkEzdWrapper.dll` 로드) - Keysight DMM & PSU (TCP/IP 기반 SCPI 통신) - 4251 센서 판독 보드 (시리얼 RS-232 기반 고유 프로토콜) ### 1.2 개발 환경 구동 요구사항 - Visual Studio 2022 이상 - MSBuild 엔진 (XAML 컴파일 지원) - MS-SQL Server Express 또는 로컬 DB 인프라 - EZCAD 2 소프트웨어 및 LMC USB 각인 카드 드라이버 --- ## 2. 설정 파일 (INI) 상세 사양 실행 파일 경로에 위치하는 INI 설정 파일들의 각 항목별 역할 및 타입 정의입니다. ### 2.1 Setting.ini 계측 장비 접속 주소, SCPI 제어 명령어 매개변수 및 레이저 각인 도안 태그 매핑(`[Tags]`) 설정을 포함합니다. ```ini ; ================================================================= ; 성능 검사 모니터링 시스템 - 레이저 마킹기 연동 설정 파일 ; ================================================================= [Settings] ; 마킹 제어 라이브러리 및 드라이버(EzCad) 폴더 경로 EzdFolderPath=c:\EzCad ; 테스트 모드 여부 (true 시 하단 테스트 마킹, 강제 검사 버튼 노출) test=false [Tags] ; 도안(.ezd) 파일 내의 텍스트 오브젝트 치환용 태그명 매핑 리스트 ; (도안에 정의된 오브젝트명과 동일하게 설정해야 정상 작동합니다) ; 일련번호 (Serial Number) 치환 태그 SerialTag=SERIAL ; 작업 년월일 (Lot No) 치환 태그 LotNoTag=YYMMDD ; 제품 모델명 (Product Name) 치환 태그 ProductTag=PRODUCT ; 2D QR 코드 데이터 치환 태그 QrCodeTag=QRCODETAG ; 검사 라인 코드 치환 태그 LineTag=LCODE ; 작업 조 (Shift) 치환 태그 ShiftTag=BAN ; ================================================================= ; 계측기 연동 설정 (SCPI / LAN) ; ================================================================= [Equipment] ; 계측기 통신 타임아웃 (ms) Timeout=5000 ; 측정 안정화 대기 시간 (ms) — Power Supply ON 후 이 시간만큼 대기 후 읽음 SettleMilliseconds=2000 ; 검사 전 보드 전원 공급 커맨드 (세미콜론으로 구분) PreBoardCommand=VOLT 5, (@2);OUTP ON, (@2) PreBoardDelayMilliseconds=2000 ; 로그아웃 시 전원 차단 커맨드 LogoutCommand=OUTP OFF, (@1) [DMM] ; Digital Multimeter — 전압 및 저항 측정 전용 (예시 IP: 192.168.1.100) VoltageConnection=LAN VoltageHost=192.168.1.100 VoltagePort=5025 VoltageIdnMatch=34465A VoltageBaudRate=115200 VoltageTerminator=LF VoltageSetupCommand= VoltageReadCommand=MEAS:VOLT:DC? ResistanceReadCommand=MEAS:RES? [CurrentDMM] ; Digital Multimeter — 전류 측정 전용 (예시 IP: 192.168.1.102 - 현재 제어 시퀀스에서 미사용) CurrentDMMConnection=LAN CurrentDMMHost=192.168.1.102 CurrentDMMPort=5025 CurrentDMMIdnMatch=34465A CurrentDMMBaudRate=115200 CurrentDMMTerminator=LF CurrentDMMReadCommand=MEAS:CURR:DC? [PowerSupply] ; Power Supply — 출력 제어 및 전류 측정 (예시 IP: 192.168.1.101) CurrentConnection=LAN CurrentHost=192.168.1.101 CurrentPort=5025 CurrentIdnMatch=E36233A CurrentBaudRate=9600 CurrentTerminator=LF CurrentSetupCommand=OUTP ON, (@1) CurrentCleanupCommand=OUTP OFF, (@1) CurrentReadCommand=MEAS:CURR? (@1) [Limits] ; 최종 계측 합/불 판정 규격 임계치 (Min: 하한치, Max: 상한치) ; UI [시험 설정] 메뉴에서 변경 시 자동 저장 및 갱신됩니다. MinVoltage=4.0 MaxVoltage=6.0 MinCurrent=8.0 MaxCurrent=10.0 MinResistance=0.4 MaxResistance=0.8 ``` ### 2.2 Database.ini 생산 이력 조회 및 적재 목적의 DB 연결 설정입니다. ```ini [Database] # SQL 데이터베이스 접속 주소 및 계정 정보 (예시 주소) Db_Server=192.168.1.200 Db_Name=MarkingDb Db_User=db_user Db_Password=db_password # 로컬 테스트 및 DB 점검 시 우회용 플래그 OfflineMode=False [Login] # 작업자 로그인 검증 시 호출할 저장 프로시저명 Procedure=dbo.CheckOperator # 작업 공정 식별 이름 (저장 프로시저 매개변수 바인딩용) ProcessName=Marking # 오프라인 로그인 미리보기 활성화 여부 OfflinePreview=false ``` ### 2.3 Sensor.ini 4251 센서 통신 보드 시리얼 통신을 위한 포트 매핑 파일입니다. ```ini [Sensor] # 시리얼 COM 포트 번호 Port=COM3 # 통신 속도 BaudRate=115200 # 보드 내부 멀티 채널 스위칭 인덱스 (1 또는 2) Channel=1 ``` --- ## 3. 데이터베이스 스키마 및 연동 규격 ### 3.1 테이블 구성 정보 - **`[dbo].[Users]` (작업자 계정 정보 테이블)** - `OperatorId` (VARCHAR(50), UNIQUE): 작업자 로그인 ID - `Password` (VARCHAR(50)): 비밀번호 - `Name` (VARCHAR(50)): 작업자 성명 - `IsActive` (BIT): 활성 상태 여부 - **`[dbo].[Marking]` (최종 성능 계측값 및 마킹 결과 저장 테이블)** - `IC_SN` (VARCHAR(50), PRIMARY KEY): 센서 일련번호 - `Marking_QR` (VARCHAR(100), UNIQUE): 고유 QR 코드 문자열 (yyMMdd + 일련번호) - `Maker` (VARCHAR(50)), `Model` (VARCHAR(50)): 제품 사양 정보 - `Variant_1`, `Variant_2` (VARCHAR(50)) - `Operator` (VARCHAR(50)): 담당 작업자 ID - `Production_Date` (DATETIME): 생산 일자 및 계측 시간 - `Line` (VARCHAR(10)): 생산 라인 (최대 10자 제한, 초과 시 코드 내에서 절삭) - `Lot_No` (VARCHAR(8)): 로트 번호 (최대 8자 제한, 초과 시 코드 내에서 절삭) - `Jig_No` (VARCHAR(10)): 지그 번호 - `PT_Vol_1` (DECIMAL(18,2)), `PT_Current_1` (DECIMAL(18,2)), `PT_Resistance_1` (DECIMAL(18,3)): 실측 전압, 전류, 저항값 - `Result` (VARCHAR(10)): 최종 종합 판정 (`PASS` 또는 `FAIL`) - `MarkedSerial` (VARCHAR(50)): 최종 마킹된 시퀀스 코드 ### 3.2 이전 공정 결과 교차 검증 (Subquery) 검사 개시 시점, 제품의 S/N(`IC_SN`)을 기반으로 선행 공정이 완료되었는지 조회합니다. ```sql SELECT (SELECT Result FROM Housing_Assembly WHERE IC_SN = @IC_SN) AS HousingResult, (SELECT Final_Result FROM Cal_EOL_Result WHERE IC_SN = @IC_SN) AS CalResult, (SELECT Result FROM EOL WHERE IC_SN = @IC_SN) AS EolResult ``` - **판정 조건**: 조회 결과 3개 항목이 모두 `PASS` 또는 `OK` 상태이어야 최종 검사 기동이 허용됩니다. ### 3.3 로그인 저장 프로시저 (`[dbo].[CheckOperator]`) - **프로시저 스펙**: ```sql CREATE PROCEDURE [dbo].[CheckOperator] @Operator VARCHAR(50), @Password VARCHAR(50), @ProcessName VARCHAR(50) = NULL AS BEGIN SELECT COUNT(*) FROM Users WHERE OperatorId = @Operator AND Password = @Password AND IsActive = 1 END ``` - **호출 매핑 코드**: ADO.NET `SqlCommand` 객체를 사용하여 `CommandType.StoredProcedure` 형식으로 호출하며 리턴값이 `1`일 경우 검증 처리합니다. --- ## 4. 하드웨어 제어 프로토콜 및 SCPI 사양 ### 4.1 4251 센서 통신 보드 시리얼 패킷 규격 센서 일련번호를 추출하고 보드를 제어하기 위해 RS-232 시리얼(115200bps)을 통해 다음 패킷 명령을 전송합니다. 1. **보드 대기 및 리셋 명령**: `"x00o"` 2. **보드 채널 결속 명령**: `"x00c_00{channel}101:owt28006727ea97c7801"` - `{channel}`은 `Sensor.ini`에서 파싱한 값 (예: `1` 또는 `2`) 3. **고유 ID(IC_SN) 읽기 명령**: `"x00c_00{channel}101:ow2800326003e"` - 송신 후 보드 응답 버퍼에서 16진수 일련번호 데이터(16자)를 추출합니다. 4. **보정 기본값 전송**: `"x00c_00{channel}001:owt28006727ea97c7801"` ### 4.2 계측 장비 제어 SCPI 명령어 구성 및 시퀀스 모든 TCP/IP 계측기는 포트 **5025**를 통해 SCPI 표준 명령으로 조작됩니다. 1. **장비 연결 및 아이덴티티 검증 (Handshake)**: - 각 계측기 접속 후 `*IDN?` 명령을 전송하여 응답 텍스트에 `Setting.ini`에 지정된 장비 모델명(예: `34465A`, `E36233A`)이 수록되어 있는지 확인합니다. 2. **테스트 주전원(CH1) 인가**: - `OUTP ON, (@1)` - 전원 공급 후 신호 안정을 위해 `SettleMilliseconds`(기본 2000ms, 즉 2초)만큼 대기합니다. 3. **측정 데이터 수집**: - **전압(V)**: 전압 DMM(예: 192.168.1.100)에 `MEAS:VOLT:DC?`를 질의하여 획득. - **저항(Ω)**: 저항 DMM(예: 192.168.1.100)에 `MEAS:RES?`를 질의하여 획득. (획득값은 kΩ 단위 조정을 위해 1000으로 나눔) - **전류(A)**: 파워서플라이(예: 192.168.1.101)의 CH1에 `MEAS:CURR? (@1)`을 질의하여 획득. (획득값은 mA 단위 조정을 위해 1000을 곱함) - *주의: 전류 측정 전용 DMM(예: 192.168.1.102) 장비는 설정 파일에 로드되나 실제 측정 시퀀스 상에서는 사용되지 않습니다.* 4. **주전원(CH1) 차단**: - `OUTP OFF, (@1)` - 계측 도중 예외가 발생하더라도 `finally` 구문 내에서 차단 명령을 전송합니다. --- ## 5. 레이저 마킹기 연동 사양 (LMC1 API) C++로 개발된 레이저 각인기 드라이버 DLL인 `MarkEzdWrapper.dll`을 P/Invoke를 통해 호출합니다. ### 5.1 연동 시 핵심 규칙 1. **세션 핸들 (`hHandle`) 관리**: - 프로그램 시작 시 `InitMarkEzd()` 함수를 호출하여 세션 포인터(`IntPtr`)를 받아 전역 변수로 관리합니다. - 각인 관련 API 함수 호출 시 이 `IntPtr` 핸들을 첫 번째 매개변수로 전달해야 합니다. 2. **유니코드 마샬링 (`CharSet.Unicode`)**: - C++ DLL 단의 모든 문자열 인자가 `const wchar_t*` (유니코드)를 사용하므로, DllImport 선언의 문자셋 속성은 `CharSet = CharSet.Unicode`로 설정해야 정상 작동합니다. 3. **HWND 부모 창 핸들 지연 초기화**: - `Init` 함수는 부모 WPF 윈도우의 핸들(`IntPtr`)을 요구합니다. - Window 생성자 시점에는 핸들이 미생성 상태이므로, 반드시 **`Dispatcher.BeginInvoke(..., DispatcherPriority.Loaded)`**를 활용하여 메인 윈도우 로드가 완료된 후에 핸들을 추출해 초기화해야 합니다. ### 5.2 DLL 가져오기 (P/Invoke) 선언 명세 ```csharp [DllImport("MarkEzdWrapper.dll", EntryPoint = "InitMarkEzd", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr InitMarkEzd(); [DllImport("MarkEzdWrapper.dll", EntryPoint = "Init", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern int Init(IntPtr hHandle, string strEzCadPath, IntPtr hOwenWnd); [DllImport("MarkEzdWrapper.dll", EntryPoint = "LoadEzdFile", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern int LoadEzdFile(IntPtr hHandle, string strEzCadFileName); [DllImport("MarkEzdWrapper.dll", EntryPoint = "ChangeTextByName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern int ChangeTextByName(IntPtr hHandle, string strTextName, string strTextNew); [DllImport("MarkEzdWrapper.dll", EntryPoint = "Mark", CallingConvention = CallingConvention.Cdecl)] private static extern int Mark(IntPtr hHandle); [DllImport("MarkEzdWrapper.dll", EntryPoint = "Close", CallingConvention = CallingConvention.Cdecl)] private static extern int Close(IntPtr hHandle); ``` --- ## 6. 데모용 시뮬레이션 격리 및 릴리즈 배포 가이드 ### 6.1 데모 모드 격리 코드 해제 방법 상용 빌드 릴리즈 시, 데이터베이스에 실제 로그인하지 않고 통과하는 데모 우회 로직을 소스 코드 단에서 제거해야 합니다. 1. **[LoginServicesStub.cs](file:///C:/Users/COMPUTER1/Desktop/mobi/marking_gui/marking_gui/Services/LoginServicesStub.cs)** 파일을 엽니다. 2. `ExistsAsync` 메서드 안의 `catch (Exception ex)` 구문 내부에 위치한 아래의 **DEMO MODE 주석 배너** 영역 코드를 삭제하거나 주석 처리하여 릴리즈 빌드를 만드십시오. ```csharp // ==================== [DEMO MODE START] ==================== // 데모 시뮬레이션용 프로시저 성공 연출 코드 // 상용 릴리즈 시 이 블록은 완전히 제거(삭제)할 수 있습니다. if (!string.IsNullOrWhiteSpace(_loginSettings.Procedure)) { System.Diagnostics.Debug.WriteLine(string.Format("[데모 시뮬레이션] 프로시저 '{0}' 호출 모사 (ID: {1}, PW: {2}, Process: {3})", _loginSettings.Procedure, operatorId, password, _loginSettings.ProcessName)); return IsDefaultAccount(operatorId, password); } // ==================== [DEMO MODE END] ==================== ``` ### 6.2 릴리즈 게시 및 단일 설치 파일(MarkingSetup.exe) 자동 생성 가이드 본 프로젝트는 Visual Studio 게시 프로필 및 WiX Toolset 커스텀 타깃이 적용되어 있어, CLI 게시 명령 한 번으로 단일 실행 설치 파일(`MarkingSetup.exe`)을 자동으로 컴파일 및 생성합니다. - **권장 CLI 게시 명령어 (Terminal)**: ```powershell dotnet publish marking_gui/marking_gui.csproj -c Release -r win-x86 --self-contained ``` - **자동 빌드 및 패키징 동작 순서**: 1. 프로젝트 릴리즈 바이너리 및 의존 라이브러리 일체 자동 수집 2. `C:\marking\libs\` 경로로 모든 런타임 DLL 격리 구성 3. WiX Toolset(`wix build`)이 가동하여 MSI 패키지 및 단일 EXE 부트스트랩 번들 컴파일 4. 최종 설치 파일 `MarkingSetup.exe`가 `C:\marking\` 및 `bin\Release\net9.0-windows\win-x86\publish\` 폴더로 자동 생성 이관 - **배포 및 전달 대상 파일**: - `MarkingSetup.exe` (단일 파일만 현장에 전달하여 1-Click 설치 진행) ### 6.3 배포 설치 디렉터리(`C:\marking\`) 파일 구조 및 런타임 생성 폴더 사양 `MarkingSetup.exe`로 인스톨된 후 `C:\marking\` 아래에 배치되는 파일 및 런타임 가동 중 생성되는 디렉터리 명세입니다. ``` C:\marking\ ├── marking_gui.exe # 메인 WPF 실행 바이너리 ├── marking_gui.dll # 핵심 애플리케이션 어셈블리 ├── marking_gui.deps.json # 종속성 매니페스트 ├── marking_gui.runtimeconfig.json # .NET 9.0 런타임 환경 구성 ├── Setting.ini # 마킹기 경로, 태그 매핑, 계측기 IP, SCPI 전원, [Limits] 판정 임계치 종합 설정 ├── Database.ini # MS-SQL 접속 계정 및 오프라인 모드(OfflineMode) 설정 ├── Sensor.ini # 4251 센서 통신 보드 시리얼 포트(COM), BaudRate, 채널 설정 ├── libs\ # C++ LMC 드라이버 라이브러리 격리 폴더 │ ├── MarkEzdWrapper.dll # C# - C++ LMC P/Invoke 래퍼 │ ├── DataMgr.dll # EZCAD 데이터 매니저 │ ├── MarkEzd.dll # EZCAD 커널 마킹 라이브러리 │ └── haspms32.dll # 동글/라이선스 보안 라이브러리 일체 ├── logs\ # 런타임 가동 중 일별 자동 생성되는 시스템/통신/마킹 이력 로그 │ └── 2026-07-23.log # 텍스트 형태의 일자별 로그 파일 └── publish_backup\ # 게시 및 버전 업데이트 시 기존 파일 자동 백업 보관 폴더 ```