2026/06/21

S2 Mini + TSOP38238 / 적외선 수신기와 리모컨







s2 mini에 적외선 수신기(TSOP38238)를 설치하고 사용하지 않는 리모콘의 각 버튼에 HA 호출서비스 할당해 리모콘에 33가지 무선 씬버튼을 만듬.
각 버튼에는 조명 제어, 음악재생, 플레이리스트 호출, 커튼 제어, 선풍기 제어, 에어컨 제어 명령 할당.

s2 mini는 핀아웃의 시작이 vcc gnd data순서로 돼있어 케이블 작업없이 TSOP38238을 핀헤더에 바로 꽂아 사용할 수 있어 선택.

개발자도구/이벤트/이벤트청취 탭의 청취할 이벤트에 esphome.ir_remote를 넣고 청취시작을 누른 후 리모콘 버튼을 눌러 address와 command를 얻음. 다른 방법으로 esphome yaml에 dump: all 옵션을 넣어 플래싱하고 모든 리모컨 버튼을 순서대로 누른 후 로그파일을 ai에 던져주고 정리.

집안에 설치된 ble gateway에 적외선 수신기를 모두 달고 리모콘을 무선버튼으로 활용하는 것도 괜찮을듯.

** 같은 제품 리모컨의 경우 따로 신호 구분이 안되지만 각각의 적외선 리시버(esphome.ir_remote)에 추가 임의 구분자를 넣어 구별 가능.  예를 들어 거실, 침실등에 각각 설치된 적외선 리시버별로 지역 구분자를 넣고 자동화 트리거 이벤트에 지역을 추가.

** TV가 삼성이라 오동작을 방지하기 위해 LG리모콘을 쓰다가 NEC호환 리모컨으로 통일.



ESPHome: ir-be.yaml 

substitutions:
  name: ir-be
  area: Bedroom
substitutions:
  name: ir-be
  area: Bedroom
esphome:
  name: ${name}
  area: ${area}
  comment: Sensor IR(B)
esp32:
  board: lolin_s2_mini
  variant: esp32s2
  framework:
    type: esp-idf
wifi:
  ssid: !secret wifi_ssid2
  password: !secret wifi_password
  min_auth_mode: WPA2
  ap:
    ssid: "${name} hotspot"
    password: !secret wifi_password
captive_portal:
logger:
api:
ota:
  - platform: esphome
    password: !secret ota_password

remote_receiver:
  pin:
    number: 16
    inverted: true
    mode:
      input: true
      pullup: true
  on_nec:
    then:
      - homeassistant.event:
          event: esphome.ir_remote
          data:
            area: bedroom
            protocol: nec
            address: !lambda 'return (int)x.address;'
            command: !lambda 'return (int)x.command;'
  on_samsung:
    then:
      - homeassistant.event:
          event: esphome.ir_remote
          data:
            protocol: samsung
            data: !lambda 'return (uint32_t)x.data;'
            nbits: !lambda 'return (int)x.nbits;'



Home Assistant: automations.yaml

- id: IR-NEC/침실
  alias: IR-NEC/침실
  mode: single
  max_exceeded: silent
  triggers:
    - trigger: event
      event_type: esphome.ir_remote
      event_data:
        area: bedroom
        protocol: nec
        address: "65025"
  variables:
    ir:
    ir: { power1: 48960, power2: 47940, lang: 48705, del: 48450,
        media1: 43605, media2: 42330, media3: 44370, media4: 43860,
        func1: 48195, func2: 61455, vol_dn: 61200, vol_up: 59160,
        menu1: 60945, menu2: 58905, menu3: 45900, menu4: 65280,
        up: 59670, down: 58650, left: 44625, right: 44880, ok: 60435,
        one: 45390, two: 61965, three: 62220, four: 46410, five: 62985,
        six: 63240, zero: 65025 }
    playlist_map:
      "47430": "Comp."
      "64005": "7080"
      "64260": "Favv"
    cmd: "{{ trigger.event.data.command }}"
  actions:
    - choose:
        - conditions: "{{ cmd == ir.power1 }}"
          sequence:
            - action: switch.toggle
              entity_id: switch.aircon_bedroom
        - conditions: "{{ cmd == ir.power2 }}"
          sequence:
            - action: input_boolean.toggle
              entity_id: input_boolean.dry_bedroom
        - conditions: "{{ cmd | string in playlist_map }}"
          sequence:
            - action: input_select.select_option
              target:
                entity_id: input_select.ma_playlist
              data:
                option: "{{ playlist_map[cmd | string] }}"