요구사항 명세(SR) 학습 노트 목차

02. 파워윈도우 — 우선순위, 위치, 그리고 손가락

출처: SR §6.2 (6.2.1 기능 범위 및 요청 우선순위 / 6.2.2 윈도우 동작 허용 및 요청 제한 / 6.2.3 윈도우 구동 / 6.2.4 Anti-pinch 안전 보호 / 6.2.5 통신 오류 및 안전 동작 / 6.2.6 상태 및 HMI 제공) 관련 TBD: TBD-007(기구 스트로크·정의된 환기 위치), TBD-008(위치 확인 방식 및 센서 조합), TBD-009(Anti-pinch 감지 방식·임계값·보호 위치·반응시간), TBD-010(원격·원터치·자동 환기 기반 닫힘 허용 정책) 담당 노드: S32K144 Power Window Controller (모터를 직접 제어하는 유일한 노드 — §7.2)


0. 왜 이 절이 가장 길고 가장 엄격한가

이 시스템에서 사람을 물리적으로 다치게 할 수 있는 액추에이터는 윈도우 모터 하나다. 도어락은 손가락을 자르지 않고, 팬은 사람을 밀지 않으며, 조명은 화상을 입히지 않는다. 창문만이 힘으로 신체를 압박한다.

그래서 §6.2는 다른 절과 문법이 다르다.

다른 절§6.2.4
"새로운 자동 기능을 수행하지 않아야 한다" (수동적 억제)"진행 중인 윈도우 닫힘 동작을 즉시 정지해야 한다" (능동적 개입)
"신뢰할 수 없는 경우 시작하지 않아야 한다""통신 오류가 발생하더라도 유지해야 한다" (§6.2.5)

억제가 아니라 개입, 그리고 통신이 죽어도 살아남는 기능. 이 두 가지가 §6.2를 다른 모든 절과 구분한다.


1. §6.2.1 — 기능 범위 및 요청 우선순위

1-1. 요청은 네 곳에서 온다

  • 시스템은 전용 윈도우 스위치, 차량 내 HMI, 권한이 있는 원격 사용자 및 Predictive ClimateWindow 기반 자동 환기 기능에서 발생한 윈도우 제어 요청을 구분하여 처리해야 한다.
요청 출처물리 경로특징
전용 윈도우 스위치도어 트림 → Power Window Controller GPIO (로컬)통신을 타지 않는다. 가장 빠르고 가장 확실하다
차량 내 HMIESP32 → (TBD-001) → Central → CAN → PW Controller통신 2홉
권한이 있는 원격 사용자모바일 앱 → BLE/Wi-Fi → ESP32 → Central → CAN → PW통신 3홉 + 인증
Window 기반 자동 환기Function Controller(Predictive Climate) → Central → CAN → PW사용자 요청이 아니라 시스템 판단

**"구분하여 처리해야 한다"**가 첫 요구사항인 이유는, 이 네 출처가 뒤에서 전부 다르게 취급되기 때문이다. 우선순위도 다르고, 통신 오류 시 처리도 다르고, 허용 조건도 다르다. 구현에서 요청 구조체에 출처 필드가 반드시 있어야 한다는 뜻이다.

typedef enum {
    WIN_SRC_LOCAL_SWITCH = 0,   /* 전용 윈도우 스위치 — 최우선 */
    WIN_SRC_HMI          = 1,   /* 차량 내 HMI */
    WIN_SRC_REMOTE       = 2,   /* 권한 있는 원격 사용자 */
    WIN_SRC_AUTO_VENT    = 3,   /* Window 기반 자동 환기 — 최하위 */
} win_src_t;

typedef enum { WIN_CMD_OPEN, WIN_CMD_CLOSE, WIN_CMD_STOP } win_cmd_t;

typedef struct {
    win_src_t  src;
    win_cmd_t  cmd;
    bool       one_touch;     /* 원터치 여부 — §6.2.1 */
    uint32_t   rx_ms;         /* 수신 시각 — age 판정용 */
} win_req_t;

1-2. 명령은 세 가지다

  • 시스템은 윈도우 열림, 닫힘 및 정지 요청을 구분하여 처리해야 한다.
  • 시스템은 전용 윈도우 스위치에 의한 수동 조작 및 원터치 조작을 처리해야 한다.
  • 시스템은 차량 내 HMI 및 권한이 있는 원격 사용자의 유효한 원터치 윈도우 제어 요청을 처리해야 한다.

정지(STOP)가 독립된 명령이라는 게 중요하다. "열림도 닫힘도 아닌 상태"가 아니라 명시적 명령이다. 그래야 다음 요구사항이 성립한다.

  • 시스템은 정지 요청을 열림 또는 닫힘 요청보다 우선하여 처리해야 한다.

정지가 방향 명령보다 항상 이긴다. 사용자가 "멈춰"라고 했을 때 다른 요청이 그걸 덮어쓰면 안 된다. 안전 기능의 기본 원칙 — 정지는 언제나 안전한 상태(safe state)이므로 최우선이다.

1-3. 우선순위 사슬

  • 시스템은 Anti-pinch 보호 동작을 일반 윈도우 제어 요청보다 우선하여 수행해야 한다.
  • 시스템은 전용 윈도우 스위치에 의한 유효한 조작 요청을 차량 내 HMI, 원격 사용자 및 Window 기반 자동 환기 요청보다 우선하여 처리해야 한다.
  • 시스템은 차량 내 HMI 에 의한 유효한 조작 요청을 원격 사용자 및 Window 기반 자동 환기 요청보다 우선하여 처리해야 한다.
  • 시스템은 권한이 있는 원격 사용자의 유효한 조작 요청을 Window 기반 자동 환기 요청보다 우선하여 처리해야 한다.

세 문장이 사슬처럼 이어지며 전순서(total order)를 만든다. 이렇게 쓴 이유가 §9의 분리 원칙이다. "스위치 > HMI > 원격 > 자동환기"를 한 문장에 쓰면 시험 항목이 하나가 되어, 어느 쌍이 깨졌는지 알 수 없다. 세 문장이면 세 개의 독립 시험이 된다.

전체 우선순위를 정리하면:

다이어그램 로딩 중…

물리적으로 차 안에 있는 사람이 이긴다는 게 이 순서의 철학이다. 스위치를 누른 사람은 창문을 직접 보고 있고, 원격 사용자는 못 본다. 자동 환기는 아무도 보고 있지 않다. 상황을 볼 수 있는 주체일수록 우선한다.

1-4. 멱등성

  • 시스템은 현재 윈도우 상태와 동일한 목표의 요청이 반복되더라도 의도하지 않은 반복 구동이 발생하지 않도록 해야 한다.

00편 패턴 E다. 윈도우에서는 특히 중요한데, 완전 닫힘 위치에서 계속 "닫힘" 명령이 들어오면 모터가 스톨(stall) 상태로 전류를 계속 먹기 때문이다. 모터 코일이 타고, 전류 기반 Anti-pinch 감지가 상시 트리거된다.

static bool win_is_redundant(const win_req_t *r)
{
    /* §6.2.3 — 완전 끝단에 도달한 방향으로의 추가 요청은 무시 */
    if (r->cmd == WIN_CMD_CLOSE && g_pos == WIN_POS_FULL_CLOSED) return true;
    if (r->cmd == WIN_CMD_OPEN  && g_pos == WIN_POS_FULL_OPEN)   return true;
    /* 이미 같은 방향으로 이동 중이면 새 구동을 시작하지 않는다 */
    if (g_moving_dir == cmd_to_dir(r->cmd)) return true;
    return false;
}

함정 — 위치를 신뢰할 수 없으면 멱등성 판단도 못 한다 위 코드는 g_pos를 믿는다. 그런데 §6.2.2는 "윈도우 위치 또는 이동 상태를 신뢰할 수 없는 경우 해당 정보에 의존하는 원터치 동작 및 Window 기반 자동 환기 동작을 시작하지 않아야 한다"고 한다. 위치 불신 상태에서는 원터치를 막고 수동 조작(누르는 동안만 이동)만 허용하는 게 정합적이다. 수동 조작은 사용자가 창문을 보면서 손가락으로 제어하므로, 시스템의 위치 정보 없이도 안전하다.


2. §6.2.2 — 윈도우 동작 허용 및 요청 제한

  • 시스템은 차량의 운영 상태 또는 안전 조건상 허용되지 않는 원격 제어 및 Window 기반 자동 환기 요청을 수행하지 않아야 한다.
  • 시스템은 윈도우 위치 또는 이동 상태를 신뢰할 수 없는 경우, 해당 정보에 의존하는 원터치 동작 및 Window 기반 자동 환기 동작을 시작하지 않아야 한다.
  • 시스템은 윈도우 제어에 필요한 통신 정보를 신뢰할 수 없는 경우, 해당 통신 정보에 따른 새로운 윈도우 이동을 시작하지 않아야 한다.
  • 시스템은 Anti-pinch 보호 기능을 사용할 수 없는 경우, 윈도우 닫힘 동작을 시작하지 않아야 한다.
  • 시스템은 수신한 윈도우 제어 요청을 수행할 수 없는 경우 해당 요청을 거부해야 한다.
  • 시스템은 윈도우 제어 요청을 거부한 경우 거부 사유를 HMI 에서 사용할 수 있도록 제공해야 한다.

2-1. 네 번째 문장이 이 절의 핵심이다

"시스템은 Anti-pinch 보호 기능을 사용할 수 없는 경우, 윈도우 닫힘 동작을 시작하지 않아야 한다."

이건 안전 기능이 살아 있어야만 위험한 동작을 허용한다는 원칙이다. 자동차 기능안전에서 안전 메커니즘의 가용성이 기능의 전제 조건이 되는 전형적 패턴이다.

주의 깊게 볼 것: 닫힘만 막고 열림은 막지 않는다. 열림 방향으로는 끼임이 발생하지 않기 때문이다(창틀 쪽으로 압박하는 게 아니라 멀어진다). 안전 조치가 위험 방향에만 적용되는 정밀한 설계다.

Anti-pinch를 "사용할 수 없는" 경우는 어떤 것들인가?

상황왜 사용 불가인가
전류 센싱 ADC 채널 고장부하 변화를 감지할 수 없음
홀 센서/리플 카운터 이상모터 속도 변화를 감지할 수 없음
위치 정보 상실보호 위치까지 얼마나 열어야 하는지 모름
초기화 미완료정상/이상 판정의 기준 프로파일이 없음
저전압센서 읽기 신뢰도 하락

2-2. 거부는 조용히 하면 안 된다

마지막 두 문장이 짝이다.

거부해야 한다.                    ← 동작
거부 사유를 HMI에서 사용할 수 있도록 제공해야 한다.  ← 설명

요청이 아무 반응 없이 사라지는 게 가장 나쁜 UX다. 사용자는 버튼이 고장 났는지, 명령이 안 갔는지, 일부러 막힌 건지 구분할 수 없다. §6.5.1이 이걸 시스템 전체 원칙으로 승격시킨다.

"차량 내 HMI 및 모바일 인터페이스는 제어 요청이 거부되거나 실패한 경우 그 사유를 사용자에게 제공해야 한다."

거부 사유는 열거형으로 정의해야 한다.

typedef enum {
    WIN_REJ_NONE = 0,
    WIN_REJ_ANTIPINCH_UNAVAILABLE,  /* §6.2.2 — Anti-pinch 사용 불가 */
    WIN_REJ_POSITION_UNRELIABLE,    /* §6.2.2 — 위치 신뢰 불가 */
    WIN_REJ_COMM_UNRELIABLE,        /* §6.2.2 — 통신 정보 신뢰 불가 */
    WIN_REJ_NOT_ALLOWED_STATE,      /* §6.2.2 — 운영/안전 조건 미충족 */
    WIN_REJ_PROTECTION_ACTIVE,      /* §6.2.4 — 보호 상태에서 새 요청 대기 중 */
    WIN_REJ_LOWER_PRIORITY,         /* §6.2.1 — 상위 요청이 진행 중 */
} win_reject_t;

3. §6.2.3 — 윈도우 구동

  • 시스템은 유효한 열림 요청을 수신한 경우 윈도우를 열림 방향으로 구동해야 한다.
  • 시스템은 유효한 닫힘 요청을 수신한 경우 윈도우를 닫힘 방향으로 구동해야 한다.
  • 시스템은 유효한 정지 요청을 수신한 경우 진행 중인 윈도우 이동을 정지해야 한다.
  • 시스템은 윈도우가 완전 열림 위치에 도달한 경우 열림 방향의 구동을 정지해야 한다.
  • 시스템은 윈도우가 완전 닫힘 위치에 도달한 경우 닫힘 방향의 구동을 정지해야 한다.
  • 시스템은 Window 기반 자동 환기 기능에서 유효한 열림 요청을 수신한 경우 정의된 환기 위치까지 윈도우를 열림 방향으로 구동해야 한다.
  • 시스템은 윈도우가 정상 끝단 이외의 위치에서 정지한 경우, 해당 상태를 완전 열림 또는 완전 닫힘 상태로 처리하지 않아야 한다.
  • 시스템은 윈도우 위치 정보를 신뢰할 수 없는 경우 정상 끝단 도달 상태를 확정하지 않아야 한다.

3-1. 위치 모델

요구사항에서 읽히는 위치 상태는 네 가지다.

다이어그램 로딩 중…

UNKNOWN 상태가 별도로 존재해야 한다는 게 마지막 두 요구사항의 요지다.

"시스템은 윈도우가 정상 끝단 이외의 위치에서 정지한 경우, 해당 상태를 완전 열림 또는 완전 닫힘 상태로 처리하지 않아야 한다."

Anti-pinch로 중간에 멈췄는데 "닫힘 완료"로 기록하면, 이후 "이미 닫혀 있으니 닫힘 요청 무시"(멱등성 로직)에 걸려 창문을 못 닫게 된다. 그리고 §6.2.6이 이걸 HMI 표시 요구사항으로 이어받는다 — "중간 위치 정지"를 별도 상태로 보여줘야 한다.

3-2. 위치를 어떻게 아는가 — TBD-008

TBD-008이 "Power Window 위치 확인 방식과 센서 조합 — 최종 위치 확인 방식과 센서 구성은 하드웨어 설계 단계에서 확정"으로 열려 있다. 대표적인 방식들:

방식원리장점단점
홀 센서 (2채널)모터에 자석+홀 IC 2개. 펄스 카운트로 이동량, 위상차로 방향정확, 방향 판별 가능부품 추가, 배선
리플 카운팅DC 모터 정류자 리플을 전류 파형에서 추출해 카운트센서 없음(원가↓)저속·기동 시 리플이 뭉개짐, 필터 설계 난이도 높음
엔코더광학/자기 엔코더고해상도비용, 오염 취약
끝단 리미트 스위치완전 열림/닫힘 위치에 스위치절대 기준점 확보중간 위치는 모름

실무에서는 홀 센서(또는 리플 카운팅) + 끝단 스톨 검출을 조합한다. 상대 위치를 세면서, 끝단에 닿으면 절대 기준으로 리셋한다. 그래야 카운트 누적 오차가 씻겨 나간다.

/* 끝단 도달 판정 — 스톨(모터 정지) 검출 */
static bool at_hard_stop(void)
{
    /* 모터에 전압을 주고 있는데 리플/홀 펄스가 멈췄다 = 물리적 끝단 또는 끼임 */
    return (g_motor_driving && (hal_now_ms() - g_last_pulse_ms) > STALL_TIMEOUT_MS);
}

함정 — 스톨과 끼임을 구분하는 것이 Anti-pinch의 전부다 위 코드만으로는 "창문이 창틀에 닿아 멈춤"과 "손가락이 껴서 멈춤"을 구분할 수 없다. 둘 다 펄스가 멈추고 전류가 치솟는다. 구분의 열쇠는 위치다. 완전 닫힘 위치 근처에서의 스톨은 정상 끝단, 그 이전 구간에서의 스톨은 끼임이다. 그래서 위치 정보 없이는 Anti-pinch가 성립하지 않고, §6.2.2가 "위치를 신뢰할 수 없으면 원터치를 시작하지 않는다"고 하는 것이다.

3-3. 자동 환기 위치 — TBD-007

"시스템은 Window 기반 자동 환기 기능에서 유효한 열림 요청을 수신한 경우 정의된 환기 위치까지 윈도우를 열림 방향으로 구동해야 한다."

**완전 열림이 아니라 "정의된 환기 위치"**다. 환기는 공기가 통하면 되므로 창문을 다 열 필요가 없고, 다 열면 비가 들이치거나 도난 위험이 생긴다. 보통 전체 스트로크의 10~20% 정도를 연다.

TBD-007이 "Power Window 기구 스트로크 및 정의된 환기 위치 — 단일 윈도우 모사 장치 기준으로 확정, 참조 절: §6.2.3 Power Window"로 이 요구사항을 명시적으로 가리킨다.


4. §6.2.4 — Anti-pinch 안전 보호

이 시스템에서 가장 중요한 6개 문장.

  • 시스템은 윈도우가 닫힘 방향으로 이동하는 동안 끼임 위험을 감지해야 한다.
  • 시스템은 끼임 위험을 감지한 경우 진행 중인 윈도우 닫힘 동작을 즉시 정지해야 한다.
  • 시스템은 끼임 위험으로 닫힘 동작을 정지한 경우 정의된 보호 위치까지 열림 방향의 보호 동작을 수행해야 한다.
  • 시스템은 Anti-pinch 보호 동작이 발생한 경우 해당 발생 상태를 사용자에게 제공해야 한다.
  • 시스템은 Anti-pinch 보호 동작이 완료된 경우 보호 동작 결과를 사용자에게 제공해야 한다.
  • 시스템은 Anti-pinch 보호 동작이 종료된 후 새로운 유효 요청이 확인되기 전까지 일반 닫힘 동작 또는 Window 기반 자동 환기 동작을 자동으로 재개하지 않아야 한다.

4-1. 여섯 문장이 그리는 완전한 사이클

다이어그램 로딩 중…

⑥이 없으면 앞의 5개가 무의미해진다. 손가락이 여전히 끼어 있는데 시스템이 "이제 괜찮겠지" 하고 다시 닫으면, 보호 동작은 그저 시간을 조금 벌었을 뿐이다. 사용자가 손을 빼고 명시적으로 새 요청을 해야 재개된다.

4-2. 끼임을 어떻게 감지하는가 — TBD-009

TBD-009: "Anti-pinch 감지 방식, 임계값, 보호 위치, 반응시간 — Load cell/current 등 벤치 시험 후 확정. 참조 절: §6.2.4 Power Window"

방식 1: 모터 전류 감시

정상 상승 구동:  전류가 완만히 증가 (마찰 · 중력)
끼임 발생:       전류가 급격히 증가 (dI/dt 급상승)
끝단 도달:       전류가 최대까지 상승하지만, 위치가 완전 닫힘 근처

임계값을 절대값으로만 잡으면 실패한다. 이유:

변수전류에 미치는 영향
온도저온에서 그리스 점도 상승 → 정상 전류가 증가
배터리 전압전압이 높으면 같은 부하에서도 전류 다름
노후레귤레이터 마모로 마찰 증가
차량 자세경사 주차 시 중력 성분 변화

그래서 실무는 **적응형 기준선(adaptive baseline)**을 쓴다. 정상 동작 중 위치 구간별 전류 프로파일을 학습해 두고, 그 프로파일 대비 초과분으로 판정한다.

/* 위치 구간별 학습된 정상 전류 (단위: mA) */
static uint16_t g_baseline_mA[WIN_ZONE_COUNT];

/* §6.2.4 — 닫힘 중 상시 호출 (예: 1 ms 주기) */
static bool pinch_detected(uint16_t i_now_mA, uint16_t pos, uint16_t speed_pps)
{
    uint8_t z = zone_of(pos);

    /* 완전 닫힘 직전 구간은 정상 스톨 구간 — 끼임 판정에서 제외 */
    if (z == WIN_ZONE_TOP_SEAL) return false;

    int32_t excess = (int32_t)i_now_mA - (int32_t)g_baseline_mA[z];

    /* 판정 1: 학습 기준선 대비 초과 전류 */
    bool over_current = (excess > (int32_t)PINCH_I_THRESHOLD_MA);

    /* 판정 2: 속도 급감 — 부하가 걸리면 모터가 느려진다 */
    bool speed_drop = (speed_pps < (g_speed_ref_pps * PINCH_SPEED_RATIO_PCT / 100u));

    /* 두 지표를 AND 로 묶어 오검출을 줄인다 */
    return over_current && speed_drop;
}

왜 AND인가? 전류만 보면 배터리 전압 변동·순간 노이즈에 오검출이 난다. 속도만 보면 저속 구간에서 오검출이 난다. 두 물리량이 동시에 끼임 방향으로 움직여야 실제 끼임일 확률이 높다. 대신 AND는 검출 지연을 늘린다 — 이게 TBD-009의 "반응시간"이 벤치 시험 대상인 이유다.

방식 2: 로드셀 / 압력 스트립 창틀에 압력 감지 스트립을 넣어 직접 힘을 측정한다. 정확하지만 부품·배선 비용이 크다. TBD-009가 "Load cell/current 등"이라고 둘 다 열어 둔 상태.

4-3. "즉시"란 얼마나 즉시인가

법규 관점에서 파워윈도우 끼임 보호는 끼임력 상한반응 시간으로 규정된다. §7.1은 이렇게 미뤄 둔다.

"파워윈도우의 법규 적용 범위와 안전 수치는 적용 국가/차종 및 프로젝트 시험 조건을 확정한 후 최종 검증 기준으로 사용한다."

프로토타입 단계에서 수치를 못 박지 않은 건 합리적이다. 다만 구현 관점에서 "즉시"는 다음을 요구한다.

  1. 감지 루프가 인터럽트/고주기 타이머에서 돌아야 한다. 메인 루프에서 100 ms마다 검사하면 그 사이에 압박이 계속된다.
  2. 정지가 소프트웨어 경로만으로 이뤄지면 안 된다. H-브리지 드라이버의 하드웨어 브레이크(양쪽 로우사이드 ON)를 쓰면 관성까지 빠르게 죽는다.
  3. 감지 → 정지 사이에 통신이 없어야 한다. §6.2.5가 이걸 못 박는다.
/* 고주기 타이머 ISR — 닫힘 구동 중에만 활성 */
void PWM_FAULT_TIMER_IRQHandler(void)
{
    uint16_t i  = adc_read_motor_current_mA();
    uint16_t p  = win_position();
    uint16_t sp = win_speed_pps();

    if (g_dir == WIN_DIR_CLOSE && pinch_detected(i, p, sp)) {
        motor_brake();                  /* ① 하드웨어 브레이크 — 즉시 */
        g_pinch_latched = true;         /* ⑥ 래치 — 자동 재개 금지 */
        g_protect_target = protect_position_from(p);
        g_state = WIN_ST_PROTECTING;    /* ③ 보호 동작은 메인 루프가 이어받는다 */
    }
    timer_clear_flag();
}

ISR에서는 정지까지만 하고 보호 구동은 메인 루프로 넘긴다. ISR을 짧게 유지하는 임베디드 기본 원칙이고, 보호 구동은 수백 ms가 걸리는 동작이라 ISR에 둘 수 없다.

4-4. "정의된 보호 위치"

보호 동작은 완전 열림이 아니다. 다 열어버리면 비·도난 문제가 생기고, 사용자 의도(닫으려 했음)에서 너무 멀어진다. 신체를 빼낼 수 있을 만큼만 열면 된다.

TBD-009가 이 값을 벤치 시험으로 확정하기로 했다. 참고로 업계 관행은 끼임 위치에서 일정 거리를 열거나 특정 절대 위치까지 여는 방식이다.

4-5. 래치와 해제

/* ⑥ 새로운 유효 요청이 확인되기 전까지 재개 금지 (§6.2.4) */
static bool win_close_allowed(const win_req_t *r)
{
    if (!g_pinch_latched) return true;

    /* 래치를 푸는 것은 "새로운 유효 요청"뿐 */
    if (r->src == WIN_SRC_AUTO_VENT) return false;   /* 자동 환기로는 못 푼다 */
    if (!req_is_new_edge(r))         return false;   /* 계속 눌려 있는 것은 새 요청이 아니다 */

    g_pinch_latched = false;
    return true;
}

함정 — "계속 눌린 스위치"를 새 요청으로 보면 안 된다 사용자가 원터치 닫힘 버튼을 누른 채로 손가락이 끼었다고 하자. 보호 동작 후 스위치는 여전히 눌린 상태다. 레벨(level)로 판정하면 즉시 재개되어 요구사항 ⑥이 무의미해진다. 엣지(edge) 판정이 필수다 — 스위치를 놓았다가 다시 눌러야 새 요청이다. 이건 요구사항 문장에 안 적혀 있지만 "새로운 유효 요청"의 유일한 정합적 해석이다.


5. §6.2.5 — 통신 오류 및 안전 동작

  • 시스템은 윈도우 제어 관련 통신 오류가 발생하더라도 로컬 윈도우 제어기에서 수행하는 Anti-pinch 보호 기능을 유지해야 한다.
  • 시스템은 통신 오류가 발생하더라도 전용 윈도우 스위치에 의한 로컬 조작 요청을 처리해야 한다.
  • 시스템은 원격 제어 통신 오류가 발생한 경우 진행 중인 원격 제어 기반 윈도우 이동을 정지해야 한다.
  • 시스템은 차량 내 HMI, 원격 사용자 또는 Window 기반 자동 환기 기능의 통신 오류로 인해 의도하지 않은 윈도우 구동이 발생하지 않아야 한다.
  • 시스템은 윈도우 제어 오류 또는 보호 상태가 해제된 후 새로운 유효 요청이 확인된 경우에만 일반 동작을 재개해야 한다.

5-1. 이 절의 전체 구조 = 로컬은 살고, 원격은 죽는다

다이어그램 로딩 중…

설계 규칙 한 줄: 창문을 직접 볼 수 있는 경로만 통신 오류에서 살아남는다.

스위치를 누르는 사람은 창문 옆에 있다. 그가 위험을 보면 손을 뗀다. 원격 사용자는 못 본다 — 그래서 통신이 불안정한 순간 원격 이동을 계속하는 건 위험하다.

5-2. "의도하지 않은 윈도우 구동"이란 무엇인가

"시스템은 차량 내 HMI, 원격 사용자 또는 Window 기반 자동 환기 기능의 통신 오류로 인해 의도하지 않은 윈도우 구동이 발생하지 않아야 한다."

이건 통신 오류가 만들어내는 유령 명령을 막으라는 뜻이다. 실제로 어떻게 발생하는가:

유령 명령의 원인방어
프레임 손상 — 비트 반전으로 STOP이 CLOSE로 읽힘CRC, 그리고 CAN 자체 CRC 외에 애플리케이션 레벨 E2E 보호
재전송/중복 — 같은 프레임이 두 번 도착시퀀스 카운터
stale 프레임 — 오래된 명령이 뒤늦게 도착타임스탬프 / age 검사 (TBD-022)
송신 노드 정지 — 마지막 명령이 버퍼에 남아 반복 송신Heartbeat 감시 (TBD-020)

TBD-020이 이걸 가리킨다: "외부 기능 ECU Heartbeat/Timeout 및 복구 정책 — Power Window/Function/Sensing ECU 의 주기와 재유효화 조건 확정".

/* 통신 명령 유효성 — 세 겹으로 거른다 */
static bool win_cmd_valid(const win_frame_t *f)
{
    if (!e2e_crc_ok(f))                                   return false;  /* 손상 */
    if (!seq_counter_advanced(f->seq, g_last_seq))        return false;  /* 중복·역순 */
    if ((hal_now_ms() - f->tx_ms) > CMD_MAX_AGE_MS)       return false;  /* stale (TBD-022) */
    if (!heartbeat_alive(f->src_node))                    return false;  /* 송신 노드 정지 (TBD-020) */
    g_last_seq = f->seq;
    return true;
}

네 검사 중 하나만 빠져도 유령 명령이 통과한다. 특히 heartbeat 검사가 없으면, 송신 노드가 죽어서 마지막 명령을 무한 반복해도 수신 측은 정상으로 본다.

5-3. 재개 조건의 통일

"시스템은 윈도우 제어 오류 또는 보호 상태가 해제된 후 새로운 유효 요청이 확인된 경우에만 일반 동작을 재개해야 한다."

§6.2.4의 ⑥과 같은 원칙을 오류 상황 전체로 확장한 문장이다. 정리하면:

윈도우가 다시 움직이려면:
  (오류 없음 OR 오류 해제됨) AND (보호 상태 아님 OR 보호 해제됨) AND 새 유효 요청
                                                                    ↑ 이게 없으면 안 움직인다

6. §6.2.6 — 상태 및 HMI 제공

  • 시스템은 HMI 에서 윈도우의 완전 열림, 완전 닫힘, 열림 중, 닫힘 중, 중간 위치 정지, Anti-pinch 보호 및 오류 상태를 구분하여 사용할 수 있도록 제공해야 한다.
  • 시스템은 윈도우 위치 또는 이동 상태를 신뢰할 수 없는 경우 해당 상태를 정상 상태로 표시하지 않아야 한다.
  • 시스템은 통신 오류 상태에서 마지막 정상 윈도우 상태를 현재 정상 상태로 표시하지 않아야 한다.
  • 시스템은 윈도우 제어 요청의 수락, 진행, 완료, 거부 또는 중단 결과를 HMI 에서 사용할 수 있도록 제공해야 한다.
  • 시스템은 윈도우 제어 기능을 정상적으로 제공할 수 없는 경우 오류 상태와 이용 제한 사유를 HMI 에서 사용할 수 있도록 제공해야 한다.

6-1. 7개 상태 + 2개 비정상 표시

첫 문장이 열거하는 상태:

typedef enum {
    WIN_ST_FULL_OPEN,      /* 완전 열림 */
    WIN_ST_FULL_CLOSED,    /* 완전 닫힘 */
    WIN_ST_OPENING,        /* 열림 중 */
    WIN_ST_CLOSING,        /* 닫힘 중 */
    WIN_ST_MID_STOPPED,    /* 중간 위치 정지 — §6.2.3의 "정상 끝단 이외" */
    WIN_ST_ANTIPINCH,      /* Anti-pinch 보호 */
    WIN_ST_ERROR,          /* 오류 */
} win_state_t;

/* 위 상태와 직교하는 신뢰도 축 — 같은 변수에 섞으면 안 된다 */
typedef enum {
    WIN_TRUST_OK,
    WIN_TRUST_STALE,       /* 통신 오류 — 마지막 값이 오래됨 */
    WIN_TRUST_UNKNOWN,     /* 위치 정보 상실 */
} win_trust_t;

두 축을 분리하는 게 핵심이다. WIN_ST_FULL_CLOSED + WIN_TRUST_STALE는 "예전에 닫혀 있었는데 지금은 모름"이고, HMI는 이걸 "닫힘"으로 그리면 안 된다.

6-2. 요청 생애주기 표시

"시스템은 윈도우 제어 요청의 수락, 진행, 완료, 거부 또는 중단 결과를 HMI 에서 사용할 수 있도록 제공해야 한다."

**5단계 요청 생애주기**가 요구사항 레벨에서 정의됐다.

다이어그램 로딩 중…

§6.5.1의 "차량 내 HMI 및 모바일 인터페이스는 사용자 제어 요청의 접수, 거부, 진행, 완료, 중단 또는 실패 결과를 사용자에게 제공해야 한다"와 같은 모델이다. 시스템 전역에서 하나의 요청 생애주기 모델을 쓴다 — 이건 아키텍처 일관성 측면에서 좋은 설계다.


7. 통합 정리 — 하나의 닫힘 요청이 통과해야 하는 관문

다이어그램 로딩 중…

여섯 개의 관문을 전부 통과해야 창문이 움직인다. 그리고 어느 관문에서 막혔는지가 사용자에게 전달된다. 이게 §6.2 전체의 요약이다.


8. 한 줄 요약

한 줄
§6.2.1요청 출처 4종을 구분한다. Anti-pinch > 정지 > 스위치 > HMI > 원격 > 자동환기. 같은 목표 반복은 재구동 없음
§6.2.2Anti-pinch를 못 쓰면 닫힘을 아예 시작하지 않는다. 거부는 사유와 함께
§6.2.3열림·닫힘·정지 + 끝단 자동 정지. 자동 환기는 "정의된 환기 위치"까지. 중간 정지를 끝단으로 처리 금지
§6.2.4감지 → 즉시 정지 → 보호 위치까지 열림 → 발생·결과 통지 → 새 요청 전까지 재개 금지
§6.2.5통신이 죽어도 Anti-pinch와 로컬 스위치는 산다. 원격 이동은 정지. 유령 명령 금지
§6.2.67개 상태 구분 + stale을 정상으로 표시 금지 + 요청 생애주기 5단계 통지

설계 판단 체크포인트

구현에 들어가기 전에 팀이 답을 갖고 있어야 하는 것들이다. 답이 안 나오면 그 자리가 곧 설계 문의 또는 TBD 후보다.

  1. Anti-pinch 감지에 전류와 속도를 AND로 묶으면 반응이 느려진다. 그럼에도 AND를 쓰는 이유는? 오검출(false positive)의 대가가 크기 때문이다. 정상 닫힘 중 노이즈로 끼임이 오검출되면 창문이 저절로 내려가고, 사용자는 창문을 닫을 수 없다. 반복되면 사용자가 기능 자체를 불신한다. 다만 반응시간은 법규 상한이 있으므로 AND 조건의 지연을 벤치에서 측정해야 한다 — TBD-009가 "반응시간"을 확정 항목으로 둔 이유.

  2. 완전 닫힘 직전 구간(TOP_SEAL)에서 끼임 판정을 제외하는 이유와, 그게 만드는 위험은? 창문이 고무 실(seal)을 압축하며 닫히므로 정상적으로 전류가 급증한다. 여기서 판정하면 매번 오검출이다. 대신 이 구간에 손가락 끝이 들어가면 보호받지 못한다 — 그래서 실무에서는 이 구간을 최대한 좁게(끝단 4 mm 등 법규 기준) 잡는다. 안전과 기능성의 트레이드오프가 물리적 거리로 표현된 지점이다.

  3. §6.2.5는 "원격 제어 통신 오류 시 진행 중인 원격 기반 이동을 정지"라고 한다. 스위치 조작으로 진행 중이던 이동은? 정지하지 않는다. 요구사항이 "원격 제어 기반 윈도우 이동"으로 한정했고, 바로 위 문장이 "통신 오류가 발생하더라도 전용 윈도우 스위치에 의한 로컬 조작 요청을 처리해야 한다"고 명시한다. 로컬 조작은 통신과 무관하게 성립한다.

  4. 위치 정보를 잃었다. 사용자가 스위치로 창문을 닫으려 한다. 허용되는가? §6.2.2는 "위치를 신뢰할 수 없는 경우 원터치 동작 및 자동 환기 동작을 시작하지 않아야 한다"고만 한다. 수동 조작(누르는 동안만 이동)은 금지 대상이 아니다. 다만 §6.2.2의 다른 문장 — "Anti-pinch 보호 기능을 사용할 수 없는 경우 닫힘 동작을 시작하지 않아야 한다" — 이 걸린다. 위치 없이 Anti-pinch가 성립하는가가 답을 가른다. 전류+속도 기반 감지가 위치 없이도 동작하도록 설계했다면 수동 닫힘은 허용되고, 위치 기반 존(zone) 판정에 의존한다면 금지된다. 이건 TBD-009의 감지 방식 확정에 달려 있다.

  5. HMI에서 "닫힘" 버튼을 눌렀는데 아무 반응이 없다. SR 관점에서 무엇이 잘못됐나? §6.2.2("거부 사유를 HMI에서 사용할 수 있도록 제공"), §6.2.6("수락·진행·완료·거부·중단 결과 제공"), §6.5.1("거부되거나 실패한 경우 사유 제공") 세 요구사항을 동시에 위반했다. 거부는 반드시 관찰 가능해야 한다 — 이게 이 SR의 일관된 태도다.

  6. 자동 환기로 창문이 열리는 중에 사용자가 스위치로 닫힘을 눌렀다. 무슨 일이 일어나야 하나? §6.2.1에 따라 스위치가 자동 환기보다 우선하므로 자동 환기 이동이 중단되고 닫힘이 시작된다. 그리고 §6.4.2의 "시스템은 전용 윈도우 스위치, 정지 요청 또는 Anti-pinch 보호 동작에 의해 자동 환기 기반 윈도우 동작이 중단된 경우 해당 자동 환기 동작을 종료해야 한다"가 이어받아 자동 환기 기능 자체를 종료시킨다. 창문만 멈추는 게 아니라 상위 기능이 꺼진다 — 사용자 의도가 시스템 판단을 이겼음을 기능 레벨에서 인정하는 것이다.

VSS 오디오 — 이벤트 음향·우선순위 중재·Ducking/Fade센싱·비전 — 유효성 3축·초음파·ROA·엔진룸 CV