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.
321 lines
17 KiB
321 lines
17 KiB
|
4 weeks ago
|
# 지그 압력 및 누출 검사 애플리케이션 (Jig Pressure & Leak Test App)
|
||
|
|
|
||
|
|
## 1. 프로젝트 개요
|
||
|
|
|
||
|
|
본 프로젝트는 특정 지그(Jig)에 제품을 고정하고 압력을 인가한 뒤, 유지 시간 동안 내부 압력의 변화를 측정하여 누출(Leak) 여부를 **자동으로 검사**하는 데스크톱 전용 모니터링 애플리케이션입니다.
|
||
|
|
|
||
|
|
| 항목 | 내용 |
|
||
|
|
|------|------|
|
||
|
|
| **프레임워크** | C# WPF (.NET Framework 4.7.2) |
|
||
|
|
| **아키텍처** | MVVM (Model-View-ViewModel) + Service Layer |
|
||
|
|
| **솔루션 파일** | `jig_test.slnx` |
|
||
|
|
| **NuGet 패키지** | `System.IO.Ports` (10.0.4), `NModbus` / `NModbus.Serial` (3.0.81) |
|
||
|
|
|
||
|
|
### 주요 기능
|
||
|
|
|
||
|
|
* **수동 검사**: 물리 스위치(i1, i2) 조작에 의해 자동으로 누출 검사 시퀀스가 트리거됨
|
||
|
|
* **자동 검사**: 버튼 한 번으로 인가 → 목표 압력 대기 → 고정 → 유지 → 배기까지 전 공정을 자동 수행
|
||
|
|
* **실시간 모니터링**: 100ms 폴링으로 I/O 상태 및 압력값을 실시간 표시
|
||
|
|
* **통신 분리 및 안정성**: `ConnectionManager`를 통한 통신 인프라 캡슐화 및 `bool` 기반 상태 관리로 안정성 확보
|
||
|
|
* **자가 복구**: 통신 끊김 감지 시 독립적 자동 재연결
|
||
|
|
* **설정 관리**: 통신 포트, 기기 ID, 검사 파라미터를 XML 파일(`config.xml`)로 저장/불러오기
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. 폴더 구조
|
||
|
|
|
||
|
|
```
|
||
|
|
jig_test/ ← 솔루션 루트
|
||
|
|
├── jig_test.slnx ← 솔루션 파일
|
||
|
|
├── README.md ← 본 문서
|
||
|
|
├── KN-2000W_..._MANUAL_W.pdf ← 압력 센서 매뉴얼
|
||
|
|
├── SemiIOLite_Manual.pdf ← I/O 보드 매뉴얼
|
||
|
|
│
|
||
|
|
└── jig_test/ ← 프로젝트 폴더
|
||
|
|
├── jig_test.csproj ← 프로젝트 설정 (.NET 4.7.2, WPF)
|
||
|
|
├── App.xaml / App.xaml.cs ← 앱 진입점, 글로벌 예외 처리
|
||
|
|
│
|
||
|
|
├── Models/ ← 데이터 모델
|
||
|
|
│ └── AppConfig.cs ← 모든 설정값 (포트, 속도, 검사파라미터)
|
||
|
|
│
|
||
|
|
├── Services/ ← 핵심 서비스 서비스 (Infrastructure 계층)
|
||
|
|
│ ├── ConfigService.cs ← XML 직렬화 기반 설정 저장/로드
|
||
|
|
│ ├── ConnectionManager.cs ← ★ 통신 인프라 (포트 수명, 폴링, 재연결 관리)
|
||
|
|
│ ├── SemiIOLiteController.cs ← I/O 보드 제어 (LS산전 ASCII 프로토콜)
|
||
|
|
│ └── PressureSensorController.cs ← 압력 센서 통신 (Modbus RTU)
|
||
|
|
│
|
||
|
|
├── ViewModels/ ← MVVM ViewModel 계층
|
||
|
|
│ ├── Base/
|
||
|
|
│ │ ├── ObservableObject.cs ← INotifyPropertyChanged 구현 기반 클래스
|
||
|
|
│ │ └── RelayCommand.cs ← ICommand 구현 (View 이벤트→ViewModel 바인딩)
|
||
|
|
│ ├── Converters/
|
||
|
|
│ │ └── InverseBooleanConverter.cs ← bool 반전 변환기
|
||
|
|
│ ├── MainViewModel.cs ← ★ 핵심 비즈니스 로직 (검사 시퀀스, UI 바인딩)
|
||
|
|
│ ├── SettingsViewModel.cs ← 통신 설정 창 로직
|
||
|
|
│ └── ParameterViewModel.cs ← 검사 파라미터 창 로직
|
||
|
|
│
|
||
|
|
└── Views/ ← MVVM View 계층 (XAML UI)
|
||
|
|
├── MainWindow.xaml / .cs ← 메인 대시보드 UI
|
||
|
|
├── SettingsWindow.xaml / .cs ← 통신 설정 다이얼로그
|
||
|
|
└── ParameterWindow.xaml / .cs ← 검사 파라미터 다이얼로그
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. 아키텍처 (MVVM 패턴)
|
||
|
|
|
||
|
|
```
|
||
|
|
┌──────────────────────────────────────────────────────────────┐
|
||
|
|
│ App.xaml.cs │
|
||
|
|
│ (글로벌 예외 처리: UI / AppDomain / Task) │
|
||
|
|
└──────────────────────┬───────────────────────────────────────┘
|
||
|
|
│ StartupUri
|
||
|
|
┌──────────────────────▼───────────────────────────────────────┐
|
||
|
|
│ VIEW (XAML) │
|
||
|
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
|
|
│ │ MainWindow.xaml ← DataBinding → MainViewModel.cs │ │
|
||
|
|
│ │ SettingsWindow ← DataBinding → SettingsViewModel │ │
|
||
|
|
│ │ ParameterWindow ← DataBinding → ParameterViewModel │ │
|
||
|
|
│ └───────────────────┬─────────────────────────────────────┘ │
|
||
|
|
└──────────────────────┼───────────────────────────────────────┘
|
||
|
|
│ Event / Method
|
||
|
|
┌──────────────────────▼───────────────────────────────────────┐
|
||
|
|
│ INFRASTRUCTURE / SERVICES │
|
||
|
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
|
|
│ │ ConnectionManager │ │
|
||
|
|
│ │ (Timer, SerialPort LifeCycle, Reconnect, Event Dispatch)│ │
|
||
|
|
│ └───────┬────────────────────────────┬────────────────────┘ │
|
||
|
|
│ │ Composition │ Composition │
|
||
|
|
│ ┌───────▼──────────┐ ┌───────▼──────────┐ │
|
||
|
|
│ │ SemiIOLite │ │ PressureSensor │ │
|
||
|
|
│ │ Controller │ │ Controller │ │
|
||
|
|
│ └───────┬──────────┘ └───────┬──────────┘ │
|
||
|
|
│ │ COM Port │ COM Port │
|
||
|
|
└──────────┼────────────────────────────┼──────────────────────┘
|
||
|
|
▼ ▼
|
||
|
|
┌──────────────┐ ┌──────────────┐
|
||
|
|
│ Semi IO Lite │ │ KN-2240W │
|
||
|
|
│ I/O Board │ │ Pressure │
|
||
|
|
│ (SIO-0201A) │ │ Sensor │
|
||
|
|
└──────────────┘ └──────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### 데이터 흐름 요약
|
||
|
|
|
||
|
|
1. **ConnectionManager → Service**: 100ms 타이머로 각 컨트롤러의 `RequestXxx` 메서드 호출 및 송신 HEX 로그 발행
|
||
|
|
2. **Service → Hardware**: 시리얼 포트를 통해 실제 물리 레이어로 데이터 송신
|
||
|
|
3. **Hardware → ConnectionManager**: `DataReceived` 이벤트 발생 시 바이트 버퍼링 및 패킷 완성 검사
|
||
|
|
4. **ConnectionManager → ViewModel**: 패킷이 완성되면 이벤트를 통해 ViewModel에 전달 (`IOPacketReceived` 등)
|
||
|
|
5. **ViewModel → View**: 수신 패킷을 파싱하여 `lock` 기반으로 압력값 갱신 및 UI 상태 프로퍼티 변경 → 바인딩 자동 반영
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. 핵심 파일 상세
|
||
|
|
|
||
|
|
### 4.1. `Models/AppConfig.cs`
|
||
|
|
|
||
|
|
모든 애플리케이션 설정을 담는 POCO 모델 클래스입니다.
|
||
|
|
|
||
|
|
| 프로퍼티 | 타입 | 기본값 | 용도 |
|
||
|
|
|----------|------|--------|------|
|
||
|
|
| `PortName` | `string` | `"COM1"` | I/O 보드 COM 포트 |
|
||
|
|
| `BaudRate` | `int` | `9600` | I/O 보드 통신 속도 |
|
||
|
|
| `PressurePortName` | `string` | `"COM2"` | 압력 센서 COM 포트 |
|
||
|
|
| `PressureBaudRate` | `int` | `9600` | 압력 센서 통신 속도 |
|
||
|
|
| `IOEnabled` | `bool` | `true` | I/O 보드 사용 여부 |
|
||
|
|
| `IOStationId` | `int` | `2` | I/O 보드 국번 ID |
|
||
|
|
| `PressureEnabled` | `bool` | `true` | 압력 센서 사용 여부 |
|
||
|
|
| `PressureSlaveId` | `int` | `1` | Modbus 슬레이브 주소 |
|
||
|
|
| `HoldTime` | `int` | `30` | 누출 검사 유지 시간 (초) |
|
||
|
|
| `AllowedErrorRange` | `double` | `0.3` | 허용 압력 오차 (bar) |
|
||
|
|
| `AutoTestTargetPressure` | `double` | `4.0` | 자동 검사 목표 압력 (bar) |
|
||
|
|
| `IsLogVisible` | `bool` | `false` | 하단 로그 창 표시 여부 |
|
||
|
|
|
||
|
|
### 4.2. `Services/ConfigService.cs`
|
||
|
|
|
||
|
|
`AppConfig`를 XML 직렬화 방식으로 저장/로드합니다.
|
||
|
|
|
||
|
|
* `Load()`: `config.xml` 파일이 없거나 손상 시 기본 `AppConfig` 반환 (안전한 폴백)
|
||
|
|
* `Save()`: 실행 파일 위치의 `config.xml`에 현재 설정을 즉시 저장
|
||
|
|
|
||
|
|
### 4.3. `Services/ConnectionManager.cs` — ★ 통신 인프라 관리자
|
||
|
|
|
||
|
|
`MainViewModel`에서 통신 관련 저수준 책임을 분리하여 캡슐화한 클래스입니다.
|
||
|
|
|
||
|
|
| 기능 | 상세 내용 |
|
||
|
|
|------|-----------|
|
||
|
|
| **포트 관리** | IO 및 압력 포트의 생성, 오픈, 클로즈, Dispose 주기 관리 |
|
||
|
|
| **폴링 루프** | 100ms `DispatcherTimer`를 구동하여 장비 상태 체크 명령 주기적 송신 |
|
||
|
|
| **버퍼 관리** | `DataReceived` 이벤트로 들어오는 단편화된 바이트를 패킷 단위로 조립 |
|
||
|
|
| **연결 상태** | 응답 타임아웃(1.5초) 감지 시 `bool` 기반 상태 갱신 및 이벤트 발행 |
|
||
|
|
| **자가 복구** | 포트 닫힘이나 연속 실패(10회) 감지 시 3초 간격 자동 재연결 시도 |
|
||
|
|
| **이벤트 발행** | 패킷 수신, 로그 발생, 연결 상태 변경 등을 이벤트를 통해 외부에 알림 |
|
||
|
|
|
||
|
|
### 4.4. `Services/SemiIOLiteController.cs` — I/O 보드 제어
|
||
|
|
|
||
|
|
LS산전 ASCII 프로토콜로 릴레이 출력을 제어하고 입력(i1, i2)을 읽습니다.
|
||
|
|
|
||
|
|
#### 릴레이 상태 (`RelayState` enum)
|
||
|
|
|
||
|
|
| 값 | 이름 | 동작 |
|
||
|
|
|----|------|------|
|
||
|
|
| `0` | `None` | 모든 릴레이 OFF (고정/밀폐 상태) |
|
||
|
|
| `1` | `Exhaust` | 릴레이1 ON — 배기 밸브 작동 |
|
||
|
|
| `2` | `Pressurize` | 릴레이2 ON — 인가 밸브 작동 |
|
||
|
|
| `3` | `Clamp` | 릴레이1+2 ON — 지그 물리 고정 |
|
||
|
|
|
||
|
|
#### 주요 메서드
|
||
|
|
|
||
|
|
| 메서드 | 역할 |
|
||
|
|
|--------|------|
|
||
|
|
| `SetStateAsync(RelayState)` | 릴레이 상태 변경 쓰기 명령 전송 + ACK 응답 대기 (최대 500ms) |
|
||
|
|
| `RequestInputState(onTx)` | 주소 `0A07`의 입력 상태 읽기 요청 전송 (비동기) |
|
||
|
|
| `ParseInputBuffer(buffer, out i1, out i2)` | 수신 버퍼를 파싱하여 i1, i2 디지털 입력 감지 |
|
||
|
|
| `CheckConnectionAsync()` | 주소 `0001` 읽기로 통신 유효성 확인 (핸드셰이크) |
|
||
|
|
|
||
|
|
### 4.5. `Services/PressureSensorController.cs` — 압력 센서 통신
|
||
|
|
|
||
|
|
KN-2240W 디지털 센서와 **Modbus RTU** 프로토콜로 통신합니다.
|
||
|
|
|
||
|
|
#### Modbus RTU 프레임 구조
|
||
|
|
|
||
|
|
| 구분 | 바이트 구성 |
|
||
|
|
|------|-------------|
|
||
|
|
| **요청 (8바이트)** | `[Slave Addr]` `[Func 0x04]` `[Start Addr Hi]` `[Start Addr Lo]` `[Count Hi]` `[Count Lo]` `[CRC Lo]` `[CRC Hi]` |
|
||
|
|
| **응답 (7바이트)** | `[Slave Addr]` `[Func 0x04]` `[Byte Count]` `[Data Hi]` `[Data Lo]` `[CRC Lo]` `[CRC Hi]` |
|
||
|
|
|
||
|
|
#### 주요 메서드
|
||
|
|
|
||
|
|
| 메서드 | 역할 |
|
||
|
|
|--------|------|
|
||
|
|
| `RequestCurrentPressure(onTx)` | 레지스터 `0x0000` 1개 읽기 요청 전송 |
|
||
|
|
| `ParsePressureResponse(buffer, out pressureValue)` | CRC 검증 + 데이터 파싱 후 원시 압력값 반환 |
|
||
|
|
| `BuildReadRequest(startAddress, count)` | Modbus RTU Read Input Registers 프레임 동적 생성 |
|
||
|
|
|
||
|
|
### 4.6. `ViewModels/MainViewModel.cs` — ★ 비즈니스 로직 및 UI 바인딩
|
||
|
|
|
||
|
|
통신 인프라를 제외한 순수 검사 시퀀스와 사용자 인터페이스 로직을 담당합니다. (~800줄)
|
||
|
|
|
||
|
|
#### 4.6.1. 이벤트 기반 데이터 처리
|
||
|
|
|
||
|
|
* `_connManager.IOPacketReceived` 구독: IO 보드 응답 시 `UpdateJigLamps` 호출
|
||
|
|
* `_connManager.PressurePacketReceived` 구독: 압력 센서 응답 시 압력값 갱신 및 UI 반영
|
||
|
|
|
||
|
|
#### 4.6.2. 자가 복구 (Self-Healing) 알고리즘 (ConnectionManager 내 구현)
|
||
|
|
|
||
|
|
```
|
||
|
|
[정상 동작] → 100ms 폴링 중 응답 수신
|
||
|
|
↓ 1.5초 무응답
|
||
|
|
[경고] → 램프 Red + 실패 카운터 증가
|
||
|
|
↓ 10회 연속 무응답
|
||
|
|
[단절 선언] → 포트 닫기 및 리소스 정리
|
||
|
|
↓ 즉시
|
||
|
|
[재연결 시도] → 3초 주기로 포트 재오픈 시도
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 4.6.3. 수동 검사 시퀀스 (StartAutoHoldSequence)
|
||
|
|
|
||
|
|
```
|
||
|
|
[스위치 → 인가 위치] _wasPressurized = true
|
||
|
|
↓
|
||
|
|
[스위치 → 고정 위치] && _wasPressurized
|
||
|
|
↓
|
||
|
|
StartAutoHoldSequence() 트리거
|
||
|
|
↓
|
||
|
|
(1) 현재 압력을 "검사 시작 압력"으로 저장
|
||
|
|
(2) HoldTime 초 동안 1초 간격 대기
|
||
|
|
(3) |최종 압력 - 시작 압력| vs AllowedErrorRange 비교
|
||
|
|
├── 이내 → PASS (LimeGreen)
|
||
|
|
└── 초과 → FAIL (Red)
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 4.6.4. 자동 검사 시퀀스 (StartAutoCycleSequence)
|
||
|
|
|
||
|
|
```
|
||
|
|
[시작 버튼 클릭] (고정 상태에서만 가능)
|
||
|
|
↓
|
||
|
|
단계 1: 인가(Pressurize) → 목표 압력 도달 대기
|
||
|
|
↓
|
||
|
|
단계 2: 고정(None) → 밸브 폐쇄
|
||
|
|
↓
|
||
|
|
단계 3: HoldTime 초 동안 압력 유지 검사
|
||
|
|
↓
|
||
|
|
단계 4: 배기(Exhaust) → 0.0bar 도달 대기 (60초 타임아웃)
|
||
|
|
↓
|
||
|
|
단계 5: 다시 고정(None) → 종료
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 4.6.5. 주요 바인딩 프로퍼티 요약
|
||
|
|
|
||
|
|
| 카테고리 | 프로퍼티 | 용도 |
|
||
|
|
|----------|----------|------|
|
||
|
|
| **장비 램프** | `LampIOStatus`, `LampPressureStatus` | I/O / 압력 센서 연결 표시등 |
|
||
|
|
| **압력** | `CurrentPressureText`, `CurrentPressureColor` | 실시간 압력값 표시 |
|
||
|
|
| **수동 결과** | `ResultText`, `ResultColor` | PASS/FAIL 결과 표시 |
|
||
|
|
| **자동 결과** | `AutoResultText`, `AutoResultColor` | 자동 검사 PASS/FAIL |
|
||
|
|
| **로그** | `IOLogText`, `PrLogText` | I/O / 압력 센서 HEX 통신 로그 |
|
||
|
|
|
||
|
|
### 4.7. `ViewModels/SettingsViewModel` / `ParameterViewModel`
|
||
|
|
|
||
|
|
* 설정 복사본(`Clone`)을 사용한 원본 보호 및 취소 기능
|
||
|
|
* 시스템의 COM 포트 자동 감지 및 폴백 처리
|
||
|
|
* 입력 유효성 검증 (정규식 필터링 및 범위 체크)
|
||
|
|
|
||
|
|
### 4.8. `Views/MainWindow.xaml` — 메인 UI 구조
|
||
|
|
|
||
|
|
* `Viewbox Stretch="Uniform"`: 창 크기 변화에도 UI 비율 유지
|
||
|
|
* 커스텀 타이틀 바 + 탭 컨트롤 기반 화면 구성
|
||
|
|
* 실시간 로그 창 (I/O 녹색, 압력 파란색) 접이식 구현 및 자동 스크롤
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. 안정성 메커니즘
|
||
|
|
|
||
|
|
### 5.1. `bool` 기반 상태 관리 (Refactoring #11)
|
||
|
|
|
||
|
|
기존에는 UI 램프의 `Brush` 색상을 비교하여 통신 상태를 판단했으나, 리액터링을 통해 `_isIOConnected`, `_isPressureConnected` 명시적 필드를 도입하여 로직의 안정성과 가독성을 높였습니다.
|
||
|
|
|
||
|
|
### 5.2. 책임 분리 (Refactoring #10)
|
||
|
|
|
||
|
|
`ConnectionManager`를 통해 통신 인프라를 캡슐화했습니다. 메인 로직은 장치와의 직접적인 포트 관리에서 자유로워졌으며, 이벤트 기반으로 응답을 처리하여 UI 스레드 정지 현상을 방지합니다.
|
||
|
|
|
||
|
|
### 5.3. 글로벌 예외 처리 (`App.xaml.cs`)
|
||
|
|
|
||
|
|
`DispatcherUnhandledException`, `AppDomain.UnhandledException`, `TaskScheduler.UnobservedTaskException`을 모두 처리하여 예기치 못한 에러 시에도 프로그램이 강제 종료되지 않도록 보호합니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. 설정 파일 (`config.xml`)
|
||
|
|
|
||
|
|
실행 파일 위치에 XML 형식으로 저장되며, 손상 시 자동으로 기본값으로 복원됩니다.
|
||
|
|
|
||
|
|
```xml
|
||
|
|
<?xml version="1.0" encoding="utf-8"?>
|
||
|
|
<AppConfig>
|
||
|
|
<PortName>COM3</PortName>
|
||
|
|
<BaudRate>9600</BaudRate>
|
||
|
|
<PressurePortName>COM4</PressurePortName>
|
||
|
|
<PressureBaudRate>9600</PressureBaudRate>
|
||
|
|
<IOEnabled>true</IOEnabled>
|
||
|
|
<IOStationId>2</IOStationId>
|
||
|
|
<PressureEnabled>true</PressureEnabled>
|
||
|
|
<HoldTime>30</HoldTime>
|
||
|
|
<AllowedErrorRange>0.3</AllowedErrorRange>
|
||
|
|
<AutoTestTargetPressure>4.0</AutoTestTargetPressure>
|
||
|
|
<IsLogVisible>false</IsLogVisible>
|
||
|
|
</AppConfig>
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 7. 유지보수 및 확장 가이드
|
||
|
|
|
||
|
|
### 새 검사 파라미터 추가 시
|
||
|
|
1. `Models/AppConfig.cs` 데이터 추가 및 `Clone()` 메서드 업데이트
|
||
|
|
2. `Views/ParameterWindow.xaml` 입력 UI 추가
|
||
|
|
3. `ViewModels/MainViewModel.UpdateParamDisplay()`에 반영
|
||
|
|
|
||
|
|
### 새 기기 추가 시
|
||
|
|
1. `Services/` 컨트롤러 구현 → `ConnectionManager.cs`에 인스턴스/폴링 추가
|
||
|
|
2. `MainViewModel.cs`에서 이벤트 구독 및 파싱 로직 연결
|