Files
HECO2/doc/260617_수정내용.md
jeon 096111e983 feat: 06-17 신규 작업본 반영 (개발사양서/기능검토/승인원/Source 등 추가)
.claude/ 제외(.gitignore 추가). 기존 초기커밋(5a96a69) 위에 신규·수정·이동분 커밋.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 07:54:58 +09:00

226 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 260617 수정내용
작업일: 2026-06-17 / 작성: Claude (jeon 지시)
대상: 실보드(룸컨+HERV+PC) 연동 검증 중 발견 이슈 + 대시보드 기능 추가.
제약: `My_RJ2.c`(룸컨), `My_bunbaegi.c`(분배기) 수정 금지. 펌웨어 수정 후 `bash build.sh all` 빌드 확인.
※ 본 문서의 펌웨어 경로 `program/User/...`는 2026-06-17 폴더 이동 후 **`SOURCE/HECO2/User/...`** 로 읽을 것(아래 #14 참조).
---
## 1. 운전모드/풍량 "두 번 눌러야 바뀜" (실제 팬/댐퍼)
- **원인:** 운전모드 전환 시 `Fan_Speed_process()`(100ms)가 첫 틱에 `Pre_Run_Mode != Run_Mode`를 보고 `Target_Fan=0`으로 비움(댐퍼 정렬 대기). 그런데 정렬 완료 후 풍량을 새 모드 VSP로 **복원하는 코드가 주석처리**돼 있었음. 복원은 디퓨저 시퀀스(18초 주기)가, 그것도 풍량 단수가 바뀔 때만 수행 → 환기1단↔공청1단처럼 단수 동일 전환은 팬이 0으로 꺼진 채 방치. 두 번째 누르면 `Pre_Run_Mode==Run_Mode`라 wipe가 안 일어나 적용됨.
- **수정:** `program/User/MyMotor.c` — 환기/자동/바이패스/공청 4개 모드 전환 블록에서 댐퍼 정렬 후(`Damper_wait_time==1`, `Step_Status==0x3F` 통과) `Fan_Speed_Setting(Run_Mode, Fan_Mode)` 호출로 새 모드 VSP 복원. 전환당 1회 실행(정상 운전 중엔 미호출).
- 어제 추가했던 `My_Homenet.c`의 즉시 `Fan_Speed_Setting` 직접호출은 wipe로 지워져 무효였음 → 근본 위치(Fan_Speed_process)에서 해결.
## 2. RJ2 베이스라인 복원 + 죽은 코드 정리
- `My_RJ2.c`를 외부 원본(`HERV_DL_MH_2nd`)으로 되돌림 → `Homenet_RJ_Request`(PC 푸시 래치) 소비 코드 제거됨.
- `My_Homenet.c`/`My_define.h`에서 더 이상 소비되지 않는 `Homenet_RJ_Request` 정의·extern·쓰기 4곳 제거. PC→룸컨 푸시는 `Command_request_type |= TYPE_MODE/TYPE_FAN_SPEED` 경로로만 동작.
## 3. 전원 OFF인데 디퓨저(시뮬) 댐퍼 열림·LED 9 유지
- **원인:** DiffuserSim 슬레이브 파서가 명령/폴링을 `byte5(Power) != 0`로 구분. 전원 OFF면 펌웨어가 `byte5=0`(Power OFF)로 댐퍼0·LED0을 보내는데, 시뮬이 이를 폴링으로 오인해 닫힘 명령을 무시.
- dump.txt 스펙: byte5 = 하위비트 전원(0/1), 상위 0x80 Control Cmd.
- **수정:** `Simulator/DiffuserSimulator/SlaveProtocol.cs``powerOff = ((rxBuf[5] & 0x7F)==0)` 분기 추가. 전원 OFF 프레임이면 급기/배기 댐퍼 0, LED 0으로 닫음(전원 우선). 전원 ON 경로는 기존 유지.
## 4. 공기질 등급 불일치 (대시보드 좋음 vs 시뮬 보통)
- **시뮬 임계 버그:** `Simulator/DiffuserSimulator/MainWindow.xaml.cs` `ThrCO2`의 NORMAL/TURBO가 사양과 달랐음 → NORMAL `{700,1000,1300,1600}``{800,1100,1400,1700}`, TURBO `{600,800,1000,1200}``{700,1000,1300,1600}`. (PM2.5/PM10/VOC는 이미 일치)
- **프리셋 중앙값:** `PreCO2` NORMAL/TURBO가 옛 임계 기준이라 어긋나 재배치(밴드 중앙). NORMAL `{400,950,1250,1550,1850}`, TURBO `{350,850,1150,1450,1750}`.
- **전수 감사(개발사양서 p.10):** 펌웨어/DemoStatus/ErvState/DashboardState/웹 THR_DEMO 모두 사양과 일치 확인. 시뮬 ThrCO2만 불일치였음.
- **결론:** 위 값(PM2.5=22 등)은 사양상 어느 프리셋에서도 보통(레벨1)이라 둘 다 보통이 맞음. 대시보드가 좋음이면 **ERV에 실린 런타임 임계값(EEPROM)이 사양 기본값이 아님** → 보드에서 임계 재설정 필요(코드 아님).
## 5. VSP 값 사양(개발사양서 p.12) 정합
- p.12 첫 표(휴벤 ECO2/좌타입 HRD1-150EPI) = 펌웨어 `MyControl.c` 기본값. 환기 SA 56/63/70/86·EA 57/63/70/85, 바이패스 SA67/EA75, 공청 SA 65/72/78/80·EA 0. (환기 터보-4=자동 250CMH 행)
- **CLAUDE.md VSP 실측표**가 구버전(SA57/EA56…)이라 p.12 값으로 갱신. 기저(50CMH)는 사용자 지시로 제외.
## 6. PC 대시보드 — 히스테리시스/VSP 창 버튼 추가
- `TestProgram/PCDashBoard` — 히스테리시스·VSP 창에 **읽어오기(STATUS값)/프리셋(사양기본값)/변경(전송)** 버튼 추가.
- `DashboardState.Def*`(불변 기본값: 임계 p.10, VSP p.12) 추가.
- VSP 창은 로컬 작업본 분리 → STATUS(1초)가 편집값 덮어쓰던 문제 해결.
## 7. 웹 대시보드 — 동일 버튼 + VSP 값
- `TestProgram/WebDashBoard/ErvCollector/wwwroot/index.html`(+ `ErvWebDashboard/index.html` 동기화):
- VSP 모달 `읽어오기/프리셋(기본값)/변경`, 히스테리시스 모달 `읽어오기/프리셋(기본값)`(전송은 기존 데드밴드/임계 변경).
- `VSP_DEFAULT`(p.12)/`DB_DEFAULT`(p.10)/`THR_DEFAULT` 추가.
- 편집 버퍼(`bufVsp/bufHyst/bufThr`) 분리 → `poll()`(1초)이 편집값 덮어쓰던 문제 해결. VSP도 즉시전송 대신 변경 버튼.
---
## 8. 공기질 등급 여전히 비정상 (깨끗한 공기인데 '최악') — EEPROM 임계 로드 버그
- **증상:** 센서 PM2.5=7/PM10=14/CO2=400/VOC=60(전부 좋음 수준)인데 대시보드가 '최악'. 펌웨어 재플래시 후에도 지속.
- **원인:** `MyControl.c Hyst_From_Page()`가 EEPROM에서 임계값을 로드할 때 유효성 검사가 `page_data[EEP_HYST_PRESET](인덱스43) <= 2` 한 바이트뿐. 구 펌웨어 EEPROM은 시그니처(0x55AA55AA)가 유효하고 인덱스43에 우연히 0~2 값이 있으면, 임계영역(56~127)의 가비지(0 등)를 그대로 로드 → 임계 0 → 모든 센서가 레벨4(최악).
- **수정:** `Hyst_Page_Valid()` 추가 — 프리셋 마커 + **임계 단조증가(L0<L1<L2<L3, L0>0)** 검증. 위배(0/가비지)면 로드 거부 → 컴파일 기본값(사양 p.10) 유지. `Hyst_From_Page()`가 이 검사를 사용.
- 자가치유 불필요: 매 부팅 가비지 거부 → 사양값 사용. STATUS도 RAM 사양값 송신 → 대시보드 일치. 대시보드에서 임계 변경 시 유효(단조)값 저장 → 다음 부팅 정상 로드.
- **후속:** 재플래시 후 대시보드 히스테리시스 '읽어오기'로 ERV 임계가 사양 기본값인지 확인. 사양값 유지 원하면 '프리셋→임계 변경/데드밴드 변경'으로 EEPROM에 영속화.
## 9. NANO100 메모리 맵 정리 + EEPROM vs Data Flash 영역 확인
- **계기:** EEPROM 가비지를 지우려 Nu-Link ICP로 칩 Data Flash(0x1CC00)에 FF를 썼는데도 안 지워짐.
- **확인(DS_Nano100(B) Rev1.09 p.106/111 + fmc.h, EEPROM_Emulate.h):**
- 칩: Nano100SE3BN = LDROM 4K / APROM 115K(0x0~0x1CC00) / Data Flash 8K(0x1CC00~0x1EC00, DFBA=Config1=0x1CC00) / SRAM 16K(0x20000000).
- **펌웨어 EEPROM 에뮬레이션은 `EEP_FLASH_BASE=0xFC00` → APROM 내부(0xFC00~0xFFFF, 512B×2페이지). 칩 Data Flash(0x1CC00)와 다른 영역.**
- 펌웨어 코드는 0x0~0xB338(~46KB). EEPROM(0xFC00)과 18KB 여유 → 코드/EEPROM 안 겹침.
- **결론:** Data Flash에 FF 써도 펌웨어 EEPROM(APROM 0xFC00)은 안 지워짐. 비우려면 칩 이레이즈 또는 0xFC00 포함 APROM 이레이즈. (또는 #8 코드수정으로 가비지 자동거부.)
- **잠재 위험:** `gcc_arm.ld`가 EEPROM/Data Flash 영역 미예약(FLASH 0x0~0x20000 통짜) → 펌웨어가 0xFC00 넘으면 충돌. 현재 여유 있음.
- **문서화:** CLAUDE.md에 "■ NANO100 메모리 맵" 섹션 추가(시스템 주소공간/플래시 내부구조/우리가 쓰는 영역/주의사항). 향후 EEPROM을 칩 Data Flash(0x1CC00)로 이전할지는 보류(이전 시 사장님 FF 워크플로로 초기화 가능 + 코드충돌 위험 0).
## 10. 스마트수면(시나리오) 모드에서 공기질 등급 멈춤 — 대시보드 불일치
- **증상:** 스마트수면 모드에서 대시보드 공기질 등급이 센서 변화에 안 따라옴(멈춤). 시뮬과 불일치.
- **원인:** `My_system.c Air_Quality_damper_process()`에서 등급(`Room_Level`) 계산 루프가 함수 **맨 아래(메인 루프)**에 있는데, 시나리오 모드(안심회복=1/집중청정=3/스마트수면=4/쾌적조리)는 `goto PASS_VOLUME`로 그 루프를 **건너뜀** → 등급이 시나리오 진입 시점 값으로 동결.
- **수정:** 등급 계산(sensor_level 4종 → 최고치 → Room_Level/ROOM_air_volume + Prev_*_Lv 갱신)을 함수 **앞쪽(Force_Damper_Mode/Ext_Run_Mode 분기 이전)으로 이동**해 모드 무관 매 틱 수행. 기존 메인 루프는 재계산 없이 Room_Level 사용만(히스테리시스 prev 이중적용 방지). 댐퍼/자동판정 로직 영향 없음.
- **주의:** 이 수정은 등급이 "갱신"되게 함. 등급이 "정확"하려면 ERV 임계값이 사양값이어야 함(#4/#8, EEPROM). 둘은 별개.
## 11. 후드 통신 "연결안됨" — 펌웨어 후드 프로토콜이 Rev1.3와 불일치
- **증상:** 후드시뮬을 ERV 보드에 연결하고 쾌적조리 선택 → "후드 연결안됨".
- **원인:** 후드시뮬은 사양서(주신전자_protocol_hood Rev1.3_20241125, **9바이트·XOR**)대로 검증돼 있는데, ERV 펌웨어 `My_Hood.c`**구버전 13바이트**(CheckSum_Creator 12B + ERV→후드 제어필드 byte8/9). ERV가 13B 응답을 기다리는데 시뮬은 9B만 보내 → 프레임 미완성 → `Hood_Rx_Complete` 안 켜짐 → `Hood_Conn_Timeout` 미갱신 → 연결안됨. (헤더 AA21/AA11은 같으나 길이·체크섬 위치가 다름)
- **수정(`My_Hood.c`, 사용자 "스펙대로"):** Rev1.3 9바이트로 통일.
- 폴 송신: `AA 21 ID(01) MODE(Run_Mode) FAN(Fan_Mode) 연동EN 연동운전중(Yeungong) ERROR(0) CS(XOR byte0~7)`, 9B 송신.
- 수신 파서: `AA 11 ... [8]=CS(XOR0~7)`, `Hood_Status = byte[3]`(FANSTATUS). case 0~8.
- CheckSum_Creator는 이미 XOR이라 그대로(길이 8). ERV→후드 직접제어필드(Hood_Power_On/Fan/Control) 제거 — Rev1.3엔 없음(ERV는 Hood_Status 읽어 단수 추종).
- **백업:** 구 13B 소스를 `program/User/My_Hood_old.c`로 보관. Makefile `USER_EXCLUDE`로 빌드 제외(중복심볼 방지).
- **후속:** 플래시 후 후드시뮬 연결 시 "연결됨"·쾌적조리 연동(단수 추종) 확인.
### 11-1. 후드 프로토콜 상세 비교 (구버전 My_Hood_old.c ↔ 수정본 My_Hood.c)
공통: RS-485, 115200 8N1. 헤더 마스터=AA 21 / 슬레이브=AA 11. 체크섬 알고리즘은 양쪽 다 **XOR**(`CheckSum_Creator`)로 동일 — 차이는 **프레임 길이·CS 범위·제어필드**.
**(A) 프레임 구조 요약**
| 항목 | 구버전(13B) | 수정본(9B, Rev1.3) |
|---|---|---|
| 프레임 길이 | 13바이트 | 9바이트 |
| CS 위치 | byte[12] | byte[8] |
| CS 범위 | XOR(byte0~11) | XOR(byte0~7) |
| ERV→후드 제어필드 | 있음(byte8/9 Power/Fan) | **없음**(스펙에 없음, ERV는 후드 단수 추종) |
| RX 상태머신 | case 0~12 | case 0~8 |
**(B) ERV→후드 폴(Master, Hood_Tx_packet) 바이트별**
| byte | 구버전 13B | 수정본 9B (Rev1.3) |
|---|---|---|
| 0 | 0xAA | 0xAA |
| 1 | 0x21 | 0x21 |
| 2 | 0x01 (ID) | 0x01 (ID) |
| 3 | Run_Mode | Run_Mode (MODE) |
| 4 | Fan_Mode | Fan_Mode (FAN) |
| 5 | Hood_YeunDong_Enable | Hood_YeunDong_Enable (연동EN) |
| 6 | Yeungong_Status | Yeungong_Status (연동운전중) |
| 7 | 0x00 | 0x00 (ERROR) |
| 8 | Hood_Power_On \| Hood_Control | **CS = XOR(0~7)** |
| 9 | Hood_Fan_Mode \| Hood_Control | — (삭제) |
| 10 | 0x00 | — (삭제) |
| 11 | 0x00 | — (삭제) |
| 12 | CS = XOR(0~11) | — (삭제) |
| 송신길이 | UART_Write(...,13) | UART_Write(...,9) |
| 기타 | `if(Hood_Control==0x80)Hood_Control=0;` | (제거) |
**(C) 후드→ERV 응답(Slave, rx_hood_check 가 기대하는 포맷) 바이트별**
| byte | 구버전 13B | 수정본 9B (Rev1.3) | 후드시뮬 BuildResponse |
|---|---|---|---|
| 0 | 0xAA | 0xAA | 0xAA |
| 1 | 0x11 | 0x11 | 0x11 |
| 2 | (data) | ID | 0x01 |
| 3 | **Hood_Status←[3]** | **FANSTATUS (Hood_Status←[3])** | fanStatus |
| 4 | (data) | LIGHTSTATUS | light |
| 5 | (data) | 0x00 | 0x00 |
| 6 | (data) | 연동CMD | cmd(연동) |
| 7 | (data) | ERROR | errorCode |
| 8 | (data) | **CS = XOR(0~7)** | XOR(0~7) |
| 9~11 | (data) | — | — |
| 12 | CS = XOR(0~11) | — | — |
| 수신길이 | 13바이트 완성 시 처리 | 9바이트 완성 시 처리 | 9바이트 송신 |
→ 양쪽 모두 `Hood_Status`는 **byte[3]**에서 읽음(인덱스 불변). 수정본은 시뮬 BuildResponse와 바이트 배치·길이·CS가 정확히 일치.
**(D) 구버전이 시뮬과 통신 실패한 이유**
1. **길이 불일치:** ERV가 13바이트를 기다리는데 시뮬은 9바이트만 송신 → 수신 파서가 case 8(시뮬 CS)을 데이터로 받고 pos=9에서 멈춰 case 12에 영영 도달 못 함 → `Hood_Rx_Complete` 미설정.
2. 설령 길이가 같아도 **CS 범위 다름**(XOR 0~11 vs 0~7) → 체크섬 불일치로 거부.
3. 결과: `Hood_Conn_Timeout` 미갱신 → 1500ms 후 0 → STATUS byte5 bit2(후드 통신연결)=0 → 대시보드 "연결안됨".
**(E) 의미적 변화**
- 구버전: ERV가 후드에 Power/Fan을 직접 명령(byte8/9)할 수 있었음.
- 수정본(Rev1.3): ERV→후드 직접제어 없음. ERV는 응답의 FANSTATUS(byte3=Hood_Status)를 읽어 풍량을 **추종**(Hood_Step_To_Fan, 1→1…5→4, 사양 260613). `Hood_Power_On/Hood_Fan_Mode/Hood_Control` 변수는 정의는 남으나 후드 송신엔 미사용.
### 11-2. 후드 "연결 감지"와 "쾌적조리 동작"은 별개 (개념 정리)
질문: 쾌적조리(후드 풍량 추종) 선택해도 후드를 안 켜면 연결상태를 알 수 없나? → **아니오, 알 수 있음.** 두 로직이 분리돼 있음.
| 로직 | 함수 | 게이트 조건 | 역할 |
|---|---|---|---|
| **연결 감지(폴링)** | `Hood_RS485_process()` | **없음 — 항상 500ms 폴** | 유효 응답 오면 `Hood_Conn_Timeout=1500` → STATUS byte5 bit2 "연결됨" |
| **쾌적조리(추종)** | `Hood_process()` | `if(Hood_YeunDong_Enable==0) return` | 후드 단수 추종(메이크업 에어). 연결 감지와 무관 |
- ERV는 **쾌적조리 선택·후드 팬 상태와 무관하게 항상 후드를 폴**한다. 슬레이브(후드/시뮬)는 팬이 꺼져 있어도 폴에 응답하면 "연결됨".
- 경우별:
- 후드 제어보드 ON, 팬/조명 OFF → 응답함(FANSTATUS=0) → **연결됨**
- 후드 제어보드 자체 전원 OFF → 무응답 → **연결안됨**
- 후드시뮬 '통신 시작' 상태(PowerOn 토글 무관) → 무조건 응답 → **연결됨**
- 한계: 후드 제어보드가 완전히 꺼지면 "전원OFF인지 / 케이블 빠짐인지" 구분 못 함 — 둘 다 "연결안됨"(제3의 '알수없음' 상태는 없음).
- ⇒ 연결상태는 항상 알 수 있고, 시뮬은 통신 시작만 했으면 연결됨이어야 정상. 직전 "연결안됨"은 #11 프로토콜 길이 불일치(13B↔9B) 때문 → 플래시로 해결.
### 11-3. 후드 UART baud 불일치 (9600 → 115200) — 통신 자체 불가의 진짜 원인
- **증상:** #11(프레임 9B) 수정·플래시 후에도 후드 통신 계속 안 됨.
- **원인:** `My_system.c UART0_Init()`**`UART_Open(UART0, 9600)`** — 후드 UART가 9600 baud. 후드시뮬·Rev1.3 스펙은 **115200**. baud가 다르면 프레임 형식과 무관하게 한 바이트도 못 읽음. 프레임은 Rev1.3로 고쳤지만 baud는 구버전(9600)이 남아 있었음.
- **수정:** `UART_Open(UART0, 115200)`. (다른 채널 UART1=HOMENET 115200과 동일선상)
-#11(프레임 9B) + #11-3(baud 115200) 둘 다 적용해야 후드 통신 성립. 플래시 후 재확인.
## 12. 후드 단수 추종이 2단 이상 안 올라감 — Set_Fan_Mode만 잡고 Fan_Mode 미반영
- **증상:** 후드시뮬 단수를 5로 올려도(후드 FANSTATUS=5 정상 송신) ERV 폴엔 FAN=2 고정. 통신은 정상(9B/115200).
- **원인:** `My_Hood.c Hood_process()`(makeup-air 후드추종)가 `Set_Fan_Mode`(목표)와 `Command_request_type`만 설정하고, 실제 `Fan_Mode`(폴 byte4에 실리는 적용값)는 **룸컨(RJ2) echo로만 반영**. 룸컨 echo 지연/미연결 시 Fan_Mode가 옛값(2)에 머물러 폴에 2가 실림.
- **수정:** PC 풍량변경(CTRL_FAN)과 동일하게 **직접 반영**. 3개 분기 모두:
- 후드 ON 진입: `Set_Run_Mode=Run_Mode=MODE_VENTILATION`, `Set_Fan_Mode=Fan_Mode=Hood_Step_To_Fan(...)`, `Fan_Speed_Setting(Run_Mode,Fan_Mode)` 추가.
- 단수 변경: `Set_Fan_Mode=Fan_Mode=f`, `if(Run_Mode!=MODE_AUTO)Fan_Speed_Setting(...)` 추가.
- 후드 OFF 복귀: `Set_*=Run_Mode/Fan_Mode=My_Memory_*`, `if(Run_Mode!=MODE_AUTO)Fan_Speed_Setting(...)` 추가.
- 룸컨 푸시(Command_request_type)·Tx_Yeundong_Delay는 유지(연동/수동 구분 불변). 직접반영은 #1(MyMotor 전환복원)과 함께 동작.
- **후드 OFF 복귀(개발사양서 p.9 3.3 관련, 사용자 결정 2026-06-17):**
- **즉시 복귀** 채택(스펙의 180s 롤백 딜레이는 미구현 — 잔여 냄새배출은 후드측이 담당).
- 감지는 **FANSTATUS=0(Hood_Status==0)만**. 사용자 확인: 후드는 전원 OFF여도 통신으로 FANSTATUS=0을 보냄. 진짜 연결끊김은 별도 통신에러로 처리(복귀 트리거 아님).
- #12의 OFF 분기 직접반영(`Run_Mode=Fan_Mode=My_Memory_*` + `Fan_Speed_Setting`)으로 즉시 복귀 성립. 이전엔 Set_* 만 설정해 룸컨 echo 의존 → 복귀 누락이 "복귀 안됨"의 원인이었음.
- **추가 관찰(별개, 미수정):**
- `Yeungong_Status`(연동운전중, 폴 byte6)가 펌웨어에서 1로 설정되는 곳이 없어 **항상 0**(시뮬 "정지" 표시). 후드에 연동운전중을 알릴 필요 있으면 set 로직 추가 필요.
- `MODE_VENTILATION=0`이라 후드 폴 byte3(MODE)=0이 환기인데, 후드시뮬 ModeName이 0→"OFF"로 표시(시뮬 라벨 불일치, 표시상 문제).
## 13. 쾌적조리 후드 OFF 시 화면 복귀 안됨 (펌웨어 복귀는 정상, 대시보드 표시만)
- **증상:** 후드 OFF로 ERV는 본래 운전모드로 복귀(펌웨어 OK)하는데, 대시보드는 **쾌적조리 버튼이 계속 강조·운전모드 버튼 잠김** 상태로 남음.
- **원인:** 대시보드가 시나리오 활성/운전모드 잠금을 **쾌적조리(=연동 Enable, byte4 bit1)** 기준으로 판단. 후드가 꺼져도(연동운전중=0) 연동 Enable은 1로 유지되므로 계속 잠김.
- **수정(대시보드만):** 판단 기준을 **연동운전중(HoodRunning, STATUS byte5 bit1 = Hood_Status!=0)** 으로 변경.
- `DashboardState.HoodRunning` 추가, `StatusMapper`에서 `s.HoodRunning` 매핑(이미 디코드돼 있던 byte5 bit1).
- `RefreshControls`: `subActive`(운전모드/풍량/프리셋 잠금)와 `ComfortCookBtn` 강조를 `ComfortCook``HoodRunning`으로.
- **결과:** 후드 ON(가동중)=쾌적조리 강조+운전모드 잠김(메이크업), 후드 OFF=쾌적조리 해제+운전모드 활성(복귀된 모드 강조). 연동 Enable 자체는 '후드 연동' 토글로 계속 표시(사양 3.1 대기 상태 = 본래 모드 가동). 펌웨어 불변.
## 14. 후드시뮬 전원 OFF 표시 텍스트 변경 (시간 불변)
- 후드시뮬 전원 OFF 시 잔여배출 카운트다운 표시: `메이크업 {N}s`**`지연배기(원래는 30초) {N}s`** (HoodSimulator `MainWindow.xaml.cs`).
- **유지 시간은 변경 없음**(`MakeupHoldSec=10`, 사용자 지시 "시간은 바꾸지마"). "(원래는 30초)"는 사양 원래값 표기용 글씨. 로그/주석도 "메이크업"→"지연배기" 일관 정리(내부 변수명 유지).
## 15. 펌웨어 폴더 이동 (사용자 작업)
- **2026-06-17 사용자가 펌웨어 폴더를 `program/``SOURCE/HECO2/`로 이동.** (User, Library, Makefile, build.sh, openocd.cfg, build 모두). 같은 SOURCE 하위에 `FND_display`도 있음.
- `build.sh`는 자기 위치 기준(BASH_SOURCE) 경로라 새 위치에서 정상 빌드 확인(`cd SOURCE/HECO2; bash build.sh all` → 오류 0).
- 갱신: CLAUDE.md(빌드 규칙·경로), 메모리(herv-firmware-build/work-scope/MEMORY). 본 문서의 기존 `program/User/...` 경로는 `SOURCE/HECO2/User/...`로 해석.
## 빌드 결과 (전체)
- 펌웨어 `cd SOURCE/HECO2 && bash build.sh all` → 경고/오류 0 (HERV.elf/hex/bin, text 43976).
- DiffuserSimulator / PCDashBoard(ErvDashboard) / ErvCollector(웹) / HoodSimulator → 모두 오류 0.
## 오늘 요약 (#1~#15)
1. 운전모드/풍량 두번눌림(MyMotor 전환복원) · 2. RJ2 복원+죽은코드정리 · 3. 전원OFF 디퓨저 닫힘(SlaveProtocol) · 4. 공기질 ThrCO2/PreCO2 + p.10 전수감사 · 5. VSP p.12 정합(CLAUDE.md) · 6. PC대시보드 읽어오기/프리셋/변경 버튼 · 7. 웹대시보드 동일+VSP · 8. EEPROM 히스테리시스 가비지 거부(Hyst_Page_Valid) · 9. NANO100 메모리맵 문서화 · 10. 스마트수면 공기질등급 갱신 · 11. 후드 프로토콜 9B/Rev1.3(+#11-3 baud 115200) · 12. 후드 단수추종 직접반영 · 13. 쾌적조리 후드OFF 화면복귀(대시보드) · 14. 후드시뮬 지연배기 텍스트 · 15. 펌웨어 폴더 이동.
## 미해결 / 후속 (다음 작업)
- **플래시 후 실보드 검증**: 운전모드/풍량 1회 적용, 전원OFF 디퓨저 닫힘, 스마트수면 등급, 후드 통신/추종/복귀(9B·115200). (스핀다운 ~5~6초는 설계상 정상)
- **공기질 등급 정확도**: ERV EEPROM 임계값이 사양 기본값인지 대시보드 히스테리시스 '읽어오기'로 확인, 아니면 '프리셋→변경'으로 사양값 기록(또는 칩 이레이즈).
- **보류**: EEPROM을 칩 Data Flash(0x1CC00)로 이전 + 링커 영역 예약(내일 결정). 기저 VSP 실구현. 후드 `Yeungong_Status`(연동운전중) set 로직, 후드시뮬 MODE 라벨(0=환기).