Arduino 端口扩展器
通过这个草图,您可以通过ESPHome控制远程Arduino板的引脚。Arduino充当端口扩展器,允许您使用比标准ESP8266/ESP32更多的引脚。

Arduino通过I²C连接到ESP。大多数Arduino使用A4
和A5
引脚作为I²C总线,因此这些引脚不可用于从ESPHome读取。
建议使用3.3V I/O电平的Arduino,但使用5V Arduino似乎也可以工作。在后一种情况下,您应该用3.3V为您的5V Arduino供电,否则您需要为I²C总线提供一个电平转换器。
目前支持:
- 读取数字输入
- 读取模拟输入
- 写入数字输出
Arduino草图可以从this gist获取,您可以将其重命名为.ino
并使用Arduino IDE来编程它。
您需要下载arduino_port_expander.h 并在ESPHome配置中包含arduino_port_expander.h。
esphome:
# ...
includes:
- arduino_port_expander.h
设置您的I²C总线并为其分配一个id
:
i2c:
id: i2c_component
默认情况下,ESP8266使用SDA
引脚GPIO4
,您需要将其连接到Arduino的A4
,而SCL
是GPIO5
,它连接到Arduino的A5
。
然后创建一个custom_component
,这将是我们稍后在创建单个IO时参考的主要组件。
custom_component:
- id: ape
lambda: |-
auto ape_component = new ArduinoPortExpander(i2c_component, 0x08);
return {ape_component};
默认的I²C地址是0x08
,但您可以在Arduino草图中更改它,以便在同一总线上拥有更多设备。
现在,是时候添加端口了。
Binary_Sensor
添加二进制传感器时,引脚配置为INPUT_PULLUP,您可以使用从0到13的任何引脚或A0
到A3
(A4
和A5
用于I²C,A6
和A7
不支持内部拉起)
要设置二进制传感器,创建一个自定义平台如下,在大括号中列出所有您想要的传感器,在下面的示例中,两个二进制传感器在引脚9和A0(编号14)上声明ℹ️ Note
Arduino引脚13通常连接有一个LED,使用它作为数字输入与内置内部拉起可能存在问题,建议使用它作为输出。
然后在同一顺序中声明二进制传感器的ESPHome引用:
binary_sensor:
- platform: custom
lambda: |-
return {ape_binary_sensor(ape, 9),
ape_binary_sensor(ape, 14) // 14 = A0
};
binary_sensors:
- id: binary_sensor_pin2
name: 二进制传感器引脚2
- id: binary_sensor_pin3
name: 二进制传感器引脚3
on_press:
...
列出的binary_sensors
支持来自Binary Sensor的所有选项,如自动化和过滤器。
Sensor
传感器允许读取模拟引脚的模拟值,这些引脚从A0
到A7
,除了A4
和A5
。返回的值从0到1023(Arduino analogRead
函数返回的值)。
Arduino模拟输入测量电压。默认情况下,草图配置为使用Arduino内部VREF比较器设置为1伏,所以电压更高的被读作1023。您可以将Arduino配置为将电压与VIN电压进行比较,这个电压可能是5伏或3.3伏,具体取决于您如何为其供电。为此,向中心构造函数传递一个额外的true值:
auto ape_component = new ArduinoPortExpander(i2c_component, 0x08, true);
要设置传感器,创建一个自定义平台如下,在大括号中列出所有您想要的传感器,在下面的示例中,两个传感器在引脚A1
和A2
上声明
然后声明传感器的ESPHome引用,与lambda中声明的顺序相同:
sensor:
- platform: custom
lambda: |-
return {ape_analog_input(ape, 1), // 1 = A1
ape_analog_input(ape, 2)};
sensors:
- name: 模拟A1
id: analog_a1
filters:
# 每60秒更新一次
- throttle: 60s
# LM35输出0.01伏每摄氏度,1023表示3.3伏
- lambda: return x * 330.0 / 1023.0;
- name: 模拟A2
id: analog_a2
filters:
- throttle: 2s
列出的sensors
支持来自Sensor的所有选项,如自动化和过滤器。
ℹ️ Note
传感器默认每轮循环周期被轮询,因此建议使用throttle
过滤器以避免淹没网络。
Output
Arduino的二进制输出支持从0到13的引脚。
要设置输出,创建一个自定义平台如下,在大括号中列出所有您想要的输出,在下面的示例中,两个输出在引脚3
和4
上声明
output:
- platform: custom
type: binary
lambda: |-
return {ape_binary_output(ape, 3),
ape_binary_output(ape, 4)};
outputs:
- id: output_pin_3
inverted: true
- id: output_pin_4
inverted: true
switch:
- platform: output
name: 开关引脚3
output: output_pin_3
light:
- platform: binary
name: 开关引脚4
output: output_pin_4
完整示例
让我们连接一个4通道继电器板和2个按钮来切换继电器,一个PIR传感器,一个窗户和一个门,一个LM35温度传感器和电压传感器。看起来对ESP8266来说有点太多了?您仍然有一些剩余的I/O。
esphome:
name: test_arduino
includes:
- arduino_port_expander.h
esp8266:
board: nodemcu
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
ota:
platform: esphome
# 定义I2C设备
# 对于ESP8266,SDA是D2,连接到Arduino的A4
# SCL是D1,连接到Arduino的A5
i2c:
id: i2c_component
logger:
level: DEBUG
# 定义端口扩展器中心,这里我们定义一个id为'expander1'的,
# 但您可以定义多个
custom_component:
- id: expander1
lambda: |-
auto expander = new ArduinoPortExpander(i2c_component, 0x08, true);
return {expander};
# 定义二进制输出,这里我们有4个,因为继电器是反向逻辑
# (接地路径使继电器开启),我们定义了ESPHome输出的inverted: true
# 选项。
output:
- platform: custom
type: binary
lambda: |-
return {ape_binary_output(expander1, 2),
ape_binary_output(expander1, 3),
ape_binary_output(expander1, 4),
ape_binary_output(expander1, 5)};
outputs:
- id: relay_1
inverted: true
- id: relay_2
inverted: true
- id: relay_3
inverted: true
- id: relay_4
inverted: true
# 将灯连接到前两个继电器
light:
- platform: binary
id: ceiling_light
name: 天花板灯
output: relay_1
- platform: binary
id: room_light
name: 客厅灯
output: relay_2
# 将风扇连接到第三个继电器
fan:
- platform: binary
id: ceiling_fan
output: relay_3
name: 天花板风扇
# 将泵连接到第4个继电器
switch:
- platform: output
name: 水箱泵
id: tank_pump
output: relay_4
# 定义二进制传感器,使用Arduino的数字引脚编号,对于模拟引脚使用14
# 表示A0,15表示A1,等等...
binary_sensor:
- platform: custom
lambda: |-
return {ape_binary_sensor(expander1, 7),
ape_binary_sensor(expander1, 8),
ape_binary_sensor(expander1, 9),
ape_binary_sensor(expander1, 10),
ape_binary_sensor(expander1, 14) // 14 = A0
};
binary_sensors:
- id: push_button1
internal: true # 不要在HA中显示
on_press:
- light.toggle: ceiling_light
- id: push_button2
internal: true # 不要在HA中显示
on_press:
- light.toggle: room_light
- id: pir_sensor
name: 客厅PIR
device_class: 运动传感器
- id: window_reed_switch
name: 客厅窗户
device_class: 窗户
- id: garage_door
name: 车库门
device_class: 车库门
# 定义模拟传感器
sensor:
- platform: custom
lambda: |-
return {ape_analog_input(expander1, 1), // 1 = A1
ape_analog_input(expander1, 2)};
sensors:
- name: LM35 客厅温度
id: lm35_temp
filters:
# 每60秒更新一次
- throttle: 60s
# LM35输出0.01伏每摄氏度,1023表示3.3伏
- lambda: return x * 330.0 / 1023.0;
- name: 模拟A2
id: analog_a2
filters:
- throttle: 2s