Announcement

Collapse
No announcement yet.

Solar Position Script

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • langenet
    replied
    @prsmith777 Nice addition. Thanks!

    Leave a comment:


  • prsmith777
    replied
    Just found this. Love it. Thanks much.

    But I couldn't get a grasp on the Azimuth, so I added a bit to make it more understandable with compass direction in the string.
    Code:
    'From c code posted here: http://www.psa.es/sdg/sunpos.htm
    'VB.NET Conversion posted here: http://www.vbforums.com/showthread.php?832645-Solar-position-calculator
    'converted for HomeSeer use by Sparkman v1.0
    
    Imports System.Math
    
    Sub Main(ByVal Parms As String)
    Dim Debug As Boolean = False
    Dim logName As String = "Solar Position"
    Dim dLatitude As Double = xxxxx
    Dim dLongitude As Double = xxxxx
    Dim hsAzimuthDevice As Integer = 5751
    Dim hsAltitudeDevice As Integer = 5750
    
    Dim pi As Double = 3.14159265358979
    Dim rad As Double = pi / 180
    Dim dEarthMeanRadius As Double = 6371.01
    Dim dAstronomicalUnit As Double = 149597890
    
    Dim iYear As Integer = DateTime.UtcNow.Year
    Dim iMonth As Integer = DateTime.UtcNow.Month
    Dim iDay As Integer = DateTime.UtcNow.Day
    Dim dHours As Double = DateTime.UtcNow.Hour
    Dim dMinutes As Double = DateTime.UtcNow.Minute
    Dim dSeconds As Double = DateTime.UtcNow.Second
    
    Dim dZenithAngle As Double
    Dim dZenithAngleParallax As Double
    Dim dAzimuth As Double
    Dim dAltitudeAngle As Double
    Dim dElapsedJulianDays As Double
    Dim dDecimalHours As Double
    Dim dEclipticLongitude As Double
    Dim dEclipticObliquity As Double
    Dim dRightAscension As Double
    Dim dDeclination As Double
    Dim dY As Double
    Dim dX As Double
    Dim dJulianDate As Double
    Dim liAux1 As Integer
    Dim liAux2 As Integer
    Dim dMeanLongitude As Double
    Dim dMeanAnomaly As Double
    Dim dOmega As Double
    Dim dSin_EclipticLongitude As Double
    Dim dGreenwichMeanSiderealTime As Double
    Dim dLocalMeanSiderealTime As Double
    Dim dLatitudeInRadians As Double
    Dim dHourAngle As Double
    Dim dCos_Latitude As Double
    Dim dSin_Latitude As Double
    Dim dCos_HourAngle As Double
    Dim dParallax As Double
    Dim intAzimuth as Integer
    Dim dirCompass as String
    
    Try
    
    ' Calculate difference in days between the current Julian Day and JD 2451545.0, which is noon 1 January 2000 Universal Time
    ' Calculate time of the day in UT decimal hours
    dDecimalHours = dHours + (dMinutes + dSeconds / 60.0) / 60.0
    ' Calculate current Julian Day
    liAux1 = (iMonth - 14) \ 12
    liAux2 = (1461 * (iYear + 4800 + liAux1)) \ 4 + (367 * (iMonth - 2 - 12 * liAux1)) \ 12 - (3 * ((iYear + 4900 + liAux1) \ 100)) \ 4 + iDay - 32075
    dJulianDate = CDbl(liAux2) - 0.5 + dDecimalHours / 24.0
    ' Calculate difference between current Julian Day and JD 2451545.0
    dElapsedJulianDays = dJulianDate - 2451545.0
    If Debug Then hs.writelog(logName,"Elapsed Julian Days Since 2000/01/01: " & CStr(dElapsedJulianDays))
    
    ' Calculate ecliptic coordinates (ecliptic longitude and obliquity of the ecliptic in radians but without limiting the angle to be less than 2*Pi
    ' (i.e., the result may be greater than 2*Pi)
    dOmega = 2.1429 - 0.0010394594 * dElapsedJulianDays
    dMeanLongitude = 4.895063 + 0.017202791698 * dElapsedJulianDays ' Radians
    dMeanAnomaly = 6.24006 + 0.0172019699 * dElapsedJulianDays
    dEclipticLongitude = dMeanLongitude + 0.03341607 * Math.Sin(dMeanAnomaly) + 0.00034894 * Math.Sin(2 * dMeanAnomaly) - 0.0001134 - 0.0000203 * Math.Sin(dOmega)
    dEclipticObliquity = 0.4090928 - 0.000000006214 * dElapsedJulianDays + 0.0000396 * Math.Cos(dOmega)
    If Debug Then hs.writelog(logName,"Ecliptic Longitude: " & CStr(dEclipticLongitude))
    If Debug Then hs.writelog(logName,"Ecliptic Obliquity: " & CStr(dEclipticObliquity))
    
    ' Calculate celestial coordinates ( right ascension and declination ) in radians but without limiting the angle to be less than 2*Pi (i.e., the result may be greater than 2*Pi)
    dSin_EclipticLongitude = Math.Sin(dEclipticLongitude)
    dY = Math.Cos(dEclipticObliquity) * dSin_EclipticLongitude
    dX = Math.Cos(dEclipticLongitude)
    dRightAscension = Math.Atan2(dY, dX)
    If dRightAscension < 0.0 Then
    dRightAscension = dRightAscension + (2 * pi)
    End If
    dDeclination = Math.Asin(Math.Sin(dEclipticObliquity) * dSin_EclipticLongitude)
    If Debug Then hs.writelog(logName,"Declination: " & CStr(dDeclination))
    
    ' Calculate local coordinates ( azimuth and zenith angle ) in degrees
    dGreenwichMeanSiderealTime = 6.6974243242 + 0.0657098283 * dElapsedJulianDays + dDecimalHours
    dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime * 15 + dLongitude) * rad
    dHourAngle = dLocalMeanSiderealTime - dRightAscension
    If Debug Then hs.writelog(logName,"Hour Angle: " & CStr(dHourAngle))
    dLatitudeInRadians = dLatitude * rad
    dCos_Latitude = Math.Cos(dLatitudeInRadians)
    dSin_Latitude = Math.Sin(dLatitudeInRadians)
    dCos_HourAngle = Math.Cos(dHourAngle)
    dZenithAngle = (Math.Acos(dCos_Latitude * dCos_HourAngle * Math.Cos(dDeclination) + Math.Sin(dDeclination) * dSin_Latitude))
    dY = -Math.Sin(dHourAngle)
    dX = Math.Tan(dDeclination) * dCos_Latitude - dSin_Latitude * dCos_HourAngle
    dAzimuth = Math.Atan2(dY, dX)
    If dAzimuth < 0.0 Then
    dAzimuth = dAzimuth + (2 * pi)
    End If
    dAzimuth = dAzimuth / rad
    
    If Debug Then hs.writelog(logName,"Azimuth: " & CStr(dAzimuth))
    
    intAzimuth =CInt(dAzimuth)
    Select Case intAzimuth
    Case 0 to 11
    dirCompass = "North"
    Case 12 to 34
    dirCompass = "North North East"
    Case 35 to 56
    dirCompass = "North East"
    Case 57 to 78
    dirCompass = "East North East"
    Case 79 to 101
    dirCompass = "East"
    Case 102 to 124
    dirCompass = "East South East"
    Case 125 to 146
    dirCompass = "South East"
    Case 147 to 167
    dirCompass = "South South East"
    Case 168 to 191
    dirCompass = "South"
    Case 192 to 214
    dirCompass = "South South West"
    Case 215 to 236
    dirCompass = "South West"
    Case 237 to 259
    dirCompass = "West South West"
    Case 260 to 281
    dirCompass = "West"
    Case 282 to 304
    dirCompass = "West North West"
    Case 305 to 325
    dirCompass = "North West"
    Case 326 to 349
    dirCompass = "North North West"
    Case 350 to 360
    dirCompass = "North"
    End Select
    
    hs.setdevicevaluebyref(hsAzimuthDevice,dAzimuth ,True)
    hs.setdevicestring(hsAzimuthDevice, Math.Round(dAzimuth,1).tostring & "° " & dirCompass, True)
    
    ' Parallax Correction
    dParallax = (dEarthMeanRadius / dAstronomicalUnit) * Math.Sin(dZenithAngle)
    dZenithAngleParallax = (dZenithAngle + dParallax) / rad
    dAltitudeAngle = (dZenithAngleParallax * -1) + 90
    
    If Debug Then hs.writelog(logName,"Altitude Angle: " & CStr(dAltitudeAngle))
    hs.setdevicevaluebyref(hsAltitudeDevice,dAltitudeAngle,True)
    
    
    Catch ex As Exception
    hs.WriteLog(logName, "Exception " & ex.ToString)
    End Try
    
    End Sub
    Click image for larger version  Name:	compass.png Views:	0 Size:	81.7 KB ID:	1389592

    Leave a comment:


  • dbrunt
    replied
    That Multisensor 6 looks nice but man, it's pricey! $90 CDN! It's LUX range says 0 to 30,000 though. Is that possible?

    Thought I'd share this link I found that provides a ton of interesting information about Sunrise, Sunset, Daylength and has Astonomical/Nautical/Civil twilight,Solar Noon, Moon Phases, Moon Rise & Moon Set, Azimuths and Altitudes: https://www.timeanddate.com/sun/cana...couver?month=6
    You can enter your longitude/latitude or pick location on a map...

    Leave a comment:


  • dbrunt
    replied
    I too have an ST815. It's mounted on outside patio just a few feet away from my south facing windows so I can differentiate sunny vs cloudy days. I'm currently using it's lux to open/close them rather than sunrise/sunset so they open and close based on morning and evening luminance. Currently I am using <40 and >40 and disabling the triggered event and enabling its twin event so each event only triggers once a day.

    However, I want to reopen the SE blind earlier and as the sun wanes westward reopen the S blind followed later by the SW blind so I can't use the single outside lux, hence my interest in this scripting. I don't want to hard code times and values as I want to automagically tune them from April to October.

    Leave a comment:


  • sparkman
    replied
    Originally posted by dmiller View Post
    I found it easier to put a multisensor 6 between the blinds and the windows. If luminance is over 1500 lux the sun is shining through the widow. I'll probably add some logic to close the blinds at a lower light level if the TV is on.

    I find that trees and partly cloudy days make projecting luminosity problematic.

    The multisensor is the only device I found that could be pointed out the windows and not immediately max out the sensor. Most devices clip before 1000 lux, which doesn't allow differentiation between a sunless sky and direct sunshine.
    I use some Everspring ST815 luminance sensors as they go up to 3000lux.

    Leave a comment:


  • dmiller
    replied
    I found it easier to put a multisensor 6 between the blinds and the windows. If luminance is over 1500 lux the sun is shining through the widow. I'll probably add some logic to close the blinds at a lower light level if the TV is on.

    I find that trees and partly cloudy days make projecting luminosity problematic.

    The multisensor is the only device I found that could be pointed out the windows and not immediately max out the sensor. Most devices clip before 1000 lux, which doesn't allow differentiation between a sunless sky and direct sunshine.

    Leave a comment:


  • dbrunt
    replied
    Yes, that helps greatly. Mine are venetian so 0 is closed down, 50 is flat and 99 is closed up so my adjustment is from 50 to 99 and then back to 50. I may have to tweak the script but I'll get it figured out. Thanks again,
    Daniel

    Leave a comment:


  • sparkman
    replied
    Originally posted by dbrunt View Post
    Hi Al,

    Many thanks for this great solution! I've been struggling for a few days with how to auto-adjust my 3 south facing iBlinds controlled window blinds to shield the sun and just discovered this thread. I've implemented the virtual devices and scripts and will see tomorrow how the blinds react. I have a south facing Everspring outdoor luminance meter to test for LUX as a group condition (>2500) so that the blinds don't close on cloudy days and also only if date is > spring equinox and < fall equinox.

    One question though is how does the third parameter 'value for adjusting the altitude to determine the shade position' affect the blind positioning? I have one that is SE, one is S and one is SW so I want to adjust them differently. SE would tilt up earlier and then back to 50% by solar noon, S would fully close up just after solar noon and then gradually return to 50% somewhat before sunset and SW would fully close later in the day returning to 50% closer to sunset. Maybe if I sleep on it, things will be clearer tomorrow...
    You're welcome. That value is a multiplier that multiplies the solar altitude with whatever you use as a multiplier to create a value to be used as the position value for the shade. For my shades, 0 is closed and 99 open. So if the solar altitude was 33 degrees and the multiplier is 2, then the shade position would be set at 66. For my mid-day events, I use a value of 1.4. The multiplier is determined by trial and error and will not be consistent throughout the day, so you may need different events for different portions of the day. Most of my shade events have conditions for a range of solar azimuths. Also,I don't use the script for all my shade events, most events just set the shade to a specific value when the solar azimuth and altitude are in the ranges set by the event conditions. Hope that helps, if not, let me know.

    Cheers
    Al

    Leave a comment:


  • dbrunt
    replied
    Hi Al,

    Many thanks for this great solution! I've been struggling for a few days with how to auto-adjust my 3 south facing iBlinds controlled window blinds to shield the sun and just discovered this thread. I've implemented the virtual devices and scripts and will see tomorrow how the blinds react. I have a south facing Everspring outdoor luminance meter to test for LUX as a group condition (>2500) so that the blinds don't close on cloudy days and also only if date is > spring equinox and < fall equinox.

    One question though is how does the third parameter 'value for adjusting the altitude to determine the shade position' affect the blind positioning? I have one that is SE, one is S and one is SW so I want to adjust them differently. SE would tilt up earlier and then back to 50% by solar noon, S would fully close up just after solar noon and then gradually return to 50% somewhat before sunset and SW would fully close later in the day returning to 50% closer to sunset. Maybe if I sleep on it, things will be clearer tomorrow...

    Leave a comment:


  • langenet
    replied
    Thanks again Al. I have the living room and office south facing as well. I'm inspired to put this to use soon!

    How often is the event called?

    Leave a comment:


  • sparkman
    replied
    Originally posted by Richel View Post

    This works great! Thanks for posting it. Now, I have to figure out how to use it to close my motorized blinds. Elliott
    Glad that it's working for you. I just posted some examples on how I use it, along with the script in this post: https://forums.homeseer.com/forum/de...42#post1286742

    Leave a comment:


  • sparkman
    replied
    Originally posted by langenet View Post

    Al this is very interesting. So you call this via an event and pass in the three parameters? How often is this run? How is the multiplier parameter determined? Hit/miss.
    I will be purchasing some Bali blinds very soon so I'm keenly interested in implementing this.. Would you mind showing your event?

    As well, do you use Alexa and do you know if you can tell Alexa to open/close the blinds natively. I suppose using Jon's helper that's possible but wasn't sure if Alexa supports this.

    Thanks,

    Robert
    Hi Robert, yes, called from events with 3 parameters. See the example events for what triggers them. The multiplier can be a bit of trial and error, but the numbers I picked initially are pretty close. There's also a minimum change that's hard coded in the script (4%) so that the blinds don't adjust too often. I don't use Alexa but assume that it will work as the child devices look like switches and dimmers inside HS.

    This event deals with the morning and early afternoon sun in a south facing window. I'll modify it when it gets a bit warmer out to close as well if no one is home, whereas in the winter, I typically want it open to get more of the solar heat. I may just base it on forecasted high temps.

    Click image for larger version  Name:	Capture.PNG Views:	1 Size:	182.3 KB ID:	1287972

    This event deal with sun later in the afternoon for the same window. There's a TV in the corner of the room and this prevents the sun shining on it, so one of the conditions is that the TV is on (right now it's assumed that when the receiver is on the TV is on).

    Click image for larger version  Name:	Capture2.PNG Views:	1 Size:	136.7 KB ID:	1287973

    Leave a comment:


  • langenet
    replied
    Originally posted by sparkman View Post

    Light levels (ie. how bright it is outside) and in one room, whether the TV is on and whether the room is occupied. I also plan to factor outside temperature and potentially the forecast high termperature to see if shades on the south side of the house should be closed. In the winter, I want them open as much as possible to get the heat from the sun, unless the low sun shines on the tv or in people's eyes that are sitting in the room. I only have a few blinds automated at this point and it's unlikely I'll do more soon, so I don't plan to develop a general purpose script/web page/plugin for it. It's kind of trial and error to determine the azimuth range, elevation and brightness of the sun for which to lower the shades and by how much. Here's a script that I run for one room which uses a multiplier with the azimuth to determine the position (0 is fully closed for my blinds and 99 is fully open).

    Code:
    Sub Main(ByVal Parms as String)
    
    dim Debug as Boolean = False
    Dim logName As String = "Solar Shade" 'set log name for HS log
    
    Dim ParmArray() as String
    ParmArray = Parms.tostring.split(",")
    dim devSolarAltitude as Double = CDbl(ParmArray(0)) 'reference ID of the device to use for Solar Altitude
    dim devShadePosition as Double = CDbl(ParmArray(1)) 'reference ID of the shade/blind device
    dim Multiplier as Double = CDbl(ParmArray(2)) 'value for adjusting the altitude to determine the shade position
    
    Dim SolarAltitude As Double
    Dim CurrentShadePosition,NewShadePosition As Integer
    SolarAltitude = hs.DeviceValueEx(devSolarAltitude)
    CurrentShadePosition = hs.DeviceValue(devShadePosition)
    
    If Debug Then hs.writelog(logName,CStr(devSolarAltitude) & ":" & CStr(SolarAltitude))
    
    NewShadePosition = CInt(SolarAltitude * Multiplier)
    If Math.Abs(NewShadePosition - CurrentShadePosition) > 4 Then 'only adjust the shades if change is more than 4%
    Select Case NewShadePosition
    Case 1 to 98
    ' Device DIM, set its current dim level
    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, CStr(NewShadePosition), false, true))
    If Debug Then hs.writelog(logName,CStr(devShadePosition) & ":" & CStr(NewShadePosition))
    Case > 98
    ' Device ON, set it to on
    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, "On", false, false))
    If Debug Then hs.writelog(logName,CStr(devShadePosition) & " Set to On")
    Case < 1
    ' Device OFF, set it to off
    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, "Off", false, true))
    If Debug Then hs.writelog(logName,CStr(devShadePosition) & " Set to Off")
    End Select
    Else
    If Debug Then hs.writelog(logName,"Blinds Not Adjusted as only different by " & Math.Abs(NewShadePosition - CurrentShadePosition) & "%")
    End If
    
    End Sub
    Al this is very interesting. So you call this via an event and pass in the three parameters? How often is this run? How is the multiplier parameter determined? Hit/miss.
    I will be purchasing some Bali blinds very soon so I'm keenly interested in implementing this.. Would you mind showing your event?

    As well, do you use Alexa and do you know if you can tell Alexa to open/close the blinds natively. I suppose using Jon's helper that's possible but wasn't sure if Alexa supports this.

    Thanks,

    Robert

    Leave a comment:


  • Richel
    replied
    Originally posted by sparkman View Post
    Below is a script that will calculate the solar azimuth and altitude (i.e. the position of the sun in the sky) and put the values in two virtual devices. ...
    This works great! Thanks for posting it. Now, I have to figure out how to use it to close my motorized blinds. Elliott

    Leave a comment:


  • sparkman
    replied
    Originally posted by Ltek View Post

    How are you doing it?
    Light levels (ie. how bright it is outside) and in one room, whether the TV is on and whether the room is occupied. I also plan to factor outside temperature and potentially the forecast high termperature to see if shades on the south side of the house should be closed. In the winter, I want them open as much as possible to get the heat from the sun, unless the low sun shines on the tv or in people's eyes that are sitting in the room. I only have a few blinds automated at this point and it's unlikely I'll do more soon, so I don't plan to develop a general purpose script/web page/plugin for it. It's kind of trial and error to determine the azimuth range, elevation and brightness of the sun for which to lower the shades and by how much. Here's a script that I run for one room which uses a multiplier with the azimuth to determine the position (0 is fully closed for my blinds and 99 is fully open).

    Code:
    Sub Main(ByVal Parms as String)
    
        dim Debug as Boolean = False
        Dim logName As String = "Solar Shade"                    'set log name for HS log
    
        Dim ParmArray() as String
        ParmArray = Parms.tostring.split(",")
        dim devSolarAltitude as Double = CDbl(ParmArray(0))        'reference ID of the device to use for Solar Altitude
        dim devShadePosition as Double = CDbl(ParmArray(1))        'reference ID of the shade/blind device
        dim Multiplier as Double = CDbl(ParmArray(2))            'value for adjusting the altitude to determine the shade position
    
        Dim SolarAltitude As Double
        Dim CurrentShadePosition,NewShadePosition As Integer
        SolarAltitude = hs.DeviceValueEx(devSolarAltitude)
        CurrentShadePosition = hs.DeviceValue(devShadePosition)
    
        If Debug Then hs.writelog(logName,CStr(devSolarAltitude) & ":" & CStr(SolarAltitude))
    
        NewShadePosition = CInt(SolarAltitude * Multiplier)
        If Math.Abs(NewShadePosition - CurrentShadePosition) > 4 Then 'only adjust the shades if change is more than 4%
            Select Case NewShadePosition
                Case 1 to 98
                    ' Device DIM, set its current dim level
                    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, CStr(NewShadePosition), false, true))
                    If Debug Then hs.writelog(logName,CStr(devShadePosition) & ":" & CStr(NewShadePosition))
                Case > 98
                    ' Device ON, set it to on
                    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, "On", false, false))
                    If Debug Then hs.writelog(logName,CStr(devShadePosition) & " Set to On")
                Case < 1
                    ' Device OFF, set it to off
                    hs.CAPIControlHandler(hs.CAPIGetSingleControl(devShadePosition, false, "Off", false, true))
                    If Debug Then hs.writelog(logName,CStr(devShadePosition) & " Set to Off")
            End Select
        Else
            If Debug Then hs.writelog(logName,"Blinds Not Adjusted as only different by " & Math.Abs(NewShadePosition - CurrentShadePosition) & "%")
        End If
    
    End Sub

    Leave a comment:

Working...
X