Arduino 端口扩展器

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

图像

Arduino通过I²C连接到ESP。大多数Arduino使用A4A5引脚作为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,而SCLGPIO5,它连接到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的任何引脚或A0A3A4A5用于I²C,A6A7不支持内部拉起)

ℹ️ Note

Arduino引脚13通常连接有一个LED,使用它作为数字输入与内置内部拉起可能存在问题,建议使用它作为输出。
要设置二进制传感器,创建一个自定义平台如下,在大括号中列出所有您想要的传感器,在下面的示例中,两个二进制传感器在引脚9和A0(编号14)上声明

然后在同一顺序中声明二进制传感器的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

传感器允许读取模拟引脚的模拟值,这些引脚从A0A7,除了A4A5。返回的值从0到1023(Arduino analogRead函数返回的值)。

Arduino模拟输入测量电压。默认情况下,草图配置为使用Arduino内部VREF比较器设置为1伏,所以电压更高的被读作1023。您可以将Arduino配置为将电压与VIN电压进行比较,这个电压可能是5伏或3.3伏,具体取决于您如何为其供电。为此,向中心构造函数传递一个额外的true值:

auto ape_component = new ArduinoPortExpander(i2c_component, 0x08, true);

要设置传感器,创建一个自定义平台如下,在大括号中列出所有您想要的传感器,在下面的示例中,两个传感器在引脚A1A2上声明

然后声明传感器的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的引脚。

要设置输出,创建一个自定义平台如下,在大括号中列出所有您想要的输出,在下面的示例中,两个输出在引脚34上声明

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

参见