Open santibur06 opened 4 years ago
What about a roller_shutter_delay
?
The thing is, when cover goes down 100% it will start counting this roller shutter delay, we can accumulate this in the tilt state
Is the roller stopping by itself? or is ESPHome commanding it to stop? can you share your yaml?
When cover goes up, if it is shuttered then we un shuttered it first, consume the shutter delay time and then we start updating the cover position.
Also related to https://github.com/esphome/feature-requests/issues/664 but not exactly the same
roller has built-in end stops so it stops by itself.
so, based on what you propose, position would stay at 0% while the cover is going up during that roller_shutter_delay right?
what do you think about using 10% of movement for that shutter delay?
0-10%: Cover goes up, consuming the _roller_shutterdelay. 11-100%: Cover goes up consuming the _(openduration - roller shutter delay)
That way you would still see position being updated whenever the cover is moving and you would also be able to set the cover to 10% and let some light come in while the window is still 100% covered.
Don't know if I'm explaining myself correctly..
here's my full yaml:
substitutions:
devicename: "8282400e6d"
upper_devicename: "8282400e6d"
cover_name: "8282400e6d"
esphome:
name: $devicename
platform: ESP8266
board: esp01_1m
wifi:
networks:
- ssid: !secret wifi_ssid
password: !secret wifi_password
- ssid: !secret wifi2_ssid
password: !secret wifi2_password
- ssid: !secret wifi3_ssid
password: !secret wifi3_password
reboot_timeout: 0s
# fast_connect: true
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: $upper_devicename
password: !secret wifi_password
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
# enabling web server
# web_server:
# port: 80
status_led:
pin:
number: GPIO13
inverted: yes
binary_sensor:
- platform: gpio
id: button_open
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
on_press:
- cover.open: my_cover
- platform: gpio
id: button_stop
pin:
number: GPIO09
mode: INPUT_PULLUP
inverted: True
on_press:
- cover.stop: my_cover
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.5s
- ON for at most 0.5s
- OFF for at most 0.5s
- ON for at most 0.5s
- OFF for at most 0.5s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.turn_on: sonoff_restart
- platform: gpio
id: button_close
pin:
number: GPIO10
mode: INPUT_PULLUP
inverted: True
on_press:
- cover.close: my_cover
switch:
- platform: restart
name: $upper_devicename Reboot
id: sonoff_restart
- platform: gpio
pin: GPIO12
interlock: &interlock [open_cover, close_cover]
restore_mode: always off
id: open_cover
- platform: gpio
pin: GPIO4
interlock: *interlock
restore_mode: always off
id: close_cover
cover:
- platform: time_based
name: $cover_name
id: my_cover
open_action:
- switch.turn_on: open_cover
open_duration: 10s
close_action:
- switch.turn_on: close_cover
close_duration: 10s
stop_action:
- switch.turn_off: open_cover
- switch.turn_off: close_cover
And what is the difference between that and what you already have?
Right now if I set the position to 50% it will unroll (the delay) and then go up but since already consumed the delay it stops at around 30% kf the window
What I'm saying is that while we unshutter it we update position but from 0 to 10% max so we can also control the unshuttering from HA. Right now it will say like 20% when it finishes unshuttering. By maxing it at 10% (or even 5%) we'll get the cover stop at more or less half the window and ir will say 50%
Hi @glmnet, just wondering if you had time to check this out.
Thanks!
Oh I am not the only one having those issues for roller covers!
Let me throw my idea here, just to see if it makes sense for this context:
ESPhome has a powerful system of filters. Right now, the code for filters is focused on sensors and using that outside the sensors seems to be hackish (I tried and half-succeeded with workarounds). However, it makes sense --in my head, at least-- to abstract those filter things into a C++ class that can be used from other components. I opened the #755 to discuss that specific refactoring, but the specifics of the consequences and potential for the cover component is more on-topic here.
To fix some ideas, let me put an example of how I would imagine my proposal. Let's start with the yaml definition:
cover:
- platform: time_based
name: "My Fancy Cover"
#(... open, close action and durations ...)
open_filters: &common_filters
- calibrate_polynomial:
degree: 2
datapoints:
- 0.0 -> 0.0
- 0.1 -> 0.15
- 0.5 -> 0.75
- 1.0 -> 1.0
close_filters: *common_filters
# conceivable case: open and close need different filters
Which would translate to: "when 10% of time has passed, the cover is opened 15%. When 50% time has passed, the cover is opened 75%".
Calibrate polynomial seems the most useful filter right now. I have an implementation of a calibrate_spline
filter, which uses spline fitting (piecewise polynomial functions). It seems to be working, I will deploy that in my ESP cover control and polish it.
At C++ level, I imagine reusing the same code geneartion that is instantiating filters but instead of instantiating them into the filter_list_
attribute of the sensor component, instantiate a FilterChain
instance which will have the filter_list_
and its appropriate methods (add_filters
, set_filters
, a new transform_value
, etc.). That FilterChain
will be used also from time based covers that are using the open_filters
and close_filters
configuration entries.
Does it make sense? I know that it seems overkill, but note that roller_shutter_delay
is not a silver-bullet as the linear speed is not constant: typically those motor have constant rotation speed, which means that the linear speed is greater when there is more cover rolled (because radius increases) and in my experiments it was quite noticeable.
hey guys @glmnet @alexbarcelo, just wondering if you were able to take a look at this, I'm struggling with my shutters, position is totally off and the feature is useless in my setup. Do you guys know of any workaround I could put in place to fix this in the meantime? I'm sorry for asking but I would implement this code fix myself if I had any idea on where to start, it's been a while since I don't touch code other than yaml... thanks!
@alexbarcelo I like your idea of using filters to create a custom "curve" for time/position relation ship. I'm in the same boat as @santibur06 - my blinds take a few seconds to start moving after issuing a command. Have you been successful in implementing your idea?
I think being able to specify this filter for opening and closing independently would be useful. In my case when the blinds are rotating to close there's a spot where they are kind of stuck for a second or so, and then rapidly move to the right position, so it would be great to be able to account for that.
Also to not depend on the refactoring required (#755) for implementing your idea, I was thinking to simply build the non-liner config into the time_based
cover. e.g something like:
cover:
- platform: time_based
name: "Balcony Louvres"
open_action:
- switch.turn_on: btn_open
open_duration: 11s
open_curve:
- 0.0 -> 0.0
- 0.4 -> 0.0
- 0.9 -> 1.0
- 1.0 -> 1.0
close_action:
- switch.turn_on: btn_close
close_duration: 10s
close_curve:
- 0.0 -> 0.0
- 0.1 -> 0.0
- 0.3 -> 0.3
- 0.4 -> 0.3
- 0.42 -> 0.4
- 0.8 -> 1.0
- 1.0 -> 1.0
stop_action:
- switch.turn_on: btn_stop
Alternatively the curve can be configured using time (to make configuration more intuitive):
close_duration: 10s
close_curve:
# 0 -> 0.0 implied
- 1s -> 0.0
- 3s -> 0.3
- 4s -> 0.3
- 4.2s -> 0.4
- 8s -> 1.0
# 10s -> 1.0 implied
@alexbarcelo what do you think?
@muxa "to simply build the non-liner config into the time_based cover" means to have certain redundancy of code, as the filters (as they are now) are not meant to be used outside the list of filters in a sensor.
Either you use those filters from outside a sensor --which will be troublesome, as the includes at C level are only granted when there are sensor components, thus making things a little bit tricky, at least in my limited knowledge of the code generation. And filters are instantiated by sensor and within a list and there's some implicit constraints here and there.
Or you add more code in the cover component, making it a bit redundant and repeating yourself --meaning more documentation and more code to maintain for two things that are very similar and behave in a very similar fashion.
I may have missed something. I was waiting for any opinion and directions from members of ESPHome, before attempting a clean PR for that (I have some hackish ugly fragile workaround for my use case, but I need to start from scratch if I want to share that). Maybe some of my assumptions are bogus? Maybe I am being overzealous on DRY matters?
@alexbarcelo I was coming with my suggestion from the premise of keeping changes isolated, but at the expense of potential code duplication.
@OttoWinter can you please comment on a preferred approach?
Code duplication for these components is fine with me. We likely won't have to touch these code areas much anyway (and if so, it's not hard to update).
The only major thing to think about here is user experience. If there are 10 different cover platforms doing essentially the same thing, it can be confusing for the user to choose the right one (a lot of this also comes down to good docs).
Why use sensor filters
though here? The backend already has support for tilt
(so the backend can report how far the individual elements are tilted). Can't we just tell the device "this is how long it takes to tilt the elements", then:
0
using supplied duration, then decrease position.1
, then position.Ok, that makes sense. Let me clean up my code and I'll be back with a PR in a few days.
I am not sure I am following you regarding the tilt thing. My covers don't physically "tilt" (not as I understand the word, non-native speaker here, maybe I am misunderstanding things). And what you are describing doesn't fit my problems: "varying speed covers" (typical roller shutter ones). Maybe it would be enough for some use cases, but I will argue that my approach solves both my use case and this other use case. Hope it makes sense.
Regarding the user experience: I will do the PR with changes on the timed based cover, as it is something that only makes sense for time based covers and is completely optional (no breaking changes). So I hope that this would not be confusing to the user --they will look into the time based cover and decide which features do they want.
leaving out of discussion tilt at all... the time -> position function makes sense on it's own, e.g. for covers which are rolling, assume a constant rotation speed of motor, the more it rolled up, the faster the cover actually goes up as the roll becomes thicker. This is just too much of details for myself, and I'm just saying that it makes sense, I wouldn't care setting up this for myself let alone implementing it.
As for the position vs time and the limits, e.g. totally open = 100%? Imagine your cover opens fully but the motor keeps winding it for a while even though you don't see the window more open, then you should set your time to the time it is fully open, not the time the motor stops, this will have the effect of the position being reported correctly at 100%. The same will be when closing the cover...
Lets imagine a cover which closes fully at 2:00 and then 15 more seconds to shut light down completely, I'd setup the close time so the position 0% = CLOSED is reached in 2:00 ... then the motor will continue shutting light down for additional 15 seconds... then this time will be consumed in the tilt state (we need to give 15 seconds time to tilt).
This is the same I wrote in the second post here, mostly. I see Otto says first decrease tilt, then decrease position, this might make sense for one type of cover, where first decreasing position and then tilt might make sense for other types of covers. I believe both can be supported without much difference.
For the decrease position then tilt, these covers apply: https://www.youtube.com/watch?v=IT06zwM87Xw For the tilt then position I'm not really sure
@alexbarcelo Have you implemented this PR yet? I'm dealing with the same issue, and can look into it, if you like.
Actually the idea of a non-linear time-based cover would be very useful for controlling motorized valves, since opening the valve is almost linear but closing it is pretty far from linear behaviour. What is your progress on this issue? :-)
I have a somewhat usable proof of concept of non-linear (a linear piecewise function) actuation. It works non-linearly, however, I have messed things and there is some inverted evaluation or something fishy. I had my hands full with my day job and some other urgent-er DIY projects, so my implementation is on "marination".
I will try to allocate some free time to clean up my code, fix the fishy math and do a PR. Probably I would complete that in a week or so :crossed_fingers:
+1 on this feature, it would be quite useful.
Any luck with the code @alexbarcelo ? I'm having the same problem with controlling shutter on specific level.
+1 on this feature also for me, it would be very useful indeed. thanks a lot!!
I added some discussion on my just-pushed PR, but maybe it is better to have it here given that the discussion has been already brewing for a while:
I have no idea how to address the
restore
mechanism. My first approach is to haveposition
the real position of the cover and use atime_position
to track the time. However, the component tracks thetime_position
, but this attribute is not stored in the restore structure, so it cannot be set. This means that the restore does not work as intended.The decision to use
position
andtime_position
also do not sit well with the idea of the time_based cover that open and close can have diferent durations. Maybe my approach is wrong? Maybe I have to throw this and start from scratch? For my scenario of a "time symmetric" cover it works good enough, but that may not be flexible enough.
I feel like I was trying to attain a "minimal changes approach" and ended up with a botched incomplete mess.
What is the status of the "calibration" implementation?? that will be great!!!
Yes, I would like to see somthing like this for my german shutters...
could be cool to port this feature as it is implemented in tasmota. Unfortunately I can't convert shutters and buttons to esphome because of the poor implementation that they have in comparison to tasmota.
@luca-iodice maybe not the users here are familiar with Tasmota (I myself have never flashed nor used it). Can you elaborate on how does Tasmota handle covers? Or point to a documentation / source code that discusses it?
It is really nice, you can different types of shutters and - most important - a calibration. Old video here: https://www.youtube.com/watch?v=Z-grrvnu2bU
I have "normal" shutters, but I need at least a calibration as possible via ShutterSetHalfway.
Describe the problem you have/What new integration you would like I'm using the time-based cover component to control my window's Roller Shutter Blinds and it works perfectly with the exception of the position calculation which seems to be a bit more complex to calculate for roller shutter blinds.
So right now the component calculates position like this:
Pretty simple, at least that's how I understand it works.
So, position should also mean how far up the cover is from the bottom of the window, so 50% would mean my window is half covered.
That's where this component is not compatible with roller shutter blinds... Say the cover is all the way down, motor has stopped rotating on its own cause it reached the bottom. Now I issue the up command and it starts rotating, it is moving up, but segment by segment, and it takes it like 5 seconds (in my case) to actually start uncovering the window. So that's 5 seconds I lose but the component is calculating the position, so by the time my window is 50% uncovered, the component thinks the cover is at 70% or more.
So yeah, the actual position of the cover may be 70% but it is not covering 30% of my window, it's actually covering 50%.
I would really like to have a way tell the component how long it takes the cover from position 0% to actually start moving up and uncovering my window.
It would work something like this:
0% - Cover all the way down 10% - Cover has rolled up a bit and light can pass by it, but it's still covering the entire window. 11% - Cover is not covering the entire window anymore, it actually started moving up. 50% - Cover is more or less covering 50% of my window. 100% - Cover is all the way up.
Please describe your use case for this integration and alternatives you've tried: This would not only be useful for Roller Shutters but also for some garage covers that show the same behavior.
Additional context I'm using Sonoff T1, 3 gang to control the shutters and aside from the issue mentioned above, it works excellent.