The basic sensor I decided to use was the SP-110 Solar Radiation Sensor. It's self-powered and thus doesn't require an additional power supply while at the same time providing a simple linear voltage output depending on the incoming solar radiation. Since it's sensitivity is 0.20mV per Wm-2 it provides signal outputs up to around 0.2V in full daylight. The price for the sensor alone is around 200€.
Using an ADC and the Raspberry Pi to measure Solar RadiationHow are we going to combine this sensor with out existing infrastructure? Theoretically, we could use our Raspberry Pi to measure the signal output and upload it to our weather database and guess what: that's exactly what we are going to do.
However, the Raspberry Pi doesn't allow us to measure analog voltage outputs directly so we need a so-called "ADC" (Analog to Digital Converter). They are cheaply available for the Raspberry Pi and are connected to it using the I2C bus. I decided to get a rather "expensive" ADC (12€, it is), the ADS1115 chip. It provides four measurable inputs or two differential measurement inputs and comes with a hardware-based amplification ("GAIN") of up to a 16x factor which we will use to enhance the measurement precision.
Adafruit provides an excellent article on how to use, wire and program with the ADS1115 chip on their website with an Arduino. Since we're using a Raspberry Pi we need to slighlty change the wiring. We need to connect the ADC VDD pin to the GPIO +V power supply pin and the GND to it's GPIO counterpart respectively. Additonally, we need to connect the SDA and SCL pins of the chip and Raspberry Pi. As explained in Adafruit's article, we can change the ADC's I2C address in order to be able to connect several different ADC chips to one Raspberry Pi. This can be done by connecting the chip's GND and ADDR port, yielding an I2C address of 0x48.
The next step is to wire the Solar Radiation Sensor to the ADC itself. As described in the SP-110 manual, we will connect the ground of the sensor to the GND of the ADC and use the A0 and A1 PINS to measure the differential input between the red and black signals coming from the sensor.
Now with all the wiring done, let's mount the sensor on the roof and begin analyzing the data!
Python Program to Retrieve the Sensor Data
Luckily, Adafruit provides source codes for nearly all of it's sensors and chips and thus we can simply use their excellent Python library which can be obtained on GitHub. Make sure you have the latest version of Python installed, too! If this is your first time you're working with I2C, you first need to enable I2C on the Raspberry Pi as described in detail here.
[code lang="python"] import time import Adafruit_ADS1x15 adc = Adafruit_ADS1x15.ADS1115() GAIN = 8 while True: difValue = -adc.read_adc_difference(0, gain=GAIN) voltageValue = (difValue) / 32767.0 * 4.096 / GAIN wattsPerM2Value = max(0,round(5000*values,2)) updateSolarRadriation(wattsPerM2Value) time.sleep(2) [/code]
So what is this code actually doing? First of all we import the needed libraries and initialize it. Note that we could pass an optional I2C address to the ADS1115 constructor, but since we are using the default value of 0x48 we are fine.
We know that the ADS1115 allows us to measure voltages between 0.0V and 4.096V on it's default GAIN value. The solar radiation can reach values as high as 1700Wm-2 which results in a signal output of 0.34V. This means that we can safely apply a GAIN amplification of at least 8 for our measurements!
Since we connected both signal outputs to A0 and A1, we read the differential value using the Python library. The chip is a 16-bit ADC using signed integers, so the measurement output will be in the range from -32767 to 32767. Knowing the maximum measureable output at initial GAIN (4.096V) we can now convert this value directly into a voltage measurement. According to the SP-110 manual and calibration information on the sensor, the sensitivity is indeed 20mV per Wm-2, which means we have to multiply the voltage by a factor of 5000 to obtain the final solar radiation measurement.
And that's it. We can now add an algorithm to take the average of all samples within a 2.5 minute interval that also connects to the SQL DB and stores the received values, and we're finished.