4 changed files with 307 additions and 23 deletions
@ -0,0 +1,158 @@ |
|||||
|
# [기술 보고서] 계측기 저항 측정 수치 변환 오류 분석 및 개선 방안 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 1. 개요 (Overview) |
||||
|
|
||||
|
| 항목 | 내용 | |
||||
|
| :--- | :--- | |
||||
|
| **보고서 제목** | 계측기 저항 측정 시 수치 변환 실패(`+9.90000000E+37`) 오류 원인 분석 및 개선안 | |
||||
|
| **발생 시스템** | 양산형 레이저 마킹 & 성능 검사 모니터링 시스템 (`marking_gui`) | |
||||
|
| **관련 장비** | Digital Multimeter (Keysight/Agilent 34465A 등) - 저항 측정 계측기 | |
||||
|
| **심각도** | **높음 (Major)** — 단선 제품 또는 프로브 미접촉 시 검사 프로세스 중단 및 시스템 오류 발생 | |
||||
|
| **작성 일자** | 2026년 9월 21일 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 2. 현상 및 에러 상세 (Issue Description) |
||||
|
|
||||
|
### 2.1. 에러 메시지 |
||||
|
```text |
||||
|
[시스템 오류] |
||||
|
계측기 오류: [RESISTANCE] 수치 변환 실패 (값: '+9.90000000E+37'). 원본 응답: [+9.90000000E+37] |
||||
|
``` |
||||
|
|
||||
|
### 2.2. 발생 상황 |
||||
|
- 생산 라인 검사 시퀀스 실행 중, 전압 측정 후 저항 측정 단계(`MEAS:RES?`)에서 발생 |
||||
|
- 오류 발생 즉시 검사 시퀀스가 비정상 중단되고 시스템 오류 팝업 및 에러 배너가 출력됨 |
||||
|
- 검사 결과 판정(PASS/NG) 및 각인, 데이터베이스 저장이 진행되지 않고 정지됨 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 3. 근본 원인 분석 (Root Cause Analysis) |
||||
|
|
||||
|
본 장애는 **계측기 하드웨어 통신 규격(SCPI)**과 **애플리케이션 데이터 타입(`decimal`) 한계**의 불일치로 인해 발생한 문제입니다. |
||||
|
|
||||
|
```mermaid |
||||
|
flowchart TD |
||||
|
A["저항 측정 지그 접촉 불량 또는 제품 단선 (Open)"] --> B["계측기(DMM): Overload (OL) 감지"] |
||||
|
B --> C["SCPI 규격 응답 전송: '+9.90000000E+37'"] |
||||
|
C --> D["애플리케이션: Regex로 '+9.90000000E+37' 추출"] |
||||
|
D --> E{"decimal.TryParse() 시도"} |
||||
|
E -- "decimal 최대치(~7.9e28) 초과" --> F["Overflow / 파싱 실패 (false)"] |
||||
|
F --> G["InvalidOperationException 발생"] |
||||
|
G --> H["검사 중단 및 '시스템 오류' 팝업 표출"] |
||||
|
``` |
||||
|
|
||||
|
### 3.1. 계측기 하드웨어/통신 관점 (SCPI 규격 특성) |
||||
|
* **표준 SCPI Overload 응답:** Keysight 및 IEEE 488.2 호환 DMM 장비는 저항 측정 시 프로브가 분리되어 있거나, 제품 내부가 단선(Open Circuit)되어 저항값이 계측 가능 범위를 초과하는 경우 **`+9.90000000E+37`** ($9.9 \times 10^{37}$)을 반환하도록 규격화되어 있습니다. |
||||
|
* 즉, 이 값은 **통신 장애나 계측기 고장이 아니라 제품의 단선(Open) 또는 지그 미접촉(Overload) 상태**를 나타내는 정상적인 계측 응답입니다. |
||||
|
|
||||
|
### 3.2. 애플리케이션 코드 관점 (자료형 오버플로우) |
||||
|
* 문제 발생 코드 위치: `marking_gui/Services/EquipmentMeasurementService.cs` 내부 `ExtractFirstDecimal` 메서드 |
||||
|
|
||||
|
```csharp |
||||
|
// EquipmentMeasurementService.cs (Line 398~411) |
||||
|
private static decimal ExtractFirstDecimal(string response, string label) |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(response)) |
||||
|
throw new InvalidOperationException($"[{label}] 계측기 응답이 비어있습니다 (응답 수신 실패)."); |
||||
|
|
||||
|
var match = Regex.Match(response, @"[-+]?\d+(?:\.\d+)?(?:[Ee][-+]?\d+)?"); |
||||
|
if (!match.Success) |
||||
|
throw new InvalidOperationException($"[{label}] 수치 파싱 실패. 원본 응답: [{response.Trim()}]"); |
||||
|
|
||||
|
// [문제 지점] decimal 타입으로 파싱 시도 |
||||
|
if (!decimal.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out decimal val)) |
||||
|
throw new InvalidOperationException($"[{label}] 수치 변환 실패 (값: '{match.Value}'). 원본 응답: [{response.Trim()}]"); |
||||
|
|
||||
|
return val; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
* **자료형 한계 비교:** |
||||
|
| 자료형 | 최소값 ~ 최대값 범위 | 9.9e37 수용 여부 | |
||||
|
| :--- | :--- | :---: | |
||||
|
| **`decimal`** (현재 적용) | 약 $-7.9 \times 10^{28} \sim +7.9 \times 10^{28}$ | **불가 (Overflow)** | |
||||
|
| **`double`** (권장) | 약 $\pm 5.0 \times 10^{-324} \sim \pm 1.7 \times 10^{308}$ | **가능 (정상 수용)** | |
||||
|
|
||||
|
* 계측기 응답값 $9.9 \times 10^{37}$은 `decimal` 최대 표현 한계($7.9 \times 10^{28}$)를 초과하므로 `decimal.TryParse()`가 `false`를 반환하며 `InvalidOperationException`을 발생시킵니다. |
||||
|
|
||||
|
### 3.3. 비즈니스 로직 관점의 문제점 |
||||
|
* 제품이 단선된 불량품인 경우, 시스템은 이를 **불합격(NG)**으로 정상 판정하고 시퀀스를 마무리해야 합니다. |
||||
|
* 현재 구현은 불량 제품이 인입되었을 때 계측기 통신 에러로 인식하여 전체 공정이 정지되는 구조적 결함을 안고 있습니다. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 4. 영향도 및 리스크 평가 (Impact & Risk) |
||||
|
|
||||
|
1. **생산 라인 지연 및 정지 (Line Stoppage):** |
||||
|
- 접촉이 불안정하거나 단선 불량품이 유입될 때마다 작업자가 에러 창을 확인하고 수동 리셋해야 하므로 공정 지연이 발생합니다. |
||||
|
2. **불량품 판정 및 이력 누락:** |
||||
|
- 예외가 발생하여 `SaveAndFinalizeAsync`가 호출되지 못하므로, 해당 불량 시료의 검사 데이터가 데이터베이스에 남지 않습니다. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 5. 개선 및 해결 방안 (Action Plan) |
||||
|
|
||||
|
### 5.1. 수치 파싱 로직 개선 (`double` 기반 전환) |
||||
|
- `ExtractFirstDecimal`의 반환 타입 및 파싱 로직을 `decimal`에서 `double`로 변경하여 $10^{37}$ 스케일의 부동소수점 값을 에러 없이 파싱합니다. |
||||
|
|
||||
|
```csharp |
||||
|
private static double ExtractFirstNumber(string response, string label) |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(response)) |
||||
|
throw new InvalidOperationException($"[{label}] 계측기 응답이 비어있습니다 (응답 수신 실패)."); |
||||
|
|
||||
|
var match = Regex.Match(response, @"[-+]?\d+(?:\.\d+)?(?:[Ee][-+]?\d+)?"); |
||||
|
if (!match.Success) |
||||
|
throw new InvalidOperationException($"[{label}] 수치 파싱 실패. 원본 응답: [{response.Trim()}]"); |
||||
|
|
||||
|
if (!double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double val)) |
||||
|
throw new InvalidOperationException($"[{label}] 수치 변환 실패 (값: '{match.Value}'). 원본 응답: [{response.Trim()}]"); |
||||
|
|
||||
|
return val; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 5.2. Overload (OL / 단선) 상태 식별 및 비즈니스 로직 연계 |
||||
|
- 계측기 반환값이 $9.0 \times 10^{37}$ 이상일 경우 오버로드(OL, 단선) 상태로 감지합니다. |
||||
|
- **판정 연계:** |
||||
|
- 저항값을 규격 상한(예: 13 k$\Omega$)을 크게 상회하는 값(예: `99999.0` k$\Omega$)으로 처리하여 자연스러운 **저항 불합격(NG)** 판정을 유도합니다. |
||||
|
- **UI 표출 연계:** |
||||
|
- GUI 저항 표시창(`txtResistance`)에 지수 형태 대신 직관적인 **`O.L`** 또는 규격 상한 초과 수치를 표시합니다. |
||||
|
|
||||
|
```csharp |
||||
|
// 저항 측정 처리 예시 |
||||
|
double rawResistance = ExtractFirstNumber(rResponse, "RESISTANCE"); |
||||
|
double resistance; |
||||
|
|
||||
|
if (rawResistance >= 9.0e37) |
||||
|
{ |
||||
|
// 오버로드 (단선 / 오픈) 상태 감지 |
||||
|
resistance = 99999.0; // 상한 초과 값 부여 -> 자동 NG 판정 유도 |
||||
|
LoggerService.Warn("[Equipment] 저항 계측 Overload 감지 (단선/프로브 미접촉 상태)"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
resistance = rawResistance / 1000.0; // Ω -> kΩ 정상 변환 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 6. 검증 계획 (Verification Plan) |
||||
|
|
||||
|
| 검증 단계 | 검증 시나리오 | 예상 결과 | |
||||
|
| :--- | :--- | :--- | |
||||
|
| **1. 파서 단위 검증** | `+9.90000000E+37` 문자열을 파서에 입력 | 예외 없이 OL 값(99999.0)으로 안전하게 변환 확인 | |
||||
|
| **2. 오픈 상태 검증** | 지그에 제품을 장착하지 않고(프로브 개방) 검사 시작 버튼 클릭 | 시스템 오류 팝업 없이 저항 화면에 `O.L` 표시 및 최종 **`NG`** 판정 확인 | |
||||
|
| **3. 정상 상태 검증** | 정상 저항 규격(8.0 ~ 13.0 k$\Omega$) 제품 장착 후 검사 시작 | 기존과 동일하게 실제 측정 수치 표시 및 **`OK`** 판정 확인 | |
||||
|
| **4. DB 적재 검증** | 단선(NG) 발생 시 시퀀스 종료 후 DB 및 UI 상태 점검 | 시스템 멈춤 없이 다음 검사 대기 상태로 정상 복귀 확인 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 7. 결론 및 건의사항 |
||||
|
|
||||
|
본 오류는 계측기의 하드웨어 고장이 아니라 **단선/오버로드 규격치 수신 시의 예외 처리 누락**에서 기인한 것입니다.\ |
||||
|
제안된 파싱 타입 변경 및 오버로드 핸들링 로직을 적용하면 단선 불량 발생 시에도 시스템 멈춤 없이 안정적으로 불합격 판정 및 공정을 지속할 수 있습니다. |
||||
Loading…
Reference in new issue