|
|
家裡的舊冷氣、電風扇、電視沒有智能功能,
但它們都聽紅外線遙控器的。

原理
- 接收器 —— 學習你原本遙控器的碼
- 發射器 —— 模擬那個遙控器發出訊號
成本大概兩百塊,比買萬用遙控器便宜而且完全本地。
要買什麼
- 紅外線接收模組(VS1838B 或類似的)—— 約 20 元
- 紅外線發射 LED —— 約 10 元(買幾顆備用)
- 一個 NPN 電晶體(S8050、2N2222 都可以)—— 約 5 元
- 一個 100Ω 左右的電阻
- ESP32
為什麼需要電晶體:
ESP32 的腳位輸出電流只有 20mA 左右,
直接接 LED 的話亮度不夠、射程只有幾十公分。
用電晶體放大之後可以到三五公尺。

接線
接收器(很簡單):
- VS1838B ESP32
- ------- -----
- VCC → 3.3V
- GND → GND
- OUT → GPIO14
複製代碼
發射器(要電晶體):
- ESP32 GPIO4 → [100Ω 電阻] → 電晶體 B(基極)
- 3.3V 或 5V → IR LED 長腳(正極)
- IR LED 短腳 → 電晶體 C(集極)
- 電晶體 E → GND
複製代碼
用 5V 供電射程比較遠,但要確認你的板子有 5V 輸出。
不想接電路的話:市面上有現成的「ESP32 紅外線模組」,
接線已經做好了。
第一步:學碼
- remote_receiver:
- pin:
- number: GPIO14
- inverted: true
- mode:
- input: true
- pullup: true
- dump: all # 印出所有能辨識的協定
- tolerance: 55%
- idle: 25ms
- buffer_size: 2kb
複製代碼
燒錄之後,接著 USB 線看日誌,然後拿遙控器對著接收器按。
日誌會出現類似:
- [I][remote.nec:070]: Received NEC: address=0x20DF, command=0x10EF
- [I][remote.pronto:229]: Received Pronto: data=0000 006D 0022 0002 0157 00AC ...
- [I][remote.raw:028]: Received Raw: 9000, -4500, 550, -550, ...
複製代碼
dump: all 會印出所有它能辨識的格式。
冷氣的特別狀況

冷氣跟電視不一樣,這點很多人不知道。
- 電視的遙控器:每個按鍵一個碼(「音量+」就是一個碼)
- 冷氣的遙控器:每次都送「完整狀態」
(溫度 + 模式 + 風速 + 擺葉,全部打包在一個很長的碼裡)
所以「冷氣調高一度」不是一個碼,而是一整組新的狀態碼。
這造成兩個問題:
- 碼很長(可能 200 個以上的脈衝)
- 組合很多 —— 16-30 度 × 4 種模式 × 4 種風速 = 幾百種
解法一:用 ESPHome 內建的冷氣元件(推薦)
ESPHome 內建了很多冷氣品牌的協定:
- climate:
- - platform: daikin # 或 coolix / fujitsu_general / mitsubishi 等
- name: "客廳冷氣"
- supports_heat: false
- supports_cool: true
複製代碼
常見的支援清單(不完整,以官方文件為準):
- coolix —— 很多品牌通用(包括不少台灣常見的)
- daikin / daikin_arc / daikin_brc
- mitsubishi
- fujitsu_general
- hitachi_ac344
- toshiba
- tcl112
- whirlpool
先試 coolix —— 它涵蓋的品牌最多。
怎麼知道哪個對:
- 用 dump: all 學碼時,日誌裡可能會直接顯示協定名稱
- 或者一個一個試(燒錄很快,OTA 幾十秒)
解法二:學幾個常用的狀態就好
實務上你可能只用三四種設定:
- 26 度冷氣自動風
- 27 度冷氣低風(睡眠)
- 除濕
- 關機
那就學這四個碼,做成四個按鈕。
- button:
- - platform: template
- name: "冷氣 26 度"
- on_press:
- - remote_transmitter.transmit_raw:
- carrier_frequency: 38kHz
- code: [9000, -4500, 550, -550, ...] # 從日誌複製
- - platform: template
- name: "冷氣關"
- on_press:
- - remote_transmitter.transmit_raw:
- carrier_frequency: 38kHz
- code: [...]
複製代碼
這個做法簡單可靠,缺點是不能任意調溫度。

發射設定
- remote_transmitter:
- pin: GPIO4
- carrier_duty_percent: 50% # 一般紅外線用 50%
複製代碼
常見的發射寫法:
- # NEC 協定(大部分電視、電風扇)
- - remote_transmitter.transmit_nec:
- address: 0x20DF
- command: 0x10EF
- # Pronto(萬用格式,最保險)
- - remote_transmitter.transmit_pronto:
- data: "0000 006D 0022 0002 0157 00AC ..."
- # Raw(最原始,一定能用但最佔空間)
- - remote_transmitter.transmit_raw:
- carrier_frequency: 38kHz
- code: [9000, -4500, 550, -550, ...]
- # 重複送幾次(訊號不穩時很有用)
- - remote_transmitter.transmit_nec:
- address: 0x20DF
- command: 0x10EF
- repeat:
- times: 3
- wait_time: 30ms
複製代碼
建議優先順序:
- 有內建協定就用內建的(最省空間、最好維護)
- 沒有的話用 Pronto(通用格式)
- 最後才用 Raw(佔很多記憶體)
紅外線的致命缺點:單向
你發出去的指令,不知道有沒有成功。
- 遙控器沒對準 → 沒反應但 HA 以為成功了
- 有人用實體遙控器關掉 → HA 不知道
- 停電之後冷氣的狀態跟 HA 不同步
三個補救方法
方法一:加功率監控(最實用)
在冷氣的電源上加一個功率監測插座(或電箱裡的計量模組):
- template:
- - binary_sensor:
- - name: 冷氣運轉中
- state: >
- {{ states('sensor.aircon_power') | float(0) > 100 }}
- delay_on: "00:01:00"
- delay_off: "00:02:00"
複製代碼
這樣至少知道「它現在到底有沒有在吹」。
方法二:加溫度驗證
- alias: 冷氣可能沒收到指令
- triggers:
- - trigger: state
- entity_id: climate.living_room
- to: cool
- actions:
- - delay: "00:10:00"
- - condition: template
- value_template: >
- {{ states('sensor.living_room_temperature') | float(0)
- >= state_attr('climate.living_room','temperature') | float(26) + 2 }}
- - action: notify.mobile_app_charles
- data:
- message: 冷氣開了十分鐘但溫度沒降,可能沒收到指令
- mode: single
複製代碼
方法三:重複發送
- repeat:
- times: 3
- wait_time: 50ms
複製代碼
成功率會提高不少。
發射器的擺放
- 要能「看到」目標裝置 —— 紅外線不會轉彎
- 距離三公尺內最穩
- 可以對著天花板或牆壁反射(房間不大的話很有效)
- 一個發射器可以控制多台裝置(只要都在射程內)
- 接兩顆 LED 朝不同方向可以涵蓋更廣
除錯
- 完全沒反應 → 用手機相機看 IR LED
(手機看得到紅外線,按下去應該會看到紫色閃光)
- 近距離可以遠距離不行 → 電晶體沒接好,或供電不足
- 有時候成功有時候不成功 → 加 repeat
- 學不到碼 → 接收器的 inverted 設定,或 tolerance 調大
手機相機那招很好用 ——
三秒就能確認「LED 到底有沒有在發光」。
---
下一篇:毫米波存在感測器 ——
偵測「有人但沒在動」。 |
|