add feedback cover component (#1942)

This commit is contained in:
Adrián Panella 2022-08-09 00:21:30 -05:00 committed by GitHub
parent abd30d2bcb
commit 475933a41f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 288 additions and 0 deletions

View File

@ -0,0 +1,267 @@
Feedback Cover
==============
.. seo::
:description: Instructions for setting up feedback covers in ESPHome.
The ``feedback`` cover platform allows you to create covers with position control that
can optionally have feedback from sensors to detect the fully-open and fully-closed states (endstops),
and from sensors to detect actual movement (opening/closing). In all the cases the current
position is approximated with the time the cover has been moving in a direction.
It supports *open*, *close*, *stop* and *toggle* actions. Tilt control is not supported.
.. figure:: images/more-info-ui.png
:align: center
:width: 50.0%
.. code-block:: yaml
# Example configuration entry
cover:
- platform: feedback
name: "Gate"
open_action:
- switch.turn_on: open_cover_switch
open_duration: 2.1min
open_endstop: open_endstop_binary_sensor
open_sensor: open_movement_binary_sensor
close_action:
- switch.turn_on: close_cover_switch
close_duration: 2min
close_endstop: close_endstop_binary_sensor
close_sensor: close_movement_binary_sensor
stop_action:
- switch.turn_off: open_cover_switch
- switch.turn_off: close_cover_switch
Use Cases
---------
It is a versatile cover that can accommodate for a number of DIY setups, or monitoring an externally controlled cover:
Time-Based
**********
Simplest case, when no sensors are available. The state is thus assumed.
It is a drop-in replacement of :doc:`/components/cover/time_based`
Endstop Sensors
***************
For cases where there are endstops at one or both ends of the cover to detect the fully-open and fully-closed states.
When any of these endstops are reached, an actual state is read and updated and the cover optionally
stopped (via ``stop_action``). The state is not assumed.
The extension also handles the case where the cover has builtin endstops, which stops the movement, independently to
the component's logic. In this case, when the cover is fully closed (either if timed based or sensor based) the
``stop_action`` is not triggered.
It is a drop-in replacement of :doc:`/components/cover/endstop`.
Movement Sensors
****************
If movement feedback is available, the cover no longer operates in *optimistic mode* (assuming that movement starts
as soon as an action is triggered) and can also react to commands issued to cover from an external control and still
keep states in sync (useful for "smartization" of and existing cover).
When there are no specific endstop sensors, and if the cover has builtin endstops and no external control logic,
these movement sensors can optionally be use to infer the endstop state.
When the movement stops (with no stop action being requested) it is assumed that it was caused by
the builtin endstops, and so the close/open state (according to current direction) was reached.
This function is activated setting ``infer_endstop`` to True.
It can be used to replace a :doc:`/components/cover/current_based`, with some modifications in the yaml. See :ref:`migrating_current_based`
Safety Features
---------------
To protect the cover hardware from damage, some safety options are available:
- *Max duration*, to protect from faulty endstops
- *Direction change wait time*, like an interlock wait time, to protect motors from sudden direction changes
- *Obstacle sensors* and *rollback*, possibility to stop and optionally rollback the cover when some external sensors detects an obstacle
(it might be a sensor for high current consumption or an infrared light detecting an obstruction in the path).
Configuration variables
-----------------------
- **name** (**Required**, string): The name of the cover.
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
- **stop_action** (**Required**, :ref:`Action <config-action>`): The action that should
be performed when the remote requests the cover to be closed or an endstop is reached.
Open options:
- **open_action** (**Required**, :ref:`Action <config-action>`): The action that should
be performed when the remote requests the cover to be opened.
- **open_duration** (**Required**, :ref:`config-time`): The amount of time it takes the cover
to open up from the fully-closed state.
- **open_endstop** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when the open position is reached.
- **open_sensor** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when the cover is moving in the open direction.
- **open_obstacle_sensor** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when an obstacle that blocks the
open direction is detected.
Close options:
- **close_action** (**Required**, :ref:`Action <config-action>`): The action that should
be performed when the remote requests the cover to be closed.
- **close_duration** (**Required**, :ref:`config-time`): The amount of time it takes the cover
to close from the fully-open state.
- **close_endstop** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when the closed position is reached.
- **close_sensor** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when the cover is moving in the close direction.
- **close_obstacle_sensor** (**Optional**, :ref:`config-id`): The ID of the
:ref:`Binary Sensor <config-binary_sensor>` that turns on when an obstacle that blocks the
close direction is detected.
Additional options:
- **has_built_in_endstop** (*Optional*, boolean): Indicates that the cover has built in end stop
detectors. In this configuration the ``stop_action`` is not performed when the open or close
time is completed and if the cover is commanded to open or close the corresponding actions
will be performed without checking current state. Defaults to ``false``.
- **infer_endstop_from_movement** (*Optional*, boolean): Whether to infer endstop state from the movement sensor.
Requires movement sensors to be set, no endstop sensors and to have builtin endstops. Defaults to ``false``.
- **assumed_state** (*Optional*, boolean): Whether the true state of the cover is not known.
This will make the Home Assistant frontend show buttons for both OPEN and CLOSE actions, instead
of hiding or disabling one of them. Defaults to ``true`` if no sensor is available to known
the actual state of the cover.
- **max_duration** (*Optional*, :ref:`config-time`): The maximum duration the cover should be opening
or closing. Useful for protecting from dysfunctional endstops.
Requires internal, builtin or inferred endstops.
- **direction_change_wait_time** (*Optional*, :ref:`config-time`): Stops cover and forces a wait time between changes in direction,
and takes it into account when computing cover position (useful to protect motors).
When this option is set (even at 0s) if an open/close action is invoked while the cover is moving in the opposite direction,
then and intermediate stop action will be invoked to generate the delay.
- **acceleration_wait_time** (*Optional*, :ref:`config-time`): Considers a wait time needed by the cover to actually
start moving after command is issued and takes it into account when computing cover position
(useful for heavy covers with large inertia).
Intended to not accumulate error when doing multiple partial open/close actions).
The open/close duration includes one instance of this delay, as it is the total amount of time from
issuing a command to reaching endstop.
Defaults to ``0s``.
- **update_interval** (*Optional*, :ref:`config-time`): The interval
to publish updated position information to the UI while the cover is moving.
Defaults to ``1s``.
- **obstacle_rollback** (*Optional*, percentage): The percentage of rollback the cover will perform in case of
obstacle detection while moving. Defaults to ``10%``.
- All other options from :ref:`Cover <config-cover>`.
Example Configurations
----------------------
.. _migrating_current_based:
Migrating Current-Based Cover
*****************************
Most options can be left untouched, but some modifications are needed:
1. All current sensing related options must be moved to auxiliary :doc:`/components/binary_sensor/analog_threshold`,
to convert current readings to binary sensors, using the corresponding thresholds and delays.
If there where any open/close obstacle current threshold defined, a separate binary sensor with that threshold should be defined.
The option ``start_sensing_delay`` should be directly replaced by a ``delayed_off`` filter in the movement sensors, or alternatively
hysteresis options could be used to reduce the noise.
2. To have the very same behavior implicit in current based cover, you must always set ``has_built_in_endstop`` and ``infer_endstop_from_movement``
to True.
.. code-block:: yaml
# Example original sensor configuration
cover:
- platform: current_based
name: "Current Based Cover"
open_sensor: open_current_sensor
open_moving_current_threshold: 0.5
open_obstacle_current_threshold: 0.8
start_sensing_delay: 0.8s
# ...rest of options
# Example converted sensor configuration
binary_sensor:
- platform: analog_threshold
id: open_binary_sensor
sensor_id: open_current_sensor
threshold: 0.5
filter:
- delayed_off: 0.8s
- platform: analog_threshold
id: open_obstacle_binary_sensor
sensor_id: open_current_sensor
threshold: 0.8
# ... repeat for close sensors
cover:
- platform: feedback
name: "Feedback Based Cover"
has_built_in_endstop: true
infer_endstop_from_movement: true
open_sensor: open_binary_sensor
open_obstacle_sensor: open_obstacle_binary_sensor
#... rest of options
3. Malfunction detection is not directly supported by Feedback Cover, as the malfunction was very narrowly defined to a specif use case
(while in other hardware configurations, the same situation is perfectly valid).
The malfunction alerted specifically when there was current in the opposite direction of the requested operation (possibly due to a relay welded).
This detection can still be achieved by putting the logic directly in the switch, (or whatever needed according to your specific use case).
.. code-block:: yaml
# Example original malfunction configuration
cover:
- platform: current_based
close_sensor: close_current
close_action:
- switch.turn_on: open_relay
open_sensor: open_current
open_action:
- switch.turn_on: open_relay
malfunction_detection: true
malfunction_action:
- logger.log: "Malfunction detected. Relay welded."
#... rest of options
# Example converted malfunction configuration
switch:
- platform: gpio
id: open_relay
#... rest of options
on_turn_off:
- delay: 200ms #allow for switching time and any discharge
- if:
condition:
binary_sensor.is_on: open_binary_sensor
# alternative can check directly
# on sensor.in_range open_current
then:
- logger.log: "Malfunction detected. Relay welded."
See Also
--------
- :doc:`index`
- :ref:`automation`
- :apiref:`feedback/feedback_cover.h`
- :ghedit:`Edit`

20
images/feedback_cover.svg Normal file
View File

@ -0,0 +1,20 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<g class="layer">
<title>Layer 1</title>
<path d="m3.859691,11l4,0l0,-2l4,0l0,2l4,0l0,-7l-12,0l0,7m12,2l-12,0l0,7l12,0l0,-7m-12,-11l12,0a2,2 0 0 1 2,2l0,16a2,2 0 0 1 -2,2l-12,0a2,2 0 0 1 -2,-2l0,-16a2,2 0 0 1 2,-2z" id="svg_1" transform="matrix(1 0 0 1 0 0)"/>
<ellipse cx="19.177173" cy="20.221166" fill="#ffffff" id="svg_6" rx="2.437574" ry="2.437574" stroke="#000000" stroke-opacity="0"/>
<use fill="#000000" id="svg_3" stroke="#000000" stroke-opacity="0" transform="matrix(0.333333 0 0 0.333333 0 0)" x="45.303208" xlink:href="#svg_2" y="47.800236"/>
<use fill="#4c4c4c" id="svg_7" transform="matrix(0.232786 0 0 0.232786 62.8523 13.3204)" x="-194.266223" xlink:href="#svg_4" y="-13.118657"/>
<use fill="#4c4c4c" id="svg_8" transform="matrix(0.232786 0 0 0.232786 104.588 20.2169)" x="-373.555514" xlink:href="#svg_4" y="-74.414128"/>
<use fill="#4c4c4c" id="svg_9" transform="matrix(0.232786 0 0 0.232786 146.443 25.5677)" x="-553.866324" xlink:href="#svg_4" y="-76.45732"/>
<use fill="#4c4c4c" id="svg_10" transform="matrix(0.232786 0 0 0.232786 146.205 28.2869)" x="-552.333963" xlink:href="#svg_4" y="-98.421519"/>
</g>
<defs>
<symbol height="24" id="svg_2" version="1.1" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="m12,20a7,7 0 0 1 -7,-7a7,7 0 0 1 7,-7a7,7 0 0 1 7,7a7,7 0 0 1 -7,7m7.03,-12.61l1.42,-1.42c-0.45,-0.51 -0.9,-0.97 -1.41,-1.41l-1.42,1.44c-1.55,-1.26 -3.5,-2 -5.62,-2a9,9 0 0 0 -9,9a9,9 0 0 0 9,9c5,0 9,-4.03 9,-9c0,-2.12 -0.74,-4.07 -1.97,-5.61m-8.03,6.61l2,0l0,-6l-2,0m4,-7l-6,0l0,2l6,0l0,-2z"/>
</symbol>
<symbol height="24" id="svg_4" version="1.1" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="m1,11l2.17,0c0.41,-1.17 1.52,-2 2.83,-2c0.65,0 1.25,0.21 1.74,0.56l6.7,-4.69l1.14,1.63l-6.69,4.7c0.07,0.25 0.11,0.52 0.11,0.8a3,3 0 0 1 -3,3c-1.31,0 -2.42,-0.83 -2.83,-2l-2.17,0l0,-2m22,0l0,2l-2.17,0c-0.41,1.17 -1.52,2 -2.83,2a3,3 0 0 1 -3,-3a3,3 0 0 1 3,-3c1.31,0 2.42,0.83 2.83,2l2.17,0m-17,0a1,1 0 0 0 -1,1a1,1 0 0 0 1,1a1,1 0 0 0 1,-1a1,1 0 0 0 -1,-1m12,0a1,1 0 0 0 -1,1a1,1 0 0 0 1,1a1,1 0 0 0 1,-1a1,1 0 0 0 -1,-1z"/>
</symbol>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -565,6 +565,7 @@ Cover Components
Cover Core, components/cover/index, folder-open.svg Cover Core, components/cover/index, folder-open.svg
Template Cover, components/cover/template, description.svg Template Cover, components/cover/template, description.svg
Feedback Cover, components/cover/feedback, feedback_cover.svg
Endstop Cover, components/cover/endstop, electric-switch.svg Endstop Cover, components/cover/endstop, electric-switch.svg
Current-Based Cover, components/cover/current_based, flash.svg Current-Based Cover, components/cover/current_based, flash.svg
Time-Based Cover, components/cover/time_based, timer.svg Time-Based Cover, components/cover/time_based, timer.svg