Files
HECO2/Protocol/각실제어/보류_각실제어_내부프로토콜_Rev3.0_2tier.md
jeon 5a96a696b1 chore: HERV 통합 저장소 초기 커밋
- 펌웨어(program), C# 대시보드(TestProgram), 시뮬레이터(Simulator),
  프로토콜/문서(Protocol, doc) 전체를 단일 저장소로 통합
- program 폴더의 별도 git 저장소를 제거하고 통합 저장소에 흡수
- 빌드 산출물(program/build, bin/obj, *.o/.elf/.bin/.hex 등) .gitignore 처리
- 사내 Synology NAS Git 원격 연결 예정

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:44:23 +09:00

547 lines
28 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.
# 각실제어 내부 통신 프로토콜 (Rev 3.0, 2-Tier 계층형)
> 휴벤ECO(ERV) ↔ **각실분배기** ↔ 디퓨저(SA/RA) · 룸컨 **내부 통신** 규격
>
> 본 규격은 [각실제어_내부프로토콜_Rev2.0_CMD.md](각실제어_내부프로토콜_Rev2.0_CMD.md) 를
> **계층형(2-Tier)** 으로 재구성한 것이다. 분배기 회로도 `Schematic/BUNBAGI_REV4.1_20251124(회로도).pdf`
> 와 펌웨어 `program/User/My_Uart.c` 를 근거로 한다.
> (Rev 2.0 은 그대로 보존하며, 본 Rev 3.0 이 상위 규격이다. DL 룸컨 232 `My_RJ2.c` 는 무관 — 변경 안 함.)
- **물리계층** : RS-485, **115200 bps, 8 Data, None Parity, 1 Stop (N81)**
- **대상 시스템** : 사양서 5페이지 구성 = **거실 + 방1~4 (5실)**
---
## 0. 무엇이 바뀌었나 (Rev 2.0 단일버스 → Rev 3.0 2-Tier)
회로도 분석 결과, 각실분배기는 **자체 MCU(Nuvoton NANO100SE3BN)를 가진 능동 컨트롤러**임이 확인되었다. 따라서 통신을 두 계층으로 분리한다.
| 구분 | Rev 2.0 (단일 버스) | Rev 3.0 (2-Tier) |
|------|---------------------|------------------|
| 버스 구조 | ERV가 모든 디퓨저/룸컨(17대)을 1버스로 직접 폴링 | **상위: ERV↔분배기 1버스 / 하위: 분배기↔실별 디퓨저·룸컨** |
| ERV 폴링 대상 | 17대 | **분배기 1대** |
| 분배기 역할 | 없음(전원·배선 통과) | **하위 5채널 로컬 마스터 + 에러격리 + 포트별 통신상태 LED** |
| 디퓨저 LED 제어 | 디퓨저에 ledDim 전송 | **디퓨저에 ledDim 전송** (유지). 조명 LED는 **RA 디퓨저에만** 있고 ERV→분배기→RA디퓨저로 밝기 제어 |
| 자동운전 판단 | ERV | **ERV** (분배기는 센서수집·명령실행만) |
| 집계 패킷 | 0x21 제안(미반영) | **상위버스 정식 패킷(`RSP_ALLROOM_*`)으로 채택** |
> **하드웨어 근거 (BUNBAGI Rev4.1)** : 상위 `M485`(RS485 1채널, U5, 커넥터 CN3) / 하위 `SA485`(RS485 **5채널**, 실별 RJ45 J1~J5, RX는 8:1 MUX U6로 실 선택, DIR 채널별) / 전원 24V(60W)·3.3V.
> ※ 분배기의 2×74HC595(U10·U12, SA=초록·RA=노랑) LED는 **각 포트 SA/RA 디퓨저의 통신상태 표시등**(분배기 보드 진단용)이며, 프로토콜과 무관하다.
> ※ **방의 조명용 LED는 RA 디퓨저에만 달려 있고**, ERV가 밝기(0~9)를 명령한다 → 분배기가 해당 RA 디퓨저로 전달.
---
## 0-1. Rev 2.0(단일버스) → Rev 3.0(2-Tier) 장단점
> 채택 전 의사결정용 요약. 결론적으로 **하드웨어(분배기 MCU·하위 5채널·SPOF 구조)와 5실 확장 요구를 고려하면 2-Tier 도입 권장**이되, 분배기 펌웨어 신규 개발과 단일 장애점(SPOF) 대비가 전제다.
### ✅ 장점
| # | 항목 | 내용 | 효과 |
|---|------|------|------|
| 1 | **ERV 폴링 부하 격감** | ERV가 17대 직접 폴링 → **분배기 1대만** 상대 | ERV 펌웨어·루프 단순, CPU 여유 |
| 2 | **갱신 속도 향상** | ERV 입장 1주기 **5.1초 → 0.6초** (상·하위 병렬, 하위는 분배기가 빠르게 순환) | 룸컨·대시보드 응답성 ↑ |
| 3 | **버스 트래픽·충돌 감소** | 상위 버스엔 노드 1개, 하위는 5채널로 부하 분산(MUX+채널별 DIR) | 패킷 충돌/재전송 ↓ |
| 4 | **실별 통신에러 격리** | 한 실 디퓨저 고장이 채널 단위로 격리 → 타 실·ERV에 영향 최소 | 가용성 ↑, 원인 국소화 |
| 5 | **신호 무결성·배선 이점** | 하위는 짧은 로컬 세그먼트 5채널 분리, 채널별 종단·DIR | 노이즈·반사 ↓ (긴 데이지체인 대비) |
| 6 | **ERV–분배기 인터페이스 추상화** | ERV는 디퓨저 주소·개수를 몰라도 됨. 디퓨저 증설/사양변경을 **분배기가 흡수** | ERV 코드 변경 없이 하위 확장 |
| 7 | **역할·개발 분담** | ERV(시스템 로직) ↔ 분배기/디퓨저/룸컨(주신) 펌웨어 디커플링 | 병행 개발·유지보수 용이 |
| 8 | **확장성** | 실/디퓨저 추가는 하위에서 처리, 멀티 분배기(`nodeId`) 대비 | 향후 평면 확장 수월 |
| 9 | **MCU 동일(Nano100)** | ERV·분배기 동일 계열 → 프레임/CRC/드라이버 코드 공유 | 개발 재사용 |
### ⚠️ 단점 / 리스크
| # | 항목 | 내용 | 완화책 |
|---|------|------|--------|
| 1 | **분배기 펌웨어 신규 개발** | 하위 마스터 + 상위 슬레이브 + MUX/DIR + 595 + 집계 캐시 로직 필요 | Nano100 공통 드라이버 재사용, `My_Uart.c` 골격 활용 |
| 2 | **지연(latency) 1홉 추가** | 명령이 ERV→분배기→디퓨저 2단. 최악 상위주기+하위주기 합산 | 긴급 제어는 분배기가 즉시 중계, 댐퍼는 비실시간이라 영향 작음 |
| 3 | **상태 동기화 시차** | ERV가 보는 값은 분배기 캐시(직전 하위 폴링 결과) → 한 박자 지연 가능 | 변경 이벤트 우선 보고, 타임스탬프/시퀀스로 정합 |
| 4 | **단일 장애점(SPOF)** | 중앙 분배기 1대 고장 시 **전 실 통신 두절** (단일버스는 ERV-디퓨저 직접이라 무관) | 분배기 워치독·자기진단, 통신두절 시 ERV 안전모드 |
| 5 | **집계 패킷이 큼** | `RSP_ALLROOM_STATUS` 93B 등 → 1프레임 손상 시 전 실 갱신 실패(재전송 단위 큼) | CRC+재요청, 필요 시 실별 분할 응답 옵션 |
| 6 | **디버깅·추적 복잡** | 장애 시 상위/하위/분배기 로직 분리 진단, 버스 스니핑 2곳 | 분배기 진단로그·상태 LED(595), SPEC/버전 패킷 |
| 7 | **프로토콜 2종 관리** | 상위·하위 CMD 세트 2개 정의·문서화·버전관리 | 본 문서 단일화, 프레임 규칙 공통 |
| 8 | **3자 버전 정합** | ERV·분배기·디퓨저/룸컨 펌웨어 호환성 관리 | `SPEC`(0x1F/0x9F) 버전 교환·검증 |
### 한눈에
| 관점 | Rev 2.0 단일버스 | Rev 3.0 2-Tier |
|------|------------------|----------------|
| ERV 부담 | 큼(17대 폴링) | **작음(1대)** |
| 갱신 주기(ERV) | 5.1초 | **0.6초** |
| 분배기 펌웨어 | 불필요 | **필요(신규)** |
| 장애 격리 | 디퓨저별(분배기 무관) | 실별(단, 분배기 SPOF) |
| 확장/유지보수 | ERV가 전부 관리 | **계층 분리로 용이** |
| 구현 난이도 | 낮음 | 중(분배기 추가) |
---
## 1. 시스템 구조
```
[상위 버스: M485 · RS485 1채널] [하위 버스: SA485 · RS485 5채널 (MUX)]
┌── ch1 거실 : SA디퓨저×2, RA디퓨저×2, 룸컨
ERV ───────────────────────── 각실분배기 ─┼── ch2 방1 : SA디퓨저, RA디퓨저, 룸컨
(Master) (Nano100) ├── ch3 방2 : SA디퓨저, RA디퓨저, 룸컨
· 상위 Slave ├── ch4 방3 : SA디퓨저, RA디퓨저, 룸컨
· 하위 Master └── ch5 방4 : SA디퓨저, RA디퓨저, 룸컨
· 포트별 통신상태 LED(74HC595, 진단용)
· 실별 전원(24V)·통신에러 격리
```
**역할 분담**
| 주체 | 책임 |
|------|------|
| **ERV (메인)** | 전열교환기 팬/VSP 제어, **자동운전 판단**(부하점수·집중/분산, 사양서 10~11P), **부가모드(스마트수면/쾌적조리/안심회복)·후드 연동(HOOD-485) 처리**, 분배기에 전원/모드/풍량 + 실별 댐퍼·LED 타겟 하달, 집계상태 수신 |
| **분배기** | 하위 5채널 폴링(실별 SA/RA 디퓨저·룸컨), **댐퍼·LED 명령 중계·실행**, 센서·룸컨명령 수집→ERV에 집계 보고, 실별 통신에러 격리, **포트별 통신상태 표시 LED**(74HC595, 진단용) |
| **디퓨저(SA/RA)** | 댐퍼 구동·각도/RPM 회신, 센서값 회신. **RA 디퓨저는 자체 조명 LED 점등(밝기 0~9)** |
| **룸컨** | 사용자 입력(전원/모드/풍량/예약 등) 보고, ERV 상태 표시 |
**데이터 흐름 (자동운전)**
```
분배기 ──(실별 원시 센서)──> ERV ──[부하점수·집중/분산 계산]──> 실별 댐퍼/풍량/LED 타겟
ERV ──(타겟)──> 분배기 ──(댐퍼·LED 실행 / 디퓨저 제어)──> 각 실
```
---
## 2. 공통 프레임 (상·하위 동일)
```
+------+------+------+------------------+--------+--------+
| STX | CMD | LEN | PAYLOAD[LEN] | CRC_H | CRC_L |
+------+------+------+------------------+--------+--------+
0xAA 1B 1B LEN bytes 16-bit CRC
```
| 필드 | 크기 | 설명 |
|---------|------|------|
| STX | 1 | 고정 `0xAA` |
| CMD | 1 | 명령/응답 코드 (상위 4장 / 하위 5장) |
| LEN | 1 | PAYLOAD 바이트 수 (0~255) |
| PAYLOAD | LEN | CMD 별 데이터 |
| CRC | 2 | **CRC-16/MODBUS** (poly 0xA001, init 0xFFFF), **CMD~PAYLOAD** 까지, **빅엔디안(CRC_H 먼저)** |
- 모든 멀티바이트 수치는 **빅엔디안**. 상·하위 버스 모두 같은 프레임/CRC 규칙을 쓴다.
- 분배기 MCU와 ERV MCU가 동일 계열(Nano100)이므로 CRC·프레임 파서 코드를 공유한다.
---
## 3. 공통 값 정의
### 3.1 전원 (Power)
`0x00`=OFF, `0x01`=ON
### 3.2 운전모드 (RunMode)
| 값 | 의미 | 펌웨어 |
|----|------|--------|
| 0x01 | 수동(환기) | MODE_VENTILATION |
| 0x02 | 자동 | MODE_AUTO |
| 0x04 | 바이패스 | MODE_BYPASS |
| 0x08 | 공기청정 | MODE_AIRCLEAN |
### 3.3 풍량 (FanSpeed)
`0`=정지, `1`=약, `2`=중, `3`=강, `4`=터보
### 3.4 LED 밝기 (LedDim) — **RA 디퓨저 조명**
`0`=OFF, `1`~`9`=1~9단(9=최대). 조명 LED는 **RA 디퓨저에만** 존재(단색, 색온도 3800K). ERV가 실별 밝기를 지시 → 분배기가 해당 실 RA 디퓨저로 전달 → RA 디퓨저가 자체 점등.
> 분배기 보드의 SA(초록)/RA(노랑) LED는 별개로, 포트별 통신상태 표시등이다(프로토콜 무관).
### 3.5 댐퍼 각도 (DamperAngle)
`0x00`=0°(닫힘) ~ `0xB4`=180°(완전개방). 슬롯 미사용 시 `0xFF`(장치 없음).
### 3.6 에러코드 (ErrorCode, **u32 비트맵**)
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x00000001 | 필터 청소 |
| 1 | 0x00000002 | 필터 교체 |
| 2 | 0x00000004 | 소자 교체 |
| 3 | 0x00000008 | 온도센서 에러 |
| 4 | 0x00000010 | 장비보호 모드 |
| 5 | 0x00000020 | EA 팬 에러 |
| 6 | 0x00000040 | 간헐운전 모드 |
| 7 | 0x00000080 | SA 팬 에러 |
| 8~12 | 0x00000100~0x00001000 | 통합센서 에러 — 거실/방1/방2/방3/방4 |
| 16~20 | 0x00010000~0x00100000 | 통신 에러 — 거실/방1/방2/방3/방4 |
### 3.7 실 번호 (Room)
`1`=거실, `2`=방1, `3`=방2, `4`=방3, `5`=방4. (하위버스 MUX 채널 ch1~ch5 와 1:1)
### 3.8 부가모드 (AddMode, 비트맵)
DL 사양 시나리오 모드. 룸컨에서 토글하며 운전모드(3.2)에 덧씌워진다. 여러 비트 동시 가능.
| 비트 | 마스크 | 의미 | 비고 (사양서 8~9P) |
|------|--------|------|--------------------|
| 0 | 0x01 | 스마트수면 | 자동·풍량1단 고정, 1시간마다 CO2 기준 댐퍼 |
| 1 | 0x02 | 쾌적조리 | 렌지후드 연동(아래 3.9), 환기·3단 급기 |
| 2 | 0x04 | 안심회복 | 침실1 음압, 환기·2단 |
> `0x00` = 부가모드 없음. (회복모드 중 수면모드 불가 등 배타조건은 ERV 로직에서 처리)
### 3.9 후드 연동 (Hood, 비트맵)
렌지후드와 전열교환기 연동. 후드 동작 시 ERV도 동작해야 하므로 ERV가 후드 상태를 감지·연동한다(HOOD-485). 쾌적조리(3.8 bit1) 활성 시 적용.
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x01 | 후드연동 활성화(enable) |
| 1 | 0x02 | 후드 현재 동작중(ON) |
> 예: `0x03` = 연동 ON + 후드 가동중 → ERV 환기·3단 급기. `0x00` = 연동 없음.
---
# 상위 버스 — ERV ↔ 각실분배기
> ERV(Master)가 분배기(유일 Slave)를 폴링한다. 분배기는 하위에서 모은 전 실 데이터를 **집계해 응답**한다.
> 멀티 분배기 확장 대비로 페이로드 선두에 `nodeId`(분배기 번호, 기본 `0x01`)를 둔다.
## 4. 상위 CMD 및 PAYLOAD
| CMD | 이름 | 방향 | PAYLOAD | 설명 |
|------|------|------|---------|------|
| 0x10 | `CMD_SYSTEM` | ERV→분배기 | 4.1 | 전원/모드/풍량/예약 + 실별 댐퍼·LED 타겟 (폴링 겸용) |
| 0x12 | `POLL_SENSOR` | ERV→분배기 | nodeId(1) | 전 실 센서 집계 요청 |
| 0x14 | `CMD_CONFIG` | ERV→분배기 | 4.5 | VSP 테이블·장치개수·ID 설정/저장 |
| 0x1F | `POLL_SPEC` | ERV→분배기 | nodeId(1) | 분배기 사양/버전 요청 |
| 0x90 | `RSP_ALLROOM_STATUS` | 분배기→ERV | 4.2 | 전 실 댐퍼·RPM·LED·룸컨명령·에러 집계 (0x10 응답) |
| 0x92 | `RSP_ALLROOM_SENSOR` | 분배기→ERV | 4.3 | 전 실 통합공기질 센서 집계 (0x12 응답) |
| 0x94 | `RSP_CONFIG` | 분배기→ERV | 4.5 | 설정 에코/저장결과 (0x14 응답) |
| 0x9F | `RSP_SPEC` | 분배기→ERV | 4.6 | 분배기 사양/버전 |
### 4.1 `CMD_SYSTEM` (0x10, ERV→분배기)
**글로벌(off 0~15, 16B)** + **실별 타겟 블록(6B) × 5실**
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | 분배기 번호(0x01) |
| 1 | 1 | power | 3.1 |
| 2 | 1 | runMode | 3.2 |
| 3 | 1 | fanSpeed | 3.3 |
| 4 | 1 | addMode | 부가모드 비트맵 (3.8) |
| 5 | 1 | hood | 후드 연동 비트맵 (3.9) |
| 6 | 1 | reserveHour | 0~8시간 |
| 7 | 4 | errorCode | ERV 시스템 에러 통보 (3.6) |
| 11 | 2 | outTemp | 외기온도 ×10 (signed) |
| 13 | 2 | inTemp | 내기온도 ×10 (signed) |
| 15 | 1 | roomCount | 실 수(=5) |
실별 타겟 블록(6B, roomCount회 반복) :
| off(상대) | 크기 | 필드 | 비고 |
|-----------|------|------|------|
| +0 | 1 | roomNo | 3.7 |
| +1 | 1 | saDamper1 | SA 디퓨저1 목표각 (3.5) |
| +2 | 1 | saDamper2 | SA 디퓨저2 (거실만, 그 외 0xFF) |
| +3 | 1 | raDamper1 | RA 디퓨저1 목표각 |
| +4 | 1 | raDamper2 | RA 디퓨저2 (거실만, 그 외 0xFF) |
| +5 | 1 | ledDim | 해당 실 RA 디퓨저 조명 밝기 (3.4) |
LEN = 16 + 6×5 = **46**.
### 4.2 `RSP_ALLROOM_STATUS` (0x90, 분배기→ERV)
**글로벌(8B)** + **실별 상태 블록(17B) × 5실**
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | |
| 1 | 1 | bunbagiState | 분배기 동작/에러 요약 |
| 2 | 1 | addModeReq | 룸컨이 요청한 부가모드 비트맵 (3.8) |
| 3 | 4 | errorCode | 전 실 통신·센서 에러 집계 (3.6) |
| 7 | 1 | roomCount | =5 |
실별 상태 블록(17B) :
| off(상대) | 크기 | 필드 | 비고 |
|-----------|------|------|------|
| +0 | 1 | roomNo | |
| +1 | 1 | saDamper1 | 실제 각도 |
| +2 | 1 | saDamper2 | (없으면 0xFF) |
| +3 | 1 | raDamper1 | |
| +4 | 1 | raDamper2 | |
| +5 | 2 | saRpm | SA 팬 실측 RPM |
| +7 | 2 | raRpm | RA 팬 실측 RPM |
| +9 | 1 | ledDim | 현재 RA 조명 LED 밝기 |
| +10 | 1 | rcCmdFlags | 룸컨 명령 비트(아래 5.5 cmdFlags 동일, bit7=부가모드 변경) |
| +11 | 1 | rcPower | 룸컨 설정 전원 |
| +12 | 1 | rcRunMode | 룸컨 설정 모드 |
| +13 | 1 | rcFanSpeed | 룸컨 설정 풍량 |
| +14 | 1 | rcReserveHour | 룸컨 설정 예약 |
| +15 | 1 | rcHeaterUV | bit0=히터,bit4=UV |
| +16 | 1 | rcFilterReset | 1=필터리셋 요청 |
LEN = 8 + 17×5 = **93**.
> `rcCmdFlags` 가 0 이 아니면, 해당 실 룸컨에서 사용자 조작이 발생했다는 뜻 → ERV가 수용해 운전상태 갱신.
### 4.3 `RSP_ALLROOM_SENSOR` (0x92, 분배기→ERV)
**글로벌(2B)** + **실별 센서 블록(19B) × 5실**
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 1 | nodeId |
| 1 | 1 | roomCount(=5) |
실별 센서 블록(19B) :
| off(상대) | 크기 | 필드 | 단위 |
|-----------|------|------|------|
| +0 | 1 | roomNo | |
| +1 | 2 | pm1p0 | ㎍/㎥ |
| +3 | 2 | pm2p5 | ㎍/㎥ |
| +5 | 2 | pm4p0 | ㎍/㎥ |
| +7 | 2 | pm10p0 | ㎍/㎥ |
| +9 | 2 | humidity | %RH ×10 |
| +11 | 2 | temperature | ℃ ×10 (signed) |
| +13 | 2 | voc | TVOC index |
| +15 | 2 | nox | NOx index |
| +17 | 2 | co2 | ppm |
LEN = 2 + 19×5 = **97**.
### 4.5 `CMD_CONFIG` (0x14) / `RSP_CONFIG` (0x94)
VSP 풍량 테이블·장치개수·Modbus ID 설정.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | |
| 1 | 1 | vspSelect | 0=None,1=환기,2=공청,3=바이패스 |
| 2 | 10 | sa1,ea1 … sa5,ea5 | 단별 VSP (각 1B) |
| 12 | 2 | rpmRefMid | 중 RPM 기준 |
| 14 | 2 | rpmDeltaMid | 중 RPM 편차 |
| 16 | 2 | rpmRefHigh | 강 RPM 기준 |
| 18 | 2 | rpmDeltaHigh | 강 RPM 편차 |
| 20 | 1 | roomconNum | 룸컨 수(1~5) |
| 21 | 1 | saDiffuserNum | SA 디퓨저 수(2~6) |
| 22 | 1 | raDiffuserNum | RA 디퓨저 수(2~6) |
| 23 | 1 | modbusId | 외부 홈넷 연동 ID |
| 24 | 1 | save | 1=EEPROM 저장 |
LEN = 25. `RSP_CONFIG` 는 동일 레이아웃 에코 + save 결과.
### 4.6 `RSP_SPEC` (0x9F)
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 1 | nodeId |
| 1 | 2 | version (예 0x0117=Ver1.23) |
| 3 | 1 | deviceType |
| 4 | 1 | capability (bit0 히터/bit1 UV/bit2 후드연동) |
LEN = 5.
---
# 하위 버스 — 각실분배기 ↔ 디퓨저 · 룸컨
> 분배기(로컬 Master)가 **MUX로 실 채널(ch1~ch5)을 선택**한 뒤 그 실의 SA/RA 디퓨저·룸컨을 폴링한다.
> 조명 LED(RA 디퓨저)는 `LCMD_DIFFUSER` 의 `ledDim` 으로 제어한다(3.4). 분배기 보드의 74HC595 LED는 별개(포트별 통신상태 표시, 진단용).
## 5. 하위 CMD 및 PAYLOAD
PAYLOAD 선두 3바이트는 장치 주소 `[DEV][ROOM][IDX]`.
- DEV : `0x10`=SA 디퓨저, `0x20`=RA 디퓨저, `0x30`=룸컨
- ROOM : 3.7 (채널과 1:1) / IDX : 같은 실·종류 일련번호(거실 SA·RA는 1,2)
| CMD | 이름 | 방향 | PAYLOAD | 설명 |
|------|------|------|---------|------|
| 0x20 | `LCMD_DIFFUSER` | 분배기→디퓨저 | 5.1 | 디퓨저 댐퍼/풍량 제어 + 폴링 |
| 0x21 | `LPOLL_ROOMCON` | 분배기→룸컨 | 5.4 | 룸컨 폴링 + ERV 상태 표시데이터 전달 |
| 0xA0 | `LRSP_DIFFUSER` | 디퓨저→분배기 | 5.2 | 댐퍼각/RPM/에러/버전 (0x20 응답) |
| 0xA1 | `LRSP_DIFFUSER_SENSOR` | 디퓨저→분배기 | 5.3 | 통합공기질 센서 (방별, 센서 부착 디퓨저) |
| 0xB0 | `LRSP_ROOMCON` | 룸컨→분배기 | 5.5 | 룸컨 사용자 명령 (0x21 응답) |
### 5.1 `LCMD_DIFFUSER` (0x20, 분배기→디퓨저)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x10(SA)/0x20(RA) |
| 3 | 1 | power | 3.1 |
| 4 | 1 | runMode | 3.2 |
| 5 | 1 | fanSpeed | 3.3 |
| 6 | 1 | ledDim | RA 디퓨저 조명 밝기 (3.4) — **RA(0x20)만 유효, SA는 0** |
| 7 | 1 | dmpAngle | 목표 댐퍼각 (3.5) |
| 8 | 1 | dmpReset | 1=댐퍼 초기화 |
LEN = 9.
### 5.2 `LRSP_DIFFUSER` (0xA0, 디퓨저→분배기)
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 3 | DEV/ROOM/IDX (에코) |
| 3 | 1 | power |
| 4 | 1 | runMode |
| 5 | 1 | fanSpeed |
| 6 | 1 | ledDim (현재 RA 조명 밝기, SA는 0) |
| 7 | 1 | dmpAngle (현재각) |
| 8 | 2 | rpm |
| 10 | 4 | errorCode (3.6) |
| 14 | 2 | version |
LEN = 16.
### 5.3 `LRSP_DIFFUSER_SENSOR` (0xA1, 디퓨저→분배기)
| off | 크기 | 필드 | 단위 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | 센서 부착 디퓨저(통상 RA) |
| 3 | 2 | pm1p0 | ㎍/㎥ |
| 5 | 2 | pm2p5 | ㎍/㎥ |
| 7 | 2 | pm4p0 | ㎍/㎥ |
| 9 | 2 | pm10p0 | ㎍/㎥ |
| 11 | 2 | humidity | %RH ×10 |
| 13 | 2 | temperature | ℃ ×10 |
| 15 | 2 | voc | TVOC |
| 17 | 2 | nox | NOx |
| 19 | 2 | co2 | ppm |
| 21 | 4 | errorCode | 3.6 |
LEN = 25.
### 5.4 `LPOLL_ROOMCON` (0x21, 분배기→룸컨)
분배기가 ERV로부터 받은 동작상태를 룸컨에 전달(표시용) + 룸컨 명령 회수.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | power | ERV 현재 전원 |
| 4 | 1 | runMode | ERV 현재 모드 |
| 5 | 1 | fanSpeed | ERV 현재 풍량 |
| 6 | 1 | addMode | 현재 부가모드 비트맵 (3.8) |
| 7 | 1 | hood | 후드 연동 상태 (3.9) |
| 8 | 1 | reserveRemain | 예약 잔여(h) |
| 9 | 4 | errorCode | 3.6 |
| 13 | 2 | outTemp | ×10 |
| 15 | 2 | inTemp | ×10 |
| 17 | 1 | ackFlags | 직전 룸컨 명령 수용 비트 |
LEN = 18.
### 5.5 `LRSP_ROOMCON` (0xB0, 룸컨→분배기)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | cmdFlags | bit0 power,1 runMode,2 fanSpeed,3 reserveHour,4 heaterUV,5 filterReset,6 ledDim,**7 addMode** |
| 4 | 1 | power | 3.1 |
| 5 | 1 | runMode | 3.2 |
| 6 | 1 | fanSpeed | 3.3 |
| 7 | 1 | reserveHour | 0~8 |
| 8 | 1 | heaterUV | bit0 히터,bit4 UV |
| 9 | 1 | filterReset | 1=리셋 |
| 10 | 1 | addMode | 부가모드 토글 비트맵 (3.8) |
| 11 | 2 | version | |
LEN = 13.
> 룸컨이 보낸 명령은 분배기가 모아 상위 `RSP_ALLROOM_STATUS` 의 `rc*` 필드로 ERV에 전달 → ERV가 판단 후 다시 하달.
---
## 6. 동작 시나리오 & 폴링 타이밍
**두 버스가 독립적으로 동작**한다.
**하위 버스 (분배기 로컬 루프)** — 분배기가 ch1~ch5를 MUX로 돌며 각 실의 SA/RA 디퓨저·룸컨 폴링. 케이블이 짧고 전용 채널이라 빠르게 순환하며 전 실 상태를 캐싱.
**상위 버스 (ERV 루프)** — ERV는 **분배기 1대만** 주기적으로 폴링:
1. ERV → 분배기 `CMD_SYSTEM(0x10)` (전원/모드/풍량 + 실별 댐퍼·LED 타겟) → 분배기 `RSP_ALLROOM_STATUS(0x90)` (전 실 댐퍼·RPM·LED·룸컨명령·에러)
2. ERV → 분배기 `POLL_SENSOR(0x12)` → 분배기 `RSP_ALLROOM_SENSOR(0x92)` (전 실 센서)
3. ERV가 센서로 **부하점수·집중/분산 계산**(사양서 10~11P) → 다음 `CMD_SYSTEM` 의 실별 댐퍼/LED/풍량 타겟에 반영
4. 룸컨 조작은 `RSP_ALLROOM_STATUS.rcCmdFlags`(+`addModeReq`) 로 ERV에 보고 → ERV 수용 → 다음 `CMD_SYSTEM` 으로 반영
5. **부가모드(3.8)** : 룸컨에서 스마트수면/쾌적조리/안심회복 토글 → ERV가 해당 시나리오 로직 수행(댐퍼·풍량 타겟 조정) → `CMD_SYSTEM.addMode` 로 현재 상태 회신(룸컨 표시)
6. **후드 연동(3.9)** : ERV가 HOOD-485로 후드 ON 감지 → (쾌적조리 활성 시) ERV 환기·3단 급기 동작 → `CMD_SYSTEM.hood` 로 후드 상태를 분배기·룸컨에 전달. 후드 OFF 시 이전 모드 복귀
7. 통신 단절 : 분배기가 실별 통신에러 비트(3.6)를 set 해 ERV에 보고, 재연결 시 clear
### 폴링 시간 (1회 = 300ms 가정)
| 버스 | 폴링 대상 | 1주기 |
|------|-----------|-------|
| **상위 (ERV↔분배기)** | 2회 (CMD_SYSTEM + POLL_SENSOR) | **600 ms** |
| 하위 (분배기↔실) | 17회(SA6+RA6+룸컨5) — **로컬에서 병렬 진행** | 분배기 내부에서 순환(ERV와 무관) |
> Rev 2.0 은 ERV가 17대를 직접 폴링 → 1주기 **5.1초**.
> Rev 3.0 은 ERV 입장에서 **0.6초**면 전 실 상태를 받는다. 하위 루프는 분배기가 별도로 빠르게 순환하므로 ERV 주기와 분리된다. → **갱신 약 8배 빨라지고 ERV 부하 격감.**
---
## 7. 펌웨어 반영 메모
- **분배기 펌웨어(Nano100)** : 신규. UART1(`SA485`, PB.4/PB.5)=하위 로컬 마스터, UART2(`M485`, PA.8/PA.9)=상위 슬레이브. MUX(SA_MUX_A/B/C/EN)로 채널 선택, DIR(SA485_DIR_01~05) 채널별. 74HC595(LED_DS/SCK/LCK)는 **포트별 SA/RA 통신상태 표시 LED** 구동(진단용). 방 조명 LED는 RA 디퓨저가 자체 점등하므로 ledDim 명령만 중계.
- **ERV 펌웨어** : `My_Uart.c` 의 17대 직접 폴링 → **분배기 1대 상위 프로토콜**로 교체. 자동로직(부하점수·집중/분산)은 ERV에 유지.
- **`My_RJ2.c`(DL 룸컨 232)는 변경하지 않는다.**
- CRC : 기존 `CRC16()`(MODBUS) 공유, 빅엔디안(Hi→Lo).
- 에러코드 `uint32_t` (방4 비트 수용).
---
## 8. 송수신 예제
> 모든 프레임 CRC는 **STX 제외 `CMD~PAYLOAD`** 구간 CRC-16/MODBUS(빅엔디안)의 실제 계산값.
> 예시 : runMode=`0x02`(자동), fan=`2`(중), addMode=`0x02`(쾌적조리), hood=`0x03`(연동ON+가동중), 댐퍼 `0xB4`=열림/`0x00`=닫힘/`0xFF`=없음, 온·습도 ×10. 폴링 1회=300ms.
### 8-A. 상위 버스 (ERV ↔ 분배기)
**① ERV → 분배기 : 전원ON·자동·풍량2·쾌적조리·후드가동 + 실별 댐퍼/LED 타겟** — `CMD_SYSTEM(0x10)` *(t=0~300ms)*
```
[TX] AA 10 2E | 01 01 02 02 02 03 00 00000000 0096 00DC 05 | <실1..5 타겟 6B> | AA 01
CMD LEN node pw md fan add hood rsv err 외15℃ 내22℃ rooms=5
↑쾌적조리 ↑후드연동ON+가동
실1(거실): 01 B4 B4 B4 B4 05 (SA1·SA2·RA1·RA2 열림, RA조명 LED 5)
실2(방1) : 02 B4 FF B4 FF 04
실3(방2) : 03 00 FF 00 FF 00 (댐퍼 닫힘, LED OFF)
실4(방3) : 04 B4 FF B4 FF 06
실5(방4) : 05 B4 FF B4 FF 03
```
**② 분배기 → ERV : 전 실 상태 집계** — `RSP_ALLROOM_STATUS(0x90)`
```
[RX] AA 90 5D | 01 00 02 00000000 05 | <실1..5 상태 17B> | C5 31
node bunSt addModeReq=02 err rooms=5
실1(거실): 01 B4 B4 B4 B4 0352 0334 05 00 01 02 02 00 00 00
roomNo SA1 SA2 RA1 RA2 saRpm=850 raRpm=820 ledDim | rcFlags pw md fan rsv hu fr
실2(방1) : 02 B4 FF B4 FF 0348 032A 04 00 01 02 02 00 00 00
실3(방2) : 03 00 FF 00 FF 0000 0000 00 00 01 02 02 00 00 00
실4(방3) : 04 B4 FF B4 FF 034D 032F 06 00 01 02 02 00 00 00
실5(방4) : 05 B4 FF B4 FF 0350 0332 03 00 01 02 02 00 00 00
```
**③ ERV → 분배기 : 센서 요청 / 분배기 응답** — `POLL_SENSOR(0x12)``RSP_ALLROOM_SENSOR(0x92)` *(t=300~600ms)*
```
[TX] AA 12 01 | 01 | <CRC>
[RX] AA 92 61 | 01 05 | <실1..5 센서 19B> | DC 05
실1(거실): 01 0005 0008 0009 000B 01C2 00DC 0064 0001 028A
roomNo pm1 pm2.5 pm4 pm10 습45.0% 온22.0℃ voc100 nox1 co2=650
실2(방1) : 02 0007 000C 000D 0012 01C4 00DD 0082 0001 02D0 (co2=720)
실3(방2) : 03 0004 0006 0007 0009 01C0 00DC 005A 0001 0262 (co2=610)
실4(방3) : 04 0009 0014 0016 001C 01C7 00DB 00A0 0002 032A (co2=810)
실5(방4) : 05 0005 0007 0008 000A 01C1 00DC 005F 0001 0280 (co2=640)
```
> ERV는 ②③으로 **전 실 상태+센서를 0.6초만에** 확보 → 부하점수·집중/분산 계산 → 다음 `CMD_SYSTEM` 타겟 갱신.
### 8-B. 하위 버스 (분배기 ↔ 디퓨저/룸컨) — 분배기 로컬 루프
**거실 RA1 디퓨저 제어/폴링**`LCMD_DIFFUSER(0x20)``LRSP_DIFFUSER(0xA0)` (RA = 조명 LED 보유)
```
[TX] AA 20 09 | 20 01 01 | 01 02 02 05 B4 00 | 6E 2B (RA,거실,1 / power mode fan led=5 dmp=B4 reset=0)
[RX] AA A0 10 | 20 01 01 | 01 02 02 05 B4 0352 00000000 0117 | ... (led현재5, dmp B4, rpm850, err0, ver1.23)
```
> SA 디퓨저는 LED가 없으므로 `ledDim=0`. 예) 거실 SA1 TX: `AA 20 09 10 01 01 01 02 02 00 B4 00 6E 6F` → RX `AA A0 10 10 01 01 01 02 02 00 B4 03 52 00 00 00 00 01 17 B9 17`.
**거실 RA1 디퓨저 센서**`LRSP_DIFFUSER_SENSOR(0xA1)`
```
[RX] AA A1 19 20 01 01 00 05 00 08 00 09 00 0B 01 C2 00 DC 00 64 00 01 02 8A 00 00 00 00 58 AE
(RA,거실,1) pm1=5 pm2.5=8 pm4=9 pm10=11 습45.0% 온22.0℃ voc100 nox1 co2=650 err0
```
**거실 룸컨 폴링**`LPOLL_ROOMCON(0x21)``LRSP_ROOMCON(0xB0)`
```
[TX] AA 21 12 30 01 01 01 02 02 02 03 00 00 00 00 00 00 96 00 DC 00 92 FA
(ERV상태 전달: 자동·풍량2·쾌적조리(02)·후드연동ON+가동(03))
[RX] AA B0 0D 30 01 01 80 01 02 02 00 00 00 02 01 10 34 4D
cmdFlags=80(부가모드 변경) ... addMode=02(쾌적조리 토글) ver0x0110
```
> 룸컨이 부가모드(쾌적조리)를 토글하면 `cmdFlags` bit7=1·`addMode`=0x02 로 보고 → 분배기가 상위 `RSP_ALLROOM_STATUS.addModeReq`·`rcCmdFlags`에 실어 ERV에 전달 → ERV가 후드연동 운전 수행.
---
> 본 문서는 2-Tier 재정의 초안(Rev 3.0)이다. 분배기/디퓨저/룸컨 펌웨어 담당과 CMD 코드·필드 세부값을 상호 합의하여 확정한다.