Start by measuring the output of the solar cell, with a 10K resistor across it. When it is at absolute max energy you should have 5 volts (assuming that is vRef, if not adjust accordingly), if more you will either have to lower the resistance of the 10K resistor or insert a voltage divider. You can test your software with a pot on 5V and Ground with the wiper going to the Arduino A0.
Their schematic is WRONG. You need a resistive load across the solar panel; and if its a 12V panel you need a potential divider as shown here to drop the voltage to something the arduino can measure. So for example if youre using an Uno you can use the internal 1.1V reference;
start with R1 = 10k and you'll need about 680 or 820 ohms for R2. RESISTANCE will be the total ie 10680
The code at a glance looks OK - except :
*R should be in OHMS
*you need to measure the ACTIVE area of the panel
*you divide by 1000 not 100 to convert mm to m
Area = PANEL_LENGTH * PANEL_WIDTH / (100*100); // we are dividing by 10000 get the area in square meters
*The value read in should be corrected to a voltage before being used.
*it doesnt include a term for efficiency (around 20%).
Tell us how its not working (ie what you expect and what you get)
/*------------------------------------------------------------------------------------------------------------------------*/
#define ANALOG_PIN A0 // Analog pin
#define RESISTANCE 10 // Resistance in thousands of ohms
#define PANEL_LENGTH 60 // Length of solar cell in mm
#define PANEL_WIDTH 20 // Width of solar cell in mm
volatile float Area;
volatile float Power;
volatile float Radiation;
/*
* Main Setup function
*/
void setup() {
// Begin serial communication
Serial.begin(9600);
while(!Serial);
delay(100);
}
void loop() {
Area = PANEL_LENGTH * PANEL_WIDTH / (100*100); // we are dividing by 10000 get the area in square meters
Power = pow(analogRead( ANALOG_PIN ), 2) / RESISTANCE ; // Calculating power v^2 / R
Radiation = Power / Area;
char *msg;
sprintf(msg, " The Solar Radiation is %f W/M2 ", Radiation); // Generating message to be printed
Serial.println(msg);
delay(1000);
}
This works. You need the 3.3V connected to A3 to give a voltage reference for measurement
Lots of prints for diagnostics.
The sprintf caused a host of problems so I've just used Serial.prints.
/*------------------------------------------------------------------------------------------------------------------------*/
#define ANALOG_PIN A0 // Analog pin
#define PANEL_LENGTH 60 // Length of active part of solar panel in mm
#define PANEL_WIDTH 20 // Width of active part of solar panel in mm
#define eff_pc 20 //percent efficiency of solar panel
//Analog input pin assignments
#define VrefPin 3 // pin A3 - the pin our reference is connected to
#define VxPin 0 // use will use analog pin 0 for voltage x
// for voltage conversion
float vRef = 3.390; // the accurate value of your reference eg 4.096
/* *** change the value to match the reference voltage you are using *** */
long nX, nRef; //the value we read from the ADC
float vX; //measured voltage values after calibration correction
// sampling parameters
int nSamp = 5; // Number of Samples to take for each reading
int interval = 7; //milliseconds interval between successive readings
float res = 1000; //resistance in OHMS
volatile float Area;
volatile float Power;
volatile float Radiation;
//take a set of "count" readings from selected analog input, with a delay of "pause" between readings.
long readInput(int pin, int count, int pause) {
long n = analogRead( pin); // dummy read
n = 0; // initialise for aggregation
delay(pause);
for (int i = 0; i < count; i++ ) {
n += analogRead( pin);
delay(pause); //short delay between readings - could use millis instead
}
return n ; //returns a number count * reading
}
// Convert the number reading to voltage
float convReadings(long nZ, long nR, float vR)
{
float ztrue = (vR * nZ) / nR; //apply correction
ztrue*=1000; //convert to mV
return (ztrue); //return the result as a voltage
}
/*
Main Setup function
*/
void setup() {
// Begin serial communication
Serial.begin(115200);
analogReference(DEFAULT); // program is being tested on a 5V Arduino Nano so this will be ROUGHLY 5.0V; as measured on mine 4.65V
nRef = analogRead(VrefPin); // dummy read to settle ADC Mux
Serial.print("starting measurement - nRef is ");
Serial.println(nRef);
Serial.println();
delay(5);
}
void loop() {
Area = PANEL_LENGTH * PANEL_WIDTH; //in mm square - keep numbers big for better accuracy
Serial.print("Area is ");
Serial.print(Area);
Serial.println(" uM");
nX = readInput(VxPin, nSamp, interval);
Serial.print("nX is ");
Serial.print(nX);
nRef = readInput(VrefPin, nSamp, interval);
Serial.print("; nRef is ");
Serial.print(nRef);
vX = convReadings(nX, nRef, vRef); //vX is now the measured voltage at VxPin
Serial.print("; Vx is ");
Serial.print(vX, 0);
Serial.println(" millivolts");
Serial.println();
Power = vX * vX / res ; // Calculating power v^2 / R in microWatts
Power /=1000;
Radiation = Power / Area; //mW/mm^2
Radiation *=1000; //W/m^2
Radiation *= 100/eff_pc; //correct for panel efficiency
Serial.print("Power is ");
Serial.print(Power);
Serial.println(" mW");
Serial.print("Radiation is ");
Serial.print(Radiation);
Serial.println(" W / m2 ");
Serial.println();
delay(1000);
}
I suspect it is necessary to measure both current and voltage to get a true measure of solar irradience. It also may be necessary to be able to vary the load so as to measure the power (current and voltage) at the maximum power point. A solar cell produces its maximum output (Watts) in bright sunlight when the load is adjusted to the maximum power point. If the solar irradience is only 50% of the max then the solar panel will produce (roughly) 50% of its maximum output. But, AFAIK, you would need to adjust the load to the new maximum power point to get a proper Wattage reading.
I think if I wanted to measure the brightness of sunlight I would just use a Light Dependent Resistor (LDR) although it would be essential to allow for its non-linear response.
I think it will just alter the efficiency. A fixed load generally seems OK if its somewhere near the max power transfer range. Hard to know what it should be without the spec for the panel.
Not sure an LDR or photodiode would give better results.
The short circuit current, not the voltage, of a solar panel or photodiode, is a measure of the solar irradiance. The current is proportional to the number of photons absorbed per second.
You can't measure that directly with an Arduino, but the voltage drop across a low value resistor (e.g. less than 100 Ohms) will be a useful approximation. Use the low voltage reference (about 1.1V on a Uno) for the ADC to measure it.
Thats right; the light splits carriers near the junction, that get swept out by the barrier potential; so you get Imax at v=0 and when the carriers create enough voltrage to foward bias the junction Inet = 0;
Because the current is dependent mainly on the illumination the device (within limits) acts as a current source so you DONT (unless you are a purist) need to measure the short circuit current.
A single junction silicon solar cell can produce a maximum open-circuit voltage of approximately 0.5 to 0.6 volts ; So the open-circuit voltage is largely independent of irradiance (and more on temperature)
So all you need to do is measure the short circuit current - ie the voltage across zero ohms. ...
Its a balance between picking a resistive load that will give enough sensitivity.
However whether its a calculator panel - about 8 - 12 cells for "5V";
or a "12V " panel, choosing a load that will reduce the output to less than half of the open circuit voltage under good illumination will give a good estimate of Isc.
jremington:
The short circuit current, not the voltage, of a solar panel or photodiode, is a measure of the solar irradiance. The current is proportional to the number of photons absorbed per second.
That seems a lot more sensible than measuring the voltage across a 10k resistor.
But, as solar radiation is in W/m2 doesn't that mean that one really ought to measure the Watts produced by the panel at the maximum power point?
Perhaps the short-circuit current is a close-enough approximation because solar cells are (very roughly) constant current devices when the load is below the MPP. It was the 10k resistor in the earlier Posts that seemed wrong, but it's a while since I have considered the behaviour of my solar panels so I did not immediately remember that they are constant current devices. I have 0.01 Ohm resistors to measure the current from my panels but I just use my multimeter occasionally.
As a quick test will show, the open circuit voltage of a solar panel, solar cell or photodiode depends only weakly on the illumination. Even rather dim light will produce close to the maximum voltage (as measured with a decent multimeter).
We have a wattmeter that records the power they produce; 3.5MWh last year.
I think 0.01 ohm would be a bit low for a 60*20mm panel! And 10k probably much too high. But if thats all the OP has to hand.. can always add a 100 ohm or so directly across the panel terminals once its working.
But, as solar radiation is in W/m2 doesn't that mean that one really ought to measure the Watts produced by the panel at the maximum power point?
No, because that is a highly nonlinear function of the incident radiation, and depends on the load.
Ideally you want to measure the number of photons per second per square meter arriving on a surface. The short circuit circuit solar panel is an approximation to that, except that it is highly wavelength dependent. That approximation is especially bad on cloudy days, because long wave IR is neglected.
johnerrington:
I think 0.01 ohm would be a bit low for a 60*20mm panel! And 10k probably much too high. But if thats all the OP has to hand.. can always add a 100 ohm or so directly across the panel terminals once its working.
The size of the panel is irrelevant - one is trying to measure the short circuit current so the lower value of resistor the better.
If a 10k resistor is all the OP has then he is not in a position to measure the short circuit current. Measurements made with it will be meaningless. The voltage across a 10k resisitor will approximate to the open-circuit voltage.
Specs for a 12V 5W battery charging panel (205*235mm) give Voc 22V Isc 0.3A; peak power 18V 0.28A
@JRemington Note Ipp is STILL at 93% of Isc even though Vpp is 80% of Voc
The example panel is 60*20 so the best Isc we can expect is (assuming its a similar construction but for 6V)
Isc = 0.3 * 1/20 = 15mA.
The resolution of a Uno using the "INTERNAL" reference is 1.1V/1024 or about 1mV
To get a voltage out that is measureable with reasonable resolution we need V on load to be "around" 0.7V so allowing headroom to prevent the input being overvoltaged.
So ideally we need a load of AROUND 47 ohms.
The size of the panel is irrelevant
Have to disagree Robin, as far as directly measuring with an arduino analog input is concerned. 15mA *.01 ohms = ?
OK in an ideal world we WOULD measure Isc. And know the exact perormance specs of our panel; And calibrate against a standard CLass A thermopile pyranometer.