docs: SG 토글 + DPS 직접입력 + ADC CSV 저장 문서 추가

- 19. Settings: SG Filter 토글 설명, DPS 슬라이더→직접입력 반영
- 21. ADC CSV: 파일 포맷, Python 읽기 예시, 저장 시점 설명
- 향후 과제: ADC CSV 완료 항목 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 11:06:36 +09:00
parent f563b20659
commit 099fcfaf97
+68 -3
View File
@@ -1125,15 +1125,26 @@ Lock → "Start Measurement" 버튼 활성화
해결: threshold를 1200~1300으로 올려서 테스트 해결: threshold를 1200~1300으로 올려서 테스트
``` ```
### Distance/Sample (초록색 슬라이더, 1.5~2.5mm) ### Distance/Sample (초록색 숫자 직접 입력, 0.5~5.0mm)
``` ```
기본값: 1.771 mm/sample 기본값: 1.771 mm/sample
용도: ADC 샘플 1개당 물리적 거리. BV 계산에 직접 영향. 용도: ADC 샘플 1개당 물리적 거리. BV 계산에 직접 영향.
d_mm = delay_offset + sample_index × distance_per_sample d_mm = delay_offset + sample_index × distance_per_sample
입력: 소수점 3자리까지 정밀 입력 가능 (슬라이더 대신 텍스트 필드)
조절: 기기별 캘리브레이션 시 팬텀 실측값과 맞추기 위해 사용 조절: 기기별 캘리브레이션 시 팬텀 실측값과 맞추기 위해 사용
``` ```
### SG Filter (토글 스위치, ON/OFF)
```
기본값: ON
용도: Savitzky-Golay 5-tap 스무딩 필터 on/off
ON: SG 적용 → 부드러운 파형, 안정적인 벽 탐지
OFF: Raw ADC 그대로 → 원본 신호로 벽 탐지 (디버깅용)
효과: 그래프에서 진한 파랑(Denoised)이 연한 파랑(Raw)과 동일해지면 OFF
```
### lr_ratio 하한 제한 ### lr_ratio 하한 제한
``` ```
@@ -1180,7 +1191,60 @@ bytes.push((crc >> 8) & 0xff);
--- ---
# 21. 향후 과제 # 21. ADC 데이터 CSV 저장
### 파일 위치
```
Downloads/VesiScan_ADC/YYYY-MM-DD.csv
```
하루 1개 CSV 파일에 매 측정마다 append. 파일 탐색기에서 바로 접근 가능.
### CSV 포맷
```csv
scan_id,timestamp,volume_ml,lr_ratio,channel,s0,s1,s2,...,s99
1,14:30:12.345,305.2,1.20,CH0,1823,1801,1788,...,1245
1,14:30:12.345,305.2,1.20,CH1,1756,1734,1721,...,1198
1,14:30:12.345,305.2,1.20,CH2,1802,1788,1775,...,1234
1,14:30:12.345,305.2,1.20,CH3,1834,1812,1799,...,1267
1,14:30:12.345,305.2,1.20,CH4,1645,1623,1610,...,1123
1,14:30:12.345,305.2,1.20,CH5,1721,1698,1685,...,1178
2,14:30:22.678,,1.00,CH0,1234,...
```
- `scan_id`: 측정 회차 (같은 ID = 같은 측정의 6채널)
- `volume_ml`: BV 추정 결과 (빈칸이면 측정 실패)
- `channel`: CH0~CH5
- `s0~s99`: ADC 100개 샘플
### Python에서 읽기
```python
import pandas as pd
df = pd.read_csv("2026-04-27.csv")
# 1회차 측정 전체
scan1 = df[df.scan_id == 1]
# CH0 ADC 100개
ch0_adc = scan1[scan1.channel == "CH0"].iloc[0, 5:].values
# 전체 측정 용적 추이
volumes = df[df.channel == "CH0"][["scan_id", "timestamp", "volume_ml"]].drop_duplicates()
```
### 저장 시점
- BV 추정 성공 시: volume_ml + lr_ratio + 6채널 ADC
- BV 추정 실패 시 (center 부족): volume_ml 빈칸 + 6채널 ADC
- 0채널 감지 시: volume_ml 빈칸 + 6채널 ADC (raw 데이터 보존)
---
# 22. 향후 과제
| 항목 | 상태 | 비고 | | 항목 | 상태 | 비고 |
|------|------|------| |------|------|------|
@@ -1195,8 +1259,9 @@ bytes.push((crc >> 8) & 0xff);
| BLE 디버그 로거 | ✅ 완료 | TX/RX 파싱 + Downloads 내보내기 | | BLE 디버그 로거 | ✅ 완료 | TX/RX 파싱 + Downloads 내보내기 |
| BLE 명령어 Endian 통일 | ✅ 완료 | 테스터 exe와 100% 동일 (BE+공백) | | BLE 명령어 Endian 통일 | ✅ 완료 | 테스터 exe와 100% 동일 (BE+공백) |
| 자동측정 (IMU 1s + 측정 10s) | ✅ 완료 | | | 자동측정 (IMU 1s + 측정 10s) | ✅ 완료 | |
| 런타임 캘리브레이션 | ✅ 완료 | Threshold + DPS 슬라이더 | | 런타임 캘리브레이션 | ✅ 완료 | Threshold 슬라이더 + DPS 직접입력 + SG 토글 |
| 도넛차트 실시간 ml | ✅ 완료 | lastVolumeMl 직접 표시 | | 도넛차트 실시간 ml | ✅ 완료 | lastVolumeMl 직접 표시 |
| ADC CSV 저장 | ✅ 완료 | Downloads/VesiScan_ADC/일별.csv |
| Python ↔ Android 1:1 검증 | ✅ 완료 | 전수 상수 비교 | | Python ↔ Android 1:1 검증 | ✅ 완료 | 전수 상수 비교 |
| 금요일 APK 배포 | 🔜 예정 | Gitea 릴리즈 | | 금요일 APK 배포 | 🔜 예정 | Gitea 릴리즈 |
| mbb 전체측정 전환 | 🔜 예정 | rbb: 헤더 파싱 검증 후 | | mbb 전체측정 전환 | 🔜 예정 | rbb: 헤더 파싱 검증 후 |