Files
HECO2/Protocol/각실제어/각실제어_내부프로토콜_Rev2.0_CMD.md
T
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

490 lines
23 KiB
Markdown
Raw 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 2.0, CMD 기반)
> 휴벤ECO(ERV) ↔ 각실분배기 ↔ 디퓨저 ↔ 룸컨 **내부 RS-485 통신** 규격
>
> 본 문서는 `Protocol/수정_Each_Room_Jushin_protocol_RS485_Rev1.2` (주신전자) 와
> 펌웨어 `program/User/My_Uart.c` (각실분배기/디퓨저 폴링) 구현을 기반으로,
> **CMD 기반으로 단순화·확장**하여 새로 정의한 규격이다.
> (DL 룸컨 232 프로토콜 `My_RJ2.c` 는 DL 사양으로 본 규격과 무관 — 변경하지 않는다.)
- **물리계층** : RS-485, **115200 bps, 8 Data, None Parity, 1 Stop (N81)**
- **토폴로지** : 1 Master(메인보드) ↔ N Slave(디퓨저/룸컨), 메인보드 폴링 방식
- **대상 시스템** : 사양서 5페이지(힘펠 배선도) 구성 = **거실 + 방1~4 (5실)**, 각 실 룸컨
- 디퓨저 : 거실 SA 2·RA 2, 방1~4 각 SA 1·RA 1 → **SA 디퓨저 6 + RA 디퓨저 6**, 룸컨 5
---
## 0. 무엇이 바뀌었나 (Rev 1.2 → Rev 2.0)
| 구분 | 기존 (Rev 1.2) | 개선 (Rev 2.0) |
|------|----------------|----------------|
| 패킷 식별 | `VSP Mode` 값(0x00/0x11/0x12/0x01~03/0x10)에 따라 **같은 byte 위치의 의미가 계속 바뀜** | **CMD 1바이트로 패킷 종류 고정** → 한 패킷은 항상 같은 레이아웃 |
| 거실 공기질 | 별도 모드 0x11 / 0x12 로 방을 쪼개서 전송 | **방별 센서 패킷 1종으로 통합**, ROOM 필드로 구분 |
| 길이 | 29/39 byte 가변, 위치로 추정 | **LEN 필드 명시** → 파싱 단순 |
| 장치 주소 | ID1(종류)+ID2(번호) 혼용, 거실=5 등 불규칙 | **DEV / ROOM / IDX 3필드**로 직관적 주소화 |
| 에러코드 | **16비트 전부 소진** → 방4 추가 불가 (한계) | **32비트로 확장** → 방4 + 향후 여유 |
| 확장성 | 4실 고정 | **5실(거실+방1~4) + 룸컨 5 / SA·RA 디퓨저 각 6** 명시 |
| 역할 정의 | 명령/상태 방향이 패킷마다 섞여 모호 | **버스 마스터=ERV(폴링) / 명령 주체=룸컨 / 실행=ERV→디퓨저** 로 명확화 |
> **제어 권한 정리** : 사용자는 룸컨에서 전원·모드·풍량·예약·필터리셋과 VSP 풍량 테이블을 설정한다.
> 룸컨은 버스상 Slave이므로 이 명령들을 ERV 폴링에 대한 응답(`CMD_ROOMCON`/`CMD_VSP_SET`)으로 올린다.
> ERV는 명령을 받아 분배기를 통해 디퓨저 댐퍼·풍량·LED를 제어하고, 센서값을 읽어 룸컨에 전달한다.
---
## 1. 공통 프레임
```
+------+------+------+------------------+--------+--------+
| STX | CMD | LEN | PAYLOAD[LEN] | CRC_H | CRC_L |
+------+------+------+------------------+--------+--------+
0xAA 1B 1B LEN bytes 16-bit CRC
```
| 필드 | 크기 | 설명 |
|---------|------|------|
| STX | 1 | 고정 `0xAA` |
| CMD | 1 | 명령/응답 코드 (2장) |
| LEN | 1 | PAYLOAD 바이트 수 (0~255) |
| PAYLOAD | LEN | CMD 별 데이터 (3·4장) |
| CRC | 2 | **CRC-16/MODBUS** (poly 0xA001, init 0xFFFF), **CMD~PAYLOAD** 까지, **빅엔디안(CRC_H 먼저)** |
- 모든 멀티바이트 수치는 **빅엔디안(상위 바이트 먼저)**. (CRC 포함, 펌웨어 `My_Uart.c` 관례 유지)
- 프레임 구분 : `STX(0xAA)` 탐색 → `LEN` 으로 길이 확보 → `CRC` 검증.
- 수신 타임아웃(예: 50ms) 내 미완성 프레임은 폐기하고 STX 재탐색.
> **CRC 계산** : `My_Uart.c` 의 `CRC16()` (MODBUS 룩업테이블) 동일. 결과 16비트를 `CRC_H = (crc>>8)`, `CRC_L = (crc&0xFF)` 순으로 전송.
---
## 2. 명령 코드 (CMD)
**버스 레벨과 제어 권한을 구분해서 이해해야 한다.**
- **버스 마스터 = ERV(메인보드)** : 모든 통신을 ERV가 폴링한다. 룸컨/디퓨저는 폴링을 받아야만 송신하는 Slave.
- **제어 권한(명령 발생) = 룸컨** : 사용자가 룸컨에서 전원/모드/풍량/예약/필터리셋, **VSP 풍량 테이블 설정·저장**을 한다.
룸컨은 Slave이므로 이 명령들을 ERV 폴링에 대한 **응답에 실어** ERV로 보낸다 (룸컨 → ERV).
- **실행 = ERV** : 룸컨 명령을 받아 분배기를 통해 **디퓨저 댐퍼 개폐·풍량·LED를 제어**하고, **센서값을 읽어 룸컨에 전달**한다.
즉 데이터 흐름은: **룸컨(명령) → ERV(실행) → 디퓨저(댐퍼/센서) → ERV(센서수집) → 룸컨(표시)**.
CMD 상위 비트로 송신 방향을 구분한다. **0x10~0x7F = ERV(Master) 송신**, **0x90~0xFF = Slave 송신(응답)**.
### 2.1 ERV(메인보드, Master) 송신
| CMD | 이름 | 대상 | PAYLOAD | 설명 |
|------|----------------------|--------|---------|------|
| 0x10 | `CMD_DIFFUSER_CTRL` | 디퓨저 | 4.1 | **ERV가 디퓨저 제어**(댐퍼각/풍량/LED/리셋) + 폴링. ERV가 제어 주체 |
| 0x20 | `POLL_ROOMCON` | 룸컨 | 4.3 | ERV가 룸컨 폴링 + **표시용 데이터 전달**(ERV 동작상태/해당 실 공기질/에러/온도). 명령 수용 결과 echo |
| 0x30 | `RSP_VSP_STATUS` | 룸컨 | 4.5 | 룸컨 요청에 대한 **현재 VSP 풍량 테이블 값 회신**(룸컨 표시용) |
| 0x40 | `POLL_SPEC` | 공통 | 없음 | 장치 사양/버전 요청 |
### 2.2 Slave(룸컨/디퓨저) 송신 = 명령/상태 보고
| CMD | 이름 | 송신자 | PAYLOAD | 설명 |
|------|------------------------|--------|---------|------|
| 0xA0 | `CMD_ROOMCON` | 룸컨 | 4.4 | **룸컨이 사용자 명령 전달**: 전원/모드/풍량/예약/히터·UV/필터리셋 (0x20 응답) |
| 0xB0 | `CMD_VSP_SET` | 룸컨 | 4.6 | **룸컨이 VSP 풍량 테이블 설정·저장** + 장치 개수 설정 (0x20 응답, VSP 세팅모드) |
| 0x90 | `RSP_DIFFUSER_STATUS` | 디퓨저 | 4.2 | 디퓨저 댐퍼각/공기질/RPM/에러/버전 (0x10 응답) |
| 0x91 | `RSP_DIFFUSER_SENSOR` | 디퓨저 | 4.7 | 통합공기질 센서값(PM/온습도/VOC/NOx/CO2) (방별) |
| 0xC0 | `RSP_SPEC` | 공통 | 4.8 | 사양/버전 (0x40 응답) |
> 모든 패킷은 대상 장치 주소(DEV/ROOM/IDX)를 선두에 싣고, 응답은 이를 그대로 에코한다.
> `CMD_ROOMCON`(0xA0)·`CMD_VSP_SET`(0xB0)은 이름은 "CMD"지만 버스상으로는 **룸컨이 ERV 폴링(0x20)에 응답하는 형태**로 전송된다. (룸컨이 명령 주체이기 때문)
---
## 3. 공통 값 정의
### 3.1 장치 주소 (DEV / ROOM / IDX)
각 PAYLOAD 선두 3바이트는 항상 장치 주소다.
| 필드 | 크기 | 값 | 의미 |
|------|------|----|------|
| DEV | 1 | `0x10`=SA 디퓨저, `0x20`=RA 디퓨저, `0x30`=룸컨 | 장치 종류 |
| ROOM | 1 | `1`=거실, `2`=방1, `3`=방2, `4`=방3, `5`=방4 | 실 번호 |
| IDX | 1 | `1`~ | 같은 실·같은 종류 장치의 일련번호 (거실 SA·RA는 `1`,`2`) |
**5실 디바이스 맵 (힘펠 배선도 기준 — SA 6 / RA 6 / 룸컨 5)**
| 실 | ROOM | SA 디퓨저 | RA 디퓨저 | 룸컨 |
|----|------|-----------|-----------|------|
| 거실 | 1 | (0x10,1,1) 거실급기1 · (0x10,1,2) 거실급기2 | (0x20,1,1) 거실배기1 · (0x20,1,2) 거실배기2 | (0x30,1,1) |
| 방1 | 2 | (0x10,2,1) | (0x20,2,1) | (0x30,2,1) |
| 방2 | 3 | (0x10,3,1) | (0x20,3,1) | (0x30,3,1) |
| 방3 | 4 | (0x10,4,1) | (0x20,4,1) | (0x30,4,1) |
| 방4 | 5 | (0x10,5,1) | (0x20,5,1) | (0x30,5,1) |
> 방1~4 구성은 모두 동일(SA 1 · RA 1 · 룸컨 1). 거실만 SA·RA 각 2대.
### 3.2 전원 (Power)
| 값 | 의미 |
|----|------|
| 0x00 | OFF |
| 0x01 | ON |
### 3.3 운전모드 (RunMode)
| 값 | 의미 | 펌웨어 매핑 |
|----|------|-------------|
| 0x01 | 수동(환기) | MODE_VENTILATION |
| 0x02 | 자동 | MODE_AUTO |
| 0x04 | 바이패스 | MODE_BYPASS |
| 0x08 | 공기청정 | MODE_AIRCLEAN |
### 3.4 풍량 (FanSpeed)
| 값 | 의미 |
|----|------|
| 0x00 | OFF/정지 |
| 0x01 | 1단 (약) |
| 0x02 | 2단 (중) |
| 0x03 | 3단 (강) |
| 0x04 | 4단 (터보) |
> 자동/공청 모드에서는 메인보드 로직(부하점수)이 단수를 결정하므로 디퓨저로 보내는 풍량은 계산 결과값.
### 3.5 LED 밝기 (LedDim)
| 값 | 의미 |
|----|------|
| 0x00 | OFF |
| 0x01~0x0A | 1~10단 (10단 최대) |
> 월패드/스마트스위치 UI는 0~9 단계. 0=OFF 포함 시 0~10으로 매핑.
### 3.6 댐퍼 각도 (DamperAngle)
| 값 | 의미 |
|----|------|
| 0x00 | 0° (닫힘) |
| 0x00~0xB4 | 0~180° (0xB4 = 180° 완전개방) |
### 3.7 에러코드 (ErrorCode, **u32 비트맵** — 확장)
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x00000001 | 필터 청소 |
| 1 | 0x00000002 | 필터 교체 |
| 2 | 0x00000004 | 소자 교체 |
| 3 | 0x00000008 | 온도센서 에러 |
| 4 | 0x00000010 | 장비보호 모드 |
| 5 | 0x00000020 | EA 팬 에러 |
| 6 | 0x00000040 | 간헐운전 모드 |
| 7 | 0x00000080 | SA 팬 에러 |
| 8 | 0x00000100 | 통합센서 에러 — 거실 |
| 9 | 0x00000200 | 통합센서 에러 — 방1 |
| 10 | 0x00000400 | 통합센서 에러 — 방2 |
| 11 | 0x00000800 | 통합센서 에러 — 방3 |
| 12 | 0x00001000 | **통합센서 에러 — 방4 (신규)** |
| 16 | 0x00010000 | 통신 에러 — 거실 |
| 17 | 0x00020000 | 통신 에러 — 방1 |
| 18 | 0x00040000 | 통신 에러 — 방2 |
| 19 | 0x00080000 | 통신 에러 — 방3 |
| 20 | 0x00100000 | **통신 에러 — 방4 (신규)** |
> 비트 13~15, 21~31 은 향후 확장용 예약.
---
## 4. PAYLOAD 상세
> 모든 PAYLOAD는 `[DEV][ROOM][IDX]` 3바이트로 시작. (3.1)
> `u16` 은 빅엔디안. 아래 off 는 PAYLOAD 내 상대 오프셋.
### 4.1 `CMD_DIFFUSER_CTRL` (0x10, Master→디퓨저)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x10(SA) 또는 0x20(RA) |
| 3 | 1 | power | 3.2 |
| 4 | 1 | runMode | 3.3 |
| 5 | 1 | fanSpeed | 3.4 |
| 6 | 1 | ledDim | 3.5 (SA 디퓨저만 유효) |
| 7 | 1 | dmpAngle | 3.6 (해당 포트의 댐퍼 목표각) |
| 8 | 1 | dmpReset | 0=정상 / 1=댐퍼 초기화 |
| 9 | 1 | reserveHour | 예약 정지 0~8시간 (0=없음) |
LEN = 10.
### 4.2 `RSP_DIFFUSER_STATUS` (0x90, 디퓨저→Master)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | 요청 에코 |
| 3 | 1 | power | 현재 전원 |
| 4 | 1 | runMode | 현재 운전모드 |
| 5 | 1 | fanSpeed | 현재 풍량 |
| 6 | 1 | ledDim | 현재 LED 밝기 |
| 7 | 1 | dmpAngle | 현재 댐퍼 각도 (3.6) |
| 8 | 2 | rpm | 해당 팬 실측 RPM (u16) |
| 10 | 4 | errorCode | 3.7 (u32) |
| 14 | 2 | version | 예) 0x0117 = Ver 1.23 |
LEN = 16.
### 4.3 `POLL_ROOMCON` (0x20, ERV→룸컨)
ERV가 룸컨을 폴링하면서 **룸컨 화면에 표시할 데이터**(ERV 동작상태·에러·온도)를 전달하고,
직전에 받은 룸컨 명령의 **수용 결과(ackFlags)** 를 에코한다.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | power | ERV 현재 전원 (3.2) |
| 4 | 1 | runMode | ERV 현재 운전모드 (3.3) |
| 5 | 1 | fanSpeed | ERV 현재 풍량 (3.4) |
| 6 | 1 | autoState | 0=분산, 1=집중 (자동모드) |
| 7 | 1 | reserveRemain | 예약 잔여 시간(hour) |
| 8 | 4 | errorCode | ERV 현재 에러 통보 (3.7, u32) |
| 12 | 2 | outTemp | 외기온도 ×10 (signed, ℃) |
| 14 | 2 | inTemp | 내기온도 ×10 (signed, ℃) |
| 16 | 1 | ackFlags | 직전 룸컨 명령 수용 비트(4.4 cmdFlags 동일 배치) |
LEN = 17.
### 4.4 `CMD_ROOMCON` (0xA0, 룸컨→ERV) — **룸컨이 명령 주체**
사용자가 룸컨에서 조작한 명령을 ERV에 전달한다. `cmdFlags`**이번에 실제로 바꾼 항목만** 표시한다(나머지는 무시).
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30, ERV 폴링(0x20)에 대한 응답으로 송신 |
| 3 | 1 | cmdFlags | bit0 power, bit1 runMode, bit2 fanSpeed, bit3 reserveHour, bit4 heaterUV, bit5 filterReset, bit6 ledDim (1=이 필드 명령 유효) |
| 4 | 1 | power | 3.2 |
| 5 | 1 | runMode | 3.3 |
| 6 | 1 | fanSpeed | 3.4 |
| 7 | 1 | reserveHour | 0~8시간 |
| 8 | 1 | heaterUV | bit0=히터, bit4=UV (1=ON) |
| 9 | 1 | filterReset | 1=필터 리셋 |
| 10 | 1 | ledDim | 3.5 (해당 실 디퓨저 LED 밝기) |
| 11 | 2 | version | 룸컨 버전 |
LEN = 13.
> ERV는 받은 명령을 실행(분배기→디퓨저 제어)하고, 다음 `POLL_ROOMCON(0x20)`의 `ackFlags`·동작상태로 결과를 회신한다.
### 4.5 `RSP_VSP_STATUS` (0x30, ERV→룸컨)
룸컨이 현재 VSP 값을 요청(`CMD_VSP_SET` 의 reqStatus=1)하면, ERV가 **저장된 현재 VSP 풍량 테이블**을 회신한다(룸컨 표시용). 레이아웃은 4.6과 동일(끝의 save/장치개수 필드는 제외, vspSelect로 어떤 모드값인지 표시).
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | vspSelect | 회신하는 모드 (`1`=환기/`2`=공청/`3`=바이패스) |
| 4 | 10 | sa1,ea1 … sa5,ea5 | SA/EA 1~5단 VSP (각 1B) |
| 14 | 2 | rpmRefMid | 중(2단) RPM 기준 |
| 16 | 2 | rpmDeltaMid | 중(2단) RPM 허용편차 |
| 18 | 2 | rpmRefHigh | 강(3단) RPM 기준 |
| 20 | 2 | rpmDeltaHigh | 강(3단) RPM 허용편차 |
LEN = 22.
### 4.6 `CMD_VSP_SET` (0xB0, 룸컨→ERV) — **VSP 설정·저장 주체는 룸컨**
룸컨에서 VSP 풍량 테이블을 한 모드씩(vspSelect) 설정하고 ERV에 저장 요청. 폴링할 장치 개수도 함께 설정.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30, ERV 폴링(0x20)에 대한 응답으로 송신 |
| 3 | 1 | vspSelect | `0`=None, `1`=환기, `2`=공청, `3`=바이패스 |
| 4 | 1 | sa1 | SA 1단 VSP |
| 5 | 1 | ea1 | EA 1단 VSP |
| 6 | 1 | sa2 | SA 2단 |
| 7 | 1 | ea2 | EA 2단 |
| 8 | 1 | sa3 | SA 3단 |
| 9 | 1 | ea3 | EA 3단 |
| 10 | 1 | sa4 | SA 4단 |
| 11 | 1 | ea4 | EA 4단 |
| 12 | 1 | sa5 | SA 5단 |
| 13 | 1 | ea5 | EA 5단 |
| 14 | 2 | rpmRefMid | 중(2단) RPM 기준 (환기/공청만) |
| 16 | 2 | rpmDeltaMid | 중(2단) RPM 허용편차 |
| 18 | 2 | rpmRefHigh | 강(3단) RPM 기준 |
| 20 | 2 | rpmDeltaHigh | 강(3단) RPM 허용편차 |
| 22 | 1 | roomconNum | 폴링할 룸컨 수 (1~5) |
| 23 | 1 | saDiffuserNum | 폴링할 SA 디퓨저 수 (2~6) |
| 24 | 1 | raDiffuserNum | 폴링할 RA 디퓨저 수 (2~6) |
| 25 | 1 | modbusId | 외부 홈넷 연동용 ID (선택) |
| 26 | 1 | save | 0=저장안함, 1=EEPROM 저장 |
| 27 | 1 | reqStatus | 1=현재 VSP 값 회신 요청(ERV가 `RSP_VSP_STATUS`로 응답) |
LEN = 28.
### 4.7 `RSP_DIFFUSER_SENSOR` (0x91, 디퓨저→Master)
통합공기질 센서(SEN66) 1실분. 기존 0x11/0x12 분리 모드를 **이 패킷 1종**으로 대체.
| off | 크기 | 필드 | 단위/비고 |
|-----|------|------|-----------|
| 0 | 3 | DEV/ROOM/IDX | 센서 부착 디퓨저(통상 RA, DEV=0x20) |
| 3 | 2 | pm1p0 | ㎍/㎥ |
| 5 | 2 | pm2p5 | ㎍/㎥ |
| 7 | 2 | pm4p0 | ㎍/㎥ |
| 9 | 2 | pm10p0 | ㎍/㎥ |
| 11 | 2 | humidity | %RH ×10 |
| 13 | 2 | temperature | ℃ ×10 (signed) |
| 15 | 2 | voc | TVOC index |
| 17 | 2 | nox | NOx index |
| 19 | 2 | co2 | ppm |
| 21 | 4 | errorCode | 센서/통신 에러 (3.7) |
LEN = 25.
### 4.8 `RSP_SPEC` (0xC0)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | |
| 3 | 2 | version | 펌웨어 버전 |
| 5 | 1 | deviceType | 장치 타입 코드 |
| 6 | 1 | capability | bit0=히터, bit1=UV, bit2=후드연동 … |
LEN = 7.
---
## 5. 동작 시나리오 (폴링)
ERV가 버스 마스터로서 **룸컨 → 디퓨저 순으로 라운드로빈 폴링**하고, 명령은 룸컨이 응답에 실어 올린다.
1. **룸컨 폴링**
- ERV → 룸컨 : `POLL_ROOMCON(0x20)` (ERV 동작상태·해당 실 공기질·온도·에러 전달 + 직전 명령 ack)
- 룸컨 → ERV : 사용자가 조작했으면 `CMD_ROOMCON(0xA0)` (cmdFlags로 바뀐 항목 표시), VSP 설정중이면 `CMD_VSP_SET(0xB0)` 으로 응답
2. **디퓨저 폴링 (ERV가 제어 주체)**
- ERV → 디퓨저 : `CMD_DIFFUSER_CTRL(0x10)` (댐퍼각/풍량/LED 지시)
- 디퓨저 → ERV : `RSP_DIFFUSER_STATUS(0x90)`, 센서 부착 디퓨저는 이어서 `RSP_DIFFUSER_SENSOR(0x91)`
3. **명령 처리 흐름** : 룸컨 명령(0xA0) 수신 → ERV가 운전모드/풍량 결정 → 각 디퓨저에 `CMD_DIFFUSER_CTRL(0x10)`로 댐퍼 개폐·풍량 지시 → 결과를 다음 `POLL_ROOMCON(0x20)`의 ackFlags·동작상태로 룸컨에 회신.
4. **자동/공청 모드** : ERV가 각 실 센서(0x91)로 부하점수·집중/분산 계산 → 디퓨저 댐퍼각·풍량을 `CMD_DIFFUSER_CTRL`로 지시 (사양서 10~11P 로직).
5. **VSP 시운전** : 룸컨이 `CMD_VSP_SET(0xB0)`으로 단별 VSP·RPM·장치개수 설정(save=1 시 ERV가 EEPROM 저장), reqStatus=1이면 ERV가 `RSP_VSP_STATUS(0x30)`로 현재값 회신.
6. **통신 단절** : 폴링 타임아웃 N회 시 ERV가 해당 실 통신에러 비트(3.7 bit16~20) set, 재연결 시 clear.
---
## 6. 펌웨어 반영 메모
- 대상 파일 : `program/User/My_Uart.c` (SC1, 각실분배기/디퓨저), `bunbaegi_parsing()` / `Bunbaegi_Polling()` 를 CMD 기반으로 교체.
- **`My_RJ2.c` (DL 룸컨 232) 는 변경하지 않는다** — DL 사양 별도 유지.
- CRC : 기존 `CRC16()` (MODBUS) 그대로 사용, 전송은 빅엔디안(Hi→Lo).
- 센서/디퓨저 배열은 현행 `[7]` (index 1~6) 유지 가능하나, ROOM(1~5)+IDX 매핑 테이블 1개로 주소→배열 변환.
- 에러코드는 `uint16_t Err_Code`**`uint32_t`** 로 확장 (방4 비트 수용).
---
## 7. 송수신 예제 — 거실 룸컨이 전 실 상태 표시
**목표** : 거실 룸컨에서 모든 방 디퓨저(SA/RA) 댐퍼·LED·센서 + ERV 동작상태(모드/풍량/예약)를 표시.
**전제** : 거실 룸컨은 디퓨저를 직접 못 읽는다. 버스 마스터는 ERV 하나뿐이므로 항상 2단계.
```
① 수집 : ERV ──폴링──> 각 디퓨저(SA/RA) ──상태/센서──> ERV (캐싱)
② 표시 : ERV ──전달──> 거실 룸컨 (화면 표시)
```
> 아래 모든 프레임의 CRC는 **STX(0xAA) 제외, `CMD~PAYLOAD` 구간**에 대한 CRC-16/MODBUS 결과를 빅엔디안(Hi,Lo)으로 붙인 실제 값이다.
> 예시 값 : runMode=`0x02`(자동), fanSpeed=`2`, 댐퍼 `0xB4`=180°(열림)/`0x00`=닫힘, 온도·습도 ×10.
> **폴링 시간** : 1회 폴링(TX 요청 → RX 응답)을 **300ms**로 가정한다. (각 [TX]/[RX] 쌍 = 300ms)
### ① 수집 단계 — ERV가 각 디퓨저를 라운드로빈 폴링
ERV가 `거실SA1 → 거실SA2 → 거실RA1 → 거실RA2 → 방1SA → 방1RA → … → 방4RA` 순으로 폴링. 대표 예 (괄호는 누적시간):
**거실 SA1 디퓨저 폴링/제어**`CMD_DIFFUSER_CTRL(0x10)` *(t=0 ~ 300ms)*
```
[TX] AA 10 0A | 10 01 01 | 01 02 02 05 B4 00 00 | E4 61
STX CMD LEN DEV ROOM IDX power runMode fan led dmp reset reserve
(SA,거실,1) ON 02(자동) 2 5 B4 0 0
```
```
[RX] AA 90 10 | 10 01 01 | 01 02 02 05 B4 03 52 00 00 00 00 01 17 | A6 08
└RSP_DIFFUSER_STATUS power mode fan led dmp rpm=0352(850) err=0(4B) ver=0117
```
**거실 RA1 디퓨저 폴링** — 상태 `RSP_DIFFUSER_STATUS(0x90)` + 센서 `RSP_DIFFUSER_SENSOR(0x91)` *(t=600 ~ 900ms)*
```
[RX] AA 91 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 | E8 AF
└센서 (RA,거실,1) pm1=5 pm2.5=8 pm4=9 pm10=11 습45.0% 온22.0℃ voc100 nox1 co2=028A(650) err=0
```
> RA 디퓨저는 한 폴링 슬롯(300ms)에서 상태(0x90)+센서(0x91)를 함께 응답.
> RA2·방1~4 디퓨저도 같은 방식으로 폴링 → ERV가 전 실 댐퍼각/LED/RPM/센서를 모두 캐싱.
**ERV 동작상태를 거실 룸컨에 전달 (+ 룸컨 명령 수신)**`POLL_ROOMCON(0x20)` *(룸컨 폴링 슬롯, 각 300ms)*
```
[TX] AA 20 11 | 30 01 01 | 01 02 02 01 00 | 00 00 00 00 | 00 96 | 00 DC | 00 | B5 61
└ERV→룸컨 (룸컨,거실,1) power mode fan auto=1(집중) reserveRemain=0
err=0(4B) 외기15.0℃ 내기22.0℃ ack=0
[RX] (거실 룸컨이 조작했으면 CMD_ROOMCON(0xA0)/CMD_VSP_SET(0xB0)로 응답, 없으면 빈 응답)
```
### ② 표시 단계 — 전 실 집계 전달
거실 룸컨이 전 실 디퓨저·센서를 한 화면에 표시하려면, ERV가 ①에서 모은 값을 집계해 거실 룸컨에 전달해야 한다.
> **참고(본 규격 미반영 제안)** : 아래 `CMD_ALLROOM_STATUS(0x21)` 는 "전 실 집계"용으로 검토한 예시 패킷이다.
> 정식 채택은 보류 상태이며, 필요 시 별도 협의 후 2·4장에 추가한다.
**헤더(9B)** + **실별 블록(18B) × 5실** :
| 헤더 off | 필드 | 실 블록 off | 필드 |
|---|---|---|---|
| 0~2 | 룸컨 주소(30·01·01) | +0 | roomNo |
| 3 | ERV power | +1,+2 | SA댐퍼1·2 (`0xFF`=없음) |
| 4 | ERV runMode | +3,+4 | RA댐퍼1·2 |
| 5 | ERV fanSpeed | +5 | LED 밝기 |
| 6 | 예약 잔여(h) | +6,+7 | PM2.5 |
| 7 | autoState | +8,+9 | PM10 |
| 8 | roomCount(=5) | +10,+11 | CO2 |
| | | +12,+13 | VOC |
| | | +14,+15 | 온도 ×10 |
| | | +16,+17 | 습도 ×10 |
```
[TX] AA 21 63 | 30 01 01 01 02 02 00 01 05 | <실1..실5 블록> | D9 F4
└CMD_ALLROOM 헤더(LEN=0x63=99) 거실은 SA·RA 2개 모두 사용
실1(거실): 01 B4 B4 B4 B4 05 00 08 00 0B 02 8A 00 64 00 DC 01 C2 SA열림×2,RA열림×2,LED5,PM2.5=8,PM10=11,CO2=650,VOC=100,22.0℃,45.0%
실2(방1) : 02 B4 FF B4 FF 04 00 0C 00 12 02 D0 00 82 00 DD 01 C4 SA/RA 각1, slot2=FF
실3(방2) : 03 00 FF 00 FF 00 00 06 00 09 02 62 00 5A 00 DC 01 C0 댐퍼 닫힘, LED OFF
실4(방3) : 04 B4 FF B4 FF 06 00 14 00 1C 03 2A 00 A0 00 DB 01 C7
실5(방4) : 05 B4 FF B4 FF 03 00 07 00 0A 02 80 00 5F 00 DC 01 C1
```
> 전체 104 byte 1프레임으로 거실 룸컨이 **전 실 SA/RA 댐퍼·LED·센서 + ERV 모드/풍량/예약**을 모두 표시.
### 폴링 주기와 전체 시간 (1회 = 300ms)
5실 구성에서 ERV가 한 바퀴 도는 동안 폴링하는 장치:
| 장치 | 개수 | 폴링 시간 (×300ms) |
|------|------|--------------------|
| SA 디퓨저 (거실2 + 방1~4 각1) | 6 | 1,800 ms |
| RA 디퓨저 (거실2 + 방1~4 각1, 상태+센서 동시) | 6 | 1,800 ms |
| 룸컨 (거실 + 방1~4) | 5 | 1,500 ms |
| **합계 (1주기)** | **17** | **5,100 ms ≈ 5.1초** |
- 거실 룸컨 화면은 **약 5.1초마다 전 실 데이터가 1회 갱신**된다.
- 갱신을 더 빠르게 하려면 : 폴링 시간 단축(예: 200ms → 17×200 = 3.4초), 또는 폴링 대상 축소.
- `0x21` 집계 프레임은 거실 룸컨 폴링 슬롯 안에서 전달되므로 별도 시간이 추가되지 않는다.
```
[1 주기 = 5.1초]
SA1 SA2 RA1 RA2 | 방1SA 방1RA | 방2SA 방2RA | 방3SA 방3RA | 방4SA 방4RA | RC거실 RC방1 RC방2 RC방3 RC방4
└─거실 4슬롯─┘ └─방1 2─┘ └─방2 2─┘ └─방3 2─┘ └─방4 2─┘ └────── 룸컨 5슬롯 ──────┘
각 슬롯 300ms × 17 = 5,100ms
```
### 요약
| 단계 | 방향 | 패킷 | 역할 |
|------|------|------|------|
| ① | ERV→디퓨저 / 디퓨저→ERV | `0x10` / `0x90`,`0x91` | 전 실 댐퍼·LED·센서 수집 |
| ② | ERV→거실룸컨 | `0x20` | ERV 동작상태(모드/풍량/예약) 전달 |
| ② | ERV→거실룸컨 | `0x21` (미반영 제안) | 전 실 디퓨저·센서 집계 전달 |
---
> 본 문서는 내부 통신 재정의 초안(Rev 2.0)이다. 디퓨저/룸컨 펌웨어 담당(주신전자)과
> CMD 코드·필드 세부값을 상호 합의하여 확정한다.