329 lines
9.6 KiB
ReStructuredText
329 lines
9.6 KiB
ReStructuredText
Arduino Port Expander
|
|
=====================
|
|
|
|
.. seo::
|
|
:description: Instructions on using an Arduino board, like the Pro Mini for expanding ports of an ESPHome node
|
|
:image: arduino_logo.svg
|
|
:keywords: Arduino port expander extender ESPHome
|
|
|
|
With this sketch you can control pins of a remote Arduino board through ESPHome. The Arduino acts as a port
|
|
expander, allowing you to use more pins than a standard ESP8266/ESP32 has.
|
|
|
|
.. figure:: images/arduino_pro_mini.jpg
|
|
:align: center
|
|
:width: 75.0%
|
|
|
|
The Arduino is connected to the ESP via I²C. Most Arduinos use the ``A4`` and ``A5`` pins for the I²C bus
|
|
so those pins are not available to read from ESPHome.
|
|
It is recommended to use a 3.3V I/O level Arduino, however using 5V Arduinos seems to work too. In the latter
|
|
case you should power your 5V Arduino with 3.3V otherwise you will need a level converter for the
|
|
I²C bus.
|
|
|
|
Currently it is supported:
|
|
|
|
- reading digital inputs
|
|
- reading analog inputs
|
|
- writing digital outputs
|
|
|
|
The Arduino sketch can be retrieved from `here <https://gist.github.com/glmnet/49ca3d6a9742fc3649f4fbdeaa4cdf5d#file-arduino_port_expander_sketch-ino>`__
|
|
you can rename it to ``.ino`` and use the Arduino IDE to program it.
|
|
|
|
You need to download `arduino_port_expander.h <https://gist.github.com/glmnet/49ca3d6a9742fc3649f4fbdeaa4cdf5d#file-arduino_port_expander-h>`__
|
|
and include the arduino_port_expander.h in the ESPHome configuration.
|
|
|
|
.. code-block:: yaml
|
|
|
|
esphome:
|
|
# ...
|
|
includes:
|
|
- arduino_port_expander.h
|
|
|
|
Setup your :ref:`I²C Bus <i2c>` and assign it an ``id``:
|
|
|
|
.. code-block:: yaml
|
|
|
|
i2c:
|
|
id: i2c_component
|
|
|
|
By default ESP8266 uses ``SDA`` pin ``GPIO4`` which you need to connect to Arduino's ``A4`` and the ``SCL``
|
|
is ``GPIO5`` which goes to Arduino's ``A5``.
|
|
|
|
Then create a ``custom_component``, this will be the main component we will be referencing later when creating
|
|
individual IOs.
|
|
|
|
.. code-block:: yaml
|
|
|
|
custom_component:
|
|
- id: ape
|
|
lambda: |-
|
|
auto ape_component = new ArduinoPortExpander(i2c_component, 0x08);
|
|
return {ape_component};
|
|
|
|
By default the I²C address is ``0x08`` but you can change it on the Arduino sketch so you can have more devices
|
|
on the same bus.
|
|
|
|
Now it is time to add the ports.
|
|
|
|
Binary_Sensor
|
|
-------------
|
|
|
|
When adding binary sensors the pins are configured as INPUT_PULLUP, you can use any PIN from 0 to 13 or
|
|
``A0`` to ``A3`` (``A4`` and ``A5`` are used for I²C and ``A6`` and ``A7`` do not support internal pull up)
|
|
|
|
.. note::
|
|
|
|
Arduino PIN 13 usually has a LED connected to it and using it as digital input with the built in internal
|
|
pull up might be problematic, using it as an output is preferred.
|
|
|
|
To setup binary sensors, create a custom platform as below, list in braces all the sensors you want,
|
|
in the example below two binary sensors are declared on pin 9 and A0 (number 14)
|
|
|
|
Then declare the ESPHome reference of the binary sensor in the same order as declared in the lambda:
|
|
|
|
.. code-block:: yaml
|
|
|
|
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: Binary sensor pin 2
|
|
- id: binary_sensor_pin3
|
|
name: Binary sensor pin 3
|
|
on_press:
|
|
...
|
|
|
|
The listed ``binary_sensors`` supports all options from :ref:`Binary Sensor <config-binary_sensor>` like
|
|
automations and filters.
|
|
|
|
Sensor
|
|
------
|
|
|
|
Sensors allows for reading the analog value of an analog pin, those are from ``A0`` to ``A7`` except for
|
|
``A4`` and ``A5``. The value returned goes from 0 to 1023 (the value returned by the Arduino ``analogRead``
|
|
function).
|
|
|
|
Arduino analog inputs measures voltage. By default the sketch is configured to use the Arduino internal VREF
|
|
comparer setup to 1 volt, so voltages bigger are read as 1023. You can configure Arduino to compare the
|
|
voltage to VIN voltage, this voltage might be 5 volts or 3.3 volts, depending on how you are powering it. To
|
|
do so, pass an additional true value to the hub constructor:
|
|
|
|
.. code-block:: cpp
|
|
|
|
auto ape_component = new ArduinoPortExpander(i2c_component, 0x08, true);
|
|
|
|
To setup sensors, create a custom platform as below, list in braces all the sensors you want,
|
|
in the example below two sensors are declared on pin ``A1`` and ``A2``
|
|
|
|
Then declare the ESPHome reference of the sensor in the same order as declared in the lambda:
|
|
|
|
.. code-block:: yaml
|
|
|
|
sensor:
|
|
- platform: custom
|
|
lambda: |-
|
|
return {ape_analog_input(ape, 1), // 1 = A1
|
|
ape_analog_input(ape, 2)};
|
|
sensors:
|
|
- name: Analog A1
|
|
id: analog_a1
|
|
filters:
|
|
- throttle: 1s
|
|
- name: Analog A2
|
|
id: analog_a2
|
|
filters:
|
|
- throttle: 2s
|
|
|
|
The listed ``sensors`` supports all options from :ref:`Sensor <config-sensor>` like
|
|
automations and filters.
|
|
|
|
.. note::
|
|
|
|
Sensors are polled by default every loop cycle so it is recommended to use the ``throttle`` filter
|
|
to not flood the network.
|
|
|
|
Output
|
|
------
|
|
|
|
Arduinos binary outputs are supported in pins from 0 to 13.
|
|
|
|
To setup outputs, create a custom platform as below, list in braces all the outputs you want,
|
|
in the example below two outputs are declared on pin ``3`` and ``4``
|
|
|
|
.. code-block:: yaml
|
|
|
|
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: Switch pin 3
|
|
output: output_pin_3
|
|
|
|
light:
|
|
- platform: binary
|
|
name: Switch pin 4
|
|
output: output_pin_4
|
|
|
|
Full Example
|
|
------------
|
|
|
|
Let's connect a 4 channel relay board and 2 push buttons to toggle the relays, a PIR sensor, a window and a door
|
|
a LM35 temperature sensor and a voltage sensor. Seems a bit too much for an ESP8266? You'll still have some
|
|
spares I/Os.
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
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
|
|
|
|
# define i2c device
|
|
# for an ESP8266 SDA is D2 and goes to Arduino's A4
|
|
# SCL is D1 and goes to Arduino's A5
|
|
i2c:
|
|
id: i2c_component
|
|
|
|
logger:
|
|
level: DEBUG
|
|
|
|
# define the port expander hub, here we define one with id 'expander1',
|
|
# but you can define many
|
|
custom_component:
|
|
- id: expander1
|
|
lambda: |-
|
|
auto expander = new ArduinoPortExpander(i2c_component, 0x08, true);
|
|
return {expander};
|
|
|
|
# define binary outputs, here we have 4, as the relays are inverse logic
|
|
# (a path to ground turns the relay ON), we defined the inverted: true
|
|
# option of ESPHome outputs.
|
|
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
|
|
|
|
# connect lights to the first 2 relays
|
|
light:
|
|
- platform: binary
|
|
id: ceiling_light
|
|
name: Ceiling light
|
|
output: relay_1
|
|
- platform: binary
|
|
id: room_light
|
|
name: Living room light
|
|
output: relay_2
|
|
|
|
# connect a fan to the third relay
|
|
fan:
|
|
- platform: binary
|
|
id: ceiling_fan
|
|
output: relay_3
|
|
name: Ceiling fan
|
|
|
|
# connect a pump to the 4th relay
|
|
switch:
|
|
- platform: output
|
|
name: Tank pump
|
|
id: tank_pump
|
|
output: relay_4
|
|
|
|
|
|
# define binary sensors, use the Arduino PIN number for digital pins and
|
|
# for analog use 14 for A0, 15 for A1 and so on...
|
|
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 # don't show on HA
|
|
on_press:
|
|
- light.toggle: ceiling_light
|
|
- id: push_button2
|
|
internal: true # don't show on HA
|
|
on_press:
|
|
- light.toggle: room_light
|
|
- id: pir_sensor
|
|
name: Living PIR
|
|
device_class: motion
|
|
- id: window_reed_switch
|
|
name: Living Window
|
|
device_class: window
|
|
- id: garage_door
|
|
name: Garage garage
|
|
device_class: garage_door
|
|
|
|
# define analog sensors
|
|
sensor:
|
|
- platform: custom
|
|
lambda: |-
|
|
return {ape_analog_input(expander1, 1), // 1 = A1
|
|
ape_analog_input(expander1, 2)};
|
|
sensors:
|
|
- name: LM35 Living room temperature
|
|
id: lm35_temp
|
|
filters:
|
|
# update every 60s
|
|
- throttle: 60s
|
|
# LM35 outputs 0.01v per ºC, and 1023 means 3.3 volts
|
|
- lambda: return x * 330.0 / 1023.0;
|
|
- name: Analog A2
|
|
id: analog_a2
|
|
filters:
|
|
- throttle: 2s
|
|
|
|
|
|
|
|
See Also
|
|
--------
|
|
|
|
- :ghedit:`Edit`
|