basbruss / adaptive-cover

An Adaptive Cover component for HomeAsisstant to control covers based on the sun's position
MIT License
73 stars 10 forks source link

Lower minimum on shaded area distance and/or 'zero shade distance' for fully closed blind until sun out of view #276

Open ThreeFN opened 1 month ago

ThreeFN commented 1 month ago

Checklist

Is your feature request related to a problem? Please describe.

I have second story due east/west windows with vertical blinds that even with set to 0.1m shaded area distance, they let a sliver if the light well into the room because the elevation/shade distance triangle is solved some 6m up from the ground.

Describe the solution you'd like

Some possible math solution ideas I've thought of that may be options: -Add window height above ground as a component of the elevations/shade area distance triangle. This should mean that shade distance will be measured at the floor and not at the window base height as the current setup functions -Allow for a lower minimum distance than 0.1m effectively allowing for the above to be 'tuned' without changing as much code -Allow a '0m' distance edge case to shade distance such that window will be closed until sun is out of view (eg a due east window would be closed from sunrise (elevation 0deg) until solar noon (elevation 90deg)). This would probably have to be coded as an edge case to not have divide by zero problems with the geometry math

Describe alternatives you've considered

-Allow adding an 'offset' to the sun elevation for user to tune (not an elegant solution I admit) -documentation guidance about 'exagerating' window height to artificially reduce the shade distance

Additional context

My experience may be exacerbated by the fact that the windows in question are only about 25-40cm tall. Based on my understanding of the math involved, the blinds will never 'find' a mathematical result where the window doesn't let some light in, and in my experience I would still like that opening to be more closed than the 0.1m shade distance allows for. I could 'exaggerate' the window height to skew the solution triangle to accommodate for a more closed result, but it seems inelegant and not as user friendly to those unfamiliar with the mechanics of how this automation works.

16-9 commented 3 weeks ago

I support the idea of capturing the window height above ground.

I have such a window, much lower than you, a foot above the ground. If the top of my window and my shade are 83" above the ground, I suspect that the % cover is miscalculated because the shade at 0% will reach only 12" above ground. 100% covers a movement spans of 71", which means that 1% equates 0.71", while the integration will assume 0.83" per 1%. Meanwhile if I state that the cover height is 71", and get the right percentage, then the height offset will be off.

The calculation of h = (d / cos(γ)) * tan(α) shall not change. However, the mapping to a cover position will. Assume T for top of the cover and B for bottom of the cover, then cover position is:

position = (h - b)/(t - b)*100.

If b = 0, position = h/83100. If b = 12, position = h/73100 - 12/73100 = h/73100 - 16.4

Not quite the same as you can see.

There might be an alternative approach to achieve the same result with some of the optional configurations, but I'll wait to read from @basbruss to find out.

basbruss commented 3 weeks ago

Some possible math solution ideas I've thought of that may be options: -Add window height above ground as a component of the elevations/shade area distance triangle. This should mean that shade distance will be measured at the floor and not at the window base height as the current setup functions

This could introduce issues with using absolute position values since the entire operation would then be calculated over a height/triangle side larger than the window or cover itself. On the other hand, we could subtract some height from the window plane to raise the base of the geometric triangle.

-Allow for a lower minimum distance than 0.1m effectively allowing for the above to be 'tuned' without changing as much code

However, lowering this parameter too much could reduce the effectiveness of the adaptive function. Getting too close to zero might lead to unwanted anomalies.

-Allow a '0m' distance edge case to shade distance such that window will be closed until sun is out of view (eg a due east window would be closed from sunrise (elevation 0deg) until solar noon (elevation 90deg)). This would probably have to be coded as an edge case to not have divide by zero problems with the geometry math

Adding an edge case to avoid divide-by-zero problems in the geometry calculations creates unneeded complexity to the code. However, this approach goes against the system's purpose of optimizing natural light while avoiding direct sunlight. If needed, you could create an automation using a binary sensor that closes the blinds fully when triggered.

basbruss commented 3 weeks ago

I have such a window, much lower than you, a foot above the ground. If the top of my window and my shade are 83" above the ground, I suspect that the % cover is miscalculated because the shade at 0% will reach only 12" above ground. 100% covers a movement spans of 71", which means that 1% equates 0.71", while the integration will assume 0.83" per 1%. Meanwhile if I state that the cover height is 71", and get the right percentage, then the height offset will be off.

The window height parameter is in many cases not the distance between the ground and the top of the window. It is exactly the height of the window measured from the bottom of the window to the top or it can be the total length of the cover between 0% and 100%.

16-9 commented 3 weeks ago

Duly noted, thanks for the clarification.

At the end of the day, what matters is how the adaptive cover maintains shading past self.distance. If we introduce b_win: float that measures the height from the ground to the bottom of the window, then I'd propose that the blind_height calculation be modified in calculate_position in the following manner;

blind_height = np.clip( (self.distance / cos(rad(self.gamma))) * tan(rad(self.sol_elev)), self.b_win, self.h_win + self.b_win, ) - self.b_win

calculate_percentage remains the same.

@ThreeFN, I made a few assumptions about your configuration. I positioned 2 x 1m-high window, 1 facing West and 1 facing East, 6m above ground, in a not-so-average location in the US (dont' ask ;-) )

With the current model, in the morning, the East shade progressively travels from 0% (at about 6:30 am) to 100% (at about 13:30), living behind a 10cm light sliver initially on the West wall and then migrating on the floor toward the East wall. The newly proposed calculation starts and ends at the same times but your shade will be fully closed during the whole duration without any configuration change.

For the West side, immediately after the East shade opens, the West shade travels from 100% to 0% (at about 20:30), again casting that light sliver the other way around. The new calculation results in an immediate drop to 0% and maintains it to the end of the cycle.

This configuration got me thinking that we could conceptually think of a reverse-protected distance down the road, where the distance would not be exposed to the sun but rather to the shadow cast by the wall below the window. If ThreeFN's room is 25m-wide east-west, he would set the distance to 25 and check the reverse-protection box. Doing so would allow the East shade to trigger 1 hour later at about 7:40am; likewise, the West shade would open up an hour earlier at about 19:30.

The sliver distance from the wall is: np.clip((self.b_win * cos(rad(self.gamma))) / tan(rad(self.sol_elev)),0,1000)