I’ve written before about getting custom motorized blinds for all my windows at my new house.
They are great. So for my new Dream Office, I wanted to also have blinds, but I wanted them to be “perfect”.
Perfect here means: I never want to have to adjust them, they should do exactly what I would have done, as if they were reading my mind.
Here are my rules:
- Default to open, maximize light if possible
- Lower (but not fully close) the shades to prevent direct sunlight from pouring in more than a foot past the window sill
- Stay open during rainy days
- Close at night for privacy
Of course we won’t be able to do these things without some automation.
To do that, I would need to encode my requirements in code, and then remote control them.
Throw in a Bond Bridge, and I get a great local API to use:
Let me walk you through my iteration towards achieving my perfect automatic blinds.
Level 1: Sunrise, Sunset, and Time
Using the Bond app, you can set up the blinds & shades to open and close on a schedule.
This is a pretty great start.
Open the blinds during the day, close them during the night.
But, as the sun is beaming right into my eyeballs, this feels … not quite satisfactory.
Also, I don’t want an app!
Level 2: Summer and Winter Schedules
With grouping and schedules, you can get pretty far with setting some blinds to open and some blinds to close during particular times.
With a lot of schedule setting, you could make blinds on the East side of your house close during the morning, and the West side close during the late afternoon.
Still not perfect though. What about rainy or cloudy days? I don’t want them to follow the schedule.
The problem is that these times are variable, dependent on Daylight Savings, and of course, the sun moves around during the year. These schedules are static.
We need to get fancier.
Level 3: Buy a Sensor
Smartwings actually will sell you a sensor that can get you closer to perfect shades.
It can close the shades during sunlight times, and open them when the sun goes away.
The biggest problem here is the fact that it is binary. It just isn’t quite perfect. It can control multiple shades at once, but for my house, I have different windows at different angles. I don’t want a light sensor for every window.
Also, it requires a AAA battery?? Why is the thing not solar powered???
Level 4: Perfect Automatic Blind Control with MATH
If you knew my exact latitude & longitude, the exact date & time, and the exact window geometry, then I can tell you exactly how far down the shades need to come down to block out the sun:

First, we need to understand how to even talk about the Sun with some terms:
- Azimuth is the compass direction the sun is at.
- Elevation is the number of degrees up off the horizon line.

You don’t need to call any APIs to compute these values. If you know the time and location, you can compute exactly where the sun is with just math. I used this go-solar library to do that.
That is a huge amount of heavy lifting done for me.
Ok so we can know where the Sun is in space at any particular time.
Now I need to answer the question of: Is the sun directly shining into my house, given a particular window geometry?
With a particular sun input (Azimuth & Elevation) and window geometry (height, max_depth, max_azimuth, azimuth), we can write a function that returns 0 (open) to 100 (fully closed).
Here is the literal code:
func calculateTarget(b *Blind, azi, elev float64) int {
// Horizontal Check
diff := math.Abs(azi - b.Orientation)
if diff > 180 {
diff = 360 - diff
}
if diff > (b.AziWidth / 2) {
return 0
}
// Vertical Check (Trees/Roof)
if elev < b.MinElev || elev > b.MaxElev {
return 0
}
// Percentage Tracking Logic
// effectiveElev adjusts for window tilt: a 90° (vertical) window uses elev as-is;
// a 45° skylight shifts the effective angle so sun must be steeper to penetrate.
effectiveElev := elev - (90 - b.Tilt)
rad := effectiveElev * (math.Pi / 180)
targetShadow := b.SillHeight + b.WinHeight - (b.MaxDepth * math.Tan(rad))
// Next we need a number between 0-100 for the blinds API.
pct := int((targetShadow / b.WinHeight) * 100)
if pct < 0 {
return 0
}
if pct > 100 {
return 100
}
return pct
}
This works great!
From math principles, we can compute exactly where the blinds should be, for any particular window, at any particular time:
Dealing with Weather
Well, it is great until you have a cloudy day. Then I found myself asking: why are the blinds closed when I don’t need them to be?
Remember, I want to maximize light, but my math doesn’t know what the weather is… yet?
No problem: I got a free API key from openweathermap.org which can give me a percent cloud cover at my exact location.
Next problem: It is all a lie :)
The API will return cloud cover 95%, the blinds will stay open, but the sun will just be burning my eyes out.
It just can’t be that precise.
It is looking at my zip code, not my back yard.
I thought I was going to have to solder up some sensors or something. Then I realized: I already have a sensor that can tell me how bright the sun is shining exactly at my house: My solar panels!

With solar panels, combined with exact knowledge about the sun’s azimuth and elevation, I can compute exactly how much power they would be producing IF it was sunny.
I already have the data readily in MQTT thanks to a previous project!
With this “ground truth” (since it is a ground-mounted solar array), I can be 100% sure if the sun is shining on my property. In fact, it isn’t even a binary number; I can tell you how cloudy it is by comparing the output to its theoretical ideal.
When you put all the math and data together, you get my perfect automatic blinds:
Rounding Errors
Looking at the time lapse, you may notice how “jerky” it is.
At first, I continuously adjusted the blinds with the 1% precision that the API allowed.
It was too much. Constantly moving these blinds a few centimeters every couple of minutes is distracting.
Even if it would make for a better time lapse video, I set it to only bother moving the blinds if it would make a >5% difference.
Why Each Window Has a “Mind of its Own”
In each of the videos you may notice that each individual window seems to have its own schedule.
This is the fine-grained math at work.
Very few windows in my house have the exact same geometry.
Most face different compass directions, or have different heights, or have different “max elevation” settings (the max incoming angle of the sun that even matters due to the roof).
There are some windows that, just due to where they point, will never move (for example, if they face North).
I personally think it is cool. Each window gets its own calculation. Some windows that activate now will end up not moving at all during the winter time.
Some windows slowly lower till about noon and then open up all the way once the sun has gone overhead.
I just really like how they all end up doing their own custom thing, but it is derived from their physical properties, not through a ton of hand-tuning.
Conclusion
This was such a cool thing to build.
I had to refresh my trig knowledge and I learned about how the Sun’s location is computed in space.
It just feels so cool every time my blinds automatically lower themselves just enough to block the blinding light.
Comment via email
