OpenSprinkler Forums OpenSprinkler Unified Firmware Penmen-Monteith ETo method python script for possible use as weather script

Viewing 25 posts - 26 through 50 (of 65 total)
  • Author
  • #39484


    Since it calculates nearly everything based on yesterday’s data I run it about 10 minutes after midnight, to account for time differences. The running every 15 minutes does nothing after about 1 am. My best guess as to why this happens is data and averaging being finalized by WU. Their data will vary slightly for the “yesterday” portion of the JSON for about an hour.
    The only other time to run anything would be just before a set run time to make sure the wind, temp, and conditions (precipitation), are still acceptable for watering.



    That makes sense. Thanks again for your help Shawn.

    So do I need to do something special with the time? Right now, the script wants to upload [-1,-1,-1,-1],[0,129,0,110,238,0,174,0,0,238,103] to my program. However this causes the time to be sunset -2047 minutes or Sunrise -1d-10h-7m. Do I need to set up the program differently, or is this just the normal way the OS deals with a -1 value for the first time?



    I’ve noticed this same behavior, it doesn’t seem to affect the actual performance (as in it doesn’t run), however, you will be unable to set a start time through the app if you wanted to change it for some reason you would need to use the api commands.



    Guys…been following this thread and am excited you guys were able to put something together. I used to use Scott’s script (which I thought was awesome) prior to some upgrades (which kill the scripts). I since moved to the Unified FW and was hoping Scott would get his scripts working again.

    Anyways I’m interest on using the script…not much of a programmer…more like a hack when it comes to coding. How do you implement the script? Or should I wait…hoping its getting implemented into unified FW?




    This sounds really promising – I’m really looking forward for this to be implemented.



    I’ve updated the Misterhouse interface module to be able to upload program data, so that’s what I’m playing around with. Right now I’m just logging the changes and reviewing manually to make sure I’m not messing anything up. I like how Shawn’s script identifies things like the loss and gain of precipitation to get a sense of how the changes are being made.

    Shawn the only issue I’ve found with the script is that it ‘oops’ if there isn’t a yesterday log and ET file. Not a big deal if it runs daily, however during my tests I had a few day gap and it wouldn’t launch until I manually copied the last day with data to the yesterday file.



    This is all really great stuff. I look forward to seeing the code in operation.

    By the way, I’m very happy with my personal weather station that I’ve connected to the Weather Underground. I bought an Ambient WS 1400 for $149 plugged it in, and its been working perfectly ever since (except during power outages, or when my WiFi network is down). I put it on top of a piece of electrical conduit from Home Depot – the hardest part of the install was just mounting it. It gives me solar radiation and rainfall rate, which I figure is an important micro climate issue to work out runoff issues. 2mm/hr for 24 hrs is way different than 48mm in one hour 🙂 Given California’s El Nino situation, this could be a big issue this winter if we get torrential rains. I also live near the coast, which has a marine layer effect that can be very localized.



    I have modified the script to search backwards for the most recent ET file, it a will also create a base 0’d file if the directory is empty. Currently I’m working on modifying the OS firmware to work entirely off the SD card allowing for more accurate programs, more programs, and better history from which trends can be recognized and adjustments could be made. I haven’t posted it to github yet because I don’t want to brick anyone’s hardware. Currently it is a pseudo functional alpha version. Another week or 2 and I should have a version worth posting.



    Hi Shawn, Any update? For some reason after Aug 17th the script stopped working for me, can’t find the right log file. Before I start troubleshooting, just thought it might a better use of time to test a newer version.



    Just a quick bump to Check Shawn if you have any more updates?



    Sorry about the long delay and no responses, life has been quite hectic. I’ll get back to working on this project later this week. I should have something useful by the weekend. The few test runs I’ve made look okay, now I just have to work on polishing everything up, and remove some of the debugging portions of the code, as it is quite verbose and annoying.



    Hi Shawn, any update? Even though watering season’s over up here in the North, I’m happy to test and provide some feedback.



    Sorry to bump this, just wondering if you might be able to post your code in whatever form it is in. I’m hoping to get this into place in the spring, and have time over the winter to get it all into place.




    Well, I’ve successfully replicated this logic in perl, and track exactly the same results given the same input set. Shawn thanks again for your help!

    I think I understand the logic, but just wanted to double check a few things if that’s OK.

    – Today’s ET is the amount of moisture change by plants.
    – A positive ET means moisture has been lost, and a negative means that there is a net increase of moisture.
    – This is where I’m not that clear: After calculating today’s ET value, the previous days ET is subtracted from today’s ET to calculate the current ET. If we can’t run today for whatever reason (too cold, precipation in forecast), then we write 0’s to today’s run time. We take the current ET – todays_rain – yesterdays irrigation – a forecast adjustment. This gives us our mm target.

    – Based on the target, we then look to how many seconds are required per zone to net the ‘water balance’ to 0. So if we have an target of 8mm for grass, and it takes 60 seconds to distribute 1mm of water, then we need to run for 4 minutes.

    Did I get it right?



    You have everything worked out correctly…one note the ET, 8mm in your example, would cause your system to run for 8min, not 4.

    ET*(timeTo1mm)=water run time



    I attached a mostly working…no guarantees…zip containing firmware that incorporates ET directly into it.
    To use it you have to have an SD card installed on your controller. It will not work with OSPI, I don’t have one and didn’t bother to make the changes for it.

    compile and upload the firmware to your controller

    After it is loaded and running things will change a bit for creating and loading programs. As the current APP/UI will not work with it for a lot of features.

    1) Connect to the IP of your controller and change your password
    2) set your time zone and location
    3) add your weather key
    4) hit submit
    5) browse to h t t p ://OS-IP/cp?pw=MD5-Password&pid=-1&v=[195,127,0,[20540,16444,12318,8252],[60,60,60,4,5,6,7,0],[0,0,0,1,0,0,1,0],[50,150]]&name=Weather1mm

    this will make a program to run everyday using et with starttimes based on sunrise and set after the duration is plant height 0= <4″ 1= >4″ following that is min and max mm to water per cycle

    6) go to the controller turn off the power, hold down B3, and turn it back on.
    7) click B3 until you reach weather algo: and set it to 3

    after that you should be running, if you want to see the python script I can make that available, right now it is messy but works fine and is used as default. Use /su to change back to and use another weather algo.

    Everything should work but I make no promises, use entirely at your own risk, and modify as you see fit. I do not have the time to support this…I will respond to general questions but it may take a while.



    Thanks for the reply Shawn! That was a typo, glad I got the logic right. I really appreciate the help and answers!

    Did you make any logic changes with your revised code?



    The logic is the same but where the calculations are completed is different. My original script did everything its self, off controller. Now the adjustment is made on the controller using the output of the script similar to how the Zimmerman method works in the current firmware (216)

    I’m provided the firmware above as is…it may not work correctly, but at least some other eyeballs on it may lead to a better end result.



    My hope is to fork the current firmware soon so it is more user friendly to edit.



    Thanks again Shawn for all your help. I’ve uploaded my perl file to github, and I think I’ve covered off all the attribution. The only slight difference I see so far with this code and the python code is that sometimes WU have multiple forecasts per hour. The python grabs the cloud cover for the first forecast, and the perl grabs the last one. This is really minor, and doesn’t really change the outputs.



    I had actually considered averaging the cloud cover by hour, and after a lot of different iterations I found grabbing any of them individually would result in a net change less than the rounding error. I would say either first or last is fine. Nice job porting it over to perl, I really need to sit down and learn it. I chose python because it is great for the “just make it work” brute force style programming. Perl had a few more rules to remember :p



    So I finally made a fork to the main project and have been running it for a few days with no issues. I’m sure there are better ways to accomplish everything but it works.

    The UI has not been updated at all so it can really only be used for displaying status. To get everything working do the following:
    1) compile and upload the firmware (I used arduino 1.0.6 and usbASP on OS HW 2.1)
    2) Change password, set your timezone and location, enter WU API key, and name your zones, using the UI.
    3) Enter a program using the api (there are some changes here so I’ll provide an example)
    3a) OS-IP/cp?pw=MD5Password&pid=-1&v=[195,127,0,[20540,16444,12318,8252],[dur1,dur2,…],[planttype1,planttype2,planttype3,1,0…],[etmin,etmax]]&name=Weather1mm (OS-IP use the ip address, pid -1 adds new program, 195 uses weather and et, 127 is everyday, starttimes are based on sunrise/set,dur is duration to 1mm of precip from sprinkler, planttype 0=grass or < 4″ tall 1=shrubs or > 4″ tall, etmin/max are min and max et to water in one run * 10 eg 50,150 will water 5 to 15 mm in one run if less than 5 it won’t water, the name can be anything)

    4) Reboot the controller while holding B3 and cycle through options until you reach “Weather Algo.” and set it to 3. Hold B3 until OS resets.
    5) Enjoy happy plants and grass, with a lower water bill.

    Things to remember:
    You must have an SD card installed, and this requires a good internet connection. If the connection fails the controller will not water.
    If you change the weather algorithm used it will reset your ET based water balance. I haven’t found a good way to do this yet.
    This requires a WU key, I do not have any other weather algorithms on my server, so if you want to use Zimmerman or auto rain delay you need to change it back to

    I know there are much better ways to do this but since it seems the idea died before it got off the ground I decided to get some sort of working implementation out in the wild. If you have suggestions, comments or issues let me know on github. The developers here will probably not be huge fans of dealing with this project. The majority of the work is not mine, so please respect the original authors works.


    Martin Penev

    ET is only riht way for automatic irrigation for me. I live near Black Sea. In my arrea we have very short ligh or storm rains and near immpossible to peredict rain forecast. Auto rain delay wont work. Hydminity is average 70%-80% so Zimmermann not return adequate to watering needed results. I run OpenSprinkler in manual mode with rain sensor. ShawnHarte thank you for solution. Can you update UI? Hope that method will be implemented is official firmware and UI.



    Unfortunately, the UI baffles me, I’m working on it but it will take me a bit of time to work out what to change, and how to make everything stable with the controller. By now I figure more people have different hardware than I have so testing is a bit rough for me as I do not have the means to test anything other than 2.1.
    I also need to work out some minor changes to the firmware. For instance plant height needs to be a station attribute, not part of the program. Right now it doesn’t matter but it isn’t the right way to do it.



    Shawn, there is one use case that I can’t quite figure out. It seems like there are cases where station run times are calculated, but the number of times to water is actually 0, so the stations don’t activate. However, the logs are written as if water has been distributed. Here’s the output from your python script (with a bunch of debugging that’s been thrown in to help understand the logging):

    Don’t know if this is expected behavior, or if either ‘times’ or station runtimes are wrong. crop values are set to 0,1,0,1,1,0,1,0,0,1,1, so only grass has numbers.

    DIR: /vol/git/EvapoTranspiration
    Calculating values. Logging to /vol/git/EvapoTranspiration/logs/WeatherCustom.log
    E: json load /vol/git/EvapoTranspiration/logs/16953 ([])
    E: json load /vol/git/EvapoTranspiration/ET/16953 ([2.1595999999999997, -1.8694000000000006])
    E: for loop logs = ([])
    E: for loop l (11)
    E: yET = ([2.1595999999999997, -1.8694000000000006])
    E: ydur = ([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1])
    E: -2.1781 = round(( 2.1596 ) – ( -1 / 54 ), 4) * -1
    E: _1mmProg[‘crop’][0] = 0
    E: tET[int(_1mmProg[‘crop’][0])] = -2.1781
    E: 1.8194 = round(( -1.8694 ) – ( -1 / 20 ), 4) * -1
    E: _1mmProg[‘crop’][1] = 1
    E: tET[int(_1mmProg[‘crop’][1])] = 1.8194
    E: -2.1899 = round(( 2.1596 ) – ( -1 / 33 ), 4) * -1
    E: _1mmProg[‘crop’][2] = 0
    E: tET[int(_1mmProg[‘crop’][2])] = -2.1899
    E: 1.8106 = round(( -1.8694 ) – ( -1 / 17 ), 4) * -1
    E: _1mmProg[‘crop’][3] = 1
    E: tET[int(_1mmProg[‘crop’][3])] = 1.8106
    E: 1.8424 = round(( -1.8694 ) – ( -1 / 37 ), 4) * -1
    E: _1mmProg[‘crop’][4] = 1
    E: tET[int(_1mmProg[‘crop’][4])] = 1.8424
    E: -2.2152 = round(( 2.1596 ) – ( -1 / 18 ), 4) * -1
    E: _1mmProg[‘crop’][5] = 0
    E: tET[int(_1mmProg[‘crop’][5])] = -2.2152
    E: 1.8324 = round(( -1.8694 ) – ( -1 / 27 ), 4) * -1
    E: _1mmProg[‘crop’][6] = 1
    E: tET[int(_1mmProg[‘crop’][6])] = 1.8324
    E: -2.2096 = round(( 2.1596 ) – ( -1 / 20 ), 4) * -1
    E: _1mmProg[‘crop’][7] = 0
    E: tET[int(_1mmProg[‘crop’][7])] = -2.2096
    E: -2.1929 = round(( 2.1596 ) – ( -1 / 30 ), 4) * -1
    E: _1mmProg[‘crop’][8] = 0
    E: tET[int(_1mmProg[‘crop’][8])] = -2.1929
    E: 1.8424 = round(( -1.8694 ) – ( -1 / 37 ), 4) * -1
    E: _1mmProg[‘crop’][9] = 1
    E: tET[int(_1mmProg[‘crop’][9])] = 1.8424
    E: 1.8069 = round(( -1.8694 ) – ( -1 / 16 ), 4) * -1
    E: _1mmProg[‘crop’][10] = 1
    E: tET[int(_1mmProg[‘crop’][10])] = 1.8069
    E: Done – mmFromLogs
    E: ymm = ([-2.1781, 1.8194, -2.1899, 1.8106, 1.8424, -2.2152, 1.8324, -2.2096, -2.1929, 1.8424, 1.8069])
    E: yET = ([-2.1929, 1.8069])
    E: ET[0] = 4.13, yET[0] = -2.1929
    E: ET[1] = 4.8255, yET[1] = 1.8069
    E: aET[0] = 8.101 (0.540066666667) // mm/Day
    E: times = 0 (max 0.540066666667/min 0.540066666667 max(min(0.540066666667, 4), 0))
    E: aET[1] = 0.7992 (0.05328) // mm/Day
    E: times = 0 (max 0.05328/min 0.05328 max(min(0.05328, 4), 0))
    E: aET[2] = 8.1128 (0.540853333333) // mm/Day
    E: times = 0 (max 0.540853333333/min 0.540853333333 max(min(0.540853333333, 4), 0))
    E: aET[3] = 0.808 (0.0538666666667) // mm/Day
    E: times = 0 (max 0.0538666666667/min 0.0538666666667 max(min(0.0538666666667, 4), 0))
    E: aET[4] = 0.7762 (0.0517466666667) // mm/Day
    E: times = 0 (max 0.0517466666667/min 0.0517466666667 max(min(0.0517466666667, 4), 0))
    E: aET[5] = 8.1381 (0.54254) // mm/Day
    E: times = 0 (max 0.54254/min 0.54254 max(min(0.54254, 4), 0))
    E: aET[6] = 0.7862 (0.0524133333333) // mm/Day
    E: times = 0 (max 0.0524133333333/min 0.0524133333333 max(min(0.0524133333333, 4), 0))
    E: aET[7] = 8.1325 (0.542166666667) // mm/Day
    E: times = 0 (max 0.542166666667/min 0.542166666667 max(min(0.542166666667, 4), 0))
    E: aET[8] = 8.1158 (0.541053333333) // mm/Day
    E: times = 0 (max 0.541053333333/min 0.541053333333 max(min(0.541053333333, 4), 0))
    E: aET[9] = 0.7762 (0.0517466666667) // mm/Day
    E: times = 0 (max 0.0517466666667/min 0.0517466666667 max(min(0.0517466666667, 4), 0))
    E: aET[10] = 0.8117 (0.0541133333333) // mm/Day
    E: times = 0 (max 0.0541133333333/min 0.0541133333333 max(min(0.0541133333333, 4), 0))
    E: open(/vol/git/EvapoTranspiration/logs/16954, ‘w’)
    E: open(/vol/git/EvapoTranspiration/ET/16954, ‘w’)
    E: File: /vol/git/EvapoTranspiration/wuData/16954
    Content-Type: text/html

    Resolved your lat:xx.xxxx, lon:-xx.xxxx, they will be stored
    0.0 mm precipitation forecast for next 3 days
    0.4 mm precipitation fallen and forecast for today
    P-M ETo
    4.13 mm lost by grass
    4.8255 mm lost by shrubs
    sunrise & sunset in minutes from midnight local time
    326 1303
    Weather Station ID: xxxxxxxx
    Current logged ET [6.3229, 3.0186]
    [54, 20, 33, 17, 37, 18, 27, 20, 30, 37, 16]
    [[-1, -1, -1, -1], [437, 0, 267, 0, 0, 146, 0, 162, 243, 0, 0]]

Viewing 25 posts - 26 through 50 (of 65 total)
  • You must be logged in to reply to this topic.

OpenSprinkler Forums OpenSprinkler Unified Firmware Penmen-Monteith ETo method python script for possible use as weather script