利用ESPHome自制万能遥控器
最近捣鼓智能家居,用ESP32/ESP8266控制家里传统红外遥控的空调。其他红外的机顶盒、电视盒子也同理。
硬件与软件准备工作
硬件 | 软件 |
---|---|
ESP32 | ESPHome v2022.2.1 |
NAS/软路由 | Homeassistant 2021.11.4 |
5mm红外发射头(940nm) | |
红外接收头(型号随意) |
红外发射和接受按照上面电路连接,红外发射头由ESP32的GPIO27控制,红外接收头由GPIO14输入。
红外接收与遥控器学习
详细参见ESPHome的Remote Receiver章节,下面粘贴我的ESPHome的编译配置yaml。
1 | esphome: |
这里说明一下官方文档没有详细说明的地方:
- 在
remote_receiver:
中inverted: True
目的是设置电平反转,我一开始忽略了,获取的红外编码正好是反的,一堆乱七八糟。后来发现ESPHome在开机的logs中对我发出警告和建议,我才知道要设置这个。 - 在
remote_receiver:
中dump: raw
的目的是接收到的所有红外编码一律不解析,按照raw格式记录。dump的可选类型很多,其中nec编码据说是使用类型最广泛的红外编码,兼容90%以上的电器。但是我觉得事实并不是这样,不然ESPHome就不会还有其他那么多其他类型可以选择了。千万不要选择all
类型,这样一段红外编码可能会被错误得尝试解析成各种类型,非常糟糕。 - 在
remote_receiver:
中idle: 50ms
非常重要,你可以理解为红外信号的超时等待时间。在一些私有协议的红外编码中(比如我家的格力空调),一条指令有可能里面的某段红外代码之间间隔比较长,会被ESPHome识别为两段甚至是多段单独的红外代码。将idle值设当设置偏大可以规避这个问题。
编译固件并上传到ESP32,打开logs,然后你就可以对准红外接收头,按下你想要学习的按键,比如以下是我抓取到的日志。我按了一个关闭空调和打开空调制冷的按钮,可以看到学习到了两段红外代码。要注意,有时候一段红外代码显示不完,ESPHome会把一段红外代码分成多条不同时间戳的log,大家不要以时间戳作为分开红外指令的标准,而是以一个1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42INFO Reading configuration /config/esp32.yaml...
INFO Starting log output from esp32.local using esphome API
INFO Successfully connected to esp32.local
[21:03:57][I][app:102]: ESPHome version 2022.2.4 compiled on Mar 5 2022, 20:52:27
[21:03:58][C][wifi:491]: WiFi:
[21:03:58][C][wifi:353]: Local MAC: 78:E3:6D:19:11:C4
[21:03:58][C][wifi:354]: SSID: 'GECOOS'[redacted]
[21:03:58][C][wifi:355]: IP Address: 192.168.0.178
[21:03:58][C][wifi:357]: BSSID: 1C:88:79:5F:E5:E2[redacted]
[21:03:58][C][wifi:358]: Hostname: 'esp32'
[21:03:58][C][wifi:360]: Signal strength: -47 dB ▂▄▆█
[21:03:58][C][wifi:364]: Channel: 6
[21:03:58][C][wifi:365]: Subnet: 255.255.255.0
[21:03:58][C][wifi:366]: Gateway: 192.168.0.1
[21:03:58][C][wifi:367]: DNS1: 192.168.0.1
[21:03:58][C][wifi:368]: DNS2: 0.0.0.0
[21:03:58][C][logger:233]: Logger:
[21:03:58][C][logger:234]: Level: DEBUG
[21:03:58][C][logger:235]: Log Baud Rate: 115200
[21:03:58][C][logger:236]: Hardware UART: UART0
[21:03:58][C][remote_receiver.esp32:054]: Remote Receiver:
[21:03:58][C][remote_receiver.esp32:055]: Pin: GPIO14
[21:03:58][C][remote_receiver.esp32:060]: Channel: 0
[21:03:58][C][remote_receiver.esp32:061]: RMT memory blocks: 3
[21:03:58][C][remote_receiver.esp32:062]: Clock divider: 80
[21:03:58][C][remote_receiver.esp32:063]: Tolerance: 25%
[21:03:58][C][remote_receiver.esp32:064]: Filter out pulses shorter than: 50 us
[21:03:58][C][remote_receiver.esp32:065]: Signal is done after 40000 us of no changes
[21:03:58][C][mdns:084]: mDNS:
[21:03:58][C][mdns:085]: Hostname: esp32
[21:03:58][C][ota:085]: Over-The-Air Updates:
[21:03:58][C][ota:086]: Address: esp32.local:3232
[21:03:58][C][ota:089]: Using Password.
[21:03:58][C][api:138]: API Server:
[21:03:58][C][api:139]: Address: esp32.local:6053
[21:03:58][C][api:143]: Using noise encryption: NO
[21:04:13][D][remote.raw:028]: Received Raw: 9021, -4476, 625, -1666, 624, -565, 624, -567, 625, -567, 621, -567, 626, -566, 622, -1666, 624, -566, 623, -1666, 626, -1691, 597, -566, 626, -1664, 625, -593, 597, -566, 624, -566, 625, -565, 624, -565, 622, -569, 624, -565, 625, -565, 625, -592, 599, -564, 624, -566, 626, -564, 626, -565, 625, -566, 623, -565, 624, -566, 624, -1666, 625, -565, 625, -1665, 626, -564, 623, -567, 624, -1666, 623, -567, 626, -19983, 625, -1665, 624, -567, 625, -564, 624, -566, 626, -1664, 623, -593, 599, -565, 624, -566, 624, -566, 624, -594, 598, -566, 622, -567, 624, -591, 598, -1666, 625, -565, 623, -567, 624, -569, 622, -564, 625, -568, 621, -569, 624, -564, 623, -567, 625, -564, 624, -566, 623, -568, 624, -566, 623, -566, 626, -566, 622, -1666, 623, -568, 623, -567, 624, -1665, 624, -7194, 9041, -4481, 626, -1665, 624, -568, 621, -566, 622, -569, 625, -567, 622, -568, 621, -1668, 622, -566, 624, -1666, 625, -1666, 623, -567, 625, -1664, 623, -594, 598, -591, 599, -566, 621, -595, 599, -565, 625, -564, 624, -566, 625, -567, 622, -569, 622, -565, 623, -569, 623, -568, 622, -567, 622, -568, 621, -567, 624, -566, 623, -1669, 623, -1692, 597, -1666, 624, -565, 625, -566, 624, -1668, 622, -565, 623, -19985, 627, -565, 626, -564, 626, -565, 623, -566, 625, -566, 623, -593, 595, -594, 600, -565, 622, -593, 597, -567, 624, -566, 623, -567, 624, -566, 625, -565, 625, -565, 626, -564, 623, -567, 623, -567, 623, -569, 622, -566, 622, -568, 622, -569, 623, -566, 623, -567, 623, -566, 624, -567, 623, -566, 624, -568, 623, -566, 622, -1667, 625, -1665, 623, -594, 596
[21:04:13][D][remote.raw:041]: Received Raw: 81
[21:04:13][D][remote.raw:041]: Received Raw: 153
[21:04:29][D][remote.raw:041]: Received Raw: 178
[21:04:29][D][remote.raw:028]: Received Raw: 9048, -4448, 653, -1665, 623, -539, 653, -537, 650, -1668, 625, -537, 654, -537, 650, -1640, 650, -539, 652, -1639, 651, -1638, 651, -539, 652, -1638, 653, -538, 651, -539, 650, -540, 652, -538, 650, -539, 652, -539, 651, -537, 652, -538, 652, -538, 652, -1638, 651, -540, 652, -537, 653, -538, 650, -567, 623, -539, 651, -539, 651, -1639, 652, -566, 623, -1639, 652, -538, 653, -537, 652, -1638, 652, -539, 651, -19956, 653, -1638, 653, -539, 652, -536, 650, -541, 650, -1666, 627, -536, 654, -536, 650, -541, 653, -537, 650, -539, 653, -565, 625, -537, 652, -538, 652, -1638, 652, -540, 650, -541, 649, -565, 625, -566, 624, -538, 651, -539, 651, -539, 653, -537, 652, -565, 624, -539, 652, -538, 652, -539, 649, -539, 653, -564, 625, -1639, 652, -539, 650, -539, 652, -565, 625, -7187, 9047, -4453, 653, -1640, 649, -566, 625, -540, 651, -1637, 652, -538, 651, -539, 651, -1638, 653, -538, 650, -1640, 651, -1640, 652, -537, 652, -1637, 653, -537, 652, -541, 649, -538, 653, -538, 652, -540, 649, -565, 626, -539, 651, -539, 653, -537, 652, -1637, 652, -538, 653, -537, 652, -565, 625, -564, 627, -537, 653, -537, 652, -1664, 627, -1636, 653, -1637, 654, -563, 626, -538, 653, -1637, 653, -537, 651, -19956, 653, -539, 654, -537, 650, -566, 625, -538, 652, -538, 652, -538, 654, -536, 651, -539, 652, -538, 653, -564, 624, -539, 651, -539, 651, -539, 651, -538, 651, -540, 651, -538, 653, -538, 652, -537, 652, -538, 652, -565, 624, -567, 625, -538, 653, -562, 626, -538, 652, -538, 651, -540, 651, -538, 654, -536, 653, -537, 651, -1665, 627, -1637, 652, -1638, 652
[21:04:29][D][remote.raw:041]: Received Raw: 132Received Raw:
字样到下一个Received Raw:
之间的数字数组作为一条完整的红外代码。可以看到我的日志里面还有很多干扰的红外代码,这是由于我的供电不稳定导致的,可以忽略。
红外发射与Home Assistant控制
详细参见ESPHome的Remote Transmitter章节
废话不说,直接上ESPHome的编译yaml文件。
1 | esphome: |
我创建了一个switch实体,这样在Home Assistant面板上就可以直接添加空调的开关。
这里注意一个细节carrier_frequency: 38kHz
必须要有,貌似是红外的载波频率,如果没有也不能正常遥控。
现在编译上传固件,然后在你的HA面板中添加BedRoom AC Switch
,然后尝试一下控制空调。
后续改进
录制开机制热和开机制冷两种红外代码,并且优化代码结构,并且根据外部气温,判断打开空调的时候让它制热还是制冷。
1 | esphome: |
户外温度是从Home Assistant的天气中读取的,其中entity_id: weather.wo_de_jia
是HA中的实体,你可以在HA面板中的“开发者工具”中查看“现有实体”。