I have a Weather Station project built with Raspberry Pi and Weather Underground. It collects humidity, temperature and atmospheric pressure. However Weather Underground can accept more data to analyze weather statistics. Solar radiation is one of these entities. I decided to check how complicated it is to calculate solar radiation for your location. Spending some time I figured out it's pretty straightforward and requires some simple input data: latitude and longitude, sunrise and sunset time, and preferred time zone and then you can use some formulas to calculate actual solar radiation. Many valuable information related solar radiation and its calculation can be find here.
What Is Solar Radiation?Solar radiation is the radiation, or energy we get from the sun. It is also known as short-wave radiation. Solar radiation comes in many forms, such as visible light, radio waves, heat (infrared), x-rays, and ultraviolet rays. Measurements for solar radiation are higher on clear, sunny day and usually low on cloudy days. When the sun is down, or there are heavy clouds blocking the sun, solar radiation is measured at zero.
Every location on Earth receives sunlight at least part of the year. The amount of solar radiation that reaches any one spot on the Earth's surface varies according to:
- Geographic location
- Time of day
- Season
- Local landscape
- Local weather
A solar radiation storm (also known as a Solar Proton Event or SPE) occurs often after major eruptions on the Sun when protons get launched at incredibly high speeds, sometimes up to several 10.000 km/s. These radiation storms can bridge the Sun-Earth distance in as little time as 30 minutes and last for multiple days. In this article we are going to explain what a solar radiation storm is and what kind of effects it has on us.
I used Visual Studio 2017 for the project but you can use any IDE or even simple text editors for the coding part, depends on your preferences.
I used Python 2.7 (because weather station also uses it) however you can easily switch to Python 3, just need to change couple imports.
Raspberry Pi is optional, it's up to you where to run your solar radiation calculation code.
You probably need to install following Python modules:
sudo pip install python-dateutil
sudo pip install pytz
sudo pip install pyyaml
Input Data To Calculate Solar RadiationTo get started we need some input data to be used in formulas:
- Latitude and Longitude can be found through different maps services, for example Google Maps
- Sunrise and Sunset times, we get it from public API
- Timezone to calculate solar radiation
I attached several sources where you can find complete code implementation. The first one is related to Weather Station plugins (which I believe is the best one because you can use your Solar Radiation calculations in real project and make them valuable). The second one is a separate GitHub repository I built for this example so you can play with it and/or use it in your other projects.
Now let's take a look on the most important code sections (took from weather station example).
Let's start with declaring some instance fields (__init__ method):
self.sunrise = None
self.sunset = None
self._timezone = None
self._today = None
Regular fields to store sunrise, sunset time, timezone and today's date, these fields store data to avoid unnecessary API calls.
Let's move forward and parse config file (parse_config method):
- I used yaml file for configuration (you can try anything else)
- If you stick with this solution, it is very simple to parse just use PyYAML library:
self.config = yaml.safe_load(open(self.config_file_name))
Important here:
- In GitHub repositories I used solar_radiation.yaml.example, so you need to rename it and set correct values for your device
- If you need to get absolute path to your file name you can use this approach:
'{}/solar_radiation.yaml'.format(os.path.dirname(os.path.abspath(__file__)))
Let's take a look on air_mass static method:
declination_angle = math.radians(SolarRadiation.declination_angle(day));
hour_angle = math.radians(SolarRadiation.hour_angle(hour));
elevation_angle = SolarRadiation.elevation_angle(hour_angle, declination_angle, latitude)
declination = math.radians(90) - elevation_angle;
return 1 / (1E-4 + math.cos(declination))
It calls other static helper methods to calculate solar radiation absorption by atmosphere and particles.
It calculates elevation and declination angles for sun depending on day of year, hour and latitude, it calculates hour angle and finally return air mass, more details can be found in code comments link.
Moving to get_sunrise_sunset method:
if (self.config and (not self.sunrise or not self.sunset or not self.is_date_today)):
self._today = self.current_date.date()
try:
response = urllib.urlopen(self.sunrise_sunset_url)
data = json.loads(response.read())
result = data['results']
sunrise = result['sunrise']
sunset = result['sunset']
# Convert to provided in config timezone, as API returns in UTC by default
self.sunrise = dateutil.parser.parse(sunrise).astimezone(self.timezone)
self.sunset = dateutil.parser.parse(sunset).astimezone(self.timezone)
except Exception as error:
self.errors.append(error)
return (self.sunrise, self.sunset)
This method is used to calculate initial values for sunrise and sunset or to recalculate them if current date changes. Storing values as class fields helps to avoid unnecessary API calls.
Last but not the lease calcluate_solar_radiation method does some adjustments to final result:
if self.is_day:
air_mass = SolarRadiation.air_mass(self.current_hour, self.day_of_year, self.latitude)
result = math.pow(0.7, air_mass)
result = 1353 * math.pow(result, 0.678)
# We ignore case more than 1100 W/m2, because the peak solar radiation is 1 kW/m2
# http://www.pveducation.org/pvcdrom/average-solar-radiation
return 0 if result > 1100 else result
Now, ready to get data (get_data method):
It is very simple (as we use it with weather station as plugin we use get_data method as single entry point to it, so it calls all required methods to calculate solar radiation). We check if config file was parsed and has valid data (not None values) returns dictionary as a result if any.
result = {}
if not self.config:
self.parse_config()
# Dictionary data for Weather Underground upload
if self.has_valid_data:
solar_radiation = self.calcluate_solar_radiation()
if solar_radiation is not None:
result['solarradiation'] = solar_radiation
return result
ConclusionAs you can see it's pretty simple, it needs some time to get what formulas do, I tried to comment code efficiently so it makes more sense when you read. Now you can use in different ways: with your weather station or other weather related projects, just for fun to get familiar with public APIs to get weather data or just for self education. If you want you can build your own weather station.
Comments