아모센스 마킹 gui
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

13 KiB

성능 검사 모니터링 시스템 기술 지식베이스 (Knowledge Base)

본 문서는 양산형 테스트 기기 모니터링 시스템의 소프트웨어 아키텍처, 주요 기능 변경 사항(저항 테스트 및 로그인 프로시저 연동), 그리고 유지보수 및 릴리즈를 위한 가이드를 정리한 지식베이스 문서입니다.


1. 시스템 개요 및 구성 (System Overview)

본 시스템은 제조 라인 최종 단계에서 제품(전기차 부품 등)의 전기적 성능 계측 데이터(전압, 전류, 저항)를 실시간으로 모니터링하고 최종 합격/불합격(PASS/FAIL) 판정을 내린 후 결과를 데이터베이스에 기록하고 설비 제어 완료 신호를 전달하는 WPF 기반 윈도우 애플리케이션입니다.

1.1. 디렉터리 및 주요 파일 구조

  • Models/
    • Product.cs: 제품 정보 및 이전 공정(Housing, Calibration, EOL) 이력 정보 관리 모델
    • MeasurementLimits.cs: 전압, 전류, 저항의 판정 기준 최소/최대 임계치를 저장하고 유효성을 검증하는 모델
  • Services/
    • MockMeasurer.cs: 2초 계측 효과 시뮬레이션용 요동치는 노이즈 생성 및 합격/불합격 최종 결정값 반환 모사 서비스
    • MssqlDatabaseService.cs: 소수점 이하 2자리 반올림 및 최종 판정 값을 MSSQL DB에 적재하기 위한 데이터 액세스 서비스 (로그 출력)
    • MemoryReaderService.cs: 메모리(바코드 스캐너 연동 등)로부터 제품의 Serial Number를 자동으로 읽어오는 서비스
    • LoginServicesStub.cs: Database.ini 파일로부터 로그인 프로시저 설정을 읽고 DB 저장 프로시저(StoredProcedure) 호출 검증을 수행하는 서비스
  • [UI Windows]
    • App.xaml / App.xaml.cs: 애플리케이션 리소스 및 OnStartup 구동 진입점 정의
    • MainWindow.xaml / MainWindow.xaml.cs: 메인 실시간 모니터링 모듈 (계측 전압/전류/저항 카드, 판정 화면, 이전 이력 그리드 표출)
    • SettingsWindow.xaml / SettingsWindow.xaml.cs: 검사 판정 기준(전압, 전류, 저항 최소/최대값)을 실시간 수정할 수 있는 환경 설정 팝업 창
    • StartupLoginWindow.xaml / StartupLoginWindow.xaml.cs: 작업자 인증 및 모델 configuration 세팅 시작 모달 화면

2. 세부 개발 및 구현 이력 (Development History)

2.1. 저항(Resistance) 테스트 검사 추가

전압과 전류에 국한되었던 기존 시스템에 저항 검사 프로세스를 추가하여 3대 전기 파라미터를 완성했습니다.

  • 물리적 개연성 반영: V = I * R 연계를 고려하여, 전압(4~6V) 및 전류(8~10A) 조건에서 저항 기본 범위를 0.4Ω ~ 0.8Ω으로 세팅했습니다.
  • UI 및 환경설정 연동: 메인 화면에 세 번째 Column으로 측정 저항 (Resistance) 카드를 시각적으로 추가하고 설정 창(SettingsWindow)의 세로 크기를 늘려 저항 판정 임계치 입력란을 통합했습니다.
  • 판정 결합: isFinalPass = isVoltageOk && isCurrentOk && isResistanceOk 조건을 통해 세 항목 중 하나라도 이탈 시 자동으로 빨간색 텍스트 및 대형 NG 판정이 출력되도록 비즈니스 로직을 보강했습니다.

2.2. 로그인 저장 프로시저 호출 연동

인라인 SQL 질의 구조를 탈피하여 외부 설정에 명시된 SQL Server 저장 프로시저를 직접 호출하도록 구현했습니다.

  • 외부 설정 로딩: Database.ini 파일을 통해 런타임에 호출할 프로시저명과 오프라인 모드 여부를 읽어옵니다.
    [Login]
    Procedure=dbo.CheckOperator
    ProcessName=Marking
    OfflinePreview=false
    
  • ADO.NET StoredProcedure 연동: SqlCommand.CommandType = CommandType.StoredProcedure 설정을 사용하여 @Operator, @Password, 그리고 선택적으로 @ProcessName 파라미터를 매핑하여 계정 검증 프로시저를 안전하게 가동합니다.

3. 유지보수 및 릴리즈 가이드 (Release & Maintenance)

3.1. 데모용 시뮬레이션 격리 코드 제거 방법 (중요)

로컬 데모 실행을 위해 실제 DB 서버 접속이 실패하더라도 프로시저 성공 여부를 모사하여 로그인을 즉시 통과시키는 임시 시뮬레이션 코드가 구현되어 있습니다. 실제 상용(Production) 배포 시에는 보안 및 실 데이터 검증을 위해 아래의 지침을 따라 데모 코드를 반드시 삭제해야 합니다.

  1. LoginServicesStub.cs 파일을 엽니다.
  2. ExistsAsync 메서드 내 catch (Exception ex) 블록 내부로 이동합니다.
  3. 아래의 DEMO MODE 주석 배너로 둘러싸인 영역을 완전히 삭제하거나 주석 처리합니다.
    // ==================== [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] ====================
    
  4. 삭제 후 빌드를 다시 수행하면, DB 통신 실패 시 로그인이 우회되지 않고 정상적으로 "로그인 DB 확인 실패" 경고가 발생하게 됩니다.

3.2. 릴리즈 게시 및 단일 설치 파일 패키징 가이드

본 프로젝트는 .NET 9.0 (WPF) 타깃의 32비트(x86) 자립형 애플리케이션으로, 프로젝트 파일(marking_gui.csproj)에 WiX Toolset 단일 통합 설치 마법사 컴파일 타깃이 통합되어 있습니다.

  • 권장 CLI 게시 명령어 (터미널):
    dotnet publish marking_gui/marking_gui.csproj -c Release -r win-x86 --self-contained
    
  • 빌드 및 패키징 동작 메커니즘:
    1. .NET 9.0 런타임이 포함된 자립형(Self-Contained) 싱글 실행 바이너리를 빌드합니다.
    2. 계측 및 각인기 드라이버 DLL들을 C:\marking\libs\ 디렉터리로 격리 수집합니다.
    3. wix build가 백그라운드에서 동작하여 Product.wxsBundle.wxs를 단일 실행 설치 파일(MarkingSetup.exe)로 원스톱 패키징합니다.
  • 출력 경로 및 최종 결과물:
    • C:\marking\MarkingSetup.exemarking_gui\bin\Release\net9.0-windows\win-x86\publish\MarkingSetup.exe
    • 현장 라인에는 단일 파일 MarkingSetup.exe만 배포하여 1-Click 설치를 진행할 수 있습니다.

3.3. 설치 경로(C:\marking\) 내 파일 구성 및 런타임 생성 폴더

  • marking_gui.exe (메인 실행 파일) 및 .NET 9.0 런타임 DLL
  • Setting.ini (장비 IP, 마킹 태그, SCPI 커맨드, [Limits] 규격 임계치)
  • Database.ini (DB 접속 주소 및 OfflineMode=true 설정)
  • Sensor.ini (4251 센서 통신 보드 COM 포트/속도/채널)
  • libs/ (LMC 레이저 각인 드라이버 격리 디렉터리: MarkEzdWrapper.dll 등)
  • logs/ (런타임 가동 시 일자별 자동 생성되는 시스템/각인/통신 이력 로그 폴더)
  • publish_backup/ (빌드 배포 시 이전 릴리즈 자동 백업 폴더)

4. 데이터베이스 구성 가이드 (Database Configuration)

본 시스템은 Microsoft SQL Server 2012 이상의 버전에 완전히 호환되도록 구성되었습니다. 데이터베이스 구성 시 sql/database_setup.sql 스크립트를 활용할 수 있습니다.

4.1. 데이터베이스 및 스키마 구조

  • 데이터베이스명: MarkingDb
  • [Users] (작업자 및 비밀번호 관리 테이블):
    • 작업자의 고유 ID(OperatorId), 패스워드(Password), 이름(Name) 및 계정 상태(IsActive)를 관리합니다.
    • 로그인 조회 속도를 향상시키기 위해 OperatorId 컬럼에 UNIQUE 제약 조건을 할당했습니다.
  • [dbo].[Marking] (공정 메타데이터 및 성능 계측값 저장 테이블):
    • 바코드 S/N(IC_SN, NVARCHAR(30), 기본키, NOT NULL)을 키로 하며, 30자 초과 시 코드 내에서 절삭합니다.
    • PCB_Barcode (NVARCHAR(30), NOT NULL): 정상 검사 시 PCB 바코드 스캔값, 강제검사(BYPASS) 시 IC_SN 값으로 자동 대체 저장됩니다.
    • 고유 QR 코드 문자열 Marking_QR (NVARCHAR(60)): IC_SN;도면품번;HKMC품번;각인번호; 포맷으로 구성되며, 60자 초과 시 절삭합니다.
    • 공정 정보(Maker, Model, Variant_1, Variant_2, Operator, Production_Date, Line, Lot_No, Jig_No) 및 최종 판정(Result)이 통합 적재됩니다. 각 문자열 컬럼은 최대 10자로 초과 시 절삭 처리됩니다.
    • 3단계에 걸친 전압/전류/저항 컬럼(PT_Vol_1~3, PT_Current_1~3, PT_Resistance_1~3)이 존재하며, 현재는 1번 컬럼들에 최종 계측 수치(소수점 2~3자리 반올림)를 저장하고 2, 3번 컬럼은 0.00으로 기본값을 보정하여 저장합니다.
    • Result 컬럼에는 OK (QR 검증 통과 시) 또는 NG (불합격 또는 QR 검증 실패 시) 두 가지 값만 저장됩니다.
    • Lot_No 컬럼은 YYMMDDLL 형식(예: 26080401)으로 입력되며 최대 10자까지 허용됩니다.

4.2. 로그인 검증 저장 프로시저 ([CheckOperator])

  • 프로시저 기능: 입력된 ID와 패스워드가 활성 상태인 작업자 테이블에 매칭되는지 대소문자 구분 없이 카운팅합니다.
  • 매개변수 정보:
    • @Operator (VARCHAR(50)): 작업자 ID
    • @Password (VARCHAR(50)): 비밀번호
    • @ProcessName (VARCHAR(50)): 호출 프로세스명 (선택사항, 기본값 NULL)
  • 리턴: 매칭되는 활성 사용자가 존재할 시 1, 존재하지 않을 시 0을 스칼라 결과로 반환합니다.

5. 레이저 각인기 연동 규격 및 구현 사양 (Laser Marking Device Integration)

본 프로그램은 LMC1 레이저 각인 컨트롤러 보드 제어를 위해 C++ DLL Wrapper인 MarkEzdWrapper.dll을 활용하며, 하드웨어와의 메모리 정합성 및 실기 작동 안전성을 완벽히 조율한 최종 기술 사양은 다음과 같습니다.

5.1. 핵심 연동 규칙 및 메커니즘

  1. IntPtr 기반의 기기 세션 핸들(hHandle) 관리:
    • InitMarkEzd() 함수를 기동하여 생성되는 장치 관리 메모리 세션 포인터(IntPtr)를 받아 전역 변수에 저장합니다.
    • 이후 모든 연동 API(Init, LoadEzdFile, ChangeTextByName, Mark, Close)의 첫 번째 매개변수로 이 IntPtr 핸들을 인계하여 호출해야 합니다. 임의의 정수 값(0 등)이나 ref int 를 대입하여 호출하면 메모리 위반 크래시(AccessViolationException)가 발생합니다.
  2. 유니코드(CharSet.Unicode) 마샬링 준수:
    • C++ DLL 단의 모든 문자열 인자는 const wchar_t* (유니코드)를 사용합니다.
    • 따라서 모든 DllImport 선언의 문자셋 속성은 반드시 CharSet = CharSet.Unicode 여야 합니다. Ansi로 지정할 시 경로명 및 파일명이 한자 깨진 글자로 읽혀 EZCAD.CFG failed 에러를 냅니다.
  3. WPF 윈도우 핸들(HWND) 지연 초기화:
    • Init API 호출 시 실제 유효한 부모 윈도우 핸들(IntPtr windowHandle)이 필요합니다.
    • MainWindow의 생성자 시점에는 핸들이 미생성 상태(IntPtr.Zero)이므로 즉시 초기화하면 안 됩니다.
    • 반드시 WPF Dispatcher.BeginInvoke(..., DispatcherPriority.Loaded) 지연 큐를 활용하여 메인 윈도우 로드가 완료된 후에 유효한 창 핸들을 추출해 이니셜라이즈 해야 합니다.

5.2. P/Invoke C# 선언 명세

[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);