I agree with peter's comment. The Davis solar radiation sensor, or any comparable sensor, is measuring a global radiation ( direct + diffuse) and the surface of the sensor is parallel to the ground. A fixed threshold, such as 120 W/m2, can be used only with sensors measuring direct radiation and that have their surface always pointing to the sun (i.e surface of sensor is always perpendicular to the axis sun-sensor). With a Davis solar sensor, applying a fixed threshold to estimate sunshine duration give innacurate values. Why? A simple example, taken from the measurements of my Davis solar sensor, will make you understand: - On December 20, at 9:30, the sun was shining, and my solar sensor, in full sun, measured 105 W / m2. - On June 11, at 10 am, the sky was cloudy, and my solar probe measured 301 W / m2. How to choose a fixed threshold so that the sun of December with 105 W / m2 is considered as sunny and that a radiation of 301W / m2 under a cloudy sky of end of June is not considered as sunny? A measurement of the global solar radiation on a plane parallel to the ground is very dependent on the elevation of the sun. This elevation changes according to the time of day and according to the seasons. So with this type of solar sensors, a valid calculation of the sunshine duration can only be done with methods taking into account the elevation of the sun at the time of the measurement, calculated according to the latitude, longitude, date and the time of observation.
Here is the weewx extension I am using, that I modified from https://github.com/brewster76/util-archer/blob/master/user/radiationhours.py by applying a formula developed by MeteoFrance to estimate sunshine duration from Davis sensors. (https://forums.infoclimat.fr/f/topic/17151-calcul-duree-ensoleillement/?do=findComment&comment=1216053). The idea is to determine at each measurements a threshold value that is calculated depending on the date, time and geographic location (latitude and longitude) of the sensor. If the measured solar radiation is higher than the calculated threshold, the sunshine duration for this measurement will be equal to the archive interval, otherwise it will be 0. """ Adds a new observation field to weewx: [sunshine_time] Installation: 1. Save this file to your user customisations directory (which is often /usr/share/weewx/user) 2. Enable this service in weewx.conf by adding user.sunduration.SunshineDuration to the process_services list. [Engine] [[Services]] # This section specifies the services that should be run. They are # grouped by type, and the order of services within each group # determines the order in which the services will be run. prep_services = weewx.engine.StdTimeSynch process_services = user.sunduration.SunshineDuration, weewx.engine.StdConvert, weewx.engine.StdCalibrate, weewx.engine.StdQC, weewx.wxservices.StdWXCalculate 3. Add [sunshine_time] to the database schema so tables include this new observation field. In weewx.conf, change the wx_binding schema from schemas.wview.schema to user.sunduration.schema_with_sunshine_time [DataBindings] [[wx_binding]] # The database must match one of the sections in [Databases]. # This is likely to be the only option you would want to change. database = archive_sqlite # The name of the table within the database table_name = archive # The manager handles aggregation of data for historical summaries manager = weewx.wxmanager.WXDaySummaryManager # The schema defines the structure of the database. # It is *only* used when the database is created. #schema = schemas.wview.schema schema = user.sunduration.schema_with_sunshine_time 4. Shutdown Weewx and update your database to bring in the new field. wee_database weewx.conf --reconfigure Make sure you know what you're doing at this point, you can potentially corrupt/lose your archive data. The weewx customization guide covers this in a lot more detail. 5. Tell Weewx about the units for this new type Add this to user/extensions.py: # # Units for sunshine_days calculated field # import weewx.units weewx.units.obs_group_dict['sunshine_time'] = 'group_interval' 6. Use [sunshine_time] in your graphs and html template tags. Lots more detail on this process can be found here: http://www.weewx.com/docs/customizing.htm#Adding_a_new_observation_type """ import syslog from math import sin,cos,pi,asin from datetime import datetime import time import weewx from weewx.wxengine import StdService import schemas.wview class SunshineDuration(StdService): def __init__(self, engine, config_dict): # Pass the initialization information on to my superclass: super(SunshineDuration, self).__init__(engine, config_dict) # Start intercepting events: self.bind(weewx.NEW_ARCHIVE_RECORD, self.newArchiveRecord) def newArchiveRecord(self, event): """Gets called on a new archive record event.""" seuil = 0 tempe = float(event.record.get('outTemp')) radiation = event.record.get('radiation') event.record['sunshine_time'] = 0.0 if radiation is not None: utcdate = datetime.utcfromtimestamp(event.record.get('dateTime')) dayofyear = int(time.strftime("%j",time.gmtime(event.record.get('dateTime')))) theta = 360 * dayofyear / 365 equatemps = 0.0172 + 0.4281 * cos((pi / 180) * theta) - 7.3515 * sin( (pi / 180) * theta) - 3.3495 * cos(2 * (pi / 180) * theta) - 9.3619 * sin( 2 * (pi / 180) * theta) latitude= float(self.config_dict["Station"]["latitude"]) longitude = float(self.config_dict["Station"]["longitude"]) corrtemps = longitude * 4 declinaison = asin(0.006918 - 0.399912 * cos((pi / 180) * theta) + 0.070257 * sin( (pi / 180) * theta) - 0.006758 * cos(2 * (pi / 180) * theta) + 0.000908 * sin( 2 * (pi / 180) * theta)) * (180 / pi) minutesjour = utcdate.hour*60 + utcdate.minute tempsolaire = (minutesjour + corrtemps + equatemps) / 60 angle_horaire = (tempsolaire - 12) * 15 hauteur_soleil = asin(sin((pi / 180) * latitude) * sin((pi / 180) * declinaison) + cos( (pi / 180) * latitude) * cos((pi / 180) * declinaison) * cos((pi / 180) * angle_horaire)) * (180 / pi) if hauteur_soleil > 3: seuil = (0.73 + 0.06 * cos((pi / 180) * 360 * dayofyear / 365)) *1080 * pow((sin(pi / 180) * hauteur_soleil), 1.25) * 0.90 mesure = (((tempe * 1 - 25) * (-0.0012) * radiation) + radiation) if mesure > seuil: event.record['sunshine_time'] = event.record['interval'] syslog.syslog(syslog.LOG_DEBUG, "Calculated sunshine_time = %f, based on radiation = %f, and threshold = %f" % (event.record['sunshine_time'], radiation, seuil)) schema_with_sunshine_time = schemas.wview.schema + [('sunshine_time', 'REAL')] -- You received this message because you are subscribed to the Google Groups "weewx-user" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/weewx-user/9f684531-e663-4532-b0fd-8a7257741645%40googlegroups.com.
